/*
* This file is part of rasdaman community.
*
* Rasdaman community is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Rasdaman community is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rasdaman community. If not, see .
*
* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
rasdaman GmbH.
*
* For more information please see
* or contact Peter Baumann via .
*/
#include "mymalloc/mymalloc.h"
/*------------------------------------------------------------------------*/
/* childs.c - child process handling. */
/* */
/*------------------------------------------------------------------------*/
/* Comments: */
/* - intended purpose: */
/* Keep all functions related to child processes in one place. */
/* - Status: */
/* - Functions to Create and Initialize a child is thrown in. */
/* - Should think over the actual design - looks somewhat */
/* messy now. It should be something more clean and of */
/* generic use, so it can be reused in future projects. */
/* - Nevertheless -- it works, and there should be no creeping */
/* surprises in the code... [FLW Alert... ;-)] */
/*------------------------------------------------------------------------*/
/*
* RCS:
* $RCSfile: childs.c,v $ $Revision: 1.6 $ $State: Exp $
* $Locker: $
*/
#include "defs.h"
#include "protos.h"
#include "types.h"
#include "server.h"
#include "http-defs.h"
#include "http.h"
extern struct ServerBase Server;
/****** childs/InitChild *****************************************************
*
* NAME
* InitChild -- data initializition after forking the child process.
*
* SYNOPSIS
* int InitChild( struct ClientBase *Client );
*
* FUNCTION
*
* RESULT
*
* NOTES
*
* BUGS
*
* SEE ALSO
*
******************************************************************************
*
*/
rc_t InitChild( struct ClientBase *Client )
{
char *UnknownIP = "0.0.0.0";
/* Init ClientBase */
strcpy( Client->Host.IPAddrString, inet_ntoa( Client->Socket.sin_addr ) );
if( Client->Host.IPAddrString == NULL )
strcpy( Client->Host.IPAddrString, UnknownIP );
Client->Host.IPAddress = inet_addr( Client->Host.IPAddrString );
Client->Comm.ConnStatus = CONN_UNDEFINED;
InitHTTPMsg( &Client->Response );
InitReqInfo( &Client->Request );
return( OK );
}
/****** childs/NewChild ******************************************************
*
* NAME
*
*
* SYNOPSIS
*
*
* FUNCTION
*
*
* INPUTS
*
*
* RESULT
*
*
* NOTES
* ### Temporary fork() wrapper.
* Will be later expanded into something more usefull...
*
* BUGS
*
*
* SEE ALSO
*
*
******************************************************************************
*
*/
pid_t NewChild( struct ChildBase *List, struct FDsets *PDSets, struct ClientBase *Client )
{
struct ChildBase *Child;
Child = (struct ChildBase*)mymalloc( sizeof( struct ChildBase ) );
if( Child == NULL ) // Failure? => QUIT.
ErrorMsg( E_SYS, FAIL, "FAIL: NewChild(): malloc() failed!" );
// Open pipe
if( pipe( Child->PD ) < 0 )
{
ErrorMsg( E_SYS, ERROR, "ERROR: NewChild(): pipe() failed." );
Child->PipeStatus = PIPE_CLOSED;
}
else
{
Child->PipeStatus = PIPE_OPEN;
}
Child->PId = fork();
if( Child->PId < 0 ) // fork() Error? => QUIT.
ErrorMsg( E_SYS, FAIL, "FAIL: NewChild(): fork() failed!" );
if( Child->PId > 0 ) // parent process?
{
// Add Pipe-Descriptors to PipeSets
if( Child->PipeStatus == PIPE_OPEN )
{
FD_SET( Child->PD[0], &PDSets->Read );
if( Child->PD[0] > PDSets->MaxFD )
PDSets->MaxFD = Child->PD[0];
close( Child->PD[1] );
}
// Add Child to List
AddChild( List, Child );
}
else // child process
{
InitChild( Client );
// Remember PD to parent
Client->Pipe = Child->PD[1];
close( Child->PD[0] );
free( Child );
}
return( Child->PId );
}
void CleanupChild( struct ChildBase *List, struct FDsets *PDSets, pid_t PId )
{
struct ChildBase *Ptr;
struct ChildBase *Tmp;
LogMsg( LG_SERVER, DEBUG, "DEBUG: Begin CleanupChild ..." );
if(PDSets == NULL)
LogMsg( LG_SERVER, DEBUG, "DEBUG: ########### PDSets is NULL!" );
if(PId == (pid_t)0)
LogMsg( LG_SERVER, DEBUG, "DEBUG: ########### ChildPid is NULL!" );
if(List == NULL)
LogMsg( LG_SERVER, DEBUG, "DEBUG: ########### ChildBase is NULL!" );
if( List->PId > 0 )
{
for( Ptr = List; Ptr->next != List; Ptr = Ptr->next )
{
if( Ptr->next->PId == PId )
{
Tmp = Ptr->next;
break;
}
}
// Close pipe
close( Tmp->PD[0] );
// Remove Pipe-Descriptors from PipeSets
FD_CLR( Tmp->PD[0], &PDSets->Read );
RemChild( List, Tmp );
}
}
void AddChild( struct ChildBase *List, struct ChildBase *Child )
{
Child->next = List->next;
Child->prev = List;
List->next->prev = Child;
List->next = Child;
List->PId++;
}
void RemChild( struct ChildBase *List, struct ChildBase *Child )
{
Child->prev->next = Child->next;
Child->next->prev = Child->prev;
List->PId--;
free( Child );
}
struct ChildBase *GetChild( struct ChildBase *List, pid_t PId )
{
struct ChildBase *Ptr;
if( List->PId > 0 )
{
for( Ptr = List; Ptr->next != List; Ptr = Ptr->next )
{
if( Ptr->next->PId == PId )
return( Ptr->next );
}
return( NULL );
}
else
return( NULL );
}