gild/wrapper.c
simon a53cbcbde3 Very nearly a useful tool. Still generating zombies, however; much work in
wrapper to get this far, but still no bananas!
1997-10-15 20:16:08 +00:00

131 lines
4.1 KiB
C

/**************************************************************************\
* *
* Project: Gild *
* wrapper.c *
* *
* Purpose: Given a open socket connected to a client, handle *
* the conversation with the client by detecting the protocol *
* in use and invoking the appropriate handler *
* *
* Author : Simon Brooke *
* Copyright: (c) Simon Brooke 1997 *
* Version : 0.1 *
* Created : 7th October 1997 *
* *
\**************************************************************************/
#include "gild.h"
extern char errorBuff[ 1024];
extern char **environ;
void die( void)
/* inherited from cgi-lib; a way of getting rid of errant programs */
{
sprintf( errorBuff, "potentially serious: handler over-ran alloted time");
error( LOG_ERR);
exit( 1); /* belt and braces; should never be called */
}
void wrapper( int conversation, char * client_id)
/* conversation is the handle on an open socket communicating with a
client. */
{
char firstln[ 1024];
char * exec_args[1]; /* 'arguments' to pass to execve */
handler * command = null;
pid_t child_pid; /* the process number of the spawned child */
int child_status; /* the status returned by wait() */
recv( conversation, firstln, 80, MSG_PEEK);
/* get the first thing the client
says, but leave it on the input
stream for the handler. */
if ( dup2( conversation, STDIN_FILENO) == -1)
{
sprintf( errorBuff,
"failed to duplicate conversation [%d] onto stdin: %s",
conversation, strerror( errno));
error( LOG_ERR);
}
if ( dup2( conversation, STDOUT_FILENO) == -1)
{
sprintf( errorBuff,
"failed to duplicate conversation [%d] onto stdout: %s",
conversation, strerror( errno));
error( LOG_ERR);
}
command = get_handler( firstln);
/* and find the appropriate handler */
if ( command == null) /* didn't find one */
{
sprintf( errorBuff, "no handler registered for %s", firstln);
error( LOG_ERR);
}
else /* did find one */
{
setenv( "REMOTE_HOST", client_id, 1);
/* set up the handler environment */
if ( command->timeout != 0)
/* prevent runaway processes; if a
timeout has been specified for this
handler, enforce it */
{
signal( SIGALRM,(void (*)())die);
alarm( command->timeout);
}
child_pid = fork();
switch ( child_pid)
{
case -1: /* blew it; whinge and die */
sprintf( errorBuff, "failed to fork in wrapper()");
error( LOG_ERR);
break;
case 0: /* we're the child process */
sprintf( errorBuff,
"using handler '%s' [%d] to handle %s request from %s",
command->command, ( int)getpid(), command->protocol,
client_id);
error( LOG_NOTICE);
/* log the request, and... */
exec_args[ 0] = command->command;
exec_args[ 1] = null;
/* set up the dummy arguments */
if ( execve( command->command,
exec_args, environ) == -1)
/* ...execute the command (shouldn't return) */
{ /* if it did we've got an error */
sprintf( errorBuff,
"error [errno %d] whislt execing handler '%s' [%d]\n",
errno, command->command, child_pid),
error( LOG_ERR);
}
break;
default: /* we're the parent */
wait( &child_status);
/* hang around for the child to die */
sprintf( errorBuff,
"handler '%s' [%d] completed; wrapper exiting normally",
command->command, child_pid),
error( LOG_NOTICE);
break;
}
}
exit( 0);
}