aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-11-08 14:07:20 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2023-11-08 14:07:20 +0100
commit58ca629fd27cd9d7f91a8ea90435cdb3f15381aa (patch)
tree6cd26e1bd56e7eed350ff8fa3d4aeecf58ef3a22
parent2de67a62e812f2e4d13280f2b78712b6d344cfb7 (diff)
downloadbusybox-w32-58ca629fd27cd9d7f91a8ea90435cdb3f15381aa.tar.gz
busybox-w32-58ca629fd27cd9d7f91a8ea90435cdb3f15381aa.tar.bz2
busybox-w32-58ca629fd27cd9d7f91a8ea90435cdb3f15381aa.zip
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 <vda.linux@googlemail.com>
-rw-r--r--debianutils/start_stop_daemon.c57
-rw-r--r--include/libbb.h11
-rw-r--r--libbb/vfork_daemon_rexec.c9
3 files changed, 41 insertions, 36 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
189struct globals { 188struct 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
362static int do_stop(void) 361static 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;
449int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) 448int 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":
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;
1309 */ 1309 */
1310enum { 1310enum {
1311 DAEMON_CHDIR_ROOT = 1 << 0, 1311 DAEMON_CHDIR_ROOT = 1 << 0,
1312 DAEMON_DEVNULL_STDIO = 1 << 1, 1312 DAEMON_DEVNULL_STDIN = 1 << 1,
1313 DAEMON_CLOSE_EXTRA_FDS = 1 << 2, 1313 DAEMON_DEVNULL_OUTERR = 2 << 1,
1314 DAEMON_ONLY_SANITIZE = 1 << 3, /* internal use */ 1314 DAEMON_DEVNULL_STDIO = 3 << 1,
1315 //DAEMON_DOUBLE_FORK = 1 << 4, /* double fork to avoid controlling tty */ 1315 DAEMON_CLOSE_EXTRA_FDS = 1 << 3,
1316 DAEMON_ONLY_SANITIZE = 1 << 4, /* internal use */
1317 //DAEMON_DOUBLE_FORK = 1 << 5, /* double fork to avoid controlling tty */
1316}; 1318};
1317#if BB_MMU 1319#if BB_MMU
1318 enum { re_execed = 0 }; 1320 enum { re_execed = 0 };
@@ -1335,6 +1337,7 @@ enum {
1335# define bb_daemonize(a) BUG_bb_daemonize_is_unavailable_on_nommu() 1337# define bb_daemonize(a) BUG_bb_daemonize_is_unavailable_on_nommu()
1336#endif 1338#endif
1337void bb_daemonize_or_rexec(int flags, char **argv) FAST_FUNC; 1339void bb_daemonize_or_rexec(int flags, char **argv) FAST_FUNC;
1340/* Unlike bb_daemonize_or_rexec, these two helpers do not setsid: */
1338void bb_sanitize_stdio(void) FAST_FUNC; 1341void bb_sanitize_stdio(void) FAST_FUNC;
1339#define bb_daemon_helper(arg) bb_daemonize_or_rexec((arg) | DAEMON_ONLY_SANITIZE, NULL) 1342#define bb_daemon_helper(arg) bb_daemonize_or_rexec((arg) | DAEMON_ONLY_SANITIZE, NULL)
1340/* Clear dangerous stuff, set PATH. Return 1 if was run by different user. */ 1343/* 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)
296 } 296 }
297 297
298 if (flags & DAEMON_DEVNULL_STDIO) { 298 if (flags & DAEMON_DEVNULL_STDIO) {
299 xdup2(fd, 0); 299 if (flags & DAEMON_DEVNULL_STDIN)
300 xdup2(fd, 1); 300 xdup2(fd, 0);
301 xdup2(fd, 2); 301 if (flags & DAEMON_DEVNULL_OUTERR) {
302 xdup2(fd, 1);
303 xdup2(fd, 2);
304 }
302 } else { 305 } else {
303 /* have 0,1,2 open at least to /dev/null */ 306 /* have 0,1,2 open at least to /dev/null */
304 while ((unsigned)fd < 2) 307 while ((unsigned)fd < 2)