Update docs for start_stop_daemon to match reality. Update
authorEric Andersen <andersen@codepoet.org>
Sat, 13 Mar 2004 08:33:10 +0000 (08:33 -0000)
committerEric Andersen <andersen@codepoet.org>
Sat, 13 Mar 2004 08:33:10 +0000 (08:33 -0000)
the reality a bit to better match debian behavior.

debianutils/start_stop_daemon.c
include/applets.h
include/usage.h

index dfa33e1..6bc259f 100644 (file)
 
 static int signal_nr = 15;
 static int user_id = -1;
+static int quiet = 0;
 static char *userspec = NULL;
 static char *cmdname = NULL;
 static char *execname = NULL;
+static char *pidfile = NULL;
 
-typedef struct pid_list {
+struct pid_list {
        struct pid_list *next;
-       int pid;
-} pid_list;
+       pid_t pid;
+};
 
-static pid_list *found = NULL;
+static struct pid_list *found = NULL;
 
 static inline void
-push(int pid)
+push(pid_t pid)
 {
-       pid_list *p;
+       struct pid_list *p;
 
        p = xmalloc(sizeof(*p));
        p->next = found;
@@ -46,21 +48,19 @@ push(int pid)
 }
 
 static int
-pid_is_exec(int pid, const char *exec)
+pid_is_exec(pid_t pid, const char *name)
 {
-       char buf[PATH_MAX];
-       FILE *fp;
-
-       sprintf(buf, "/proc/%d/cmdline", pid);
-       fp = fopen(buf, "r");
-       if (fp && fgets (buf, sizeof (buf), fp) ) {
-               fclose(fp);
-           if (strncmp (buf, exec, strlen(exec)) == 0)
-               return 1;
-       }
-       return 0;
-}
+       char buf[32];
+       struct stat sb, exec_stat;
 
+       if (name && stat(name, &exec_stat))
+               bb_perror_msg_and_die("stat %s", name);
+
+       sprintf(buf, "/proc/%d/exe", pid);
+       if (stat(buf, &sb) != 0)
+               return 0;
+       return (sb.st_dev == exec_stat.st_dev && sb.st_ino == exec_stat.st_ino);
+}
 
 static int
 pid_is_user(int pid, int uid)
@@ -74,9 +74,8 @@ pid_is_user(int pid, int uid)
        return (sb.st_uid == uid);
 }
 
-
 static int
-pid_is_cmd(int pid, const char *name)
+pid_is_cmd(pid_t pid, const char *name)
 {
        char buf[32];
        FILE *f;
@@ -116,9 +115,24 @@ check(int pid)
 }
 
 
+static void
+do_pidfile(const char *name)
+{
+       FILE *f;
+       pid_t pid;
+
+       f = fopen(name, "r");
+       if (f) {
+               if (fscanf(f, "%d", &pid) == 1)
+                       check(pid);
+               fclose(f);
+       } else if (errno != ENOENT)
+               bb_perror_msg_and_die("open pidfile %s", name);
+
+}
 
 static void
-do_procfs(void)
+do_procinit(void)
 {
        DIR *procdir;
        struct dirent *entry;
@@ -145,9 +159,14 @@ static void
 do_stop(void)
 {
        char what[1024];
-       pid_list *p;
+       struct pid_list *p;
        int killed = 0;
 
+       if (pidfile)
+               do_pidfile(pidfile);
+       else
+               do_procinit();
+
        if (cmdname)
                strcpy(what, cmdname);
        else if (execname)
@@ -158,7 +177,8 @@ do_stop(void)
                bb_error_msg_and_die ("internal error, please report");
 
        if (!found) {
-               printf("no %s found; none killed.\n", what);
+               if (!quiet)
+                       printf("no %s found; none killed.\n", what);
                return;
        }
        for (p = found; p; p = p->next) {
@@ -169,7 +189,7 @@ do_stop(void)
                        bb_perror_msg("warning: failed to kill %d:", p->pid);
                }
        }
-       if (killed) {
+       if (!quiet && killed) {
                printf("stopped %s (pid", what);
                for (p = found; p; p = p->next)
                        if(p->pid < 0)
@@ -183,17 +203,20 @@ static const struct option ssd_long_options[] = {
        { "stop",               0,              NULL,           'K' },
        { "start",              0,              NULL,           'S' },
        { "background", 0,              NULL,           'b' },
+       { "quiet",              0,              NULL,           'q' },
        { "startas",    1,              NULL,           'a' },
        { "name",               1,              NULL,           'n' },
        { "signal",             1,              NULL,           's' },
        { "user",               1,              NULL,           'u' },
        { "exec",               1,              NULL,           'x' },
+       { "pidfile",    1,              NULL,           'p' },
        { 0,                    0,              0,                      0 }
 };
 
 #define SSD_CTX_STOP   1
 #define SSD_CTX_START  2
 #define SSD_OPT_BACKGROUND     4
+#define SSD_OPT_QUIET  8
 
 int
 start_stop_daemon_main(int argc, char **argv)
@@ -205,8 +228,8 @@ start_stop_daemon_main(int argc, char **argv)
        bb_applet_long_options = ssd_long_options;
 
        bb_opt_complementaly = "K~S:S~K";
-       opt = bb_getopt_ulflags(argc, argv, "KSba:n:s:u:x:", 
-                       &startas, &cmdname, &signame, &userspec, &execname);
+       opt = bb_getopt_ulflags(argc, argv, "KSbqa:n:s:u:x:p:",
+                       &startas, &cmdname, &signame, &userspec, &execname, &pidfile);
 
        /* Check one and only one context option was given */
        if ((opt & 0x80000000UL) || (opt & (SSD_CTX_STOP | SSD_CTX_START)) == 0) {
@@ -232,7 +255,7 @@ start_stop_daemon_main(int argc, char **argv)
        if (userspec && sscanf(userspec, "%d", &user_id) != 1)
                user_id = my_getpwnam(userspec);
 
-       do_procfs();
+       do_procinit();
 
        if (opt & SSD_CTX_STOP) {
                do_stop();
@@ -240,7 +263,8 @@ start_stop_daemon_main(int argc, char **argv)
        }
 
        if (found) {
-               printf("%s already running.\n%d\n", execname ,found->pid);
+               if (!quiet)
+                       printf("%s already running.\n%d\n", execname ,found->pid);
                return EXIT_SUCCESS;
        }
        *--argv = startas;
index f3b5f3d..585ea1f 100644 (file)
 #endif
 #ifdef CONFIG_RUN_PARTS
        APPLET_ODDNAME("run-parts", run_parts_main, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts)
-#endif 
+#endif
 #ifdef CONFIG_RX
        APPLET(rx, rx_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER)
 #endif
index ec8f3c8..272c3d0 100644 (file)
 "\n" \
 "      <id>:<runlevels>:<action>:<process>\n" \
 "\n" \
-"      <id>: \n" \
+"      <id>:\n" \
 "\n" \
 "              WARNING: This field has a non-traditional meaning for BusyBox init!\n" \
 "              The id field is used by BusyBox init to specify the controlling tty for\n" \
 "              will be run.  BusyBox init does nothing with utmp.  We don't need no\n" \
 "              stinkin' utmp.\n" \
 "\n" \
-"      <runlevels>: \n" \
+"      <runlevels>:\n" \
 "\n" \
 "              The runlevels field is completely ignored.\n" \
 "\n" \
-"      <action>: \n" \
+"      <action>:\n" \
 "\n" \
-"              Valid actions include: sysinit, respawn, askfirst, wait, \n" \
+"              Valid actions include: sysinit, respawn, askfirst, wait,\n" \
 "              once, restart, ctrlaltdel, and shutdown.\n" \
 "\n" \
 "              The available actions can be classified into two groups: actions\n" \
 "                      respawn, except that before running the specified process it\n" \
 "                      displays the line "Please press Enter to activate this console."\n" \
 "                      and then waits for the user to press enter before starting the\n" \
-"                      specified process.  \n" \
+"                      specified process.\n" \
 "\n" \
 "              Unrecognized actions (like initdefault) will cause init to emit an\n" \
 "              error message, and then go along with its business.  All actions are\n" \
 "              run in the order they appear in /etc/inittab.\n" \
 "\n" \
-"      <process>: \n" \
+"      <process>:\n" \
 "\n" \
 "              Specifies the process to be executed and it's command line.\n" \
 "\n" \
        "\tc or u:\tMake a character (un-buffered) device.\n" \
        "\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes."
 #define mknod_example_usage \
-       "$ mknod /dev/fd0 b 2 0 \n" \
+       "$ mknod /dev/fd0 b 2 0\n" \
        "$ mknod -m 644 /tmp/pipe p\n"
 
 #define mkswap_trivial_usage \
        "f\n"
 
 #define start_stop_daemon_trivial_usage \
-       "[OPTIONS]"
+       "[OPTIONS] [-S|--start|-K|--stop] ... [-- arguments...]\n"
 #define start_stop_daemon_full_usage \
-       "Program to start and stop services.\n"\
-       "Options:\n" \
-       "-S\t\t\tstart\n"\
-       "-K\t\t\tstop\n"\
-       "-b\t\t\tforce process into background (daemonize)\n"\
-       "-x <executable>\t\tprogram to start/check if it is running\n"\
-       "-u <username>|<uid>\tstop this user's processes\n"\
-       "-n <process-name>\tstop processes with this name\n"\
-       "-s <signal>\t\tsignal to send (default 15)\n"\
-       "-a <pathname>\t\tprogram to start (default <executable>)\n"
+       "Program to start and stop services."\
+       "\n\nOptions:"\
+       "\n\t-S|--start\t\t\tstart"\
+       "\n\t-K|--stop\t\t\tstop"\
+       "\n\t-a|--startas <pathname>\t\tstart the process specified by pathname"\
+       "\n\t-b|--background\t\t\tforce process into background"\
+       "\n\t-u|--user <username>|<uid>\tstop this user's processes"\
+       "\n\t-x|--exec <executable>\t\tprogram to start/check if it is running"\
+       "\n\t-n|--name <process-name>\tstop processes with this name"\
+       "\n\t-p|--pidfile <pid-file>\t\tsave or load pid using a pid-file"\
+       "\n\t-q|--quiet\t\t\tbe quiet" \
+       "\n\t-s|--signal <signal>\t\tsignal to send (default TERM)\n"
 
 #define strings_trivial_usage \
     "[-afo] [-n length] [file ... ]"
        "$ echo $?\n" \
        "1\n" \
        "$ test 1 -eq 1\n" \
-       "$ echo $? \n" \
+       "$ echo $?\n" \
        "0\n" \
        "$ [ -d /etc ]\n" \
        "$ echo $?\n" \
        "COMMAND [OPTIONS] ..."
 
 #define vconfig_full_usage \
-"Usage: add             [interface-name] [vlan_id] \n" \
-"       rem             [vlan-name] \n" \
-"       set_flag        [interface-name] [flag-num]       [0 | 1] \n" \
-"       set_egress_map  [vlan-name]      [skb_priority]   [vlan_qos] \n" \
-"       set_ingress_map [vlan-name]      [skb_priority]   [vlan_qos] \n" \
-"       set_name_type   [name-type] \n"
+"Usage: add             [interface-name] [vlan_id]\n" \
+"       rem             [vlan-name]\n" \
+"       set_flag        [interface-name] [flag-num]       [0 | 1]\n" \
+"       set_egress_map  [vlan-name]      [skb_priority]   [vlan_qos]\n" \
+"       set_ingress_map [vlan-name]      [skb_priority]   [vlan_qos]\n" \
+"       set_name_type   [name-type]\n"
 
 #define vi_trivial_usage \
        "[OPTION] [FILE]..."