diff options
Diffstat (limited to 'debianutils/start_stop_daemon.c')
-rw-r--r-- | debianutils/start_stop_daemon.c | 57 |
1 files changed, 28 insertions, 29 deletions
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 04ba8baa7..00fa0a82c 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c | |||
@@ -71,7 +71,7 @@ Options which are valid for --start only: | |||
71 | done after the chroot if the -r|--chroot option is set. | 71 | done after the chroot if the -r|--chroot option is set. |
72 | When not specified, start-stop-daemon will change directory to the | 72 | When not specified, start-stop-daemon will change directory to the |
73 | root directory before starting the process. | 73 | root directory before starting the process. |
74 | ^^^^ Seems to be false, no default "/" chdir is done. | 74 | ^^^^ Gentoo does not have the default chdir("/"). Debian does. |
75 | Tested -S with 1.21.22: | 75 | Tested -S with 1.21.22: |
76 | "start-stop-daemon -S -x /bin/pwd" is the minimum needed to run pwd. | 76 | "start-stop-daemon -S -x /bin/pwd" is the minimum needed to run pwd. |
77 | "start-stop-daemon -S -a /bin/pwd -n pwd" works too. | 77 | "start-stop-daemon -S -a /bin/pwd -n pwd" works too. |
@@ -111,7 +111,6 @@ Misc options: | |||
111 | //config: -o|--oknodo ignored since we exit with 0 anyway | 111 | //config: -o|--oknodo ignored since we exit with 0 anyway |
112 | //config: -v|--verbose | 112 | //config: -v|--verbose |
113 | //config: -N|--nicelevel N | 113 | //config: -N|--nicelevel N |
114 | //config: -O|--output FILE | ||
115 | 114 | ||
116 | //applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon)) | 115 | //applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon)) |
117 | /* not NOEXEC: uses bb_common_bufsiz1 */ | 116 | /* not NOEXEC: uses bb_common_bufsiz1 */ |
@@ -136,6 +135,7 @@ Misc options: | |||
136 | //usage: "\n -x EXECUTABLE Program to run" | 135 | //usage: "\n -x EXECUTABLE Program to run" |
137 | //usage: "\n -a NAME Zeroth argument" | 136 | //usage: "\n -a NAME Zeroth argument" |
138 | //usage: "\n -b Background" | 137 | //usage: "\n -b Background" |
138 | //usage: "\n -O FILE Append stdout and stderr to FILE" | ||
139 | //usage: IF_FEATURE_START_STOP_DAEMON_FANCY( | 139 | //usage: IF_FEATURE_START_STOP_DAEMON_FANCY( |
140 | //usage: "\n -N N Change nice level" | 140 | //usage: "\n -N N Change nice level" |
141 | //usage: ) | 141 | //usage: ) |
@@ -150,7 +150,6 @@ Misc options: | |||
150 | //usage: "\n -o Exit with status 0 if nothing is done" | 150 | //usage: "\n -o Exit with status 0 if nothing is done" |
151 | //usage: "\n -v Verbose" | 151 | //usage: "\n -v Verbose" |
152 | //usage: "\n -q Quiet" | 152 | //usage: "\n -q Quiet" |
153 | //usage: "\n -O FILE Append stdout and stderr to FILE" | ||
154 | //usage: ) | 153 | //usage: ) |
155 | 154 | ||
156 | /* Override ENABLE_FEATURE_PIDFILE */ | 155 | /* Override ENABLE_FEATURE_PIDFILE */ |
@@ -178,20 +177,20 @@ enum { | |||
178 | OPT_d = (1 << 11), // -d | 177 | OPT_d = (1 << 11), // -d |
179 | OPT_x = (1 << 12), // -x | 178 | OPT_x = (1 << 12), // -x |
180 | OPT_p = (1 << 13), // -p | 179 | OPT_p = (1 << 13), // -p |
181 | OPT_OKNODO = (1 << 14) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o | 180 | OPT_OUTPUT = (1 << 14), // -O |
182 | OPT_VERBOSE = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v | 181 | OPT_OKNODO = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o |
183 | OPT_NICELEVEL = (1 << 16) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N | 182 | OPT_VERBOSE = (1 << 16) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v |
184 | OPT_OUTPUT = (1 << 17) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -O | 183 | OPT_NICELEVEL = (1 << 17) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N |
185 | }; | 184 | }; |
186 | #define QUIET (option_mask32 & OPT_QUIET) | 185 | #define QUIET (option_mask32 & OPT_QUIET) |
187 | #define TEST (option_mask32 & OPT_TEST) | 186 | #define TEST (option_mask32 & OPT_TEST) |
188 | 187 | ||
189 | struct globals { | 188 | struct globals { |
190 | struct pid_list *found_procs; | 189 | struct pid_list *found_procs; |
191 | char *userspec; | 190 | const char *userspec; |
192 | char *cmdname; | 191 | const char *cmdname; |
193 | char *execname; | 192 | const char *execname; |
194 | char *pidfile; | 193 | const char *pidfile; |
195 | char *execname_cmpbuf; | 194 | char *execname_cmpbuf; |
196 | unsigned execname_sizeof; | 195 | unsigned execname_sizeof; |
197 | int user_id; | 196 | int user_id; |
@@ -361,7 +360,7 @@ static void do_procinit(void) | |||
361 | 360 | ||
362 | static int do_stop(void) | 361 | static int do_stop(void) |
363 | { | 362 | { |
364 | char *what; | 363 | const char *what; |
365 | struct pid_list *p; | 364 | struct pid_list *p; |
366 | int killed = 0; | 365 | int killed = 0; |
367 | 366 | ||
@@ -408,7 +407,7 @@ static int do_stop(void) | |||
408 | } | 407 | } |
409 | ret: | 408 | ret: |
410 | if (ENABLE_FEATURE_CLEAN_UP) | 409 | if (ENABLE_FEATURE_CLEAN_UP) |
411 | free(what); | 410 | free((char *)what); |
412 | return killed; | 411 | return killed; |
413 | } | 412 | } |
414 | 413 | ||
@@ -449,22 +448,22 @@ int start_stop_daemon_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
449 | int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | 448 | int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) |
450 | { | 449 | { |
451 | unsigned opt; | 450 | unsigned opt; |
452 | char *signame; | 451 | const char *signame; |
453 | char *startas = NULL; | 452 | const char *startas = NULL; |
454 | char *chuid; | 453 | char *chuid; |
455 | char *chdir; | 454 | const char *chdir; |
455 | const char *output = NULL; | ||
456 | #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | 456 | #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY |
457 | // char *retry_arg = NULL; | 457 | // const char *retry_arg = NULL; |
458 | // int retries = -1; | 458 | // int retries = -1; |
459 | char *opt_N; | 459 | const char *opt_N; |
460 | char *output; | ||
461 | #endif | 460 | #endif |
462 | 461 | ||
463 | INIT_G(); | 462 | INIT_G(); |
464 | 463 | ||
465 | opt = GETOPT32(argv, "^" | 464 | opt = GETOPT32(argv, "^" |
466 | "KSbqtma:n:s:u:c:d:x:p:" | 465 | "KSbqtma:n:s:u:c:d:x:p:O:" |
467 | IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:O:R:") | 466 | IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:") |
468 | "\0" | 467 | "\0" |
469 | "K:S:K--S:S--K" | 468 | "K:S:K--S:S--K" |
470 | /* -K or -S is required; they are mutually exclusive */ | 469 | /* -K or -S is required; they are mutually exclusive */ |
@@ -479,9 +478,8 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
479 | IF_FEATURE_START_STOP_DAEMON_FANCY(":q-v") /* -q turns off -v */ | 478 | IF_FEATURE_START_STOP_DAEMON_FANCY(":q-v") /* -q turns off -v */ |
480 | , | 479 | , |
481 | LONGOPTS | 480 | LONGOPTS |
482 | &startas, &cmdname, &signame, &userspec, &chuid, &chdir, &execname, &pidfile | 481 | &startas, &cmdname, &signame, &userspec, &chuid, &chdir, &execname, &pidfile, &output |
483 | IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) | 482 | IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) |
484 | IF_FEATURE_START_STOP_DAEMON_FANCY(,&output) | ||
485 | /* We accept and ignore -R <param> / --retry <param> */ | 483 | /* We accept and ignore -R <param> / --retry <param> */ |
486 | IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL) | 484 | IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL) |
487 | ); | 485 | ); |
@@ -519,7 +517,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
519 | } | 517 | } |
520 | if (!startas) /* -a is not given: use -x EXECUTABLE or argv[0] */ | 518 | if (!startas) /* -a is not given: use -x EXECUTABLE or argv[0] */ |
521 | startas = execname; | 519 | startas = execname; |
522 | *--argv = startas; | 520 | *--argv = (char *)startas; |
523 | } | 521 | } |
524 | if (execname) { | 522 | if (execname) { |
525 | G.execname_sizeof = strlen(execname) + 1; | 523 | G.execname_sizeof = strlen(execname) + 1; |
@@ -578,8 +576,11 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
578 | } | 576 | } |
579 | /* Child */ | 577 | /* Child */ |
580 | setsid(); /* detach from controlling tty */ | 578 | setsid(); /* detach from controlling tty */ |
581 | /* Redirect stdio to /dev/null, close extra FDs */ | 579 | /* Redirect stdin to /dev/null, close extra FDs */ |
582 | bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS); | 580 | /* Testcase: "start-stop-daemon -Sb -d /does/not/exist usleep 1" should not eat error message */ |
581 | bb_daemon_helper(DAEMON_DEVNULL_STDIN + DAEMON_CLOSE_EXTRA_FDS); | ||
582 | if (!output) | ||
583 | output = bb_dev_null; /* redirect output just before execv */ | ||
583 | /* On Linux, session leader can acquire ctty | 584 | /* On Linux, session leader can acquire ctty |
584 | * unknowingly, by opening a tty. | 585 | * unknowingly, by opening a tty. |
585 | * Prevent this: stop being a session leader. | 586 | * Prevent this: stop being a session leader. |
@@ -618,14 +619,12 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
618 | if (opt & OPT_d) { | 619 | if (opt & OPT_d) { |
619 | xchdir(chdir); | 620 | xchdir(chdir); |
620 | } | 621 | } |
621 | #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | 622 | if (output) { |
622 | if (opt & OPT_OUTPUT) { | ||
623 | int outfd = xopen(output, O_WRONLY | O_CREAT | O_APPEND); | 623 | int outfd = xopen(output, O_WRONLY | O_CREAT | O_APPEND); |
624 | xmove_fd(outfd, STDOUT_FILENO); | 624 | xmove_fd(outfd, STDOUT_FILENO); |
625 | xdup2(STDOUT_FILENO, STDERR_FILENO); | 625 | xdup2(STDOUT_FILENO, STDERR_FILENO); |
626 | /* on execv error, the message goes to -O file. This is intended */ | 626 | /* on execv error, the message goes to -O file. This is intended */ |
627 | } | 627 | } |
628 | #endif | ||
629 | /* Try: | 628 | /* Try: |
630 | * strace -oLOG start-stop-daemon -S -x /bin/usleep -a qwerty 500000 | 629 | * strace -oLOG start-stop-daemon -S -x /bin/usleep -a qwerty 500000 |
631 | * should exec "/bin/usleep", but argv[0] should be "qwerty": | 630 | * should exec "/bin/usleep", but argv[0] should be "qwerty": |