diff options
-rw-r--r-- | debianutils/start_stop_daemon.c | 82 | ||||
-rw-r--r-- | include/applets.h | 2 | ||||
-rw-r--r-- | include/usage.h | 52 |
3 files changed, 81 insertions, 55 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 @@ | |||
23 | 23 | ||
24 | static int signal_nr = 15; | 24 | static int signal_nr = 15; |
25 | static int user_id = -1; | 25 | static int user_id = -1; |
26 | static int quiet = 0; | ||
26 | static char *userspec = NULL; | 27 | static char *userspec = NULL; |
27 | static char *cmdname = NULL; | 28 | static char *cmdname = NULL; |
28 | static char *execname = NULL; | 29 | static char *execname = NULL; |
30 | static char *pidfile = NULL; | ||
29 | 31 | ||
30 | typedef struct pid_list { | 32 | struct pid_list { |
31 | struct pid_list *next; | 33 | struct pid_list *next; |
32 | int pid; | 34 | pid_t pid; |
33 | } pid_list; | 35 | }; |
34 | 36 | ||
35 | static pid_list *found = NULL; | 37 | static struct pid_list *found = NULL; |
36 | 38 | ||
37 | static inline void | 39 | static inline void |
38 | push(int pid) | 40 | push(pid_t pid) |
39 | { | 41 | { |
40 | pid_list *p; | 42 | struct pid_list *p; |
41 | 43 | ||
42 | p = xmalloc(sizeof(*p)); | 44 | p = xmalloc(sizeof(*p)); |
43 | p->next = found; | 45 | p->next = found; |
@@ -46,21 +48,19 @@ push(int pid) | |||
46 | } | 48 | } |
47 | 49 | ||
48 | static int | 50 | static int |
49 | pid_is_exec(int pid, const char *exec) | 51 | pid_is_exec(pid_t pid, const char *name) |
50 | { | 52 | { |
51 | char buf[PATH_MAX]; | 53 | char buf[32]; |
52 | FILE *fp; | 54 | struct stat sb, exec_stat; |
53 | |||
54 | sprintf(buf, "/proc/%d/cmdline", pid); | ||
55 | fp = fopen(buf, "r"); | ||
56 | if (fp && fgets (buf, sizeof (buf), fp) ) { | ||
57 | fclose(fp); | ||
58 | if (strncmp (buf, exec, strlen(exec)) == 0) | ||
59 | return 1; | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | 55 | ||
56 | if (name && stat(name, &exec_stat)) | ||
57 | bb_perror_msg_and_die("stat %s", name); | ||
58 | |||
59 | sprintf(buf, "/proc/%d/exe", pid); | ||
60 | if (stat(buf, &sb) != 0) | ||
61 | return 0; | ||
62 | return (sb.st_dev == exec_stat.st_dev && sb.st_ino == exec_stat.st_ino); | ||
63 | } | ||
64 | 64 | ||
65 | static int | 65 | static int |
66 | pid_is_user(int pid, int uid) | 66 | pid_is_user(int pid, int uid) |
@@ -74,9 +74,8 @@ pid_is_user(int pid, int uid) | |||
74 | return (sb.st_uid == uid); | 74 | return (sb.st_uid == uid); |
75 | } | 75 | } |
76 | 76 | ||
77 | |||
78 | static int | 77 | static int |
79 | pid_is_cmd(int pid, const char *name) | 78 | pid_is_cmd(pid_t pid, const char *name) |
80 | { | 79 | { |
81 | char buf[32]; | 80 | char buf[32]; |
82 | FILE *f; | 81 | FILE *f; |
@@ -116,9 +115,24 @@ check(int pid) | |||
116 | } | 115 | } |
117 | 116 | ||
118 | 117 | ||
118 | static void | ||
119 | do_pidfile(const char *name) | ||
120 | { | ||
121 | FILE *f; | ||
122 | pid_t pid; | ||
123 | |||
124 | f = fopen(name, "r"); | ||
125 | if (f) { | ||
126 | if (fscanf(f, "%d", &pid) == 1) | ||
127 | check(pid); | ||
128 | fclose(f); | ||
129 | } else if (errno != ENOENT) | ||
130 | bb_perror_msg_and_die("open pidfile %s", name); | ||
131 | |||
132 | } | ||
119 | 133 | ||
120 | static void | 134 | static void |
121 | do_procfs(void) | 135 | do_procinit(void) |
122 | { | 136 | { |
123 | DIR *procdir; | 137 | DIR *procdir; |
124 | struct dirent *entry; | 138 | struct dirent *entry; |
@@ -145,9 +159,14 @@ static void | |||
145 | do_stop(void) | 159 | do_stop(void) |
146 | { | 160 | { |
147 | char what[1024]; | 161 | char what[1024]; |
148 | pid_list *p; | 162 | struct pid_list *p; |
149 | int killed = 0; | 163 | int killed = 0; |
150 | 164 | ||
165 | if (pidfile) | ||
166 | do_pidfile(pidfile); | ||
167 | else | ||
168 | do_procinit(); | ||
169 | |||
151 | if (cmdname) | 170 | if (cmdname) |
152 | strcpy(what, cmdname); | 171 | strcpy(what, cmdname); |
153 | else if (execname) | 172 | else if (execname) |
@@ -158,7 +177,8 @@ do_stop(void) | |||
158 | bb_error_msg_and_die ("internal error, please report"); | 177 | bb_error_msg_and_die ("internal error, please report"); |
159 | 178 | ||
160 | if (!found) { | 179 | if (!found) { |
161 | printf("no %s found; none killed.\n", what); | 180 | if (!quiet) |
181 | printf("no %s found; none killed.\n", what); | ||
162 | return; | 182 | return; |
163 | } | 183 | } |
164 | for (p = found; p; p = p->next) { | 184 | for (p = found; p; p = p->next) { |
@@ -169,7 +189,7 @@ do_stop(void) | |||
169 | bb_perror_msg("warning: failed to kill %d:", p->pid); | 189 | bb_perror_msg("warning: failed to kill %d:", p->pid); |
170 | } | 190 | } |
171 | } | 191 | } |
172 | if (killed) { | 192 | if (!quiet && killed) { |
173 | printf("stopped %s (pid", what); | 193 | printf("stopped %s (pid", what); |
174 | for (p = found; p; p = p->next) | 194 | for (p = found; p; p = p->next) |
175 | if(p->pid < 0) | 195 | if(p->pid < 0) |
@@ -183,17 +203,20 @@ static const struct option ssd_long_options[] = { | |||
183 | { "stop", 0, NULL, 'K' }, | 203 | { "stop", 0, NULL, 'K' }, |
184 | { "start", 0, NULL, 'S' }, | 204 | { "start", 0, NULL, 'S' }, |
185 | { "background", 0, NULL, 'b' }, | 205 | { "background", 0, NULL, 'b' }, |
206 | { "quiet", 0, NULL, 'q' }, | ||
186 | { "startas", 1, NULL, 'a' }, | 207 | { "startas", 1, NULL, 'a' }, |
187 | { "name", 1, NULL, 'n' }, | 208 | { "name", 1, NULL, 'n' }, |
188 | { "signal", 1, NULL, 's' }, | 209 | { "signal", 1, NULL, 's' }, |
189 | { "user", 1, NULL, 'u' }, | 210 | { "user", 1, NULL, 'u' }, |
190 | { "exec", 1, NULL, 'x' }, | 211 | { "exec", 1, NULL, 'x' }, |
212 | { "pidfile", 1, NULL, 'p' }, | ||
191 | { 0, 0, 0, 0 } | 213 | { 0, 0, 0, 0 } |
192 | }; | 214 | }; |
193 | 215 | ||
194 | #define SSD_CTX_STOP 1 | 216 | #define SSD_CTX_STOP 1 |
195 | #define SSD_CTX_START 2 | 217 | #define SSD_CTX_START 2 |
196 | #define SSD_OPT_BACKGROUND 4 | 218 | #define SSD_OPT_BACKGROUND 4 |
219 | #define SSD_OPT_QUIET 8 | ||
197 | 220 | ||
198 | int | 221 | int |
199 | start_stop_daemon_main(int argc, char **argv) | 222 | start_stop_daemon_main(int argc, char **argv) |
@@ -205,8 +228,8 @@ start_stop_daemon_main(int argc, char **argv) | |||
205 | bb_applet_long_options = ssd_long_options; | 228 | bb_applet_long_options = ssd_long_options; |
206 | 229 | ||
207 | bb_opt_complementaly = "K~S:S~K"; | 230 | bb_opt_complementaly = "K~S:S~K"; |
208 | opt = bb_getopt_ulflags(argc, argv, "KSba:n:s:u:x:", | 231 | opt = bb_getopt_ulflags(argc, argv, "KSbqa:n:s:u:x:p:", |
209 | &startas, &cmdname, &signame, &userspec, &execname); | 232 | &startas, &cmdname, &signame, &userspec, &execname, &pidfile); |
210 | 233 | ||
211 | /* Check one and only one context option was given */ | 234 | /* Check one and only one context option was given */ |
212 | if ((opt & 0x80000000UL) || (opt & (SSD_CTX_STOP | SSD_CTX_START)) == 0) { | 235 | if ((opt & 0x80000000UL) || (opt & (SSD_CTX_STOP | SSD_CTX_START)) == 0) { |
@@ -232,7 +255,7 @@ start_stop_daemon_main(int argc, char **argv) | |||
232 | if (userspec && sscanf(userspec, "%d", &user_id) != 1) | 255 | if (userspec && sscanf(userspec, "%d", &user_id) != 1) |
233 | user_id = my_getpwnam(userspec); | 256 | user_id = my_getpwnam(userspec); |
234 | 257 | ||
235 | do_procfs(); | 258 | do_procinit(); |
236 | 259 | ||
237 | if (opt & SSD_CTX_STOP) { | 260 | if (opt & SSD_CTX_STOP) { |
238 | do_stop(); | 261 | do_stop(); |
@@ -240,7 +263,8 @@ start_stop_daemon_main(int argc, char **argv) | |||
240 | } | 263 | } |
241 | 264 | ||
242 | if (found) { | 265 | if (found) { |
243 | printf("%s already running.\n%d\n", execname ,found->pid); | 266 | if (!quiet) |
267 | printf("%s already running.\n%d\n", execname ,found->pid); | ||
244 | return EXIT_SUCCESS; | 268 | return EXIT_SUCCESS; |
245 | } | 269 | } |
246 | *--argv = startas; | 270 | *--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 @@ | |||
501 | #endif | 501 | #endif |
502 | #ifdef CONFIG_RUN_PARTS | 502 | #ifdef CONFIG_RUN_PARTS |
503 | APPLET_ODDNAME("run-parts", run_parts_main, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts) | 503 | APPLET_ODDNAME("run-parts", run_parts_main, _BB_DIR_BIN, _BB_SUID_NEVER, run_parts) |
504 | #endif | 504 | #endif |
505 | #ifdef CONFIG_RX | 505 | #ifdef CONFIG_RX |
506 | APPLET(rx, rx_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) | 506 | APPLET(rx, rx_main, _BB_DIR_USR_BIN, _BB_SUID_NEVER) |
507 | #endif | 507 | #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 @@ | |||
1156 | "\n" \ | 1156 | "\n" \ |
1157 | " <id>:<runlevels>:<action>:<process>\n" \ | 1157 | " <id>:<runlevels>:<action>:<process>\n" \ |
1158 | "\n" \ | 1158 | "\n" \ |
1159 | " <id>: \n" \ | 1159 | " <id>:\n" \ |
1160 | "\n" \ | 1160 | "\n" \ |
1161 | " WARNING: This field has a non-traditional meaning for BusyBox init!\n" \ | 1161 | " WARNING: This field has a non-traditional meaning for BusyBox init!\n" \ |
1162 | " The id field is used by BusyBox init to specify the controlling tty for\n" \ | 1162 | " The id field is used by BusyBox init to specify the controlling tty for\n" \ |
@@ -1169,13 +1169,13 @@ | |||
1169 | " will be run. BusyBox init does nothing with utmp. We don't need no\n" \ | 1169 | " will be run. BusyBox init does nothing with utmp. We don't need no\n" \ |
1170 | " stinkin' utmp.\n" \ | 1170 | " stinkin' utmp.\n" \ |
1171 | "\n" \ | 1171 | "\n" \ |
1172 | " <runlevels>: \n" \ | 1172 | " <runlevels>:\n" \ |
1173 | "\n" \ | 1173 | "\n" \ |
1174 | " The runlevels field is completely ignored.\n" \ | 1174 | " The runlevels field is completely ignored.\n" \ |
1175 | "\n" \ | 1175 | "\n" \ |
1176 | " <action>: \n" \ | 1176 | " <action>:\n" \ |
1177 | "\n" \ | 1177 | "\n" \ |
1178 | " Valid actions include: sysinit, respawn, askfirst, wait, \n" \ | 1178 | " Valid actions include: sysinit, respawn, askfirst, wait,\n" \ |
1179 | " once, restart, ctrlaltdel, and shutdown.\n" \ | 1179 | " once, restart, ctrlaltdel, and shutdown.\n" \ |
1180 | "\n" \ | 1180 | "\n" \ |
1181 | " The available actions can be classified into two groups: actions\n" \ | 1181 | " The available actions can be classified into two groups: actions\n" \ |
@@ -1209,13 +1209,13 @@ | |||
1209 | " respawn, except that before running the specified process it\n" \ | 1209 | " respawn, except that before running the specified process it\n" \ |
1210 | " displays the line "Please press Enter to activate this console."\n" \ | 1210 | " displays the line "Please press Enter to activate this console."\n" \ |
1211 | " and then waits for the user to press enter before starting the\n" \ | 1211 | " and then waits for the user to press enter before starting the\n" \ |
1212 | " specified process. \n" \ | 1212 | " specified process.\n" \ |
1213 | "\n" \ | 1213 | "\n" \ |
1214 | " Unrecognized actions (like initdefault) will cause init to emit an\n" \ | 1214 | " Unrecognized actions (like initdefault) will cause init to emit an\n" \ |
1215 | " error message, and then go along with its business. All actions are\n" \ | 1215 | " error message, and then go along with its business. All actions are\n" \ |
1216 | " run in the order they appear in /etc/inittab.\n" \ | 1216 | " run in the order they appear in /etc/inittab.\n" \ |
1217 | "\n" \ | 1217 | "\n" \ |
1218 | " <process>: \n" \ | 1218 | " <process>:\n" \ |
1219 | "\n" \ | 1219 | "\n" \ |
1220 | " Specifies the process to be executed and it's command line.\n" \ | 1220 | " Specifies the process to be executed and it's command line.\n" \ |
1221 | "\n" \ | 1221 | "\n" \ |
@@ -1651,7 +1651,7 @@ | |||
1651 | "\tc or u:\tMake a character (un-buffered) device.\n" \ | 1651 | "\tc or u:\tMake a character (un-buffered) device.\n" \ |
1652 | "\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes." | 1652 | "\tp:\tMake a named pipe. MAJOR and MINOR are ignored for named pipes." |
1653 | #define mknod_example_usage \ | 1653 | #define mknod_example_usage \ |
1654 | "$ mknod /dev/fd0 b 2 0 \n" \ | 1654 | "$ mknod /dev/fd0 b 2 0\n" \ |
1655 | "$ mknod -m 644 /tmp/pipe p\n" | 1655 | "$ mknod -m 644 /tmp/pipe p\n" |
1656 | 1656 | ||
1657 | #define mkswap_trivial_usage \ | 1657 | #define mkswap_trivial_usage \ |
@@ -2212,18 +2212,20 @@ | |||
2212 | "f\n" | 2212 | "f\n" |
2213 | 2213 | ||
2214 | #define start_stop_daemon_trivial_usage \ | 2214 | #define start_stop_daemon_trivial_usage \ |
2215 | "[OPTIONS]" | 2215 | "[OPTIONS] [-S|--start|-K|--stop] ... [-- arguments...]\n" |
2216 | #define start_stop_daemon_full_usage \ | 2216 | #define start_stop_daemon_full_usage \ |
2217 | "Program to start and stop services.\n"\ | 2217 | "Program to start and stop services."\ |
2218 | "Options:\n" \ | 2218 | "\n\nOptions:"\ |
2219 | "-S\t\t\tstart\n"\ | 2219 | "\n\t-S|--start\t\t\tstart"\ |
2220 | "-K\t\t\tstop\n"\ | 2220 | "\n\t-K|--stop\t\t\tstop"\ |
2221 | "-b\t\t\tforce process into background (daemonize)\n"\ | 2221 | "\n\t-a|--startas <pathname>\t\tstart the process specified by pathname"\ |
2222 | "-x <executable>\t\tprogram to start/check if it is running\n"\ | 2222 | "\n\t-b|--background\t\t\tforce process into background"\ |
2223 | "-u <username>|<uid>\tstop this user's processes\n"\ | 2223 | "\n\t-u|--user <username>|<uid>\tstop this user's processes"\ |
2224 | "-n <process-name>\tstop processes with this name\n"\ | 2224 | "\n\t-x|--exec <executable>\t\tprogram to start/check if it is running"\ |
2225 | "-s <signal>\t\tsignal to send (default 15)\n"\ | 2225 | "\n\t-n|--name <process-name>\tstop processes with this name"\ |
2226 | "-a <pathname>\t\tprogram to start (default <executable>)\n" | 2226 | "\n\t-p|--pidfile <pid-file>\t\tsave or load pid using a pid-file"\ |
2227 | "\n\t-q|--quiet\t\t\tbe quiet" \ | ||
2228 | "\n\t-s|--signal <signal>\t\tsignal to send (default TERM)\n" | ||
2227 | 2229 | ||
2228 | #define strings_trivial_usage \ | 2230 | #define strings_trivial_usage \ |
2229 | "[-afo] [-n length] [file ... ]" | 2231 | "[-afo] [-n length] [file ... ]" |
@@ -2478,7 +2480,7 @@ | |||
2478 | "$ echo $?\n" \ | 2480 | "$ echo $?\n" \ |
2479 | "1\n" \ | 2481 | "1\n" \ |
2480 | "$ test 1 -eq 1\n" \ | 2482 | "$ test 1 -eq 1\n" \ |
2481 | "$ echo $? \n" \ | 2483 | "$ echo $?\n" \ |
2482 | "0\n" \ | 2484 | "0\n" \ |
2483 | "$ [ -d /etc ]\n" \ | 2485 | "$ [ -d /etc ]\n" \ |
2484 | "$ echo $?\n" \ | 2486 | "$ echo $?\n" \ |
@@ -2750,12 +2752,12 @@ | |||
2750 | "COMMAND [OPTIONS] ..." | 2752 | "COMMAND [OPTIONS] ..." |
2751 | 2753 | ||
2752 | #define vconfig_full_usage \ | 2754 | #define vconfig_full_usage \ |
2753 | "Usage: add [interface-name] [vlan_id] \n" \ | 2755 | "Usage: add [interface-name] [vlan_id]\n" \ |
2754 | " rem [vlan-name] \n" \ | 2756 | " rem [vlan-name]\n" \ |
2755 | " set_flag [interface-name] [flag-num] [0 | 1] \n" \ | 2757 | " set_flag [interface-name] [flag-num] [0 | 1]\n" \ |
2756 | " set_egress_map [vlan-name] [skb_priority] [vlan_qos] \n" \ | 2758 | " set_egress_map [vlan-name] [skb_priority] [vlan_qos]\n" \ |
2757 | " set_ingress_map [vlan-name] [skb_priority] [vlan_qos] \n" \ | 2759 | " set_ingress_map [vlan-name] [skb_priority] [vlan_qos]\n" \ |
2758 | " set_name_type [name-type] \n" | 2760 | " set_name_type [name-type]\n" |
2759 | 2761 | ||
2760 | #define vi_trivial_usage \ | 2762 | #define vi_trivial_usage \ |
2761 | "[OPTION] [FILE]..." | 2763 | "[OPTION] [FILE]..." |