Very nearly a useful tool. Still generating zombies, however; much work in
wrapper to get this far, but still no bananas!
This commit is contained in:
parent
98b634bc9d
commit
a53cbcbde3
8
Makefile
8
Makefile
|
@ -5,7 +5,7 @@ CC= gcc
|
||||||
CFLAGS= -g
|
CFLAGS= -g
|
||||||
LD= gcc
|
LD= gcc
|
||||||
LDFLAGS= -g
|
LDFLAGS= -g
|
||||||
BINDIR= /usr/local/bin
|
HOMEDIR= /usr/local/etc/gild
|
||||||
TARGETS= gild
|
TARGETS= gild
|
||||||
COMPONENTS = gild.o wrapper.o config.o log.o
|
COMPONENTS = gild.o wrapper.o config.o log.o
|
||||||
|
|
||||||
|
@ -21,7 +21,9 @@ clean:
|
||||||
rm core *.o $(TARGETS)
|
rm core *.o $(TARGETS)
|
||||||
|
|
||||||
install: $(TARGETS)
|
install: $(TARGETS)
|
||||||
install --strip $(TARGETS) $(BINDIR)
|
install --strip $(TARGETS) gild.conf $(HOMEDIR)
|
||||||
|
install handlers/* $(HOMEDIR)/handlers
|
||||||
|
|
||||||
version: $(TARGETS)
|
version: $(TARGETS)
|
||||||
cvs commit gild.c wrapper.c config.c log.c Makefile gild.h gild.conf
|
cvs commit gild.c wrapper.c config.c log.c Makefile gild.h \
|
||||||
|
gild.conf handlers
|
2
config.c
2
config.c
|
@ -12,6 +12,8 @@
|
||||||
* *
|
* *
|
||||||
\**************************************************************************/
|
\**************************************************************************/
|
||||||
|
|
||||||
|
/* $Header$ */
|
||||||
|
|
||||||
#include "gild.h"
|
#include "gild.h"
|
||||||
|
|
||||||
extern char errorBuff[]; /* where I assemble logging messages */
|
extern char errorBuff[]; /* where I assemble logging messages */
|
||||||
|
|
14
gild.c
14
gild.c
|
@ -23,8 +23,6 @@ int port = DEFAULT_PORT_NO; /* the port I shall listen on */
|
||||||
char errorBuff[ 1024]; /* somewhere to assemble error messages */
|
char errorBuff[ 1024]; /* somewhere to assemble error messages */
|
||||||
extern handler * handlers;
|
extern handler * handlers;
|
||||||
/* the list of handlers I support */
|
/* the list of handlers I support */
|
||||||
FILE * logstream = stderr; /* where I stick log messages */
|
|
||||||
|
|
||||||
|
|
||||||
void error( int severity)
|
void error( int severity)
|
||||||
/* log the current contents of errorBuff and then if severity is bad die */
|
/* log the current contents of errorBuff and then if severity is bad die */
|
||||||
|
@ -49,8 +47,6 @@ int main( int argc, char * argv[])
|
||||||
( struct sockaddr_in *)malloc( sizeof( struct sockaddr_in));
|
( struct sockaddr_in *)malloc( sizeof( struct sockaddr_in));
|
||||||
/* the address I bind the keyhole to */
|
/* the address I bind the keyhole to */
|
||||||
|
|
||||||
fprintf( stderr, "%s starting...", GILD_ID);
|
|
||||||
|
|
||||||
for ( arg = 1; argc > arg; arg ++)
|
for ( arg = 1; argc > arg; arg ++)
|
||||||
{ /* process arguments */
|
{ /* process arguments */
|
||||||
switch ( argv[ arg][ 0])
|
switch ( argv[ arg][ 0])
|
||||||
|
@ -115,8 +111,11 @@ int main( int argc, char * argv[])
|
||||||
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
/* we become a real class one daemon */
|
/* we become a real class one daemon */
|
||||||
if ( fork() != 0) exit(0);
|
if ( fork() != 0) /* we're the parent */
|
||||||
/* the parent exits */
|
{
|
||||||
|
exit(0); /* so die */
|
||||||
|
}
|
||||||
|
/* otherwise (we're the child)... */
|
||||||
setsid(); /* release the controlling tty */
|
setsid(); /* release the controlling tty */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -171,12 +170,15 @@ int main( int argc, char * argv[])
|
||||||
|
|
||||||
wrapper( conversation, client_addr);
|
wrapper( conversation, client_addr);
|
||||||
/* wrapper (q.v.) handles the conversation */
|
/* wrapper (q.v.) handles the conversation */
|
||||||
|
|
||||||
|
exit( 0); /* after completing wrapper, die */
|
||||||
break;
|
break;
|
||||||
default: /* I'm the parent */
|
default: /* I'm the parent */
|
||||||
close( conversation);
|
close( conversation);
|
||||||
free( client); /* prevent memory bloat */
|
free( client); /* prevent memory bloat */
|
||||||
if ( client_addr != null)
|
if ( client_addr != null)
|
||||||
free( client_addr);
|
free( client_addr);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Sample GILD configuration file
|
# Sample GILD configuration file
|
||||||
# $Header$
|
# $Header$
|
||||||
# protocol pattern handler timeout
|
# protocol pattern handler timeout
|
||||||
|
|
||||||
http ^.*HTTP/[0-1] handlers/http 5
|
http ^.*HTTP/[0-1] handlers/http 5
|
||||||
crp CRP/1 handlers/crp 10
|
crp CRP/1 handlers/crp 10
|
||||||
|
|
1
gild.h
1
gild.h
|
@ -40,7 +40,6 @@
|
||||||
#define STDOUT_FILENO 1
|
#define STDOUT_FILENO 1
|
||||||
#define STDERR_FILENO 2
|
#define STDERR_FILENO 2
|
||||||
|
|
||||||
|
|
||||||
#define ever (;;)
|
#define ever (;;)
|
||||||
#define null (((void *) 0))
|
#define null (((void *) 0))
|
||||||
|
|
||||||
|
|
|
@ -73,14 +73,14 @@ then
|
||||||
case $command in
|
case $command in
|
||||||
"HEAD"|"Head"|"head") exit 0;;
|
"HEAD"|"Head"|"head") exit 0;;
|
||||||
"GET"|"Get"|"get" ) cat $file;;
|
"GET"|"Get"|"get" ) cat $file;;
|
||||||
* ) echo "Whoops! Unexpected error!";;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo "$now: $REMOTE_HOST: $command: $rq_file" \
|
echo "$now: $REMOTE_HOST: $command: $rq_file" \
|
||||||
>> $SERVER_ROOT/logs/access_log
|
>> $SERVER_ROOT/logs/access_log
|
||||||
else
|
else # didn't find it; report and log
|
||||||
cat $SERVER_ROOT/error/404.html
|
cat $SERVER_ROOT/error/404.html
|
||||||
echo "$now: $REMOTE_HOST: No such file [$rq_file]" \
|
echo "$now: $REMOTE_HOST: No such file [$rq_file]" \
|
||||||
>> $SERVER_ROOT/logs/error_log
|
>> $SERVER_ROOT/logs/error_log
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
exit 0 # yes, I know it _shouldn't_ be necessary
|
||||||
|
|
4
log.c
4
log.c
|
@ -21,8 +21,12 @@
|
||||||
int log( int level, char *message)
|
int log( int level, char *message)
|
||||||
/* hand this message over to the syslog daemon for recording */
|
/* hand this message over to the syslog daemon for recording */
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf( stderr, "%s: DEBUG: %s\n", GILD_ID, message);
|
||||||
|
#else
|
||||||
openlog( GILD_NAME, 0, LOG_DAEMON);
|
openlog( GILD_NAME, 0, LOG_DAEMON);
|
||||||
syslog( level, message);
|
syslog( level, message);
|
||||||
closelog();
|
closelog();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
67
wrapper.c
67
wrapper.c
|
@ -16,26 +16,27 @@
|
||||||
|
|
||||||
#include "gild.h"
|
#include "gild.h"
|
||||||
|
|
||||||
char errorBuff[ 1024];
|
extern char errorBuff[ 1024];
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
void die( void) /* inherited from cgi-lib; a way of
|
void die( void)
|
||||||
getting rid of errant programs */
|
/* inherited from cgi-lib; a way of getting rid of errant programs */
|
||||||
{
|
{
|
||||||
sprintf( errorBuff, "potentially serious: handler over-ran alloted time");
|
sprintf( errorBuff, "potentially serious: handler over-ran alloted time");
|
||||||
error( LOG_ERR);
|
error( LOG_ERR);
|
||||||
|
exit( 1); /* belt and braces; should never be called */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void wrapper( int conversation, char * client_id)
|
void wrapper( int conversation, char * client_id)
|
||||||
/* conversation is the handle on an open socket communicating with a
|
/* conversation is the handle on an open socket communicating with a
|
||||||
client. What I want to do is quite simple, and there must be a
|
client. */
|
||||||
straightforward way of doing it: attach the conversation to both
|
|
||||||
the standard input and the standard output of a process, and then
|
|
||||||
exec the handler within that process... I can't (at present) find
|
|
||||||
an easy way of doing that, however */
|
|
||||||
{
|
{
|
||||||
char firstln[ 1024];
|
char firstln[ 1024];
|
||||||
|
char * exec_args[1]; /* 'arguments' to pass to execve */
|
||||||
handler * command = null;
|
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);
|
recv( conversation, firstln, 80, MSG_PEEK);
|
||||||
/* get the first thing the client
|
/* get the first thing the client
|
||||||
|
@ -67,11 +68,8 @@ void wrapper( int conversation, char * client_id)
|
||||||
}
|
}
|
||||||
else /* did find one */
|
else /* did find one */
|
||||||
{
|
{
|
||||||
sprintf( errorBuff,
|
setenv( "REMOTE_HOST", client_id, 1);
|
||||||
"using handler '%s' to handle %s request from %s",
|
/* set up the handler environment */
|
||||||
command->command, command->protocol, client_id);
|
|
||||||
error( LOG_NOTICE);
|
|
||||||
/* log the request */
|
|
||||||
|
|
||||||
if ( command->timeout != 0)
|
if ( command->timeout != 0)
|
||||||
/* prevent runaway processes; if a
|
/* prevent runaway processes; if a
|
||||||
|
@ -82,10 +80,46 @@ void wrapper( int conversation, char * client_id)
|
||||||
alarm( command->timeout);
|
alarm( command->timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
setenv( "REMOTE_HOST", client_id, 1);
|
child_pid = fork();
|
||||||
/* set up the handler environment */
|
|
||||||
|
|
||||||
system( command->command);
|
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);
|
exit( 0);
|
||||||
|
@ -94,4 +128,3 @@ void wrapper( int conversation, char * client_id)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue