]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
You can now build dhcpcd without support for writing ntp, nis and info files
authorRoy Marples <roy@marples.name>
Tue, 3 Apr 2007 07:03:04 +0000 (07:03 +0000)
committerRoy Marples <roy@marples.name>
Tue, 3 Apr 2007 07:03:04 +0000 (07:03 +0000)
which makes the binary a few k smaller.
Support OpenNTP as well as NTP.
Re-work the state engine a little, so we renew and rebind correctly.
Subsequent debug options stop dhcpcd from daemonising.

ChangeLog
Makefile
client.c
configure.c
configure.h
dhcp.c
dhcpcd.8
dhcpcd.c
dhcpcd.h
pathnames.h
signals.c

index a0b86fe4fe08459365dae9b7e283d8f792ae3e93..298d94a997f0313aa790fbefbeb193d6158eb009 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+You can now build dhcpcd without support for writing ntp, nis and info files
+which makes the binary a few k smaller.
+Support OpenNTP as well as NTP.
+Re-work the state engine a little, so we renew and rebind correctly.
+Subsequent debug options stop dhcpcd from daemonising.
 When we get an invalid length for a DHCP option, try and continue anyway.
 When MTU is less than 576 we now ignore it instead of setting the MTU to 576.
 Build correctly on dietlibc, thanks to d00mer.
index 544e82598e77fd78aaadd0c6400378433c31b1eb..578b521d987dc3d3f7799f2fa2fc66040c9aeb52 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # Should work for both GNU make and BSD make
 
-VERSION = 3.0.16
+VERSION = 3.0.17_pre2
 
 CFLAGS ?= -O2 -pipe
 
@@ -8,7 +8,7 @@ CFLAGS ?= -O2 -pipe
 # IMPORTANT: We should be using c99 instead of gnu99 but for some reason
 # generic linux headers as of 2.6.19 don't allow this in asm/types.h
 CFLAGS += -pedantic -std=gnu99 \
-    -Wall -Wunused -Wimplicit -Wshadow -Wformat=2 \
+    -Wall -Wextra -Wunused -Wimplicit -Wshadow -Wformat=2 \
     -Wmissing-declarations -Wno-missing-prototypes -Wwrite-strings \
     -Wbad-function-cast -Wnested-externs -Wcomment -Winline \
     -Wchar-subscripts -Wcast-align -Wno-format-nonliteral
index d780358ee4e6837d8c7b6c7faa8344253315137c..afdc4f56a1b6781e88b8aaac32dd90b20f8ed941 100644 (file)
--- a/client.c
+++ b/client.c
@@ -21,7 +21,6 @@
 
 #include <sys/types.h>
 #include <sys/select.h>
-#include <sys/wait.h>
 #include <arpa/inet.h>
 #ifdef __linux__
 #include <netinet/ether.h>
   send_message (iface, dhcp, xid, _type, options); \
 }
 
+#define DROP_CONFIG \
+{ \
+  memset (&dhcp->address, 0, sizeof (struct in_addr)); \
+  if (iface->previous_address.s_addr != 0 && ! options->persistent) \
+    configure (options, iface, dhcp); \
+  free_dhcp (dhcp); \
+  memset (dhcp, 0, sizeof (dhcp_t)); \
+}
+
 static int daemonise (const char *pidfile)
 {
   logger (LOG_DEBUG, "forking to background");
@@ -240,10 +248,6 @@ int dhcp_run (const options_t *options)
        {
          switch (sig)
            {
-           case SIGCHLD:
-             /* Silently ignore this signal and wait for it
-                This stops zombies */
-             wait (0);
              break;
            case SIGINT:
              logger (LOG_INFO, "received SIGINT, stopping");
@@ -311,17 +315,7 @@ int dhcp_run (const options_t *options)
                  xid = 0;
                  SOCKET_MODE (SOCKET_CLOSED);
                  if (! options->persistent)
-                   {
-                     free_dhcp (dhcp);
-                     memset (dhcp, 0, sizeof (dhcp_t));
-                     configure (options, iface, dhcp);
-                   }
-                 if (! daemonised)
-                   {
-                     retval = -1;
-                     goto eexit;
-                   }
-                 break;
+                   DROP_CONFIG;
                }
 
              if (xid == 0)
@@ -368,22 +362,25 @@ int dhcp_run (const options_t *options)
              break;
            case STATE_REBINDING:
              logger (LOG_ERR, "lost lease, attemping to rebind");
+             memset (&dhcp->address, 0, sizeof (struct in_addr));
              SOCKET_MODE (SOCKET_OPEN);
-             SEND_MESSAGE (DHCP_DISCOVER);
+             SEND_MESSAGE (DHCP_REQUEST);
              timeout = dhcp->leasetime - dhcp->rebindtime;
-             state = STATE_INIT;
+             state = STATE_REQUESTING;
              break;
            case STATE_REQUESTING:
-             logger (LOG_ERR, "timed out");
-             if (! daemonised)
+             if (iface->previous_address.s_addr != 0)
+               logger (LOG_ERR, "lost lease");
+             else
+               logger (LOG_ERR, "timed out");
+             if (! daemonised && options->daemonise)
                goto eexit;
 
              state = STATE_INIT;
              SOCKET_MODE (SOCKET_CLOSED);
              timeout = 0;
              xid = 0;
-             free_dhcp (dhcp);
-             memset (dhcp, 0, sizeof (dhcp_t));
+             DROP_CONFIG;
              break;
 
            case STATE_RELEASED:
@@ -420,12 +417,12 @@ int dhcp_run (const options_t *options)
              if (xid != message.xid)
                {
                  logger (LOG_ERR,
-                         "ignoring packet with xid %d as it's not ours (%d)",
+                         "ignoring packet with xid 0x%x as it's not ours (0x%x)",
                          message.xid, xid);
                  continue;
                }
 
-             logger (LOG_DEBUG, "got a packet with xid %d", message.xid);
+             logger (LOG_DEBUG, "got a packet with xid 0x%x", message.xid);
              memset (new_dhcp, 0, sizeof (dhcp_t));
              if ((type = parse_dhcpmessage (new_dhcp, &message)) < 0)
                {
@@ -461,9 +458,7 @@ int dhcp_run (const options_t *options)
              state = STATE_INIT;
              timeout = 0;
              xid = 0;
-             free_dhcp (dhcp);
-             memset (dhcp, 0, sizeof (dhcp_t));
-             configure (options, iface, dhcp);
+             DROP_CONFIG;
              continue;
            }
 
@@ -502,12 +497,7 @@ int dhcp_run (const options_t *options)
                          SOCKET_MODE (SOCKET_OPEN);
                          SEND_MESSAGE (DHCP_DECLINE);
                          SOCKET_MODE (SOCKET_CLOSED);
-
-                         free_dhcp (dhcp);
-                         memset (dhcp, 0, sizeof (dhcp_t));
-                         if (daemonised)
-                           configure (options, iface, dhcp);
+                         DROP_CONFIG;
 
                          xid = 0;
                          timeout = 0;
@@ -592,7 +582,7 @@ int dhcp_run (const options_t *options)
                      goto eexit;
                    }
 
-                 if (! daemonised)
+                 if (! daemonised && options->daemonise)
                    {
                      if ((daemonise (options->pidfile)) < 0 )
                        {
@@ -627,12 +617,7 @@ int dhcp_run (const options_t *options)
 
 eexit:
   SOCKET_MODE (SOCKET_CLOSED);
-
-  /* Remove our config if we need to */
-  free_dhcp (dhcp);
-  memset (dhcp, 0, sizeof (dhcp_t));
-  if (iface->previous_address.s_addr != 0 && ! options->persistent && daemonised)
-    configure (options, iface, dhcp);
+  DROP_CONFIG;
   free (dhcp);
 
   if (iface)
index 21e073877fa24a8f45726ef71be68e9114874de9..ce43d015ad95d7af9d7ca43bb5eb8a64188912ae 100644 (file)
 #include "logger.h"
 #include "socket.h"
 
-static char *cleanmetas (const char *cstr)
-{
-  /* The largest single element we can have is 256 bytes according to the RFC,
-     so this buffer size should be safe even if it's all ' */
-  static char buffer[1024]; 
-  char *b = buffer;
-
-  memset (buffer, 0, sizeof (buffer));
-  if (cstr == NULL || strlen (cstr) == 0)
-      return b;
-
-  do
-    if (*cstr == 39)
-      {
-       *b++ = '\'';
-       *b++ = '\\';
-       *b++ = '\'';
-       *b++ = '\'';
-      }
-    else
-      *b++ = *cstr;
-  while (*cstr++);
-
-  *b++ = 0;
-  b = buffer;
-
-  return b;
-}
 
 /* IMPORTANT: Ensure that the last parameter is NULL when calling */
 static int exec_cmd (const char *cmd, const char *args, ...)
@@ -105,7 +77,7 @@ static int exec_cmd (const char *cmd, const char *args, ...)
 
   if ((pid = fork ()) == 0)
     {
-      if (execve (cmd, argv, NULL) && errno != ENOENT)
+      if (execv (cmd, argv) && errno != ENOENT)
        logger (LOG_ERR, "error executing \"%s\": %s",
                cmd, strerror (errno));
       exit (0);
@@ -121,8 +93,13 @@ static void exec_script (const char *script, const char *infofile,
 {
   struct stat buf;
 
+#ifdef ENABLE_INFO
   if (! script || ! infofile || ! arg)
     return;
+#else
+  if (! script || ! arg)
+    return ;
+#endif
 
   if (stat (script, &buf) < 0)
     {
@@ -131,8 +108,13 @@ static void exec_script (const char *script, const char *infofile,
       return;
     }
 
+#ifdef ENABLE_INFO
   logger (LOG_DEBUG, "exec \"%s %s %s\"", script, infofile, arg);
   exec_cmd (script, infofile, arg, NULL);
+#else
+  logger (LOG_DEBUG, "exec \"%s \"\" %s\"", script, infofile, arg);
+  exec_cmd (script, infofile, "", arg, NULL);
+#endif
 }
 
 static int make_resolv (const char *ifname, const dhcp_t *dhcp)
@@ -142,6 +124,7 @@ static int make_resolv (const char *ifname, const dhcp_t *dhcp)
   char resolvconf[PATH_MAX] = {0};
   address_t *address;
 
+#ifdef RESOLVCONF
   if (stat (RESOLVCONF, &buf) == 0)
     {
       logger (LOG_DEBUG, "sending DNS information to resolvconf");
@@ -152,6 +135,7 @@ static int make_resolv (const char *ifname, const dhcp_t *dhcp)
        logger (LOG_ERR, "popen: %s", strerror (errno));
     }
   else
+#endif
     {
       logger (LOG_DEBUG, "writing "RESOLVFILE);
       if (! (f = fopen(RESOLVFILE, "w")))
@@ -185,6 +169,7 @@ static int make_resolv (const char *ifname, const dhcp_t *dhcp)
 
 static void restore_resolv(const char *ifname)
 {
+#ifdef RESOLVCONF
   struct stat buf;
 
   if (stat (RESOLVCONF, &buf) < 0)
@@ -192,9 +177,11 @@ static void restore_resolv(const char *ifname)
 
   logger (LOG_DEBUG, "removing information from resolvconf");
   exec_cmd (RESOLVCONF, "-d", ifname, NULL);
+#endif
 }
 
-static int make_ntp (const char *ifname, const dhcp_t *dhcp)
+#ifdef ENABLE_NTP
+static int _make_ntp (const char *file, const char *ifname, const dhcp_t *dhcp)
 {
   FILE *f;
   address_t *address;
@@ -202,17 +189,18 @@ static int make_ntp (const char *ifname, const dhcp_t *dhcp)
   char buffer[1024];
   int tomatch = 0;
   char *token;
+  bool ntp = false;
 
   for (address = dhcp->ntpservers; address; address = address->next)
     tomatch++;
 
   /* Check that we really need to update the servers
      We do this because ntp has to be restarted to work with a changed config */
-  if (! (f = fopen(NTPFILE, "r")))
+  if (! (f = fopen (file, "r")))
     {
       if (errno != ENOENT)
        {
-         logger (LOG_ERR, "fopen `%s': %s", NTPFILE, strerror (errno));
+         logger (LOG_ERR, "fopen `%s': %s", file, strerror (errno));
          return -1;
        }
     }
@@ -244,36 +232,85 @@ static int make_ntp (const char *ifname, const dhcp_t *dhcp)
       /* File has the same name servers that we do, so no need to restart ntp */
       if (tomatch == 0)
        {
-         logger (LOG_DEBUG, "ntp already configured, skipping");
+         logger (LOG_DEBUG, "%s already configured, skipping", file);
          return 0;
        }
     }
 
-  logger (LOG_DEBUG, "writing "NTPFILE);
-  if (! (f = fopen(NTPFILE, "w")))
+  logger (LOG_DEBUG, "writing %s", file);
+  if (! (f = fopen (file, "w")))
     {
-      logger (LOG_ERR, "fopen `%s': %s", NTPFILE, strerror (errno));
+      logger (LOG_ERR, "fopen `%s': %s", file, strerror (errno));
       return -1;
     }
 
   fprintf (f, "# Generated by dhcpcd for interface %s\n", ifname);
-  fprintf (f, "restrict default noquery notrust nomodify\n");
-  fprintf (f, "restrict 127.0.0.1\n");
+#ifdef NTPFILE
+  if (strcmp (file, NTPFILE) == 0)
+    {
+      ntp = true;
+      fprintf (f, "restrict default noquery notrust nomodify\n");
+      fprintf (f, "restrict 127.0.0.1\n");
+    }
+#endif
 
   for (address = dhcp->ntpservers; address; address = address->next)
     {
       a = inet_ntoa (address->address);
-      fprintf (f, "restrict %s nomodify notrap noquery\nserver %s\n", a, a);
+      if (ntp)
+       fprintf (f, "restrict %s nomodify notrap noquery\n", a);
+      fprintf (f, "server %s\n", a);
     }
 
-  fprintf (f, "driftfile " NTPDRIFTFILE "\n");
-  fprintf (f, "logfile " NTPLOGFILE "\n");
+  if (ntp)
+    {
+      fprintf (f, "driftfile " NTPDRIFTFILE "\n");
+      fprintf (f, "logfile " NTPLOGFILE "\n");
+    }
   fclose (f);
 
-  exec_cmd (NTPSERVICE, NTPRESTARTARGS, NULL);
-  return 0;
+  return 1;
+}
+
+static int make_ntp (const char *ifname, const dhcp_t *dhcp)
+{
+  /* On some systems we have only have one ntp service, but we don't know
+     which configuration file we're using. So we need to write to both and
+     restart accordingly. */
+
+  bool restart_ntp = false;
+  bool restart_openntp = false;
+  int retval = 0;
+
+#ifdef NTPFILE
+  if (_make_ntp (NTPFILE, ifname, dhcp) > 0)
+    restart_ntp = true;
+#endif
+
+#ifdef OPENNTPFILE
+  if (_make_ntp (OPENNTPFILE, ifname, dhcp) > 0)
+    restart_openntp = true;
+#endif
+
+#ifdef NTPSERVICE
+  if (restart_ntp)
+    retval += exec_cmd (NTPSERVICE, NTPRESTARTARGS, NULL);
+#endif
+
+#if defined (NTPSERVICE) && defined (OPENNTPSERVICE)
+  if (restart_openntp &&
+      (strcmp (NTPSERVICE, OPENNTPSERVICE) != 0 || ! restart_ntp))
+    retval += exec_cmd (OPENNTPSERVICE, OPENNTPRESTARTARGS, NULL);
+#elif defined (OPENNTPSERVICE) && ! defined (NTPSERVICE)
+  if (restart_openntp) 
+    retval += exec_cmd (OPENNTPSERVICE, OPENNTPRESTARTARGS, NULL);
+#endif
+
+  return retval;
 }
+#endif
 
+#ifdef ENABLE_NIS
 static int make_nis (const char *ifname, const dhcp_t *dhcp)
 {
   FILE *f;
@@ -308,6 +345,37 @@ static int make_nis (const char *ifname, const dhcp_t *dhcp)
   exec_cmd (NISSERVICE, NISRESTARTARGS, NULL);
   return 0;
 }
+#endif
+
+#ifdef ENABLE_INFO
+static char *cleanmetas (const char *cstr)
+{
+  /* The largest single element we can have is 256 bytes according to the RFC,
+     so this buffer size should be safe even if it's all ' */
+  static char buffer[1024]; 
+  char *b = buffer;
+
+  memset (buffer, 0, sizeof (buffer));
+  if (cstr == NULL || strlen (cstr) == 0)
+      return b;
+
+  do
+    if (*cstr == 39)
+      {
+       *b++ = '\'';
+       *b++ = '\\';
+       *b++ = '\'';
+       *b++ = '\'';
+      }
+    else
+      *b++ = *cstr;
+  while (*cstr++);
+
+  *b++ = 0;
+  b = buffer;
+
+  return b;
+}
 
 static int write_info(const interface_t *iface, const dhcp_t *dhcp,
                      const options_t *options)
@@ -417,6 +485,7 @@ static int write_info(const interface_t *iface, const dhcp_t *dhcp,
   fclose (f);
   return 0;
 }
+#endif
 
 int configure (const options_t *options, interface_t *iface,
               const dhcp_t *dhcp)
@@ -567,11 +636,15 @@ int configure (const options_t *options, interface_t *iface,
   else
     logger (LOG_DEBUG, "no dns information to write");
 
+#ifdef ENABLE_NTP
   if (options->dontp && dhcp->ntpservers)
     make_ntp(iface->name, dhcp);
+#endif
 
+#ifdef ENABLE_NIS
   if (options->donis && (dhcp->nisservers || dhcp->nisdomain))
     make_nis(iface->name, dhcp);
+#endif
 
   /* Now we have made a resolv.conf we can obtain a hostname if we need one */
   if (options->dohostname && ! dhcp->hostname)
@@ -606,7 +679,9 @@ int configure (const options_t *options, interface_t *iface,
        }
     }
 
+#ifdef ENABLE_INFO
   write_info (iface, dhcp, options);
+#endif
 
   if (iface->previous_address.s_addr != dhcp->address.s_addr ||
       iface->previous_netmask.s_addr != dhcp->netmask.s_addr)
index a7e54632a88d69d72e88293c109c8fe8fe93a522..4d766d262b232a45ef3703ebac4d070fd0652b80 100644 (file)
 #ifndef DHCPCONFIG_H
 #define DHCPCONFIG_H
 
+/* If you disable all 3 options you can shrink the binary by around 5-10k
+   unstripped depending on platform and CFLAGS
+*/
+#define ENABLE_NTP
+#define ENABLE_NIS
+#define ENABLE_INFO
+
 #include "dhcpcd.h"
 #include "interface.h"
 #include "dhcp.h"
diff --git a/dhcp.c b/dhcp.c
index d1c42201f9970370c8e53e57dc934827c7bce298..efe016a7abb4a75b45d7315244e56e2b8eaf2adc 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -80,10 +80,9 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
 
   memset (&message, 0, sizeof (dhcpmessage_t));
 
-  if (iface->previous_address.s_addr != 0
-      && (type == DHCP_INFORM || type == DHCP_RELEASE
-         || (type == DHCP_REQUEST
-             && iface->previous_address.s_addr == dhcp->address.s_addr)))
+  if (type == DHCP_INFORM ||
+      type == DHCP_RELEASE ||
+      type == DHCP_REQUEST)
     {
       message.ciaddr = iface->previous_address.s_addr;
       from.s_addr = iface->previous_address.s_addr;
@@ -272,7 +271,7 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
   make_dhcp_packet (&packet, (unsigned char *) &message, message_length,
                    from, to);
 
-  logger (LOG_DEBUG, "sending %s with xid %d", dhcp_message[(int) type], xid);
+  logger (LOG_DEBUG, "sending %s with xid 0x%x", dhcp_message[(int) type], xid);
   return send_packet (iface, ETHERTYPE_IP, (unsigned char *) &packet,
                      message_length + sizeof (struct ip) +
                      sizeof (struct udphdr));
index 0f0c4543fd52474cedc501d280c3f90a74f0dfad..a9388769f8592ced3006986f8ec6fa087b4e759f 100644 (file)
--- a/dhcpcd.8
+++ b/dhcpcd.8
@@ -61,6 +61,7 @@ section below.
 .TP
 .BI \-d
 Echos debugging and information messages to the console.
+Subsequent debug options stop \fBdhcpcd\fR from daemonising.
 .TP
 .BI \-h \ hostname
 specifies a string used for the hostname option field when
index 24c5c16010834554a7e73c280f3b04d0f2aa03a7..2e3280d62dccdb50480e4234683dbca71f94aa5a 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -110,6 +110,7 @@ int main(int argc, char **argv)
   int option_index = 0;
   char prefix[IF_NAMESIZE + 3];
   pid_t pid;
+  int debug = 0;
 
   const struct option longopts[] =
     {
@@ -158,6 +159,7 @@ int main(int argc, char **argv)
   options.donis = true;
   options.dontp = true;
   options.dogateway = true;
+  options.daemonise = true;
   gethostname (options.hostname, sizeof (options.hostname));
   if (strcmp (options.hostname, "(none)") == 0 ||
       strcmp (options.hostname, "localhost") == 0)
@@ -183,12 +185,21 @@ int main(int argc, char **argv)
        options.script = optarg;
        break;
       case 'd':
-       setloglevel(LOG_DEBUG);
+       debug++;
+       switch (debug)
+         {
+           case 1:
+               setloglevel(LOG_DEBUG);
+               break;
+           case 2:
+               options.daemonise = false;
+               break;
+         }
        break;
       case 'h':
        if (strlen (optarg) > HOSTNAME_MAX_LEN)
          {
-           logger(LOG_ERR, "`%s' too long for HostName string, max is %d",
+           logger (LOG_ERR, "`%s' too long for HostName string, max is %d",
                   optarg, HOSTNAME_MAX_LEN);
            exit (EXIT_FAILURE);
          }
@@ -196,14 +207,14 @@ int main(int argc, char **argv)
          strcpy (options.hostname, optarg);
        break;
       case 'i':
-       if (strlen(optarg) > CLASS_ID_MAX_LEN)
+       if (strlen (optarg) > CLASS_ID_MAX_LEN)
          {
            logger (LOG_ERR, "`%s' too long for ClassID string, max is %d",
                    optarg, CLASS_ID_MAX_LEN);
            exit (EXIT_FAILURE);
          }
        else
-         sprintf(options.classid, "%s", optarg);
+         sprintf (options.classid, "%s", optarg);
        break;
       case 'k':
        options.signal = SIGHUP;
@@ -217,7 +228,7 @@ int main(int argc, char **argv)
          }
        break;
       case 'm':
-       STRINGINT(optarg, options.metric);
+       STRINGINT (optarg, options.metric);
        break;
       case 'n':
        options.signal = SIGALRM;
index 25e7ef97a6429a57912a4dda349f20892906c4cc..fc77f3817b1c7e24e98e061879008ccd1c864a19 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
@@ -59,6 +59,7 @@ typedef struct options_t {
   bool dodomainname;
   int signal;
   bool persistent;
+  bool daemonise;
 
   char *script;
   char pidfile[PATH_MAX];
index b80a9e154d49c799bb1cfef65a49bc41547a2e32..c8b5710ae5856e96bb0f7c560fbfed7f5042d580 100644 (file)
 #define NTPSERVICE             ETCDIR "/init.d/ntpd"
 #define NTPRESTARTARGS         "--quiet", "conditionalrestart"
 
+#define OPENNTPFILE            ETCDIR "/ntpd.conf"
+#define OPENNTPSERVICE         ETCDIR "/init.d/ntpd"
+#define OPENNTPRESTARTARGS     "--quiet", "conditionalrestart"
+
 #define DEFAULT_SCRIPT         ETCDIR "/" PACKAGE ".sh"
 
 #define STATEDIR               "/var"
index 5aa29e91ab0edf0b94e63315dafc5d087b6e8dbb..0a50ed36fc9e8b9dcdbc8cdbacbc7a9bc3733420 100644 (file)
--- a/signals.c
+++ b/signals.c
@@ -21,6 +21,7 @@
 
 #include <sys/socket.h>
 #include <sys/select.h>
+#include <sys/wait.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
@@ -34,6 +35,15 @@ static int signal_pipe[2];
 
 static void signal_handler (int sig)
 {
+  /* Silently ignore this signal and wait for it. This stops zombies.
+     We do this here instead of client.c so that we don't spam the log file
+     with "waiting on select messages" */
+  if (sig == SIGCHLD)
+    {
+      wait (0);
+      return;
+    }
+  
   if (send (signal_pipe[1], &sig, sizeof (sig), MSG_DONTWAIT) < 0)
     logger (LOG_ERR, "Could not send signal: %s", strerror (errno));
 }