X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=libbb%2Fvfork_daemon_rexec.c;h=9624efbb95b3de09f2606ced75fba4dfbc4aa17d;hb=d50dda8c3501af9d593cd11272a15b480864a01c;hp=3a386c5c9b517248fa9203602ddc1d56119410e5;hpb=c4e4be9414f8c7318c0f87b0838d88bb9ef75732;p=oweals%2Fbusybox.git diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 3a386c5c9..9624efbb9 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -98,11 +98,6 @@ int wait4pid(int pid) if (WIFSIGNALED(status)) return WTERMSIG(status) + 1000; return 0; - if (WIFEXITED(status)) - return WEXITSTATUS(status); - if (WIFSIGNALED(status)) - return WTERMSIG(status) + 1000; - return 0; } #if ENABLE_FEATURE_PREFER_APPLETS @@ -137,26 +132,6 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** * die_sleep and longjmp here instead. */ die_sleep = -1; - /* Reset the libc getopt() function, which keeps internal state. - * - * BSD-derived getopt() functions require that optind be reset 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 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 ump 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 /* option_mask32 = 0; - not needed */ argc = 1; @@ -171,6 +146,15 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); /* Finally we can call NOFORK applet's main() */ 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) @@ -179,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) @@ -246,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); } @@ -260,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()