diff options
Diffstat (limited to 'libbb/vfork_daemon_rexec.c')
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 144 |
1 files changed, 46 insertions, 98 deletions
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index dabd1a6..cf88a2b 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -102,120 +102,68 @@ int wait_pid(int *wstat, int pid) int spawn_and_wait(char **argv) { +#if ENABLE_FEATURE_EXEC_PREFER_APPLETS int rc; + const struct bb_applet *a = find_applet_by_name(argv[0]); -#if ENABLE_FEATURE_EXEC_PREFER_APPLETS - { - const struct bb_applet *a = find_applet_by_name(argv[0]); - if (a && (a->nofork + if (a && (a->nofork #ifndef BB_NOMMU - || a->noexec /* NOEXEC cannot be used on NOMMU */ + || a->noexec /* NOEXEC cannot be used on NOMMU */ #endif - )) { - int argc = 1; - char **pp = argv; - while (*++pp) - argc++; + )) { + int argc = 1; + char **pp = argv; + while (*++pp) + argc++; #ifndef BB_NOMMU - if (a->nofork) + if (a->nofork) #endif - { - int old_sleep = die_sleep; - int old_x = xfunc_error_retval; - die_sleep = -1; /* special flag */ - /* xfunc_die() checks for it */ - - rc = setjmp(die_jmp); - if (!rc) { - const struct bb_applet *old_a = current_applet; - current_applet = a; - applet_name = a->name; + { + int old_sleep = die_sleep; + int old_x = xfunc_error_retval; + die_sleep = -1; /* special flag */ + /* xfunc_die() checks for it */ + + rc = setjmp(die_jmp); + if (!rc) { + const struct bb_applet *old_a = current_applet; + current_applet = a; + applet_name = a->name; // what else should we save/restore? - rc = a->main(argc, argv); - current_applet = old_a; - applet_name = old_a->name; - } else { - /* xfunc died in NOFORK applet */ - if (rc == -111) - rc = 0; - } - - die_sleep = old_sleep; - xfunc_error_retval = old_x; - return rc; +// TODO: what if applet will mangle argv vector? +// xargs needs argv untouched because it frees the vector! +// shouldn't we pass a copy? + rc = a->main(argc, argv); + current_applet = old_a; + applet_name = old_a->name; + } else { + /* xfunc died in NOFORK applet */ + if (rc == -111) + rc = 0; } + + die_sleep = old_sleep; + xfunc_error_retval = old_x; + return rc; + } #ifndef BB_NOMMU /* MMU only */ - /* a->noexec is true */ - rc = fork(); - if (rc) - goto w; - /* child */ - current_applet = a; - run_current_applet_and_exit(argc, argv); + /* a->noexec is true */ + rc = fork(); + if (rc) + goto w; + /* child */ + current_applet = a; + run_current_applet_and_exit(argc, argv); #endif - } - } rc = spawn(argv); w: -#else /* !FEATURE_EXEC_PREFER_APPLETS */ - rc = spawn(argv); -#endif /* FEATURE_EXEC_PREFER_APPLETS */ return wait4pid(rc); -} - - -#if 0 //ndef BB_NOMMU -// Die with an error message if we can't daemonize. -void xdaemon(int nochdir, int noclose) -{ - if (daemon(nochdir, noclose)) - bb_perror_msg_and_die("daemon"); -} +#else /* !FEATURE_EXEC_PREFER_APPLETS */ + return wait4pid(spawn(argv)); #endif - -#if 0 // def BB_NOMMU -void vfork_daemon_rexec(int nochdir, int noclose, char **argv) -{ - int fd; - - /* Maybe we are already re-execed and come here again? */ - if (re_execed) - return; - - setsid(); - - if (!nochdir) - xchdir("/"); - - if (!noclose) { - /* if "/dev/null" doesn't exist, bail out! */ - fd = xopen(bb_dev_null, O_RDWR); - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - while (fd > 2) - close(fd--); - } - - switch (vfork()) { - case 0: /* child */ - /* Make certain we are not a session leader, or else we - * might reacquire a controlling terminal */ - if (vfork()) - _exit(0); - /* High-order bit of first char in argv[0] is a hidden - * "we have (alrealy) re-execed, don't do it again" flag */ - argv[0][0] |= 0x80; - execv(CONFIG_BUSYBOX_EXEC_PATH, argv); - bb_perror_msg_and_die("exec %s", CONFIG_BUSYBOX_EXEC_PATH); - case -1: /* error */ - bb_perror_msg_and_die("vfork"); - default: /* parent */ - exit(0); - } } -#endif /* BB_NOMMU */ + #ifdef BB_NOMMU void forkexit_or_rexec(char **argv) |