X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=libbb%2Fvfork_daemon_rexec.c;h=9be90172290ef67bfd611c64371befa24c2e56b8;hb=d7171c114028815df4e92f9c26875f1d60c6af2a;hp=da0dc03e58b236f38c360a383f75e30aea185bb1;hpb=d48e81f0cda73aca49cd852212a62e879cf35b86;p=oweals%2Fbusybox.git diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index da0dc03e5..9be901722 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -15,7 +15,6 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include #include "busybox.h" /* uses applet tables */ /* This does a fork/exec in one call, using vfork(). Returns PID of new child, @@ -26,7 +25,7 @@ pid_t FAST_FUNC spawn(char **argv) volatile int failed; pid_t pid; -// Ain't it a good place to fflush(NULL)? + fflush_all(); /* Be nice to nommu machines. */ failed = 0; @@ -42,6 +41,8 @@ pid_t FAST_FUNC spawn(char **argv) * (but don't run atexit() stuff, which would screw up parent.) */ failed = errno; + /* mount, for example, does not want the message */ + /*bb_perror_msg("can't execute '%s'", argv[0]);*/ _exit(111); } /* parent */ @@ -66,9 +67,9 @@ pid_t FAST_FUNC xspawn(char **argv) return pid; } -int FAST_FUNC safe_waitpid(int pid, int *wstat, int options) +pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options) { - int r; + pid_t r; do r = waitpid(pid, wstat, options); @@ -76,13 +77,13 @@ int FAST_FUNC safe_waitpid(int pid, int *wstat, int options) return r; } -int FAST_FUNC wait_any_nohang(int *wstat) +pid_t FAST_FUNC wait_any_nohang(int *wstat) { return safe_waitpid(-1, wstat, WNOHANG); } // Wait for the specified child PID to exit, returning child's error return. -int FAST_FUNC wait4pid(int pid) +int FAST_FUNC wait4pid(pid_t pid) { int status; @@ -125,6 +126,7 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n int rc, argc; applet_name = APPLET_NAME(applet_no); + xfunc_error_retval = EXIT_FAILURE; /* Special flag for xfunc_die(). If xfunc will "die" @@ -132,7 +134,30 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n * die_sleep and longjmp here instead. */ die_sleep = -1; - /* option_mask32 = 0; - not needed */ + /* In case getopt() or getopt32() was already called: + * reset the libc getopt() function, which keeps internal state. + * + * BSD-derived getopt() functions require that optind be set to 1 in + * order to reset getopt() state. This used to be generally accepted + * way of resetting getopt(). However, glibc's getopt() + * has additional getopt() state beyond optind, and requires that + * optind be set to zero to reset its state. So the unfortunate state of + * affairs is that BSD-derived versions of getopt() misbehave if + * optind is set to 0 in order to reset getopt(), and glibc's getopt() + * will core dump if optind is set 1 in order to reset getopt(). + * + * More modern versions of BSD require that optreset be set to 1 in + * order to reset getopt(). Sigh. Standards, anyone? + */ +#ifdef __GLIBC__ + optind = 0; +#else /* BSD style */ + optind = 1; + /* optreset = 1; */ +#endif + /* optarg = NULL; opterr = 1; optopt = 63; - do we need this too? */ + /* (values above are what they initialized to in glibc and uclibc) */ + /* option_mask32 = 0; - not needed, no applet depends on it being 0 */ argc = 1; while (argv[argc]) @@ -161,8 +186,16 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n rc = 0; } - /* Restoring globals */ + /* Restoring some globals */ restore_nofork_data(old); + + /* Other globals can be simply reset to defaults */ +#ifdef __GLIBC__ + optind = 0; +#else /* BSD style */ + optind = 1; +#endif + return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ } @@ -219,35 +252,32 @@ void FAST_FUNC re_exec(char **argv) bb_perror_msg_and_die("exec %s", bb_busybox_exec_path); } -void FAST_FUNC forkexit_or_rexec(char **argv) +pid_t FAST_FUNC fork_or_rexec(char **argv) { pid_t pid; /* Maybe we are already re-execed and come here again? */ if (re_execed) - return; - + return 0; pid = vfork(); if (pid < 0) /* wtf? */ bb_perror_msg_and_die("vfork"); if (pid) /* parent */ - exit(EXIT_SUCCESS); + return pid; /* child - re-exec ourself */ re_exec(argv); } #else /* Dance around (void)...*/ -#undef forkexit_or_rexec -void FAST_FUNC forkexit_or_rexec(void) +#undef fork_or_rexec +pid_t FAST_FUNC fork_or_rexec(void) { pid_t pid; pid = fork(); if (pid < 0) /* wtf? */ bb_perror_msg_and_die("fork"); - if (pid) /* parent */ - exit(EXIT_SUCCESS); - /* child */ + return pid; } -#define forkexit_or_rexec(argv) forkexit_or_rexec() +#define fork_or_rexec(argv) fork_or_rexec() #endif /* Due to a #define in libbb.h on MMU systems we actually have 1 argument - @@ -278,7 +308,8 @@ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv) fd = dup(fd); /* have 0,1,2 open at least to /dev/null */ if (!(flags & DAEMON_ONLY_SANITIZE)) { - forkexit_or_rexec(argv); + if (fork_or_rexec(argv)) + exit(EXIT_SUCCESS); /* parent */ /* if daemonizing, make sure we detach from stdio & ctty */ setsid(); dup2(fd, 0);