start_stop_daemon: NOMMU fix; smaller fixes
authorDenis Vlasenko <vda.linux@googlemail.com>
Tue, 31 Jul 2007 17:09:44 +0000 (17:09 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Tue, 31 Jul 2007 17:09:44 +0000 (17:09 -0000)
debianutils/start_stop_daemon.c
include/libbb.h
libbb/vfork_daemon_rexec.c

index 1933e1cfc3411051955a4cdac2d41b2dab40607f..d8a0d7d46adb697aafad746fd97ae07469c16e31 100644 (file)
@@ -8,6 +8,9 @@
  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
 
+/* NB: we have a problem here with /proc/NN/exe usage, similar to
+ * one fixed in killall/pidof */
+
 #include <getopt.h>
 #include <sys/resource.h>
 
@@ -28,33 +31,22 @@ struct pid_list {
 
 static struct pid_list *found;
 
-static inline void push(pid_t pid)
-{
-       struct pid_list *p;
-
-       p = xmalloc(sizeof(*p));
-       p->next = found;
-       p->pid = pid;
-       found = p;
-}
-
 static int pid_is_exec(pid_t pid, const char *name)
 {
        char buf[sizeof("/proc//exe") + sizeof(int)*3];
        char *execbuf;
-       int sz;
-       int equal;
+       int n;
 
-       sprintf(buf, "/proc/%d/exe", pid);
-       sz = strlen(name) + 1;
-       execbuf = xzalloc(sz);
-       readlink(buf, execbuf, sz);
+       sprintf(buf, "/proc/%u/exe", pid);
+       n = strlen(name) + 1;
+       execbuf = xzalloc(n + 1);
+       readlink(buf, execbuf, n);
 
        /* if readlink fails, execbuf still contains "" */
-       equal = !strcmp(execbuf, name);
+       n = strcmp(execbuf, name);
        if (ENABLE_FEATURE_CLEAN_UP)
                free(execbuf);
-       return equal;
+       return ~n; /* nonzero (true) if execbuf == name */
 }
 
 static int pid_is_user(int pid, int uid)
@@ -90,9 +82,10 @@ static int pid_is_cmd(pid_t pid, const char *name)
        return r;
 }
 
-
 static void check(int pid)
 {
+       struct pid_list *p;
+
        if (execname && !pid_is_exec(pid, execname)) {
                return;
        }
@@ -102,14 +95,16 @@ static void check(int pid)
        if (cmdname && !pid_is_cmd(pid, cmdname)) {
                return;
        }
-       push(pid);
+       p = xmalloc(sizeof(*p));
+       p->next = found;
+       p->pid = pid;
+       found = p;
 }
 
-
 static void do_pidfile(void)
 {
        FILE *f;
-       pid_t pid;
+       unsigned pid;
 
        f = fopen(pidfile, "r");
        if (f) {
@@ -143,10 +138,9 @@ static void do_procinit(void)
        }
        closedir(procdir);
        if (!foundany)
-               bb_error_msg_and_die ("nothing in /proc - not mounted?");
+               bb_error_msg_and_die("nothing in /proc - not mounted?");
 }
 
-
 static int do_stop(void)
 {
        char *what;
@@ -155,11 +149,13 @@ static int do_stop(void)
 
        do_procinit();
 
-       if (cmdname)
-               what = xstrdup(cmdname);
-       else if (execname)
-               what = xstrdup(execname);
-       else if (pidfile)
+       if (cmdname) {
+               if (ENABLE_FEATURE_CLEAN_UP) what = xstrdup(cmdname);
+               if (!ENABLE_FEATURE_CLEAN_UP) what = cmdname;
+       } else if (execname) {
+               if (ENABLE_FEATURE_CLEAN_UP) what = xstrdup(execname);
+               if (!ENABLE_FEATURE_CLEAN_UP) what = execname;
+       } else if (pidfile)
                what = xasprintf("process in pidfile '%s'", pidfile);
        else if (userspec)
                what = xasprintf("process(es) owned by '%s'", userspec);
@@ -169,25 +165,25 @@ static int do_stop(void)
        if (!found) {
                if (!quiet)
                        printf("no %s found; none killed\n", what);
-               if (ENABLE_FEATURE_CLEAN_UP)
-                       free(what);
-               return -1;
+               killed = -1;
+               goto ret;
        }
        for (p = found; p; p = p->next) {
                if (kill(p->pid, signal_nr) == 0) {
-                       p->pid = -p->pid;
+                       p->pid = - p->pid;
                        killed++;
                } else {
-                       bb_perror_msg("warning: failed to kill %d", p->pid);
+                       bb_perror_msg("warning: killing process %u", p->pid);
                }
        }
        if (!quiet && killed) {
                printf("stopped %s (pid", what);
                for (p = found; p; p = p->next)
                        if (p->pid < 0)
-                               printf(" %d", -p->pid);
+                               printf(" %u", - p->pid);
                puts(")");
        }
+ ret:
        if (ENABLE_FEATURE_CLEAN_UP)
                free(what);
        return killed;
@@ -287,7 +283,7 @@ int start_stop_daemon_main(int argc, char **argv)
 
        if (opt & CTX_STOP) {
                int i = do_stop();
-               return (opt & OPT_OKNODO) ? 0 : (i<=0);
+               return (opt & OPT_OKNODO) ? 0 : (i <= 0);
        }
 
        do_procinit();
@@ -299,7 +295,24 @@ int start_stop_daemon_main(int argc, char **argv)
        }
        *--argv = startas;
        if (opt & OPT_BACKGROUND) {
+#if BB_MMU
                bb_daemonize(0);
+#else
+               pid_t pid = vfork();
+               if (pid < 0) /* error */
+                       bb_perror_msg_and_die("vfork");
+               if (pid == 0) /* parent */
+                       return 0;
+               }
+               /* child */
+               /* Redirect stdio to /dev/null, close extra FDs.
+                * We do not actually daemonize because of DAEMON_ONLY_SANITIZE */
+               bb_daemonize_or_rexec(
+                       DAEMON_DEVNULL_STDIO
+                       + DAEMON_CLOSE_EXTRA_FDS
+                       + DAEMON_ONLY_SANITIZE,
+                       NULL /* argv, unused */ );
+#endif
        }
        if (opt & OPT_MAKEPID) {
                /* user wants _us_ to make the pidfile */
index ddbde1833be5758739dbb5bbac1e023ba80f72ff..547b8f798181f1796a42ac270b52c81d5581eefc 100644 (file)
@@ -573,7 +573,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet
  */
 enum {
        DAEMON_CHDIR_ROOT = 1,
-       DAEMON_DEVNULL_STDIO = /* 2 */ 0, /* no users so far */
+       DAEMON_DEVNULL_STDIO = 2,
        DAEMON_CLOSE_EXTRA_FDS = 4,
        DAEMON_ONLY_SANITIZE = 8, /* internal use */
 };
index ea7b475eb0bad2f29fbb0cd69c335225b7f79e65..f7c620996b422f18103351417a7224279e201471 100644 (file)
@@ -244,8 +244,6 @@ void bb_daemonize_or_rexec(int flags, char **argv)
 {
        int fd;
 
-       fd = xopen(bb_dev_null, O_RDWR);
-
        if (flags & DAEMON_CHDIR_ROOT)
                xchdir("/");
 
@@ -255,6 +253,8 @@ void bb_daemonize_or_rexec(int flags, char **argv)
                close(2);
        }
 
+       fd = xopen(bb_dev_null, O_RDWR);
+
        while ((unsigned)fd < 2)
                fd = dup(fd); /* have 0,1,2 open at least to /dev/null */