From 372a98e2893234a482e59ca32313db1bb86146d7 Mon Sep 17 00:00:00 2001 From: mdw Date: Sat, 3 Feb 2001 20:30:03 +0000 Subject: [PATCH] Support re-reading config files on SIGHUP. --- exec.c | 12 ++++-- file.c | 10 +++-- fw.1 | 67 +++++++++++++++++++++++++------ fw.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++--------------- scan.c | 7 +++- socket.c | 14 ++++--- 6 files changed, 190 insertions(+), 56 deletions(-) diff --git a/exec.c b/exec.c index 284bba4..e73500d 100644 --- a/exec.c +++ b/exec.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: exec.c,v 1.3 2000/07/01 11:28:52 mdw Exp $ + * $Id: exec.c,v 1.4 2001/02/03 20:30:03 mdw Exp $ * * Source and target for executable programs * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: exec.c,v $ + * Revision 1.4 2001/02/03 20:30:03 mdw + * Support re-reading config files on SIGHUP. + * * Revision 1.3 2000/07/01 11:28:52 mdw * Use new mLib selbuf features. * @@ -155,7 +158,7 @@ typedef struct xept { struct xept *next, *prev; pid_t kid; endpt *f; - const char *desc; + char *desc; int st; xargs *xa; xopts *xo; @@ -697,6 +700,7 @@ static void xept_destroy(xept *xe) else xept_list = xe->next; + free(xe->desc); if (xe->f) xe->f->ops->close(xe->f); x_tidy(xe->xa, xe->xo); @@ -1029,7 +1033,7 @@ static endpt *exec_endpt(xdata *x, const char *desc) xe->xo = x->xo; xe->xo->ref++; xe->kid = -1; xe->f = 0; - xe->desc = desc; + xe->desc = xstrdup(desc); return (&xe->e); } @@ -1107,6 +1111,7 @@ tidy: static void xsource_destroy(source *s) { xsource *xs = (xsource *)s; + free(xs->s.desc); exec_destroy(&xs->x); DESTROY(xs); } @@ -1160,6 +1165,7 @@ static endpt *xtarget_create(target *t, const char *desc) static void xtarget_destroy(target *t) { xtarget *xt = (xtarget *)t; + free(xt->t.desc); exec_destroy(&xt->x); DESTROY(xt); } diff --git a/file.c b/file.c index b0a79dc..60a233d 100644 --- a/file.c +++ b/file.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: file.c,v 1.3 1999/12/22 15:43:47 mdw Exp $ + * $Id: file.c,v 1.4 2001/02/03 20:30:03 mdw Exp $ * * File source and target * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: file.c,v $ + * Revision 1.4 2001/02/03 20:30:03 mdw + * Support re-reading config files on SIGHUP. + * * Revision 1.3 1999/12/22 15:43:47 mdw * Fix log messages. * @@ -546,8 +549,7 @@ tidy: static void fsource_destroy(source *s) { fsource *fs = (fsource *)s; - - /* free(fs->s.desc); */ + free(fs->s.desc); file_destroy(&fs->f); DESTROY(fs); } @@ -602,7 +604,7 @@ static void ftarget_destroy(target *t) { ftarget *ft = (ftarget *)t; file_destroy(&ft->f); - /* free(ft->t.desc); */ + free(ft->t.desc); DESTROY(ft); } diff --git a/fw.1 b/fw.1 index df52079..878ad3a 100644 --- a/fw.1 +++ b/fw.1 @@ -1,6 +1,6 @@ .\" -*-nroff-*- .\" -.\" $Id: fw.1,v 1.9 2000/03/23 00:37:33 mdw Exp $ +.\" $Id: fw.1,v 1.10 2001/02/03 20:30:03 mdw Exp $ .\" .\" Manual page for fw .\" @@ -28,6 +28,9 @@ .\" ---- Revision history --------------------------------------------------- .\" .\" $Log: fw.1,v $ +.\" Revision 1.10 2001/02/03 20:30:03 mdw +.\" Support re-reading config files on SIGHUP. +.\" .\" Revision 1.9 2000/03/23 00:37:33 mdw .\" Add option to change user and group after initialization. Naughtily .\" reassign short equivalents of --grammar and --options. @@ -270,8 +273,8 @@ are self-delimiting. Note that while some characters, e.g., .RB ` [ ' and .RB ` ; ', -require escaping by the shell, they are strictly optional in the grammar -and can be omitted in quick hacks at the shell prompt. +require escaping by the shell, they are mostly optional in the grammar +and can tend to be omitted in quick hacks at the shell prompt. .TP .I "whitespace characters" Whitespace characters separate words but are otherwise ignored. All @@ -818,13 +821,10 @@ are accepted in place of Sets the root directory for the program, using the .BR chroot (2) system call. You must be the superuser for this option to work. The -default is not to set a root directory. The synonyms -.BR cd , -.B chdir -and -.B cwd -are accepted in place of -.B dir . +default is not to set a root directory. The synonym +.B chroot +is accepted in place of +.BR root . .OE .OS "Exec options" .B exec.user @@ -1100,7 +1100,9 @@ options to control the attributes of the socket file created. Sockets are removed if .B fw exits normally (which it will do if it runs out of sources or -connections, or if killed by SIGINT or SIGTERM). +connections, or if +.B fw +shuts down in a clean way). .SH "EXAMPLES" To forward the local port 25 to a main mail server: .VS @@ -1122,6 +1124,49 @@ from stdin, null to null, stdout .VE . .\"-------------------------------------------------------------------------- +.SH "SIGNAL HANDLING" +. +The +.B fw +program responds to various signals when it's running. If it receives +.B SIGTERM +or +.BR SIGINT , +.B fw +performs a +.I graceful +shutdown: it removes all of its sources, and will exit when no more +connections are running. (Note that if the disposition +.B SIGINT +was to ignore it, +.B fw +does not re-enable the signal. You'll have to send +.B SIGTERM +in that case.) If +.B fw +receives +.BR SIGQUIT , +it performs an +.I abrupt +shutdown: it removes all sources and extant connections and closes down +more-or-less immediately. +.PP +Finally, if any configuration files (other than standard input) were +provided to +.B fw +on its command line using the +.B \-f +option, a +.B SIGHUP +signal may be sent to instruct +.B fw +to reload its configuration. Any existing connections are allowed to +run their course. If no such configuration files are available, +.B fw +just logs a message about the signal and continues. +.PP +. +.\"-------------------------------------------------------------------------- .SH "GRAMMAR SUMMARY" . .SS "Basic syntax" diff --git a/fw.c b/fw.c index 6b8f16d..fdaf9a5 100644 --- a/fw.c +++ b/fw.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: fw.c,v 1.9 2001/01/20 11:55:17 mdw Exp $ + * $Id: fw.c,v 1.10 2001/02/03 20:30:03 mdw Exp $ * * Port forwarding thingy * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: fw.c,v $ + * Revision 1.10 2001/02/03 20:30:03 mdw + * Support re-reading config files on SIGHUP. + * * Revision 1.9 2001/01/20 11:55:17 mdw * Handle select errors more robustly. * @@ -65,6 +68,7 @@ #include "config.h" +#include #include #include #include @@ -103,8 +107,14 @@ sel_state *sel; /* Multiplexor for nonblocking I/O */ /*----- Static variables --------------------------------------------------*/ +typedef struct conffile { + struct conffile *next; + char *name; +} conffile; + static unsigned flags = 0; /* Global state flags */ static unsigned active = 0; /* Number of active things */ +static conffile *conffiles = 0; /* List of configuration files */ #define FW_SYSLOG 1u #define FW_QUIET 2u @@ -189,14 +199,72 @@ static void fw_exit(void) static void fw_tidy(int n, void *p) { - const char *sn = "unexpected signal (bug!)"; - if (n == SIGTERM) - sn = "SIGTERM"; - else if (n == SIGINT) - sn = "SIGINT"; - - fw_log(-1, "closing down on %s", sn); - fw_exit(); + const char *sn = 0; + switch (n) { + case SIGTERM: sn = "SIGTERM"; break; + case SIGINT: sn = "SIGINT"; break; + default: abort(); + } + + fw_log(-1, "closing down gracefully on %s", sn); + source_killall(); +} + +/* --- @fw_die@ --- * + * + * Arguments: @int n@ = signal number + * @void *p@ = an uninteresting argument + * + * Returns: --- + * + * Use: Handles various signals and causes an abrupt shutdown. + */ + +static void fw_die(int n, void *p) +{ + const char *sn = 0; + switch (n) { + case SIGQUIT: sn = "SIGQUIT"; break; + default: abort(); + } + + fw_log(-1, "closing down abruptly on %s", sn); + source_killall(); + endpt_killall(); +} + +/* --- @fw_reload@ --- * + * + * Arguments: @int n@ = a signal number + * @void *p@ = an uninteresting argument + * + * Returns: --- + * + * Use: Handles a hangup signal by re-reading configuration files. + */ + +static void fw_reload(int n, void *p) +{ + FILE *fp; + scanner sc; + conffile *cf; + + assert(n == SIGHUP); + if (!conffiles) { + fw_log(-1, "no configuration files to reload: ignoring SIGHUP"); + return; + } + fw_log(-1, "reloading configuration files..."); + source_killall(); + scan_create(&sc); + for (cf = conffiles; cf; cf = cf->next) { + if ((fp = fopen(cf->name, "r")) == 0) + fw_log(-1, "error loading `%s': %s", cf->name, strerror(errno)); + else + scan_add(&sc, scan_file(fp, cf->name, 0)); + } + conf_parse(&sc); + fw_log(-1, "... reload completed OK"); } /* --- Standard GNU help options --- */ @@ -357,17 +425,16 @@ int main(int argc, char *argv[]) { unsigned f = 0; sel_state sst; - sig s_term, s_int; + sig s_term, s_quit, s_int, s_hup; scanner sc; uid_t drop = -1; gid_t dropg = -1; + conffile *cf, **cff = &conffiles; - enum { - f_bogus = 1, - f_file = 2, - f_syslog = 4, - f_fork = 8 - }; +#define f_bogus 1u +#define f_file 2u +#define f_syslog 4u +#define f_fork 8u /* --- Initialize things --- */ @@ -382,20 +449,6 @@ int main(int argc, char *argv[]) fattr_init(&fattr_global); scan_create(&sc); - /* --- Set up some signal handlers --- * - * - * Don't enable @SIGINT@ if the caller already disabled it. - */ - - { - struct sigaction sa; - - sig_add(&s_term, SIGTERM, fw_tidy, 0); - sigaction(SIGINT, 0, &sa); - if (sa.sa_handler != SIG_IGN) - sig_add(&s_int, SIGINT, fw_tidy, 0); - } - atexit(fw_exit); /* --- Parse command line options --- */ @@ -463,6 +516,10 @@ int main(int argc, char *argv[]) FILE *fp; if ((fp = fopen(optarg, "r")) == 0) die(1, "couldn't open file `%s': %s", optarg, strerror(errno)); + cf = CREATE(conffile); + cf->name = optarg; + *cff = cf; + cff = &cf->next; scan_add(&sc, scan_file(fp, optarg, 0)); } f |= f_file; @@ -512,6 +569,7 @@ int main(int argc, char *argv[]) usage(stderr); exit(1); } + *cff = 0; /* --- Deal with the remaining arguments --- */ @@ -531,6 +589,22 @@ int main(int argc, char *argv[]) conf_parse(&sc); + /* --- Set up some signal handlers --- * + * + * Don't enable @SIGINT@ if the caller already disabled it. + */ + + { + struct sigaction sa; + + sig_add(&s_term, SIGTERM, fw_tidy, 0); + sig_add(&s_quit, SIGQUIT, fw_die, 0); + sigaction(SIGINT, 0, &sa); + if (sa.sa_handler != SIG_IGN) + sig_add(&s_int, SIGINT, fw_tidy, 0); + sig_add(&s_hup, SIGHUP, fw_reload, 0); + } + /* --- Drop privileges --- */ #ifdef HAVE_SETGROUPS @@ -579,7 +653,7 @@ int main(int argc, char *argv[]) while (active) { if (!sel_select(sel)) selerr = 0; - else { + else if (errno != EINTR && errno != EAGAIN) { fw_log(-1, "error from select: %s", strerror(errno)); selerr++; if (selerr > 8) { diff --git a/scan.c b/scan.c index c29b48b..84260ed 100644 --- a/scan.c +++ b/scan.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: scan.c,v 1.3 2000/08/01 17:58:10 mdw Exp $ + * $Id: scan.c,v 1.4 2001/02/03 20:30:03 mdw Exp $ * * Character scanners * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: scan.c,v $ + * Revision 1.4 2001/02/03 20:30:03 mdw + * Support re-reading config files on SIGHUP. + * * Revision 1.3 2000/08/01 17:58:10 mdw * Fix subtleties with functions. * @@ -104,7 +107,7 @@ static scansrc_ops fscan_ops = { fscan_scan, fscan_destroy }; scansrc *scan_file(FILE *fp, char *name, unsigned f) { - fscan *fs = CREATE(fs); + fscan *fs = CREATE(fscan); fs->ss.ops = &fscan_ops; fs->ss.src = name; fs->ss.line = 1; diff --git a/socket.c b/socket.c index afa3dc0..0a80b48 100644 --- a/socket.c +++ b/socket.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: socket.c,v 1.5 2000/03/23 23:20:42 mdw Exp $ + * $Id: socket.c,v 1.6 2001/02/03 20:30:03 mdw Exp $ * * Socket source and target definitions * @@ -29,6 +29,9 @@ /*----- Revision history --------------------------------------------------* * * $Log: socket.c,v $ + * Revision 1.6 2001/02/03 20:30:03 mdw + * Support re-reading config files on SIGHUP. + * * Revision 1.5 2000/03/23 23:20:42 mdw * Remove listener even if connection option isn't SOCKOPT_LIMITED. * @@ -123,7 +126,7 @@ typedef struct starget { typedef struct stept { endpt e; conn c; - const char *desc; + char *desc; } stept; /* --- Socket source endpoint --- */ @@ -254,6 +257,7 @@ static void stept_close(endpt *e) REFFD_DEC(ee->e.out); } + free(ee->desc); fw_dec(); DESTROY(ee); } @@ -636,7 +640,7 @@ static void ssource_destroy(source *s) ss->a->ops->freeopts(ss->ao); else DESTROY(ss->ao); - /* free(ss->s.desc); */ + free(ss->s.desc); ss->a->ops->destroy(ss->a); ss->t->ops->destroy(ss->t); source_remove(&ss->s); @@ -697,7 +701,7 @@ static endpt *starget_create(target *t, const char *desc) e->e.other = 0; e->e.f = EPF_FILE | SKF_CONN; e->e.t = 0; - e->desc = desc; + e->desc = xstrdup(desc); /* --- Pay attention --- * * @@ -729,7 +733,7 @@ static void starget_destroy(target *t) { starget *st = (starget *)t; st->a->ops->destroy(st->a); - /* free(st->t.desc); */ + free(st->t.desc); DESTROY(st); } -- 2.11.0