From 0c71497e654fb5e9a9272f81ddb5d994d2839df4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 7 Nov 2023 06:55:35 +0100 Subject: start-stop-daemon: fix --help: -K or -S is required function old new delta .rodata 105381 105382 +1 packed_usage 34638 34602 -36 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 1/-36) Total: -35 bytes Signed-off-by: Denys Vlasenko --- debianutils/start_stop_daemon.c | 46 ++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) (limited to 'debianutils') diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 3e5dd9faa..16df67b3e 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -11,11 +11,12 @@ /* This is how it is supposed to work: -start-stop-daemon [OPTIONS] [--start|--stop] [[--] arguments...] +start-stop-daemon [OPTIONS] [--start|--stop] [[--] ARGS...] One (only) of these must be given: -S,--start Start -K,--stop Stop + -T,--status Check for the existence of a process, return exitcode (since version 1.16.1) Search for matching processes. If --stop is given, stop all matching processes (by sending a signal). @@ -36,20 +37,41 @@ with /proc/$PID/exe or argv[0] (comm can't be matched, it never contains path)] Unlike -n, we match against the full path: "ntpd" != "./ntpd" != "/path/to/ntpd" -p,--pidfile PID_FILE Look for processes with PID from this file + --ppid PPID Look for processes with parent pid (since version 1.17.7) Options which are valid for --start only: - -x,--exec EXECUTABLE Program to run (1st arg of execvp). Mandatory. + -x,--exec EXECUTABLE Program to run (1st arg of execvp). + If no -x, EXECUTABLE is taken from ARGS[0] -a,--startas NAME argv[0] (defaults to EXECUTABLE) -b,--background Put process into background + -O,--output FILE Redirect stdout and stderr to FILE when forcing the + daemon into the background (since version 1.20.6). Only + relevant when using --background. + Probably O_CREAT|O_TRUNC? What if execv fails - where does error msg go? "Old" stderr? FILE? Nowhere? -N,--nicelevel N Add N to process' nice level -c,--chuid USER[:[GRP]] Change to specified user [and group] -m,--make-pidfile Write PID to the pidfile (both -m and -p must be given!) + -P,--procsched policy:priority + This alters the process scheduler policy and priority of the + process before starting it (since version 1.15.0). The + priority can be optionally specified by appending a : + followed by the value. The default priority is 0. The + currently supported policy values are other, fifo and rr. + -r,--chroot root Change directory and chroot to root before starting the + process. Please note that the pidfile is also written after + the chroot. + -d,--chdir path Change directory to path before starting the process. This is + done after the chroot if the -r|--chroot option is set. When + not specified, start-stop-daemon will change directory to the + root directory before starting the process. Options which are valid for --stop only: -s,--signal SIG Signal to send (default:TERM) -t,--test Exit with status 0 if process is found (we don't actually start or stop daemons) + --remove-pidfile Used when stopping a program that does not remove its own pid + file (since version 1.17.19). Requires -p PIDFILE? Misc options: -o,--oknodo Exit with status 0 if nothing is done @@ -84,11 +106,11 @@ Misc options: //kbuild:lib-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o //usage:#define start_stop_daemon_trivial_usage -//usage: "[OPTIONS] [-S|-K] ... [-- ARGS...]" +//usage: "-S|-K [OPTIONS] [-- ARGS...]" //usage:#define start_stop_daemon_full_usage "\n\n" //usage: "Search for matching processes, and then\n" -//usage: "-K: stop all matching processes\n" //usage: "-S: start a process unless a matching process is found\n" +//usage: "-K: stop all matching processes\n" //usage: "\nProcess matching:" //usage: "\n -u USERNAME|UID Match only this user's processes" //usage: "\n -n NAME Match processes with NAME" @@ -422,15 +444,19 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) opt = GETOPT32(argv, "^" "KSbqtma:n:s:u:c:x:p:" IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:") + "\0" + "K:S:K--S:S--K" /* -K or -S is required; they are mutually exclusive */ - /* -p is required if -m is given */ - /* -xpun (at least one) is required if -K is given */ + ":m?p" /* -p is required if -m is given */ + ":K?xpun" /* -xpun (at least one) is required if -K is given */ + /* (the above does not seem to be enforced by Debian, it does nothing + * if no matching is specified with -K, and it ignores ARGS + * - does not take ARGS[0] as program name to kill) + */ // /* -xa (at least one) is required if -S is given */ //WRONG: "start-stop-daemon -S -- sleep 5" is a valid invocation - /* -q turns off -v */ - "\0" - "K:S:K--S:S--K:m?p:K?xpun" - IF_FEATURE_START_STOP_DAEMON_FANCY("q-v"), + IF_FEATURE_START_STOP_DAEMON_FANCY(":q-v") /* -q turns off -v */ + , LONGOPTS &startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) -- cgit v1.2.3-55-g6feb From 73f28134fc0987474384fde345559d4b34bf5385 Mon Sep 17 00:00:00 2001 From: ejaaskel Date: Tue, 7 Nov 2023 07:12:40 +0100 Subject: start-stop-daemon: add -d DIR chdir option Add option to change the running directory before starting the process. This can be done using -d or --chdir options. Add also test cases to start-stop-daemon to test out the directory change option. function old new delta packed_usage 34602 34648 +46 start_stop_daemon_main 1107 1130 +23 start_stop_daemon_longopts 156 164 +8 .rodata 105382 105384 +2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/0 up/down: 79/0) Total: 79 bytes Signed-off-by: ejaaskel Signed-off-by: Denys Vlasenko --- TODO | 2 -- debianutils/start_stop_daemon.c | 34 +++++++++++++++++++++------------- testsuite/start-stop-daemon.tests | 20 ++++++++++++++++++++ 3 files changed, 41 insertions(+), 15 deletions(-) (limited to 'debianutils') diff --git a/TODO b/TODO index 72ae0f88d..6c7415a81 100644 --- a/TODO +++ b/TODO @@ -222,8 +222,6 @@ Minor stuff: --- unify progress_meter. wget, flash_eraseall, pipe_progress, fbsplash, setfiles. --- - support start-stop-daemon -d ---- (TODO list after discussion 11.05.2009) diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 16df67b3e..750167349 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -11,7 +11,7 @@ /* This is how it is supposed to work: -start-stop-daemon [OPTIONS] [--start|--stop] [[--] ARGS...] +start-stop-daemon [OPTIONS] [--start|--stop] [[--] ARGS] One (only) of these must be given: -S,--start Start @@ -58,13 +58,14 @@ Options which are valid for --start only: priority can be optionally specified by appending a : followed by the value. The default priority is 0. The currently supported policy values are other, fifo and rr. - -r,--chroot root Change directory and chroot to root before starting the + -r,--chroot DIR Change directory and chroot to DIR before starting the process. Please note that the pidfile is also written after the chroot. - -d,--chdir path Change directory to path before starting the process. This is - done after the chroot if the -r|--chroot option is set. When - not specified, start-stop-daemon will change directory to the + -d,--chdir DIR Change directory to DIR before starting the process. This is + done after the chroot if the -r|--chroot option is set. + When not specified, start-stop-daemon will change directory to the root directory before starting the process. + ^^^^ Seems to be false, no default "/" chdir is done. Options which are valid for --stop only: -s,--signal SIG Signal to send (default:TERM) @@ -106,7 +107,7 @@ Misc options: //kbuild:lib-$(CONFIG_START_STOP_DAEMON) += start_stop_daemon.o //usage:#define start_stop_daemon_trivial_usage -//usage: "-S|-K [OPTIONS] [-- ARGS...]" +//usage: "-S|-K [OPTIONS] [-- ARGS]" //usage:#define start_stop_daemon_full_usage "\n\n" //usage: "Search for matching processes, and then\n" //usage: "-S: start a process unless a matching process is found\n" @@ -127,6 +128,7 @@ Misc options: //usage: "\n -N N Change nice level" //usage: ) //usage: "\n -c USER[:[GRP]] Change user/group" +//usage: "\n -d DIR Change to DIR" //usage: "\n -m Write PID to pidfile specified by -p" //usage: "\n-K only:" //usage: "\n -s SIG Signal to send" @@ -160,11 +162,12 @@ enum { OPT_s = (1 << 8), // -s OPT_u = (1 << 9), // -u OPT_c = (1 << 10), // -c - OPT_x = (1 << 11), // -x - OPT_p = (1 << 12), // -p - OPT_OKNODO = (1 << 13) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o - OPT_VERBOSE = (1 << 14) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v - OPT_NICELEVEL = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N + OPT_d = (1 << 11), // -d + OPT_x = (1 << 12), // -x + OPT_p = (1 << 13), // -p + OPT_OKNODO = (1 << 14) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o + OPT_VERBOSE = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v + OPT_NICELEVEL = (1 << 16) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N }; #define QUIET (option_mask32 & OPT_QUIET) #define TEST (option_mask32 & OPT_TEST) @@ -413,6 +416,7 @@ static const char start_stop_daemon_longopts[] ALIGN1 = "signal\0" Required_argument "s" "user\0" Required_argument "u" "chuid\0" Required_argument "c" + "chdir\0" Required_argument "d" "exec\0" Required_argument "x" "pidfile\0" Required_argument "p" # if ENABLE_FEATURE_START_STOP_DAEMON_FANCY @@ -433,6 +437,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) char *signame; char *startas = NULL; char *chuid; + char *chdir; #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY // char *retry_arg = NULL; // int retries = -1; @@ -442,7 +447,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) INIT_G(); opt = GETOPT32(argv, "^" - "KSbqtma:n:s:u:c:x:p:" + "KSbqtma:n:s:u:c:d:x:p:" IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:") "\0" "K:S:K--S:S--K" @@ -458,7 +463,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_START_STOP_DAEMON_FANCY(":q-v") /* -q turns off -v */ , LONGOPTS - &startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile + &startas, &cmdname, &signame, &userspec, &chuid, &chdir, &execname, &pidfile IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) /* We accept and ignore -R / --retry */ IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL) @@ -586,6 +591,9 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) setgroups(1, &ugid.gid); } } + if (opt & OPT_d) { + xchdir(chdir); + } /* Try: * strace -oLOG start-stop-daemon -S -x /bin/usleep -a qwerty 500000 * should exec "/bin/usleep", but argv[0] should be "qwerty": diff --git a/testsuite/start-stop-daemon.tests b/testsuite/start-stop-daemon.tests index 0757b1288..e1e49ab5f 100755 --- a/testsuite/start-stop-daemon.tests +++ b/testsuite/start-stop-daemon.tests @@ -11,6 +11,21 @@ testing "start-stop-daemon -x without -a" \ "0\n" \ "" "" +testing "start-stop-daemon -x with -d on existing directory" \ + 'start-stop-daemon -S -d /tmp -x true 2>&1; echo $?' \ + "0\n" \ + "" "" + +testing "start-stop-daemon -x with -d on existing and check dir" \ + 'output=$(start-stop-daemon -S -d /tmp -x pwd); echo $output' \ + "/tmp\n" \ + "" "" + +testing "start-stop-daemon -x with --chdir on existing and check dir" \ + 'output=$(start-stop-daemon -S --chdir /tmp -x pwd); echo $output' \ + "/tmp\n" \ + "" "" + testing "start-stop-daemon -a without -x" \ 'start-stop-daemon -S -a false 2>&1; echo $?' \ "1\n" \ @@ -21,6 +36,11 @@ testing "start-stop-daemon without -x and -a" \ "1\n" \ "" "" +testing "start-stop-daemon -x with -d on non-existing directory" \ + 'start-stop-daemon -S -d /non-existent -x true > /dev/null 2>&1; echo $?' \ + "1\n" \ + "" "" + # This runs /bin/false with argv[0..2] of { "qwerty", "false", NULL }. # # Unfortunately, this does not actually check argv[0] correctness, -- cgit v1.2.3-55-g6feb From da8d1d84fd46e61eec0772ff339fde0952777a5f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 7 Nov 2023 15:59:11 +0100 Subject: start-stop-daemon: update comment, no code changes Signed-off-by: Denys Vlasenko --- debianutils/start_stop_daemon.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'debianutils') diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 750167349..8573c6990 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -17,6 +17,10 @@ One (only) of these must be given: -S,--start Start -K,--stop Stop -T,--status Check for the existence of a process, return exitcode (since version 1.16.1) + 0 - program is running + 1 - program is not running and the pid file exists. + 3 - program is not running. + 4 - can't determine program status. Search for matching processes. If --stop is given, stop all matching processes (by sending a signal). @@ -45,9 +49,10 @@ Options which are valid for --start only: -a,--startas NAME argv[0] (defaults to EXECUTABLE) -b,--background Put process into background -O,--output FILE Redirect stdout and stderr to FILE when forcing the - daemon into the background (since version 1.20.6). Only - relevant when using --background. - Probably O_CREAT|O_TRUNC? What if execv fails - where does error msg go? "Old" stderr? FILE? Nowhere? + daemon into the background (since version 1.20.6). + Requires --background and absolute pathname (tested with 1.21.22). + Uses O_CREAT|O_APPEND! + If execv fails, error message goes to FILE. -N,--nicelevel N Add N to process' nice level -c,--chuid USER[:[GRP]] Change to specified user [and group] -m,--make-pidfile Write PID to the pidfile @@ -66,6 +71,11 @@ Options which are valid for --start only: When not specified, start-stop-daemon will change directory to the root directory before starting the process. ^^^^ Seems to be false, no default "/" chdir is done. + Tested -S with 1.21.22: + "start-stop-daemon -S -n pwd -a /bin/pwd" is the minimum needed to run pwd. + "start-stop-daemon -S -n pwd -x /bin/pwd" works too. + "start-stop-daemon -S -a /bin/pwd -x /bin/pwd" works too. + Earlier versions were less picky (which?) Options which are valid for --stop only: -s,--signal SIG Signal to send (default:TERM) -- cgit v1.2.3-55-g6feb From 389c0458da7d6e941886ea3b846c98cfd63dfdd3 Mon Sep 17 00:00:00 2001 From: Louai Al-Khanji Date: Tue, 7 Nov 2023 21:41:32 +0100 Subject: start-stop-daemon: implement option -O|--output If specified redirect command stdout and stderr to given pathname. function old new delta start_stop_daemon_main 1130 1186 +56 start_stop_daemon_longopts 164 173 +9 packed_usage 34653 34656 +3 .rodata 105384 105386 +2 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/0 up/down: 70/0) Total: 70 bytes Signed-off-by: Louai Al-Khanji Signed-off-by: Denys Vlasenko --- debianutils/start_stop_daemon.c | 46 ++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'debianutils') diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 8573c6990..56a933fcb 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -18,9 +18,9 @@ One (only) of these must be given: -K,--stop Stop -T,--status Check for the existence of a process, return exitcode (since version 1.16.1) 0 - program is running - 1 - program is not running and the pid file exists. - 3 - program is not running. - 4 - can't determine program status. + 1 - program is not running and the pid file exists + 3 - program is not running + 4 - can't determine program status Search for matching processes. If --stop is given, stop all matching processes (by sending a signal). @@ -41,6 +41,7 @@ with /proc/$PID/exe or argv[0] (comm can't be matched, it never contains path)] Unlike -n, we match against the full path: "ntpd" != "./ntpd" != "/path/to/ntpd" -p,--pidfile PID_FILE Look for processes with PID from this file + --pid PID Look for process with this pid (since version 1.17.6) --ppid PPID Look for processes with parent pid (since version 1.17.7) Options which are valid for --start only: @@ -72,10 +73,10 @@ Options which are valid for --start only: root directory before starting the process. ^^^^ Seems to be false, no default "/" chdir is done. Tested -S with 1.21.22: - "start-stop-daemon -S -n pwd -a /bin/pwd" is the minimum needed to run pwd. - "start-stop-daemon -S -n pwd -x /bin/pwd" works too. - "start-stop-daemon -S -a /bin/pwd -x /bin/pwd" works too. - Earlier versions were less picky (which?) + "start-stop-daemon -S -x /bin/pwd" is the minimum needed to run pwd. + "start-stop-daemon -S -a /bin/pwd -n pwd" works too. + "start-stop-daemon -S -a /bin/pwd" does NOT work. + Earlier versions were less picky (which? Or is it only Gentoo's clone?) Options which are valid for --stop only: -s,--signal SIG Signal to send (default:TERM) @@ -110,6 +111,7 @@ Misc options: //config: -o|--oknodo ignored since we exit with 0 anyway //config: -v|--verbose //config: -N|--nicelevel N +//config: -O|--output FILE //applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon)) /* not NOEXEC: uses bb_common_bufsiz1 */ @@ -147,8 +149,9 @@ Misc options: //usage: IF_FEATURE_START_STOP_DAEMON_FANCY( //usage: "\n -o Exit with status 0 if nothing is done" //usage: "\n -v Verbose" -//usage: ) //usage: "\n -q Quiet" +//usage: "\n -O PILE Append stdout and stderr to FILE" +//usage: ) /* Override ENABLE_FEATURE_PIDFILE */ #define WANT_PIDFILE 1 @@ -178,6 +181,7 @@ enum { OPT_OKNODO = (1 << 14) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o OPT_VERBOSE = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v OPT_NICELEVEL = (1 << 16) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N + OPT_OUTPUT = (1 << 17) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -O }; #define QUIET (option_mask32 & OPT_QUIET) #define TEST (option_mask32 & OPT_TEST) @@ -420,6 +424,7 @@ static const char start_stop_daemon_longopts[] ALIGN1 = "oknodo\0" No_argument "o" "verbose\0" No_argument "v" "nicelevel\0" Required_argument "N" + "output\0" Required_argument "O" # endif "startas\0" Required_argument "a" "name\0" Required_argument "n" @@ -452,33 +457,42 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) // char *retry_arg = NULL; // int retries = -1; char *opt_N; + char *output; #endif INIT_G(); opt = GETOPT32(argv, "^" "KSbqtma:n:s:u:c:d:x:p:" - IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:") + IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:O:R:") "\0" "K:S:K--S:S--K" /* -K or -S is required; they are mutually exclusive */ ":m?p" /* -p is required if -m is given */ ":K?xpun" /* -xpun (at least one) is required if -K is given */ - /* (the above does not seem to be enforced by Debian, it does nothing + /* (the above does not seem to be enforced by Gentoo, it does nothing * if no matching is specified with -K, and it ignores ARGS * - does not take ARGS[0] as program name to kill) */ -// /* -xa (at least one) is required if -S is given */ -//WRONG: "start-stop-daemon -S -- sleep 5" is a valid invocation +// ":S?xa" /* -xa (at least one) is required if -S is given */ +//Gentoo clone: "start-stop-daemon -S -- sleep 5" is a valid invocation IF_FEATURE_START_STOP_DAEMON_FANCY(":q-v") /* -q turns off -v */ , LONGOPTS &startas, &cmdname, &signame, &userspec, &chuid, &chdir, &execname, &pidfile IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) + IF_FEATURE_START_STOP_DAEMON_FANCY(,&output) /* We accept and ignore -R / --retry */ IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL) ); +//-O requires --background and absolute pathname (tested with 1.21.22). +//We don't bother requiring that (smaller code): +//#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY +// if ((opt & OPT_OUTPUT) && !(opt & OPT_BACKGROUND)) +// bb_show_usage(); +//#endif + if (opt & OPT_s) { signal_nr = get_signum(signame); if (signal_nr < 0) bb_show_usage(); @@ -604,6 +618,14 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_d) { xchdir(chdir); } +#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY + if (opt & OPT_OUTPUT) { + int outfd = xopen(output, O_WRONLY | O_CREAT | O_APPEND); + xmove_fd(outfd, STDOUT_FILENO); + xdup2(STDOUT_FILENO, STDERR_FILENO); + /* on execv error, the message goes to -O file. This is intended */ + } +#endif /* Try: * strace -oLOG start-stop-daemon -S -x /bin/usleep -a qwerty 500000 * should exec "/bin/usleep", but argv[0] should be "qwerty": -- cgit v1.2.3-55-g6feb From 2de67a62e812f2e4d13280f2b78712b6d344cfb7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 8 Nov 2023 12:36:11 +0100 Subject: start-stop-daemon: typo fix Signed-off-by: Denys Vlasenko --- debianutils/start_stop_daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debianutils') diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 56a933fcb..04ba8baa7 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -150,7 +150,7 @@ Misc options: //usage: "\n -o Exit with status 0 if nothing is done" //usage: "\n -v Verbose" //usage: "\n -q Quiet" -//usage: "\n -O PILE Append stdout and stderr to FILE" +//usage: "\n -O FILE Append stdout and stderr to FILE" //usage: ) /* Override ENABLE_FEATURE_PIDFILE */ -- cgit v1.2.3-55-g6feb From 58ca629fd27cd9d7f91a8ea90435cdb3f15381aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 8 Nov 2023 14:07:20 +0100 Subject: start-stop-daemon: do not lose error messages with -b function old new delta start_stop_daemon_main 1186 1206 +20 bb_daemonize_or_rexec 196 212 +16 bb_banner 47 46 -1 packed_usage 34656 34645 -11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/2 up/down: 36/-12) Total: 24 bytes Signed-off-by: Denys Vlasenko --- debianutils/start_stop_daemon.c | 57 ++++++++++++++++++++--------------------- include/libbb.h | 11 +++++--- libbb/vfork_daemon_rexec.c | 9 ++++--- 3 files changed, 41 insertions(+), 36 deletions(-) (limited to 'debianutils') 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: done after the chroot if the -r|--chroot option is set. When not specified, start-stop-daemon will change directory to the root directory before starting the process. - ^^^^ Seems to be false, no default "/" chdir is done. + ^^^^ Gentoo does not have the default chdir("/"). Debian does. Tested -S with 1.21.22: "start-stop-daemon -S -x /bin/pwd" is the minimum needed to run pwd. "start-stop-daemon -S -a /bin/pwd -n pwd" works too. @@ -111,7 +111,6 @@ Misc options: //config: -o|--oknodo ignored since we exit with 0 anyway //config: -v|--verbose //config: -N|--nicelevel N -//config: -O|--output FILE //applet:IF_START_STOP_DAEMON(APPLET_ODDNAME(start-stop-daemon, start_stop_daemon, BB_DIR_SBIN, BB_SUID_DROP, start_stop_daemon)) /* not NOEXEC: uses bb_common_bufsiz1 */ @@ -136,6 +135,7 @@ Misc options: //usage: "\n -x EXECUTABLE Program to run" //usage: "\n -a NAME Zeroth argument" //usage: "\n -b Background" +//usage: "\n -O FILE Append stdout and stderr to FILE" //usage: IF_FEATURE_START_STOP_DAEMON_FANCY( //usage: "\n -N N Change nice level" //usage: ) @@ -150,7 +150,6 @@ Misc options: //usage: "\n -o Exit with status 0 if nothing is done" //usage: "\n -v Verbose" //usage: "\n -q Quiet" -//usage: "\n -O FILE Append stdout and stderr to FILE" //usage: ) /* Override ENABLE_FEATURE_PIDFILE */ @@ -178,20 +177,20 @@ enum { OPT_d = (1 << 11), // -d OPT_x = (1 << 12), // -x OPT_p = (1 << 13), // -p - OPT_OKNODO = (1 << 14) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o - OPT_VERBOSE = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v - OPT_NICELEVEL = (1 << 16) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N - OPT_OUTPUT = (1 << 17) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -O + OPT_OUTPUT = (1 << 14), // -O + OPT_OKNODO = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o + OPT_VERBOSE = (1 << 16) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v + OPT_NICELEVEL = (1 << 17) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N }; #define QUIET (option_mask32 & OPT_QUIET) #define TEST (option_mask32 & OPT_TEST) struct globals { struct pid_list *found_procs; - char *userspec; - char *cmdname; - char *execname; - char *pidfile; + const char *userspec; + const char *cmdname; + const char *execname; + const char *pidfile; char *execname_cmpbuf; unsigned execname_sizeof; int user_id; @@ -361,7 +360,7 @@ static void do_procinit(void) static int do_stop(void) { - char *what; + const char *what; struct pid_list *p; int killed = 0; @@ -408,7 +407,7 @@ static int do_stop(void) } ret: if (ENABLE_FEATURE_CLEAN_UP) - free(what); + free((char *)what); return killed; } @@ -449,22 +448,22 @@ int start_stop_daemon_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) { unsigned opt; - char *signame; - char *startas = NULL; + const char *signame; + const char *startas = NULL; char *chuid; - char *chdir; + const char *chdir; + const char *output = NULL; #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY -// char *retry_arg = NULL; +// const char *retry_arg = NULL; // int retries = -1; - char *opt_N; - char *output; + const char *opt_N; #endif INIT_G(); opt = GETOPT32(argv, "^" - "KSbqtma:n:s:u:c:d:x:p:" - IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:O:R:") + "KSbqtma:n:s:u:c:d:x:p:O:" + IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:") "\0" "K:S:K--S:S--K" /* -K or -S is required; they are mutually exclusive */ @@ -479,9 +478,8 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) IF_FEATURE_START_STOP_DAEMON_FANCY(":q-v") /* -q turns off -v */ , LONGOPTS - &startas, &cmdname, &signame, &userspec, &chuid, &chdir, &execname, &pidfile + &startas, &cmdname, &signame, &userspec, &chuid, &chdir, &execname, &pidfile, &output IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N) - IF_FEATURE_START_STOP_DAEMON_FANCY(,&output) /* We accept and ignore -R / --retry */ IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL) ); @@ -519,7 +517,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) } if (!startas) /* -a is not given: use -x EXECUTABLE or argv[0] */ startas = execname; - *--argv = startas; + *--argv = (char *)startas; } if (execname) { G.execname_sizeof = strlen(execname) + 1; @@ -578,8 +576,11 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) } /* Child */ setsid(); /* detach from controlling tty */ - /* Redirect stdio to /dev/null, close extra FDs */ - bb_daemon_helper(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS); + /* Redirect stdin to /dev/null, close extra FDs */ + /* Testcase: "start-stop-daemon -Sb -d /does/not/exist usleep 1" should not eat error message */ + bb_daemon_helper(DAEMON_DEVNULL_STDIN + DAEMON_CLOSE_EXTRA_FDS); + if (!output) + output = bb_dev_null; /* redirect output just before execv */ /* On Linux, session leader can acquire ctty * unknowingly, by opening a tty. * Prevent this: stop being a session leader. @@ -618,14 +619,12 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_d) { xchdir(chdir); } -#if ENABLE_FEATURE_START_STOP_DAEMON_FANCY - if (opt & OPT_OUTPUT) { + if (output) { int outfd = xopen(output, O_WRONLY | O_CREAT | O_APPEND); xmove_fd(outfd, STDOUT_FILENO); xdup2(STDOUT_FILENO, STDERR_FILENO); /* on execv error, the message goes to -O file. This is intended */ } -#endif /* Try: * strace -oLOG start-stop-daemon -S -x /bin/usleep -a qwerty 500000 * should exec "/bin/usleep", but argv[0] should be "qwerty": diff --git a/include/libbb.h b/include/libbb.h index 0883fb565..ef5d04713 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1309,10 +1309,12 @@ void _exit_FAILURE(void) NORETURN FAST_FUNC; */ enum { DAEMON_CHDIR_ROOT = 1 << 0, - DAEMON_DEVNULL_STDIO = 1 << 1, - DAEMON_CLOSE_EXTRA_FDS = 1 << 2, - DAEMON_ONLY_SANITIZE = 1 << 3, /* internal use */ - //DAEMON_DOUBLE_FORK = 1 << 4, /* double fork to avoid controlling tty */ + DAEMON_DEVNULL_STDIN = 1 << 1, + DAEMON_DEVNULL_OUTERR = 2 << 1, + DAEMON_DEVNULL_STDIO = 3 << 1, + DAEMON_CLOSE_EXTRA_FDS = 1 << 3, + DAEMON_ONLY_SANITIZE = 1 << 4, /* internal use */ + //DAEMON_DOUBLE_FORK = 1 << 5, /* double fork to avoid controlling tty */ }; #if BB_MMU enum { re_execed = 0 }; @@ -1335,6 +1337,7 @@ enum { # define bb_daemonize(a) BUG_bb_daemonize_is_unavailable_on_nommu() #endif void bb_daemonize_or_rexec(int flags, char **argv) FAST_FUNC; +/* Unlike bb_daemonize_or_rexec, these two helpers do not setsid: */ void bb_sanitize_stdio(void) FAST_FUNC; #define bb_daemon_helper(arg) bb_daemonize_or_rexec((arg) | DAEMON_ONLY_SANITIZE, NULL) /* Clear dangerous stuff, set PATH. Return 1 if was run by different user. */ diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index a570ddbf2..2055c4b71 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -296,9 +296,12 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv) } if (flags & DAEMON_DEVNULL_STDIO) { - xdup2(fd, 0); - xdup2(fd, 1); - xdup2(fd, 2); + if (flags & DAEMON_DEVNULL_STDIN) + xdup2(fd, 0); + if (flags & DAEMON_DEVNULL_OUTERR) { + xdup2(fd, 1); + xdup2(fd, 2); + } } else { /* have 0,1,2 open at least to /dev/null */ while ((unsigned)fd < 2) -- cgit v1.2.3-55-g6feb From 59cf2c23aebaeed29fd5a8a0f112e01c1f1dd45f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 8 Nov 2023 14:42:00 +0100 Subject: start-stop-daemon: make --output not depend on FANCY Signed-off-by: Denys Vlasenko --- debianutils/start_stop_daemon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'debianutils') diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index 00fa0a82c..271bc4edf 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c @@ -419,11 +419,11 @@ static const char start_stop_daemon_longopts[] ALIGN1 = "quiet\0" No_argument "q" "test\0" No_argument "t" "make-pidfile\0" No_argument "m" + "output\0" Required_argument "O" # if ENABLE_FEATURE_START_STOP_DAEMON_FANCY "oknodo\0" No_argument "o" "verbose\0" No_argument "v" "nicelevel\0" Required_argument "N" - "output\0" Required_argument "O" # endif "startas\0" Required_argument "a" "name\0" Required_argument "n" -- cgit v1.2.3-55-g6feb