Re-organisation to move source into a src directory, tidying up top-level,
which will hopefully make installation easier for someone else.
This commit is contained in:
parent
ac5b7d07f7
commit
464bcf4977
30
Makefile
30
Makefile
|
@ -1,30 +0,0 @@
|
||||||
# Makefile for itinerary engine utilities
|
|
||||||
# $Header$
|
|
||||||
|
|
||||||
CC= gcc
|
|
||||||
CFLAGS= -g
|
|
||||||
LD= gcc
|
|
||||||
LDFLAGS= -g
|
|
||||||
HOMEDIR= /usr/local/etc/gild
|
|
||||||
TARGETS= gild
|
|
||||||
COMPONENTS = gild.o wrapper.o config.o log.o
|
|
||||||
|
|
||||||
all: $(TARGETS)
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) $(CFLAGS) -c $<
|
|
||||||
|
|
||||||
gild: $(COMPONENTS) gild.h Makefile
|
|
||||||
$(LD) $(LDFLAGS) -o gild $(COMPONENTS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm core *.o $(TARGETS)
|
|
||||||
|
|
||||||
install: $(TARGETS)
|
|
||||||
install --strip $(TARGETS) $(HOMEDIR)
|
|
||||||
install gild.conf $(HOMEDIR)
|
|
||||||
cd handlers; make install
|
|
||||||
|
|
||||||
version: $(TARGETS)
|
|
||||||
cvs commit gild.c wrapper.c config.c log.c Makefile gild.h \
|
|
||||||
gild.conf handlers
|
|
113
config.c
113
config.c
|
@ -1,113 +0,0 @@
|
||||||
/**************************************************************************\
|
|
||||||
* *
|
|
||||||
* Project: Gild *
|
|
||||||
* config.c *
|
|
||||||
* *
|
|
||||||
* Purpose: Handle configuration file *
|
|
||||||
* *
|
|
||||||
* Author : Simon Brooke *
|
|
||||||
* Copyright: (c) Simon Brooke 1997 *
|
|
||||||
* Version : 0.1 *
|
|
||||||
* Created : 8th October 1997 *
|
|
||||||
* *
|
|
||||||
\**************************************************************************/
|
|
||||||
|
|
||||||
/* $Header$ */
|
|
||||||
|
|
||||||
#include "gild.h"
|
|
||||||
|
|
||||||
extern char errorBuff[]; /* where I assemble logging messages */
|
|
||||||
handler * handlers = ( handler *) null;
|
|
||||||
/* the list of handlers I handle */
|
|
||||||
|
|
||||||
int parse_config( char * path)
|
|
||||||
/* parse the config file and identify the handlers I handle */
|
|
||||||
{
|
|
||||||
FILE * configFile; /* the file handle from which to load config */
|
|
||||||
char * line[ 1024]; /* a buffer to read lines into */
|
|
||||||
int n = 0; /* number of handlers we find */
|
|
||||||
|
|
||||||
sprintf( errorBuff, "Loading configuration from %s", path);
|
|
||||||
error( LOG_NOTICE);
|
|
||||||
|
|
||||||
configFile = fopen( path, "r");
|
|
||||||
|
|
||||||
if ( configFile == ( FILE *)null)
|
|
||||||
{
|
|
||||||
sprintf( errorBuff, "failed to open configuration file %s: %s",
|
|
||||||
path, strerror( errno));
|
|
||||||
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 %d", protocol,
|
|
||||||
pattern, command, &timeout) == 4)
|
|
||||||
/* otherwise look for four fields. If
|
|
||||||
we find them... */
|
|
||||||
{
|
|
||||||
handler * newhandler =
|
|
||||||
( struct handler *) malloc( sizeof( struct handler));
|
|
||||||
/* create a handler */
|
|
||||||
struct re_pattern_buffer * patternBuff =
|
|
||||||
( struct re_pattern_buffer *)
|
|
||||||
malloc( sizeof( struct re_pattern_buffer));
|
|
||||||
/* and reserve space for a compiled regex */
|
|
||||||
|
|
||||||
if ( newhandler == ( handler *) null)
|
|
||||||
{ /* unlikely, but... best check */
|
|
||||||
sprintf( errorBuff,
|
|
||||||
"out of memory whilst allocating handler?");
|
|
||||||
error( LOG_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
regcomp( patternBuff, pattern,
|
|
||||||
REG_ICASE | REG_NEWLINE);
|
|
||||||
/* and load it with the values we found */
|
|
||||||
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;
|
|
||||||
|
|
||||||
n ++; /* increment the counter */
|
|
||||||
|
|
||||||
/* and log it. */
|
|
||||||
sprintf( errorBuff,
|
|
||||||
"registering handler [%s] for protocol %s",
|
|
||||||
newhandler->command, newhandler->protocol);
|
|
||||||
error( LOG_NOTICE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ( n); /* say how many we found */
|
|
||||||
}
|
|
||||||
|
|
||||||
handler * get_handler( char * match)
|
|
||||||
/* find a handler whose pattern matches match, and return it's command */
|
|
||||||
{
|
|
||||||
handler * h = null, * i;
|
|
||||||
regmatch_t pmatch[ 2];
|
|
||||||
|
|
||||||
for ( i = handlers; ( h == null) && ( i != null); i = i->next)
|
|
||||||
/* scan down the list of handlers looking
|
|
||||||
for a match... */
|
|
||||||
{
|
|
||||||
if ( regexec( i->pattern, match, 2, pmatch, 0) == 0)
|
|
||||||
{
|
|
||||||
h = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return( h);
|
|
||||||
}
|
|
186
gild.c
186
gild.c
|
@ -1,186 +0,0 @@
|
||||||
/***********************************************************************\
|
|
||||||
* *
|
|
||||||
* Project: Gild *
|
|
||||||
* gild.c *
|
|
||||||
* *
|
|
||||||
* Purpose: Generalised Internet Listener Daemon *
|
|
||||||
* -- a daemon which listens for requests on a specified *
|
|
||||||
* IP port, and despatches them to specified handlers *
|
|
||||||
* depending on the content of the first line. *
|
|
||||||
* *
|
|
||||||
* Author : Simon Brooke *
|
|
||||||
* Copyright: (c) Simon Brooke 1997 *
|
|
||||||
* Version : 0.1 *
|
|
||||||
* Created : 5th October 1997 *
|
|
||||||
* *
|
|
||||||
\***********************************************************************/
|
|
||||||
|
|
||||||
/* $Header$ */
|
|
||||||
|
|
||||||
#include "gild.h"
|
|
||||||
|
|
||||||
int port = DEFAULT_PORT_NO; /* the port I shall listen on */
|
|
||||||
char errorBuff[ 1024]; /* somewhere to assemble error messages */
|
|
||||||
extern handler * handlers;
|
|
||||||
/* the list of handlers I support */
|
|
||||||
|
|
||||||
void error( int severity)
|
|
||||||
/* log the current contents of errorBuff and then if severity is bad die */
|
|
||||||
{
|
|
||||||
log( severity, errorBuff);
|
|
||||||
|
|
||||||
switch ( severity)
|
|
||||||
{
|
|
||||||
case LOG_ERR:
|
|
||||||
exit( 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main( int argc, char * argv[])
|
|
||||||
{
|
|
||||||
char * configPath = CONFIG_PATH; /* the path to my default config file */
|
|
||||||
int arg; /* the argument being handled */
|
|
||||||
int keyhole; /* where I listen, of course */
|
|
||||||
struct sockaddr_in * address =
|
|
||||||
( struct sockaddr_in *)malloc( sizeof( struct sockaddr_in));
|
|
||||||
/* the address I bind the keyhole to */
|
|
||||||
|
|
||||||
for ( arg = 1; argc > arg; arg ++)
|
|
||||||
{ /* process arguments */
|
|
||||||
switch ( argv[ arg][ 0])
|
|
||||||
{
|
|
||||||
case '-':
|
|
||||||
switch( argv[ arg][ 1])
|
|
||||||
{
|
|
||||||
case 'f': /* specify a config file to load */
|
|
||||||
arg ++;
|
|
||||||
configPath = argv[ arg];
|
|
||||||
break;
|
|
||||||
case 'p': /* specify a port to listen on */
|
|
||||||
arg ++;
|
|
||||||
port = atoi( argv[ arg]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf( stderr,
|
|
||||||
"unrecognised command line switch [-%c]",
|
|
||||||
argv[ arg][ 1]);
|
|
||||||
exit( 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf( stderr, "unrecognised command line token [%s]",
|
|
||||||
argv[ arg]);
|
|
||||||
exit( 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( parse_config( configPath) == 0)
|
|
||||||
{
|
|
||||||
fprintf( stderr, "failed to load any handlers");
|
|
||||||
exit( 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
keyhole = socket( AF_INET, SOCK_STREAM, 0);
|
|
||||||
if ( keyhole == -1)
|
|
||||||
{
|
|
||||||
fprintf( stderr, "failed to intialise socket");
|
|
||||||
exit( 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset( address, 0, sizeof( address));
|
|
||||||
/* sanitation */
|
|
||||||
|
|
||||||
/* now set up the address preparatory
|
|
||||||
to binding it */
|
|
||||||
address->sin_family = AF_INET;
|
|
||||||
/* it's an internet address */
|
|
||||||
address->sin_addr.s_addr = htonl( INADDR_ANY);
|
|
||||||
/* and we don't mind where it comes from */
|
|
||||||
address->sin_port = htons( port);
|
|
||||||
/* that's the port we listen on, remember? */
|
|
||||||
|
|
||||||
if ( bind( keyhole, ( struct sockaddr *)address,
|
|
||||||
sizeof( struct sockaddr_in)) == -1)
|
|
||||||
{ /* attempt to bind keyhole to address */
|
|
||||||
fprintf( stderr, "failed to bind socket");
|
|
||||||
exit( 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
/* we become a real class one daemon */
|
|
||||||
if ( fork() != 0) /* we're the parent */
|
|
||||||
{
|
|
||||||
exit(0); /* so die */
|
|
||||||
}
|
|
||||||
/* otherwise (we're the child)... */
|
|
||||||
setsid(); /* release the controlling tty */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
signal( SIGCHLD, SIG_IGN); /* allow chidren to die naturally */
|
|
||||||
|
|
||||||
if ( listen( keyhole, MAX_PENDING_REQUESTS) == -1)
|
|
||||||
{
|
|
||||||
sprintf( errorBuff, "failed in listen()?");
|
|
||||||
error( LOG_ERR);
|
|
||||||
}
|
|
||||||
sprintf( errorBuff, "started; awaiting requests on port %d", port);
|
|
||||||
error( LOG_NOTICE);
|
|
||||||
|
|
||||||
for ever
|
|
||||||
{
|
|
||||||
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 */
|
|
||||||
|
|
||||||
if ( client == 0)
|
|
||||||
{ /* unlikely, but might as well check... */
|
|
||||||
sprintf( errorBuff, "Out of memory?");
|
|
||||||
error( LOG_ERR);
|
|
||||||
}
|
|
||||||
memset( client, 0, sizeof( client));
|
|
||||||
/* sanitation */
|
|
||||||
|
|
||||||
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]",
|
|
||||||
errno);
|
|
||||||
error( LOG_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch( fork())
|
|
||||||
{
|
|
||||||
case -1: /* Blew it: whinge and die */
|
|
||||||
sprintf( errorBuff, "failed to fork?");
|
|
||||||
error( LOG_ERR);
|
|
||||||
break;
|
|
||||||
case 0: /* I'm the child */
|
|
||||||
close( keyhole);
|
|
||||||
|
|
||||||
wrapper( conversation, client_addr);
|
|
||||||
/* wrapper (q.v.) handles the conversation */
|
|
||||||
|
|
||||||
exit( 0); /* after completing wrapper, die */
|
|
||||||
break;
|
|
||||||
default: /* I'm the parent */
|
|
||||||
close( conversation);
|
|
||||||
free( client); /* prevent memory bloat */
|
|
||||||
if ( client_addr != null)
|
|
||||||
free( client_addr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
72
gild.h
72
gild.h
|
@ -1,72 +0,0 @@
|
||||||
/**************************************************************************\
|
|
||||||
* *
|
|
||||||
* Project: Gild *
|
|
||||||
* gild.h *
|
|
||||||
* *
|
|
||||||
* Purpose: public header file for gild server. *
|
|
||||||
* *
|
|
||||||
* Author : Simon Brooke *
|
|
||||||
* Copyright: (c) Simon Brooke 1997 *
|
|
||||||
* Version : 0.1 *
|
|
||||||
* Created : 6th October 1997 *
|
|
||||||
* *
|
|
||||||
\**************************************************************************/
|
|
||||||
|
|
||||||
/* $Header$ */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <regex.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <syslog.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <linux/in.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define GILD_NAME "gild"
|
|
||||||
#define GILD_VERSION "$Revision$"
|
|
||||||
#define GILD_ID "gild $Revision$"
|
|
||||||
|
|
||||||
#define CONFIG_PATH "/usr/local/etc/gild/gild.conf"
|
|
||||||
#define DEFAULT_PORT_NO 8421
|
|
||||||
#define MAX_PENDING_REQUESTS 5
|
|
||||||
|
|
||||||
#define STDIN_FILENO 0
|
|
||||||
#define STDOUT_FILENO 1
|
|
||||||
#define STDERR_FILENO 2
|
|
||||||
|
|
||||||
#define ever (;;)
|
|
||||||
#define null (((void *) 0))
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct handler
|
|
||||||
{
|
|
||||||
struct handler * next; /* next one down the chain */
|
|
||||||
char * protocol; /* a name for the protocol handled */
|
|
||||||
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 */
|
|
||||||
|
|
||||||
handler * get_handler( char * match);
|
|
||||||
/* find a handler whose pattern matches match, and return it's command */
|
|
||||||
|
|
||||||
int log( int level, char *message);
|
|
||||||
/* hand this message over to the syslog daemon for recording */
|
|
||||||
|
|
||||||
int parse_config( char * path);
|
|
||||||
/* parse the config file and identify the handlers I handle */
|
|
||||||
|
|
||||||
void wrapper( int conversation, char * client_id);
|
|
||||||
/* conversation is the handle on an open socket communicating with a
|
|
||||||
client. */
|
|
32
log.c
32
log.c
|
@ -1,32 +0,0 @@
|
||||||
/***********************************************************************\
|
|
||||||
* *
|
|
||||||
* Project: Gild *
|
|
||||||
* log.c *
|
|
||||||
* *
|
|
||||||
* Purpose: Interface to syslogd. Why do our own logging, *
|
|
||||||
* which only adds to sysadmin hassle and confusion, *
|
|
||||||
* when we can use the system log? *
|
|
||||||
* *
|
|
||||||
* Author : Simon Brooke *
|
|
||||||
* Copyright: (c) Simon Brooke 1997 *
|
|
||||||
* Version : 0.1 *
|
|
||||||
* Created : 15th October 1997 *
|
|
||||||
* *
|
|
||||||
\***********************************************************************/
|
|
||||||
|
|
||||||
/* $Header$ */
|
|
||||||
|
|
||||||
#include "gild.h"
|
|
||||||
|
|
||||||
int log( int level, char *message)
|
|
||||||
/* 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);
|
|
||||||
syslog( level, message);
|
|
||||||
closelog();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
100
wrapper.c
100
wrapper.c
|
@ -1,100 +0,0 @@
|
||||||
/**************************************************************************\
|
|
||||||
* *
|
|
||||||
* 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 *
|
|
||||||
* *
|
|
||||||
\**************************************************************************/
|
|
||||||
|
|
||||||
/* $Header */
|
|
||||||
|
|
||||||
#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;
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
||||||
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, ( int)getpid()),
|
|
||||||
error( LOG_ERR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit( 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue