diff options
| author | Ron Yorston <rmy@pobox.com> | 2023-12-05 07:44:02 +0000 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2023-12-05 07:44:02 +0000 |
| commit | 7dff7f37600209353cf4e86d1cca29bacf5f7372 (patch) | |
| tree | fd2d62684e46663ebd435391058dcf8558c6b70d /debianutils | |
| parent | f444dc586b16c104a82d201d3a7caca68affe51b (diff) | |
| parent | 28f41260935852eda6bd8ab1f26347c012ae0a53 (diff) | |
| download | busybox-w32-7dff7f37600209353cf4e86d1cca29bacf5f7372.tar.gz busybox-w32-7dff7f37600209353cf4e86d1cca29bacf5f7372.tar.bz2 busybox-w32-7dff7f37600209353cf4e86d1cca29bacf5f7372.zip | |
Merge branch 'busybox' into mergeFRP-5236-g7dff7f376
Diffstat (limited to 'debianutils')
| -rw-r--r-- | debianutils/start_stop_daemon.c | 131 |
1 files changed, 98 insertions, 33 deletions
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 3e5dd9faa..271bc4edf 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c | |||
| @@ -11,11 +11,16 @@ | |||
| 11 | /* | 11 | /* |
| 12 | This is how it is supposed to work: | 12 | This is how it is supposed to work: |
| 13 | 13 | ||
| 14 | start-stop-daemon [OPTIONS] [--start|--stop] [[--] arguments...] | 14 | start-stop-daemon [OPTIONS] [--start|--stop] [[--] ARGS] |
| 15 | 15 | ||
| 16 | One (only) of these must be given: | 16 | One (only) of these must be given: |
| 17 | -S,--start Start | 17 | -S,--start Start |
| 18 | -K,--stop Stop | 18 | -K,--stop Stop |
| 19 | -T,--status Check for the existence of a process, return exitcode (since version 1.16.1) | ||
| 20 | 0 - program is running | ||
| 21 | 1 - program is not running and the pid file exists | ||
| 22 | 3 - program is not running | ||
| 23 | 4 - can't determine program status | ||
| 19 | 24 | ||
| 20 | Search for matching processes. | 25 | Search for matching processes. |
| 21 | If --stop is given, stop all matching processes (by sending a signal). | 26 | If --stop is given, stop all matching processes (by sending a signal). |
| @@ -36,20 +41,49 @@ with /proc/$PID/exe or argv[0] (comm can't be matched, it never contains path)] | |||
| 36 | Unlike -n, we match against the full path: | 41 | Unlike -n, we match against the full path: |
| 37 | "ntpd" != "./ntpd" != "/path/to/ntpd" | 42 | "ntpd" != "./ntpd" != "/path/to/ntpd" |
| 38 | -p,--pidfile PID_FILE Look for processes with PID from this file | 43 | -p,--pidfile PID_FILE Look for processes with PID from this file |
| 44 | --pid PID Look for process with this pid (since version 1.17.6) | ||
| 45 | --ppid PPID Look for processes with parent pid (since version 1.17.7) | ||
| 39 | 46 | ||
| 40 | Options which are valid for --start only: | 47 | Options which are valid for --start only: |
| 41 | -x,--exec EXECUTABLE Program to run (1st arg of execvp). Mandatory. | 48 | -x,--exec EXECUTABLE Program to run (1st arg of execvp). |
| 49 | If no -x, EXECUTABLE is taken from ARGS[0] | ||
| 42 | -a,--startas NAME argv[0] (defaults to EXECUTABLE) | 50 | -a,--startas NAME argv[0] (defaults to EXECUTABLE) |
| 43 | -b,--background Put process into background | 51 | -b,--background Put process into background |
| 52 | -O,--output FILE Redirect stdout and stderr to FILE when forcing the | ||
| 53 | daemon into the background (since version 1.20.6). | ||
| 54 | Requires --background and absolute pathname (tested with 1.21.22). | ||
| 55 | Uses O_CREAT|O_APPEND! | ||
| 56 | If execv fails, error message goes to FILE. | ||
| 44 | -N,--nicelevel N Add N to process' nice level | 57 | -N,--nicelevel N Add N to process' nice level |
| 45 | -c,--chuid USER[:[GRP]] Change to specified user [and group] | 58 | -c,--chuid USER[:[GRP]] Change to specified user [and group] |
| 46 | -m,--make-pidfile Write PID to the pidfile | 59 | -m,--make-pidfile Write PID to the pidfile |
| 47 | (both -m and -p must be given!) | 60 | (both -m and -p must be given!) |
| 61 | -P,--procsched policy:priority | ||
| 62 | This alters the process scheduler policy and priority of the | ||
| 63 | process before starting it (since version 1.15.0). The | ||
| 64 | priority can be optionally specified by appending a : | ||
| 65 | followed by the value. The default priority is 0. The | ||
| 66 | currently supported policy values are other, fifo and rr. | ||
| 67 | -r,--chroot DIR Change directory and chroot to DIR before starting the | ||
| 68 | process. Please note that the pidfile is also written after | ||
| 69 | the chroot. | ||
| 70 | -d,--chdir DIR Change directory to DIR before starting the process. This is | ||
| 71 | done after the chroot if the -r|--chroot option is set. | ||
| 72 | When not specified, start-stop-daemon will change directory to the | ||
| 73 | root directory before starting the process. | ||
| 74 | ^^^^ Gentoo does not have the default chdir("/"). Debian does. | ||
| 75 | Tested -S with 1.21.22: | ||
| 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. | ||
| 78 | "start-stop-daemon -S -a /bin/pwd" does NOT work. | ||
| 79 | Earlier versions were less picky (which? Or is it only Gentoo's clone?) | ||
| 48 | 80 | ||
| 49 | Options which are valid for --stop only: | 81 | Options which are valid for --stop only: |
| 50 | -s,--signal SIG Signal to send (default:TERM) | 82 | -s,--signal SIG Signal to send (default:TERM) |
| 51 | -t,--test Exit with status 0 if process is found | 83 | -t,--test Exit with status 0 if process is found |
| 52 | (we don't actually start or stop daemons) | 84 | (we don't actually start or stop daemons) |
| 85 | --remove-pidfile Used when stopping a program that does not remove its own pid | ||
| 86 | file (since version 1.17.19). Requires -p PIDFILE? | ||
| 53 | 87 | ||
| 54 | Misc options: | 88 | Misc options: |
| 55 | -o,--oknodo Exit with status 0 if nothing is done | 89 | -o,--oknodo Exit with status 0 if nothing is done |
| @@ -84,11 +118,11 @@ Misc options: | |||
| 84 | //kbuild:lib-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o | 118 | //kbuild:lib-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o |
| 85 | 119 | ||
| 86 | //usage:#define start_stop_daemon_trivial_usage | 120 | //usage:#define start_stop_daemon_trivial_usage |
| 87 | //usage: "[OPTIONS] [-S|-K] ... [-- ARGS...]" | 121 | //usage: "-S|-K [OPTIONS] [-- ARGS]" |
| 88 | //usage:#define start_stop_daemon_full_usage "\n\n" | 122 | //usage:#define start_stop_daemon_full_usage "\n\n" |
| 89 | //usage: "Search for matching processes, and then\n" | 123 | //usage: "Search for matching processes, and then\n" |
| 90 | //usage: "-K: stop all matching processes\n" | ||
| 91 | //usage: "-S: start a process unless a matching process is found\n" | 124 | //usage: "-S: start a process unless a matching process is found\n" |
| 125 | //usage: "-K: stop all matching processes\n" | ||
| 92 | //usage: "\nProcess matching:" | 126 | //usage: "\nProcess matching:" |
| 93 | //usage: "\n -u USERNAME|UID Match only this user's processes" | 127 | //usage: "\n -u USERNAME|UID Match only this user's processes" |
| 94 | //usage: "\n -n NAME Match processes with NAME" | 128 | //usage: "\n -n NAME Match processes with NAME" |
| @@ -101,10 +135,12 @@ Misc options: | |||
| 101 | //usage: "\n -x EXECUTABLE Program to run" | 135 | //usage: "\n -x EXECUTABLE Program to run" |
| 102 | //usage: "\n -a NAME Zeroth argument" | 136 | //usage: "\n -a NAME Zeroth argument" |
| 103 | //usage: "\n -b Background" | 137 | //usage: "\n -b Background" |
| 138 | //usage: "\n -O FILE Append stdout and stderr to FILE" | ||
| 104 | //usage: IF_FEATURE_START_STOP_DAEMON_FANCY( | 139 | //usage: IF_FEATURE_START_STOP_DAEMON_FANCY( |
| 105 | //usage: "\n -N N Change nice level" | 140 | //usage: "\n -N N Change nice level" |
| 106 | //usage: ) | 141 | //usage: ) |
| 107 | //usage: "\n -c USER[:[GRP]] Change user/group" | 142 | //usage: "\n -c USER[:[GRP]] Change user/group" |
| 143 | //usage: "\n -d DIR Change to DIR" | ||
| 108 | //usage: "\n -m Write PID to pidfile specified by -p" | 144 | //usage: "\n -m Write PID to pidfile specified by -p" |
| 109 | //usage: "\n-K only:" | 145 | //usage: "\n-K only:" |
| 110 | //usage: "\n -s SIG Signal to send" | 146 | //usage: "\n -s SIG Signal to send" |
| @@ -113,8 +149,8 @@ Misc options: | |||
| 113 | //usage: IF_FEATURE_START_STOP_DAEMON_FANCY( | 149 | //usage: IF_FEATURE_START_STOP_DAEMON_FANCY( |
| 114 | //usage: "\n -o Exit with status 0 if nothing is done" | 150 | //usage: "\n -o Exit with status 0 if nothing is done" |
| 115 | //usage: "\n -v Verbose" | 151 | //usage: "\n -v Verbose" |
| 116 | //usage: ) | ||
| 117 | //usage: "\n -q Quiet" | 152 | //usage: "\n -q Quiet" |
| 153 | //usage: ) | ||
| 118 | 154 | ||
| 119 | /* Override ENABLE_FEATURE_PIDFILE */ | 155 | /* Override ENABLE_FEATURE_PIDFILE */ |
| 120 | #define WANT_PIDFILE 1 | 156 | #define WANT_PIDFILE 1 |
| @@ -138,21 +174,23 @@ enum { | |||
| 138 | OPT_s = (1 << 8), // -s | 174 | OPT_s = (1 << 8), // -s |
| 139 | OPT_u = (1 << 9), // -u | 175 | OPT_u = (1 << 9), // -u |
| 140 | OPT_c = (1 << 10), // -c | 176 | OPT_c = (1 << 10), // -c |
| 141 | OPT_x = (1 << 11), // -x | 177 | OPT_d = (1 << 11), // -d |
| 142 | OPT_p = (1 << 12), // -p | 178 | OPT_x = (1 << 12), // -x |
| 143 | OPT_OKNODO = (1 << 13) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o | 179 | OPT_p = (1 << 13), // -p |
| 144 | OPT_VERBOSE = (1 << 14) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v | 180 | OPT_OUTPUT = (1 << 14), // -O |
| 145 | OPT_NICELEVEL = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N | 181 | OPT_OKNODO = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o |
| 182 | OPT_VERBOSE = (1 << 16) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v | ||
| 183 | OPT_NICELEVEL = (1 << 17) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N | ||
| 146 | }; | 184 | }; |
| 147 | #define QUIET (option_mask32 & OPT_QUIET) | 185 | #define QUIET (option_mask32 & OPT_QUIET) |
| 148 | #define TEST (option_mask32 & OPT_TEST) | 186 | #define TEST (option_mask32 & OPT_TEST) |
| 149 | 187 | ||
| 150 | struct globals { | 188 | struct globals { |
| 151 | struct pid_list *found_procs; | 189 | struct pid_list *found_procs; |
| 152 | char *userspec; | 190 | const char *userspec; |
| 153 | char *cmdname; | 191 | const char *cmdname; |
| 154 | char *execname; | 192 | const char *execname; |
| 155 | char *pidfile; | 193 | const char *pidfile; |
| 156 | char *execname_cmpbuf; | 194 | char *execname_cmpbuf; |
| 157 | unsigned execname_sizeof; | 195 | unsigned execname_sizeof; |
| 158 | int user_id; | 196 | int user_id; |
| @@ -322,7 +360,7 @@ static void do_procinit(void) | |||
| 322 | 360 | ||
| 323 | static int do_stop(void) | 361 | static int do_stop(void) |
| 324 | { | 362 | { |
| 325 | char *what; | 363 | const char *what; |
| 326 | struct pid_list *p; | 364 | struct pid_list *p; |
| 327 | int killed = 0; | 365 | int killed = 0; |
| 328 | 366 | ||
| @@ -369,7 +407,7 @@ static int do_stop(void) | |||
| 369 | } | 407 | } |
| 370 | ret: | 408 | ret: |
| 371 | if (ENABLE_FEATURE_CLEAN_UP) | 409 | if (ENABLE_FEATURE_CLEAN_UP) |
| 372 | free(what); | 410 | free((char *)what); |
| 373 | return killed; | 411 | return killed; |
| 374 | } | 412 | } |
| 375 | 413 | ||
| @@ -381,6 +419,7 @@ static const char start_stop_daemon_longopts[] ALIGN1 = | |||
| 381 | "quiet\0" No_argument "q" | 419 | "quiet\0" No_argument "q" |
| 382 | "test\0" No_argument "t" | 420 | "test\0" No_argument "t" |
| 383 | "make-pidfile\0" No_argument "m" | 421 | "make-pidfile\0" No_argument "m" |
| 422 | "output\0" Required_argument "O" | ||
| 384 | # if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | 423 | # if ENABLE_FEATURE_START_STOP_DAEMON_FANCY |
| 385 | "oknodo\0" No_argument "o" | 424 | "oknodo\0" No_argument "o" |
| 386 | "verbose\0" No_argument "v" | 425 | "verbose\0" No_argument "v" |
| @@ -391,6 +430,7 @@ static const char start_stop_daemon_longopts[] ALIGN1 = | |||
| 391 | "signal\0" Required_argument "s" | 430 | "signal\0" Required_argument "s" |
| 392 | "user\0" Required_argument "u" | 431 | "user\0" Required_argument "u" |
| 393 | "chuid\0" Required_argument "c" | 432 | "chuid\0" Required_argument "c" |
| 433 | "chdir\0" Required_argument "d" | ||
| 394 | "exec\0" Required_argument "x" | 434 | "exec\0" Required_argument "x" |
| 395 | "pidfile\0" Required_argument "p" | 435 | "pidfile\0" Required_argument "p" |
| 396 | # if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | 436 | # if ENABLE_FEATURE_START_STOP_DAEMON_FANCY |
| @@ -408,36 +448,49 @@ int start_stop_daemon_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
| 408 | int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | 448 | int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) |
| 409 | { | 449 | { |
| 410 | unsigned opt; | 450 | unsigned opt; |
| 411 | char *signame; | 451 | const char *signame; |
| 412 | char *startas = NULL; | 452 | const char *startas = NULL; |
| 413 | char *chuid; | 453 | char *chuid; |
| 454 | const char *chdir; | ||
| 455 | const char *output = NULL; | ||
| 414 | #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | 456 | #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY |
| 415 | // char *retry_arg = NULL; | 457 | // const char *retry_arg = NULL; |
| 416 | // int retries = -1; | 458 | // int retries = -1; |
| 417 | char *opt_N; | 459 | const char *opt_N; |
| 418 | #endif | 460 | #endif |
| 419 | 461 | ||
| 420 | INIT_G(); | 462 | INIT_G(); |
| 421 | 463 | ||
| 422 | opt = GETOPT32(argv, "^" | 464 | opt = GETOPT32(argv, "^" |
| 423 | "KSbqtma:n:s:u:c:x:p:" | 465 | "KSbqtma:n:s:u:c:d:x:p:O:" |
| 424 | IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:") | 466 | IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:") |
| 425 | /* -K or -S is required; they are mutually exclusive */ | ||
| 426 | /* -p is required if -m is given */ | ||
| 427 | /* -xpun (at least one) is required if -K is given */ | ||
| 428 | // /* -xa (at least one) is required if -S is given */ | ||
| 429 | //WRONG: "start-stop-daemon -S -- sleep 5" is a valid invocation | ||
| 430 | /* -q turns off -v */ | ||
| 431 | "\0" | 467 | "\0" |
| 432 | "K:S:K--S:S--K:m?p:K?xpun" | 468 | "K:S:K--S:S--K" |
| 433 | IF_FEATURE_START_STOP_DAEMON_FANCY("q-v"), | 469 | /* -K or -S is required; they are mutually exclusive */ |
| 470 | ":m?p" /* -p is required if -m is given */ | ||
| 471 | ":K?xpun" /* -xpun (at least one) is required if -K is given */ | ||
| 472 | /* (the above does not seem to be enforced by Gentoo, it does nothing | ||
| 473 | * if no matching is specified with -K, and it ignores ARGS | ||
| 474 | * - does not take ARGS[0] as program name to kill) | ||
| 475 | */ | ||
| 476 | // ":S?xa" /* -xa (at least one) is required if -S is given */ | ||
| 477 | //Gentoo clone: "start-stop-daemon -S -- sleep 5" is a valid invocation | ||
| 478 | IF_FEATURE_START_STOP_DAEMON_FANCY(":q-v") /* -q turns off -v */ | ||
| 479 | , | ||
| 434 | LONGOPTS | 480 | LONGOPTS |
| 435 | &startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile | 481 | &startas, &cmdname, &signame, &userspec, &chuid, &chdir, &execname, &pidfile, &output |
| 436 | IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) | 482 | IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) |
| 437 | /* We accept and ignore -R <param> / --retry <param> */ | 483 | /* We accept and ignore -R <param> / --retry <param> */ |
| 438 | IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL) | 484 | IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL) |
| 439 | ); | 485 | ); |
| 440 | 486 | ||
| 487 | //-O requires --background and absolute pathname (tested with 1.21.22). | ||
| 488 | //We don't bother requiring that (smaller code): | ||
| 489 | //#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY | ||
| 490 | // if ((opt & OPT_OUTPUT) && !(opt & OPT_BACKGROUND)) | ||
| 491 | // bb_show_usage(); | ||
| 492 | //#endif | ||
| 493 | |||
| 441 | if (opt & OPT_s) { | 494 | if (opt & OPT_s) { |
| 442 | signal_nr = get_signum(signame); | 495 | signal_nr = get_signum(signame); |
| 443 | if (signal_nr < 0) bb_show_usage(); | 496 | if (signal_nr < 0) bb_show_usage(); |
| @@ -464,7 +517,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
| 464 | } | 517 | } |
| 465 | 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] */ |
| 466 | startas = execname; | 519 | startas = execname; |
| 467 | *--argv = startas; | 520 | *--argv = (char *)startas; |
| 468 | } | 521 | } |
| 469 | if (execname) { | 522 | if (execname) { |
| 470 | G.execname_sizeof = strlen(execname) + 1; | 523 | G.execname_sizeof = strlen(execname) + 1; |
| @@ -523,8 +576,11 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
| 523 | } | 576 | } |
| 524 | /* Child */ | 577 | /* Child */ |
| 525 | setsid(); /* detach from controlling tty */ | 578 | setsid(); /* detach from controlling tty */ |
| 526 | /* Redirect stdio to /dev/null, close extra FDs */ | 579 | /* Redirect stdin to /dev/null, close extra FDs */ |
| 527 | 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 */ | ||
| 528 | /* On Linux, session leader can acquire ctty | 584 | /* On Linux, session leader can acquire ctty |
| 529 | * unknowingly, by opening a tty. | 585 | * unknowingly, by opening a tty. |
| 530 | * Prevent this: stop being a session leader. | 586 | * Prevent this: stop being a session leader. |
| @@ -560,6 +616,15 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |||
| 560 | setgroups(1, &ugid.gid); | 616 | setgroups(1, &ugid.gid); |
| 561 | } | 617 | } |
| 562 | } | 618 | } |
| 619 | if (opt & OPT_d) { | ||
| 620 | xchdir(chdir); | ||
| 621 | } | ||
| 622 | if (output) { | ||
| 623 | int outfd = xopen(output, O_WRONLY | O_CREAT | O_APPEND); | ||
| 624 | xmove_fd(outfd, STDOUT_FILENO); | ||
| 625 | xdup2(STDOUT_FILENO, STDERR_FILENO); | ||
| 626 | /* on execv error, the message goes to -O file. This is intended */ | ||
| 627 | } | ||
| 563 | /* Try: | 628 | /* Try: |
| 564 | * 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 |
| 565 | * should exec "/bin/usleep", but argv[0] should be "qwerty": | 630 | * should exec "/bin/usleep", but argv[0] should be "qwerty": |
