(Needs a fresh dhcrelay.c)

Using rdaemon(), we can delay going in the background 'til very late,
that is after the chroot.  Thanks to this we can catch errors like
a missing _dhcp user or /var/empty directory, by returning a proper exit
status.  (Also, thanks to the log_perror approach in dhcrelay, those
errors also go to syslog, where the admin can easily find them after
boot.)

This is similar to what has already applied in usr.sbin/tftpd.

ok?


Index: dhcrelay.c
===================================================================
RCS file: /cvs/src/usr.sbin/dhcrelay/dhcrelay.c,v
retrieving revision 1.41
diff -u -p -p -u -r1.41 dhcrelay.c
--- dhcrelay.c  4 Sep 2016 10:43:52 -0000       1.41
+++ dhcrelay.c  4 Sep 2016 12:23:46 -0000
@@ -48,6 +48,7 @@
 #include <net/if.h>
 
 #include <errno.h>
+#include <fcntl.h>
 #include <netdb.h>
 #include <paths.h>
 #include <pwd.h>
@@ -62,6 +63,7 @@
 #include "dhcpd.h"
 
 void    usage(void);
+int     rdaemon(int);
 void    relay(struct interface_info *, struct dhcp_packet *, int,
            unsigned int, struct iaddr, struct hardware *);
 char   *print_hw_addr(int, int, unsigned char *);
@@ -91,7 +93,7 @@ struct server_list {
 int
 main(int argc, char *argv[])
 {
-       int                      ch, daemonize, opt, rdomain;
+       int                      ch, devnull = -1, daemonize, opt, rdomain;
        extern char             *__progname;
        struct server_list      *sp = NULL;
        struct passwd           *pw;
@@ -158,8 +160,11 @@ main(int argc, char *argv[])
                argv++;
        }
 
-       if (daemonize)
-               log_perror = 0;
+       if (daemonize) {
+               devnull = open(_PATH_DEVNULL, O_RDWR, 0);
+               if (devnull == -1)
+                       error("open(%s): %m", _PATH_DEVNULL);
+       }
 
        if (interfaces == NULL)
                error("no interface given");
@@ -230,8 +235,6 @@ main(int argc, char *argv[])
 
        time(&cur_time);
        bootp_packet_handler = relay;
-       if (daemonize)
-               daemon(0, 0);
 
        if ((pw = getpwnam("_dhcp")) == NULL)
                error("user \"_dhcp\" not found");
@@ -244,6 +247,12 @@ main(int argc, char *argv[])
            setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
                error("can't drop privileges: %m");
 
+       if (daemonize) {
+               if (rdaemon(devnull) == -1)
+                       error("rdaemon: %m");
+               log_perror = 0;
+       }
+
        dispatch();
        /* not reached */
 
@@ -354,6 +363,31 @@ usage(void)
        fprintf(stderr, "usage: %s [-do] -i interface server1 [... serverN]\n",
            __progname);
        exit(1);
+}
+
+int
+rdaemon(int devnull)
+{
+
+       switch (fork()) {
+       case -1:
+               return (-1);
+       case 0:
+               break;
+       default:
+               _exit(0);
+       }
+
+       if (setsid() == -1)
+               return (-1);
+
+       (void)dup2(devnull, STDIN_FILENO);
+       (void)dup2(devnull, STDOUT_FILENO);
+       (void)dup2(devnull, STDERR_FILENO);
+       if (devnull > 2)
+               (void)close(devnull);
+
+       return (0);
 }
 
 char *

-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to