X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=secnet.git;a=blobdiff_plain;f=secnet.c;h=a21e52b39753c68c3fa562203c429b218088ebc3;hp=cb6823873a5b55581fcae640490b69a7a9a49780;hb=4f5e39ecfaa49376b0a5c3a4c384e91a828c1105;hpb=b2a56f7c93d221607864761c590952b9a614dc9f;ds=sidebyside diff --git a/secnet.c b/secnet.c index cb68238..a21e52b 100644 --- a/secnet.c +++ b/secnet.c @@ -1,9 +1,3 @@ -/* $Log: secnet.c,v $ - * Revision 1.1 1996/03/13 22:27:41 sde1000 - * Initial revision - * - */ - extern char version[]; #include "secnet.h" @@ -18,9 +12,11 @@ extern char version[]; #include "util.h" #include "conffile.h" +#include "process.h" /* XXX should be from autoconf */ static char *configfile="/etc/secnet/secnet.conf"; +static char *sites_key="sites"; bool_t just_check_config=False; static char *userid=NULL; static uid_t uid=0; @@ -29,6 +25,16 @@ static char *pidfile=NULL; bool_t require_root_privileges=False; string_t require_root_privileges_explanation=NULL; +static pid_t secnet_pid; + +/* from log.c */ +extern uint32_t message_level; +extern bool_t secnet_is_daemon; +extern struct log_if *system_log; + +/* from process.c */ +extern void start_signal_handling(void); + /* Structures dealing with poll() call */ struct poll_interest { beforepoll_fn *before; @@ -62,10 +68,11 @@ static void parse_options(int argc, char **argv) {"debug", 1, 0, 'd'}, {"config", 1, 0, 'c'}, {"just-check-config", 0, 0, 'j'}, + {"sites-key", 1, 0, 's'}, {0,0,0,0} }; - c=getopt_long(argc, argv, "vwdnjc:ft:", + c=getopt_long(argc, argv, "vwdnjc:ft:s:", long_options, &option_index); if (c==-1) break; @@ -73,29 +80,32 @@ static void parse_options(int argc, char **argv) switch(c) { case 2: /* Help */ - fprintf(stderr, - "Usage: secnet [OPTION]...\n\n" - " -f, --silent, --quiet suppress error messages\n" - " -w, --nowarnings suppress warnings\n" - " -v, --verbose output extra diagnostics\n" - " -c, --config=filename specify a configuration file\n" - " -j, --just-check-config stop after reading configfile\n" - " -n, --nodetach do not run in background\n" - " -d, --debug=item,... set debug options\n" - " --help display this help and exit\n" - " --version output version information and exit\n" + printf("Usage: secnet [OPTION]...\n\n" + " -f, --silent, --quiet suppress error messages\n" + " -w, --nowarnings suppress warnings\n" + " -v, --verbose output extra diagnostics\n" + " -c, --config=filename specify a configuration file\n" + " -j, --just-check-config stop after reading " + "configuration file\n" + " -s, --sites-key=name configuration key that " + "specifies active sites\n" + " -n, --nodetach do not run in background\n" + " -d, --debug=item,... set debug options\n" + " --help display this help and exit\n" + " --version output version information " + "and exit\n" ); exit(0); break; case 1: /* Version */ - fprintf(stderr,"%s\n",version); + printf("%s\n",version); exit(0); break; case 'v': - message_level|=M_INFO|M_NOTICE|M_WARNING|M_ERROR|M_SECURITY| + message_level|=M_INFO|M_NOTICE|M_WARNING|M_ERR|M_SECURITY| M_FATAL; break; @@ -126,16 +136,23 @@ static void parse_options(int argc, char **argv) just_check_config=True; break; + case 's': + if (optarg) + sites_key=safe_strdup(optarg,"sites-key"); + else + fatal("secnet: no sites key specified"); + break; + case '?': break; default: - Message(M_ERROR,"secnet: Unknown getopt code %c\n",c); + Message(M_ERR,"secnet: Unknown getopt code %c\n",c); } } if (argc-optind != 0) { - Message(M_ERROR,"secnet: You gave extra command line parameters, " + Message(M_ERR,"secnet: You gave extra command line parameters, " "which were ignored.\n"); } } @@ -152,7 +169,7 @@ static void setup(dict_t *config) l=dict_lookup(config,"system"); if (!l || list_elem(l,0)->type!=t_dict) { - fatal("configuration does not include a \"system\" dictionary\n"); + fatal("configuration does not include a \"system\" dictionary"); } system=list_elem(l,0)->data.dict; loc=list_elem(l,0)->loc; @@ -160,7 +177,7 @@ static void setup(dict_t *config) /* Arrange systemwide log facility */ l=dict_lookup(system,"log"); if (!l) { - fatal("configuration does not include a system/log facility\n"); + fatal("configuration does not include a system/log facility"); } system_log=init_log(l); @@ -176,7 +193,7 @@ static void setup(dict_t *config) } while(pw); endpwent(); if (uid==0) { - fatal("userid \"%s\" not found\n",userid); + fatal("userid \"%s\" not found",userid); } } @@ -185,16 +202,16 @@ static void setup(dict_t *config) /* Check whether we need root privileges */ if (require_root_privileges && uid!=0) { - fatal("the following configured feature (\"%s\") requires " - "that secnet retain root privileges while running.\n", + fatal("the configured feature \"%s\" requires " + "that secnet retain root privileges while running.", require_root_privileges_explanation); } /* Go along site list, starting sites */ - l=dict_lookup(config,"sites"); + l=dict_lookup(config,sites_key); if (!l) { - Message(M_WARNING,"secnet: configuration did not define any " - "remote sites\n"); + Message(M_WARNING,"secnet: configuration key \"%s\" is missing; no " + "remote sites are defined\n",sites_key); } else { i=0; while ((site=list_elem(l, i++))) { @@ -248,16 +265,17 @@ static void run(void) fds=alloca(sizeof(*fds)*total_nfds); if (!fds) { - fatal("run: couldn't alloca\n"); + fatal("run: couldn't alloca"); } - Message(M_NOTICE,"%s: starting\n",version); + Message(M_NOTICE,"%s [%d]: starting\n",version,secnet_pid); - while (!finished) { + do { if (gettimeofday(&tv_now, NULL)!=0) { fatal_perror("main loop: gettimeofday"); } - now=(tv_now.tv_sec*1000)+(tv_now.tv_usec/1000); + now=((uint64_t)tv_now.tv_sec*(uint64_t)1000)+ + ((uint64_t)tv_now.tv_usec/(uint64_t)1000); idx=0; for (i=reg; i; i=i->next) { i->after(i->state, fds+idx, i->nfds, &tv_now, &now); @@ -272,16 +290,17 @@ static void run(void) if (rv!=0) { /* XXX we need to handle this properly: increase the nfds available */ - fatal("run: beforepoll_fn (%s) returns %d\n",i->desc,rv); + fatal("run: beforepoll_fn (%s) returns %d",i->desc,rv); } if (timeout<-1) { - fatal("run: beforepoll_fn (%s) set timeout to %d\n",timeout); + fatal("run: beforepoll_fn (%s) set timeout to %d",timeout); } idx+=nfds; remain-=nfds; i->nfds=nfds; } do { + if (finished) break; rv=poll(fds, idx, timeout); if (rv<0) { if (errno!=EINTR) { @@ -289,7 +308,7 @@ static void run(void) } } } while (rv<0); - } + } while (!finished); } static void droppriv(void) @@ -330,14 +349,34 @@ static void droppriv(void) } else if (p==0) { /* Child process - all done, just carry on */ if (pf) fclose(pf); + /* Close stdin, stdout and stderr; we don't need them any more */ + /* XXX we must leave stderr pointing to something useful - + a pipe to a log destination, for example, or just leave + it alone. */ + close(0); + close(1); + /* XXX close(2); */ secnet_is_daemon=True; + setsid(); } else { /* Error */ fatal_perror("cannot fork"); exit(1); } } + secnet_pid=getpid(); +} +static signal_notify_fn finish,ignore_hup; +static void finish(void *st, int signum) +{ + finished=True; + Message(M_NOTICE,"%s [%d]: received %s\n",version,secnet_pid,(string_t)st); +} +static void ignore_hup(void *st, int signum) +{ + Message(M_INFO,"%s [%d]: received SIGHUP\n",version,secnet_pid); + return; } int main(int argc, char **argv) @@ -364,11 +403,15 @@ int main(int argc, char **argv) enter_phase(PHASE_DROPPRIV); droppriv(); + start_signal_handling(); + request_signal_notification(SIGTERM,finish,"SIGTERM"); + if (!background) request_signal_notification(SIGINT,finish,"SIGINT"); + request_signal_notification(SIGHUP,ignore_hup,NULL); enter_phase(PHASE_RUN); run(); enter_phase(PHASE_SHUTDOWN); + Message(M_NOTICE,"%s [%d]: finished\n",version,secnet_pid); return 0; } -