From f54afde7464a893c9407d9e4fce6e7e3124a4da3 Mon Sep 17 00:00:00 2001 From: simon <> Date: Wed, 15 Oct 1997 16:48:54 +0000 Subject: [PATCH] Significantly improved; wrapper processes given configurable 'die' timeouts; client identified and passed in environment to handlers; logging through syslogd sorted and working well. --- Makefile | 6 +++++- config.c | 29 ++++++++++++++++------------- gild.c | 38 ++++++++++++++++++++++---------------- gild.conf | 10 +++++----- gild.h | 23 ++++++++++++----------- log.c | 4 ++-- wrapper.c | 41 ++++++++++++++++++++++++++++++++--------- 7 files changed, 94 insertions(+), 57 deletions(-) diff --git a/Makefile b/Makefile index 979ddc8..2f117a4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ # Makefile for itinerary engine utilities +# $Header$ CC= gcc CFLAGS= -g @@ -6,7 +7,7 @@ LD= gcc LDFLAGS= -g BINDIR= /usr/local/bin TARGETS= gild -COMPONENTS = gild.o wrapper.o config.o +COMPONENTS = gild.o wrapper.o config.o log.o all: $(TARGETS) @@ -21,3 +22,6 @@ clean: install: $(TARGETS) install --strip $(TARGETS) $(BINDIR) + +version: $(TARGETS) + cvs commit gild.c wrapper.c config.c log.c Makefile gild.h gild.conf \ No newline at end of file diff --git a/config.c b/config.c index b9c666c..73cf0dc 100644 --- a/config.c +++ b/config.c @@ -26,7 +26,7 @@ int parse_config( char * path) int n = 0; /* number of handlers we find */ sprintf( errorBuff, "Loading configuration from %s", path); - error( NOTICE); + error( LOG_NOTICE); configFile = fopen( path, "r"); @@ -34,19 +34,21 @@ int parse_config( char * path) { sprintf( errorBuff, "failed to open configuration file %s: %s", path, strerror( errno)); - error( FATAL_ERROR); + error( LOG_ERR); } while( ! feof( configFile)) { char buff[ 1024], protocol[ 1024], pattern[ 1024], command[ 1024]; + int timeout; /* how long to wait for the handler to + complete */ fgets( buff, 1024, configFile); /* get a line from the config file */ if ( buff[ 0] == '#'); /* it's a comment, and can be ignored */ - else if ( fscanf( configFile, "%s %s %s", protocol, - pattern, command) == 3) + else if ( fscanf( configFile, "%s %s %s %d", protocol, + pattern, command, &timeout) == 4) /* otherwise look for four fields. If we find them... */ { @@ -62,7 +64,7 @@ int parse_config( char * path) { /* unlikely, but... best check */ sprintf( errorBuff, "out of memory whilst allocating handler?"); - error( FATAL_ERROR); + error( LOG_ERR); } regcomp( patternBuff, pattern, @@ -71,6 +73,8 @@ int parse_config( char * path) newhandler->protocol = strdup( protocol); newhandler->pattern = patternBuff; newhandler->command = strdup( command); + newhandler->timeout = timeout; + /* then splice it into the handler chain */ newhandler->next = handlers; handlers = newhandler; @@ -81,28 +85,27 @@ int parse_config( char * path) sprintf( errorBuff, "registering handler [%s] for protocol %s", newhandler->command, newhandler->protocol); - error( NOTICE); + error( LOG_NOTICE); } } return ( n); /* say how many we found */ } -char * get_handler_command( char * match) +handler * get_handler( char * match) /* find a handler whose pattern matches match, and return it's command */ { - handler * h; - char * command = null; + handler * h = null, * i; regmatch_t pmatch[ 2]; - for ( h = handlers; ( command == null) && ( h != null); h = h->next) + for ( i = handlers; ( h == null) && ( i != null); i = i->next) /* scan down the list of handlers looking for a match... */ { - if ( regexec( h->pattern, match, 2, pmatch, 0) == 0) + if ( regexec( i->pattern, match, 2, pmatch, 0) == 0) { - command = h->command; + h = i; } } - return( command); + return( h); } diff --git a/gild.c b/gild.c index 9c5ad49..738dd2a 100644 --- a/gild.c +++ b/gild.c @@ -49,8 +49,7 @@ int main( int argc, char * argv[]) ( struct sockaddr_in *)malloc( sizeof( struct sockaddr_in)); /* the address I bind the keyhole to */ - sprintf( errorBuff, "GILD starting..."); - error( LOG_NOTICE); + fprintf( stderr, "%s starting...", GILD_ID); for ( arg = 1; argc > arg; arg ++) { /* process arguments */ @@ -68,29 +67,31 @@ int main( int argc, char * argv[]) port = atoi( argv[ arg]); break; default: - sprintf( errorBuff, + fprintf( stderr, "unrecognised command line switch [-%c]", argv[ arg][ 1]); - error( LOG_ERR); + exit( 1); break; } + break; default: - sprintf( errorBuff, "unrecognised command line token [%s]", + fprintf( stderr, "unrecognised command line token [%s]", argv[ arg]); + exit( 1); } } if ( parse_config( configPath) == 0) { - sprintf( errorBuff, "failed to load any handlers"); - error( LOG_ERR); + fprintf( stderr, "failed to load any handlers"); + exit( 1); } keyhole = socket( AF_INET, SOCK_STREAM, 0); if ( keyhole == -1) { - sprintf( errorBuff, "failed to intialise socket"); - error( LOG_ERR); + fprintf( stderr, "failed to intialise socket"); + exit( 1); } memset( address, 0, sizeof( address)); @@ -108,8 +109,8 @@ int main( int argc, char * argv[]) if ( bind( keyhole, ( struct sockaddr *)address, sizeof( struct sockaddr_in)) == -1) { /* attempt to bind keyhole to address */ - sprintf( errorBuff, "failed to bind socket"); - error( LOG_ERR); + fprintf( stderr, "failed to bind socket"); + exit( 1); } #ifndef DEBUG @@ -124,7 +125,7 @@ int main( int argc, char * argv[]) sprintf( errorBuff, "failed in listen()?"); error( LOG_ERR); } - sprintf( errorBuff, "GILD: awaiting requests on port %d", port); + sprintf( errorBuff, "started; awaiting requests on port %d", port); error( LOG_NOTICE); for ever @@ -132,6 +133,8 @@ int main( int argc, char * argv[]) struct sockaddr_in * client = ( struct sockaddr_in *) malloc( sizeof( struct sockaddr_in)); /* the address of the client calling in */ + char * client_addr = null; + /* the network address of the client */ int conversation; /* a handle on the conversation we're having */ int clientsize = sizeof( struct sockaddr_in); /* the size of the client object */ @@ -147,6 +150,9 @@ int main( int argc, char * argv[]) conversation = accept( keyhole, ( struct sockaddr *)client, &clientsize); + client_addr = strdup( inet_ntoa( client->sin_addr)); + + if ( conversation == -1) { /* again, check we set it up OK */ sprintf( errorBuff, "Could not establish conversation [%d]", @@ -154,9 +160,6 @@ int main( int argc, char * argv[]) error( LOG_ERR); } - sprintf( errorBuff, "Connection received"); - error( LOG_NOTICE); - switch( fork()) { case -1: /* Blew it: whinge and die */ @@ -166,11 +169,14 @@ int main( int argc, char * argv[]) case 0: /* I'm the child */ close( keyhole); - wrapper( conversation); + wrapper( conversation, client_addr); /* wrapper (q.v.) handles the conversation */ break; default: /* I'm the parent */ close( conversation); + free( client); /* prevent memory bloat */ + if ( client_addr != null) + free( client_addr); } } } diff --git a/gild.conf b/gild.conf index 9ede594..e77757e 100644 --- a/gild.conf +++ b/gild.conf @@ -1,5 +1,5 @@ - -http ^.*HTTP/[0-1] handlers/http -crp CRP/1 handlers/crp - - +# Sample GILD configuration file +# $Header$ +# protocol pattern handler timeout +http ^.*HTTP/[0-1] handlers/http 5 +crp CRP/1 handlers/crp 10 diff --git a/gild.h b/gild.h index 5e95117..450e639 100644 --- a/gild.h +++ b/gild.h @@ -16,13 +16,17 @@ #include #include -#include #include +#include +#include +#include +#include +#include +#include #include #include -#include +#include -#include #define GILD_NAME "gild" #define GILD_VERSION "$Revision$" @@ -36,7 +40,6 @@ #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -#define DEBUG 1 #define ever (;;) #define null (((void *) 0)) @@ -49,12 +52,14 @@ typedef struct handler regex_t * pattern; /* the pattern to match to select this handler */ char * command; /* the command to invoke this handler */ + int timeout; /* how long to allow for this handler to + complete, or 0 if infinite */ } handler; void error( int severity); /* log the current contents of errorBuff and then if severity is bad die */ -char * get_handler_command( char * match); +handler * get_handler( char * match); /* find a handler whose pattern matches match, and return it's command */ int log( int level, char *message); @@ -63,10 +68,6 @@ int log( int level, char *message); int parse_config( char * path); /* parse the config file and identify the handlers I handle */ -void wrapper( int conversation); +void wrapper( int conversation, char * client_id); /* 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 - 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 */ + client. */ diff --git a/log.c b/log.c index 6e774b9..e2ddb45 100644 --- a/log.c +++ b/log.c @@ -21,8 +21,8 @@ int log( int level, char *message) /* hand this message over to the syslog daemon for recording */ { - openlog( GILD_ID, 0, LOG_DAEMON); + openlog( GILD_NAME, 0, LOG_DAEMON); syslog( level, message); - closelog); + closelog(); } diff --git a/wrapper.c b/wrapper.c index a9fe763..8d0e358 100644 --- a/wrapper.c +++ b/wrapper.c @@ -16,9 +16,17 @@ #include "gild.h" -extern char * errorBuff; +char errorBuff[ 1024]; -void wrapper( int conversation) +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); +} + + +void wrapper( int conversation, char * client_id) /* 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 straightforward way of doing it: attach the conversation to both @@ -27,10 +35,7 @@ void wrapper( int conversation) an easy way of doing that, however */ { char firstln[ 1024]; - char * command; - - printf( "wrapper started with fdes [%d]\n", - conversation); + handler * command = null; recv( conversation, firstln, 80, MSG_PEEK); /* get the first thing the client @@ -53,16 +58,34 @@ void wrapper( int conversation) error( LOG_ERR); } - command = get_handler_command( firstln); + command = get_handler( firstln); /* and find the appropriate handler */ - if ( ! command) /* didn't find one */ + if ( command == null) /* didn't find one */ { sprintf( errorBuff, "no handler registered for %s", firstln); error( LOG_ERR); } else /* did find one */ { - system( command); + sprintf( errorBuff, + "using handler '%s' to handle %s request from %s", + command->command, command->protocol, client_id); + error( LOG_NOTICE); + /* log the request */ + + 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); + } + + setenv( "REMOTE_HOST", client_id, 1); + /* set up the handler environment */ + + system( command->command); } exit( 0);