X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=libbb%2Fvfork_daemon_rexec.c;h=9624efbb95b3de09f2606ced75fba4dfbc4aa17d;hb=d50dda8c3501af9d593cd11272a15b480864a01c;hp=1d6817ee654deadf104e77566e6449d0909a8525;hpb=1aa7e477b1b727db77cac2d717f0fcca40587f78;p=oweals%2Fbusybox.git diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 1d6817ee6..9624efbb9 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -66,6 +66,21 @@ pid_t xspawn(char **argv) return pid; } +int safe_waitpid(int pid, int *wstat, int options) +{ + int r; + + do + r = waitpid(pid, wstat, options); + while ((r == -1) && (errno == EINTR)); + return r; +} + +int 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 wait4pid(int pid) { @@ -76,7 +91,7 @@ int wait4pid(int pid) /* we expect errno to be already set from failed [v]fork/exec */ return -1; } - if (waitpid(pid, &status, 0) == -1) + if (safe_waitpid(pid, &status, 0) == -1) return -1; if (WIFEXITED(status)) return WEXITSTATUS(status); @@ -85,21 +100,6 @@ int wait4pid(int pid) return 0; } -int wait_nohang(int *wstat) -{ - return waitpid(-1, wstat, WNOHANG); -} - -int wait_pid(int *wstat, int pid) -{ - int r; - - do - r = waitpid(pid, wstat, 0); - while ((r == -1) && (errno == EINTR)); - return r; -} - #if ENABLE_FEATURE_PREFER_APPLETS void save_nofork_data(struct nofork_save_area *save) { @@ -126,12 +126,14 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** applet_name = APPLET_NAME(applet_no); xfunc_error_retval = EXIT_FAILURE; - /*option_mask32 = 0; - not needed */ - /* special flag for xfunc_die(). If xfunc will "die" + + /* Special flag for xfunc_die(). If xfunc will "die" * in NOFORK applet, xfunc_die() sees negative * die_sleep and longjmp here instead. */ die_sleep = -1; + /* option_mask32 = 0; - not needed */ + argc = 1; while (argv[argc]) argc++; @@ -143,7 +145,16 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** char *tmp_argv[argc+1]; memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); /* Finally we can call NOFORK applet's main() */ - rc = applet_mains[applet_no](argc, tmp_argv); + rc = applet_main[applet_no](argc, tmp_argv); + + /* The whole reason behind nofork_save_area is that _main + * may exit non-locally! For example, in hush Ctrl-Z tries + * (modulo bugs) to dynamically create a child (backgrounded task) + * if it detects that Ctrl-Z was pressed when a NOFORK was running. + * Testcase: interactive "rm -i". + * Don't fool yourself into thinking "and _main() returns + * quickly here" and removing "useless" nofork_save_area code. */ + } else { /* xfunc died in NOFORK applet */ /* in case they meant to return 0... */ if (rc == -2222) @@ -152,7 +163,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** /* Restoring globals */ restore_nofork_data(old); - return rc; + return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ } int run_nofork_applet(int applet_no, char **argv) @@ -219,7 +230,7 @@ void forkexit_or_rexec(char **argv) if (pid < 0) /* wtf? */ bb_perror_msg_and_die("vfork"); if (pid) /* parent */ - exit(0); + exit(EXIT_SUCCESS); /* child - re-exec ourself */ re_exec(argv); } @@ -233,7 +244,7 @@ void forkexit_or_rexec(void) if (pid < 0) /* wtf? */ bb_perror_msg_and_die("fork"); if (pid) /* parent */ - exit(0); + exit(EXIT_SUCCESS); /* child */ } #define forkexit_or_rexec(argv) forkexit_or_rexec()