Author: des
Date: Thu Oct 13 17:20:45 2011
New Revision: 226345
URL: http://svn.freebsd.org/changeset/base/226345

Log:
  Make dhclient use a pid file.  Modify the rc script accordingly; while
  there, clean it up and add some error checks.
  
  Glanced at by:        brooks@
  MFC after:    3 weeks

Modified:
  head/etc/rc.d/dhclient
  head/sbin/dhclient/Makefile
  head/sbin/dhclient/dhclient.8
  head/sbin/dhclient/dhclient.c
  head/sbin/dhclient/dhcpd.h
  head/sbin/dhclient/errwarn.c

Modified: head/etc/rc.d/dhclient
==============================================================================
--- head/etc/rc.d/dhclient      Thu Oct 13 16:29:24 2011        (r226344)
+++ head/etc/rc.d/dhclient      Thu Oct 13 17:20:45 2011        (r226345)
@@ -9,55 +9,39 @@
 . /etc/rc.subr
 . /etc/network.subr
 
+ifn="$2"
+
 name="dhclient"
 rcvar=
-start_cmd="dhclient_start"
-stop_cmd="dhclient_stop"
+pidfile="/var/run/${name}.${ifn}.pid"
+start_precmd="dhclient_prestart"
 
-dhclient_start()
+dhclient_prestart()
 {
-       # prevent unnecessary restarts
-       # XXX: dhclient had better create a pidfile
-       if [ -x /bin/pgrep ]; then
-               pids=`/bin/pgrep -f "dhclient: $ifn(\$| .*)"`
-               if [ -n "$pids" ]; then
-                       sleep 1
-                       pids=`/bin/pgrep -f "dhclient: $ifn(\$| .*)"`
-                       if [ -n "$pids" ]; then
-                               exit 0
-                       fi
-               elif [ -e /var/run/dhclient.pid ]; then
-                       if [ -n "`pgrep -F /var/run/dhclient.pid`" ]; then
-                               exit 0
-                       fi
-               fi
-       fi
-
-       # Override for $ifn specific flags (see rc.subr for $flags setting)
-       specific=`get_if_var $ifn dhclient_flags_IF`
+       # Interface-specific flags (see rc.subr for $flags setting)
+       specific=$(get_if_var $ifn dhclient_flags_IF)
        if [ -z "$flags" -a -n "$specific" ]; then
                rc_flags=$specific
        fi
 
-       background_dhclient=`get_if_var $ifn background_dhclient_IF 
$background_dhclient`
+       background_dhclient=$(get_if_var $ifn background_dhclient_IF 
$background_dhclient)
        if checkyesno background_dhclient; then
                rc_flags="${rc_flags} -b"
        fi
 
-       ${dhclient_program} ${rc_flags} $ifn
-}
-
-dhclient_stop()
-{
-       ifconfig $ifn down      # cause dhclient to die
+       rc_flags="${rc_flags} ${ifn}"
 }
 
-ifn="$2"
-
 load_rc_config $name
 load_rc_config network
 
-if ! dhcpif $ifn; then
+if [ -z $ifn ] ; then
+       # only complain if a command was specified but no interface
+       if [ -n "$1" ] ; then
+               echo 1>&2 "$0: no interface specified"
+               return 1
+       fi
+elif [ -n "${rc_force}" ] && ! dhcpif $ifn; then
        return 1
 fi
 

Modified: head/sbin/dhclient/Makefile
==============================================================================
--- head/sbin/dhclient/Makefile Thu Oct 13 16:29:24 2011        (r226344)
+++ head/sbin/dhclient/Makefile Thu Oct 13 17:20:45 2011        (r226345)
@@ -39,6 +39,8 @@ PROG= dhclient
 SCRIPTS=dhclient-script
 MAN=   dhclient.8 dhclient.conf.5 dhclient.leases.5 dhcp-options.5 \
        dhclient-script.8
+DPADD= ${LIBUTIL}
+LDADD= -lutil
 
 WARNS?=        2
 

Modified: head/sbin/dhclient/dhclient.8
==============================================================================
--- head/sbin/dhclient/dhclient.8       Thu Oct 13 16:29:24 2011        
(r226344)
+++ head/sbin/dhclient/dhclient.8       Thu Oct 13 17:20:45 2011        
(r226345)
@@ -38,7 +38,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 13, 2007
+.Dd October 13, 2011
 .Dt DHCLIENT 8
 .Os
 .Sh NAME
@@ -49,6 +49,7 @@
 .Op Fl bdqu
 .Op Fl c Ar file
 .Op Fl l Ar file
+.Op Fl p Ar file
 .Ar interface
 .Sh DESCRIPTION
 The
@@ -83,6 +84,10 @@ will revert to running in the background
 Specify an alternate location,
 .Ar file ,
 for the leases file.
+.It Fl p Ar file
+Specify an alternate location for the PID file.
+The default is
+.Pa /var/run/dhclient. Ns Ar interface Ns Pa .pid .
 .It Fl q
 Forces
 .Nm

Modified: head/sbin/dhclient/dhclient.c
==============================================================================
--- head/sbin/dhclient/dhclient.c       Thu Oct 13 16:29:24 2011        
(r226344)
+++ head/sbin/dhclient/dhclient.c       Thu Oct 13 17:20:45 2011        
(r226345)
@@ -95,6 +95,9 @@ struct iaddr iaddr_broadcast = { 4, { 25
 struct in_addr inaddr_any;
 struct sockaddr_in sockaddr_broadcast;
 
+char *path_dhclient_pidfile;
+struct pidfh *pidfile;
+
 /*
  * ASSERT_STATE() does nothing now; it used to be
  * assert (state_is == state_shouldbe).
@@ -316,6 +319,8 @@ die:
        if (ifi->client->alias)
                script_write_params("alias_", ifi->client->alias);
        script_go();
+       if (pidfile != NULL)
+               pidfile_remove(pidfile);
        exit(1);
 }
 
@@ -327,12 +332,13 @@ main(int argc, char *argv[])
        int                      pipe_fd[2];
        int                      immediate_daemon = 0;
        struct passwd           *pw;
+       pid_t                    otherpid;
 
        /* Initially, log errors to stderr as well as to syslogd. */
        openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
        setlogmask(LOG_UPTO(LOG_DEBUG));
 
-       while ((ch = getopt(argc, argv, "bc:dl:qu")) != -1)
+       while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
                switch (ch) {
                case 'b':
                        immediate_daemon = 1;
@@ -346,6 +352,9 @@ main(int argc, char *argv[])
                case 'l':
                        path_dhclient_db = optarg;
                        break;
+               case 'p':
+                       path_dhclient_pidfile = optarg;
+                       break;
                case 'q':
                        quiet = 1;
                        break;
@@ -362,6 +371,21 @@ main(int argc, char *argv[])
        if (argc != 1)
                usage();
 
+       if (path_dhclient_pidfile == NULL) {
+               asprintf(&path_dhclient_pidfile,
+                   "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
+               if (path_dhclient_pidfile == NULL)
+                       error("asprintf");
+       }
+       pidfile = pidfile_open(path_dhclient_pidfile, 0600, &otherpid);
+       if (pidfile == NULL) {
+               if (errno == EEXIST)
+                       error("dhclient already running, pid: %d.", otherpid);
+               if (errno == EAGAIN)
+                       error("dhclient already running.");
+               warning("Cannot open or create pidfile: %m");
+       }
+
        if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
                error("calloc");
        if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
@@ -385,6 +409,12 @@ main(int argc, char *argv[])
 
        read_client_conf();
 
+       /* The next bit is potentially very time-consuming, so write out
+          the pidfile right away.  We will write it out again with the
+          correct pid after daemonizing. */
+       if (pidfile != NULL)
+               pidfile_write(pidfile);
+
        if (!interface_link_status(ifi->name)) {
                fprintf(stderr, "%s: no link ...", ifi->name);
                fflush(stderr);
@@ -2298,6 +2328,9 @@ go_daemon(void)
        if (daemon(1, 0) == -1)
                error("daemon");
 
+       if (pidfile != NULL)
+               pidfile_write(pidfile);
+
        /* we are chrooted, daemon(3) fails to open /dev/null */
        if (nullfd != -1) {
                dup2(nullfd, STDIN_FILENO);

Modified: head/sbin/dhclient/dhcpd.h
==============================================================================
--- head/sbin/dhclient/dhcpd.h  Thu Oct 13 16:29:24 2011        (r226344)
+++ head/sbin/dhclient/dhcpd.h  Thu Oct 13 17:20:45 2011        (r226345)
@@ -41,7 +41,7 @@
  * $FreeBSD$
  */
 
-#include <sys/types.h>
+#include <sys/param.h>
 
 #include <sys/socket.h>
 #include <sys/sockio.h>
@@ -60,6 +60,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <libutil.h>
 #include <limits.h>
 #include <netdb.h>
 #include <paths.h>
@@ -353,6 +354,8 @@ extern int log_perror;
 
 extern struct client_config top_level_config;
 
+extern struct pidfh *pidfile;
+
 void dhcpoffer(struct packet *);
 void dhcpack(struct packet *);
 void dhcpnak(struct packet *);

Modified: head/sbin/dhclient/errwarn.c
==============================================================================
--- head/sbin/dhclient/errwarn.c        Thu Oct 13 16:29:24 2011        
(r226344)
+++ head/sbin/dhclient/errwarn.c        Thu Oct 13 17:20:45 2011        
(r226345)
@@ -83,6 +83,8 @@ error(char *fmt, ...)
                fprintf(stderr, "exiting.\n");
                fflush(stderr);
        }
+       if (pidfile != NULL)
+               pidfile_remove(pidfile);
        exit(1);
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to