chiark / gitweb /
Support re-reading config files on SIGHUP.
authormdw <mdw>
Sat, 3 Feb 2001 20:30:03 +0000 (20:30 +0000)
committermdw <mdw>
Sat, 3 Feb 2001 20:30:03 +0000 (20:30 +0000)
exec.c
file.c
fw.1
fw.c
scan.c
socket.c

diff --git a/exec.c b/exec.c
index 284bba4ef2633d7e278d6cbe8cd832511110bcd3..e73500d947987b77c5e53bed5d21e496c2adf4f8 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
 /* -*-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
  *
  *
  * Source and target for executable programs
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: exec.c,v $
 /*----- 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.
  *
  * 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;
   struct xept *next, *prev;
   pid_t kid;
   endpt *f;
-  const char *desc;
+  char *desc;
   int st;
   xargs *xa;
   xopts *xo;
   int st;
   xargs *xa;
   xopts *xo;
@@ -697,6 +700,7 @@ static void xept_destroy(xept *xe)
   else
     xept_list = xe->next;
 
   else
     xept_list = xe->next;
 
+  free(xe->desc);
   if (xe->f)
     xe->f->ops->close(xe->f);
   x_tidy(xe->xa, xe->xo);
   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->xo = x->xo; xe->xo->ref++;
   xe->kid = -1;
   xe->f = 0;
-  xe->desc = desc;
+  xe->desc = xstrdup(desc);
   return (&xe->e);
 }
 
   return (&xe->e);
 }
 
@@ -1107,6 +1111,7 @@ tidy:
 static void xsource_destroy(source *s)
 {
   xsource *xs = (xsource *)s;
 static void xsource_destroy(source *s)
 {
   xsource *xs = (xsource *)s;
+  free(xs->s.desc);
   exec_destroy(&xs->x);
   DESTROY(xs);
 }
   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;
 static void xtarget_destroy(target *t)
 {
   xtarget *xt = (xtarget *)t;
+  free(xt->t.desc);
   exec_destroy(&xt->x);
   DESTROY(xt);
 }
   exec_destroy(&xt->x);
   DESTROY(xt);
 }
diff --git a/file.c b/file.c
index b0a79dce212c66091938ee121672f5b1f43853dc..60a233de3f8f08dd4d8b71fcfb13873bbc596c47 100644 (file)
--- a/file.c
+++ b/file.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
 /* -*-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
  *
  *
  * File source and target
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: file.c,v $
 /*----- 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.
  *
  * 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;
 static void fsource_destroy(source *s)
 {
   fsource *fs = (fsource *)s;
-
-  /* free(fs->s.desc); */
+  free(fs->s.desc);
   file_destroy(&fs->f);
   DESTROY(fs);
 }
   file_destroy(&fs->f);
   DESTROY(fs);
 }
@@ -602,7 +604,7 @@ static void ftarget_destroy(target *t)
 {
   ftarget *ft = (ftarget *)t;
   file_destroy(&ft->f);
 {
   ftarget *ft = (ftarget *)t;
   file_destroy(&ft->f);
-  /* free(ft->t.desc); */
+  free(ft->t.desc);
   DESTROY(ft);
 }
 
   DESTROY(ft);
 }
 
diff --git a/fw.1 b/fw.1
index df52079502dc931ffcf6f80c0e78ff6c25944c75..878ad3a15279b031287166f49aeeb0780f013dd4 100644 (file)
--- a/fw.1
+++ b/fw.1
@@ -1,6 +1,6 @@
 .\" -*-nroff-*-
 .\"
 .\" -*-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
 .\"
 .\"
 .\" Manual page for fw
 .\"
@@ -28,6 +28,9 @@
 .\" ---- Revision history ---------------------------------------------------
 .\" 
 .\" $Log: fw.1,v $
 .\" ---- 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.
 .\" 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 ` ; ',
 .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
 .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
 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
 .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
 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
 .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
 .
 .\"--------------------------------------------------------------------------
 .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"
 .SH "GRAMMAR SUMMARY"
 .
 .SS "Basic syntax"
diff --git a/fw.c b/fw.c
index 6b8f16d82a1dc93245bb4bee4b6fe9da59e322a2..fdaf9a5cc497ffd95e283cb3af4d473a89d08f0f 100644 (file)
--- a/fw.c
+++ b/fw.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
 /* -*-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
  *
  *
  * Port forwarding thingy
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: fw.c,v $
 /*----- 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.
  *
  * Revision 1.9  2001/01/20 11:55:17  mdw
  * Handle select errors more robustly.
  *
@@ -65,6 +68,7 @@
 
 #include "config.h"
 
 
 #include "config.h"
 
+#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <signal.h>
 #include <ctype.h>
 #include <errno.h>
 #include <signal.h>
@@ -103,8 +107,14 @@ sel_state *sel;                            /* Multiplexor for nonblocking I/O */
 
 /*----- Static variables --------------------------------------------------*/
 
 
 /*----- 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 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
 
 #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)
 {
 
 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 --- */
 }
 
 /* --- Standard GNU help options --- */
@@ -357,17 +425,16 @@ int main(int argc, char *argv[])
 {
   unsigned f = 0;
   sel_state sst;
 {
   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;
   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 --- */
 
 
   /* --- Initialize things --- */
 
@@ -382,20 +449,6 @@ int main(int argc, char *argv[])
   fattr_init(&fattr_global);
   scan_create(&sc);
 
   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 --- */
   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));
          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;
          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);
   }
     usage(stderr);
     exit(1);
   }
+  *cff = 0;
 
   /* --- Deal with the remaining arguments --- */
 
 
   /* --- Deal with the remaining arguments --- */
 
@@ -531,6 +589,22 @@ int main(int argc, char *argv[])
 
   conf_parse(&sc);
 
 
   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
   /* --- Drop privileges --- */
 
 #ifdef HAVE_SETGROUPS
@@ -579,7 +653,7 @@ int main(int argc, char *argv[])
     while (active) {
       if (!sel_select(sel))
         selerr = 0;
     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) {
        fw_log(-1, "error from select: %s", strerror(errno));
        selerr++;
        if (selerr > 8) {
diff --git a/scan.c b/scan.c
index c29b48bb3440b1c57fef1531106143cbb143a33d..84260ed25d6577637cb948e39604d6bd9b0ae565 100644 (file)
--- a/scan.c
+++ b/scan.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
 /* -*-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
  *
  *
  * Character scanners
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: scan.c,v $
 /*----- 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 <ctype.h> functions.
  *
  * Revision 1.3  2000/08/01 17:58:10  mdw
  * Fix subtleties with <ctype.h> functions.
  *
@@ -104,7 +107,7 @@ static scansrc_ops fscan_ops = { fscan_scan, fscan_destroy };
 
 scansrc *scan_file(FILE *fp, char *name, unsigned f)
 {
 
 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;
   fs->ss.ops = &fscan_ops;
   fs->ss.src = name;
   fs->ss.line = 1;
index afa3dc0646e7c153d7952febfb141804445cf548..0a80b48f32b5829e04ba8367958a259344184549 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
 /* -*-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
  *
  *
  * Socket source and target definitions
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: socket.c,v $
 /*----- 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.
  *
  * 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;
 typedef struct stept {
   endpt e;
   conn c;
-  const char *desc;
+  char *desc;
 } stept;
 
 /* --- Socket source endpoint --- */
 } stept;
 
 /* --- Socket source endpoint --- */
@@ -254,6 +257,7 @@ static void stept_close(endpt *e)
     REFFD_DEC(ee->e.out);
   }
 
     REFFD_DEC(ee->e.out);
   }
 
+  free(ee->desc);
   fw_dec();
   DESTROY(ee);
 }
   fw_dec();
   DESTROY(ee);
 }
@@ -636,7 +640,7 @@ static void ssource_destroy(source *s)
     ss->a->ops->freeopts(ss->ao);
   else
     DESTROY(ss->ao);
     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);
   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->e.other = 0;
   e->e.f = EPF_FILE | SKF_CONN;
   e->e.t = 0;
-  e->desc = desc;
+  e->desc = xstrdup(desc);
 
   /* --- Pay attention --- *
    *
 
   /* --- Pay attention --- *
    *
@@ -729,7 +733,7 @@ static void starget_destroy(target *t)
 {
   starget *st = (starget *)t;
   st->a->ops->destroy(st->a);
 {
   starget *st = (starget *)t;
   st->a->ops->destroy(st->a);
-  /* free(st->t.desc); */
+  free(st->t.desc);
   DESTROY(st);
 }
 
   DESTROY(st);
 }