From 63a1a7aaa520d84bcf37b7351e3923bd308ab8ea Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Sat, 13 Mar 2004 08:33:10 +0000 Subject: [PATCH] Update docs for start_stop_daemon to match reality. Update the reality a bit to better match debian behavior. --- debianutils/start_stop_daemon.c | 80 +++++++++++++++++++++------------ include/applets.h | 2 +- include/usage.h | 52 ++++++++++----------- 3 files changed, 80 insertions(+), 54 deletions(-) diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index dfa33e1f9..6bc259fb3 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -23,21 +23,23 @@ 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,22 +48,20 @@ 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; + char buf[32]; + struct stat sb, exec_stat; - 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; + 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; diff --git a/include/applets.h b/include/applets.h index f3b5f3d1c..585ea1f68 100644 --- a/include/applets.h +++ b/include/applets.h @@ -501,7 +501,7 @@ #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 diff --git a/include/usage.h b/include/usage.h index ec8f3c808..272c3d055 100644 --- a/include/usage.h +++ b/include/usage.h @@ -1156,7 +1156,7 @@ "\n" \ " :::\n" \ "\n" \ -" : \n" \ +" :\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" \ @@ -1169,13 +1169,13 @@ " will be run. BusyBox init does nothing with utmp. We don't need no\n" \ " stinkin' utmp.\n" \ "\n" \ -" : \n" \ +" :\n" \ "\n" \ " The runlevels field is completely ignored.\n" \ "\n" \ -" : \n" \ +" :\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" \ @@ -1209,13 +1209,13 @@ " 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" \ -" : \n" \ +" :\n" \ "\n" \ " Specifies the process to be executed and it's command line.\n" \ "\n" \ @@ -1651,7 +1651,7 @@ "\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 \ @@ -2212,18 +2212,20 @@ "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 \t\tprogram to start/check if it is running\n"\ - "-u |\tstop this user's processes\n"\ - "-n \tstop processes with this name\n"\ - "-s \t\tsignal to send (default 15)\n"\ - "-a \t\tprogram to start (default )\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 \t\tstart the process specified by pathname"\ + "\n\t-b|--background\t\t\tforce process into background"\ + "\n\t-u|--user |\tstop this user's processes"\ + "\n\t-x|--exec \t\tprogram to start/check if it is running"\ + "\n\t-n|--name \tstop processes with this name"\ + "\n\t-p|--pidfile \t\tsave or load pid using a pid-file"\ + "\n\t-q|--quiet\t\t\tbe quiet" \ + "\n\t-s|--signal \t\tsignal to send (default TERM)\n" #define strings_trivial_usage \ "[-afo] [-n length] [file ... ]" @@ -2478,7 +2480,7 @@ "$ echo $?\n" \ "1\n" \ "$ test 1 -eq 1\n" \ - "$ echo $? \n" \ + "$ echo $?\n" \ "0\n" \ "$ [ -d /etc ]\n" \ "$ echo $?\n" \ @@ -2750,12 +2752,12 @@ "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]..."