#define BB_EXECVP(prog,cmd) execvp(prog,cmd)
#define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__)
#endif
-int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
+void BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC;
+void exec_prog_or_SHELL(char **argv) NORETURN FAST_FUNC;
-/* xvfork() can't be a _function_, return after vfork mangles stack
+/* xvfork() can't be a _function_, return after vfork in child mangles stack
* in the parent. It must be a macro. */
#define xvfork() \
({ \
#if BB_MMU
pid_t xfork(void) FAST_FUNC;
#endif
+void xvfork_parent_waits_and_exits(void) FAST_FUNC;
/* NOMMU friendy fork+exec: */
pid_t spawn(char **argv) FAST_FUNC;
}
#endif
-int FAST_FUNC BB_EXECVP_or_die(char **argv)
+void FAST_FUNC BB_EXECVP_or_die(char **argv)
{
BB_EXECVP(argv[0], argv);
/* SUSv3-mandated exit codes */
xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
bb_perror_msg_and_die("can't execute '%s'", argv[0]);
}
+
+/* Typical idiom for applets which exec *optional* PROG [ARGS] */
+void FAST_FUNC exec_prog_or_SHELL(char **argv)
+{
+ if (argv[0]) {
+ BB_EXECVP_or_die(argv);
+ }
+ run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
+}
return pid;
}
#endif
+
+void FAST_FUNC xvfork_parent_waits_and_exits(void)
+{
+ pid_t pid;
+
+ fflush_all();
+ pid = xvfork();
+ if (pid > 0) {
+ /* Parent */
+ int exit_status = wait_for_exitstatus(pid);
+ if (WIFSIGNALED(exit_status))
+ kill_myself_with_sig(WTERMSIG(exit_status));
+ _exit(WEXITSTATUS(exit_status));
+ }
+ /* Child continues */
+}
ns->ns_nsfile8 + 3 /* skip over "ns/" */
);
}
- /*close(ns_ctx->fd);*/
+ close(ns_ctx->fd); /* should close fds, to not confuse exec'ed PROG */
/*ns_ctx->fd = -1;*/
}
}
xfchdir(root_fd);
xchroot(".");
- /*close(root_fd);*/
+ close(root_fd);
/*root_fd = -1;*/
}
if (wd_fd >= 0) {
xfchdir(wd_fd);
- /*close(wd_fd);*/
+ close(wd_fd);
/*wd_fd = -1;*/
}
* explicitly requested by the user not to.
*/
if (!(opts & OPT_nofork) && (opts & OPT_pid)) {
- pid_t pid = xvfork();
- if (pid > 0) {
- /* Parent */
- int exit_status = wait_for_exitstatus(pid);
- if (WIFSIGNALED(exit_status))
- kill_myself_with_sig(WTERMSIG(exit_status));
- return WEXITSTATUS(exit_status);
- }
+ xvfork_parent_waits_and_exits();
/* Child continues */
}
if (opts & OPT_setuid)
xsetuid(uid);
- if (*argv) {
- BB_EXECVP_or_die(argv);
- }
-
- run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
+ exec_prog_or_SHELL(argv);
}
if (fdp.wr >= 0) {
close(fdp.wr); /* Release child */
- /*close(fdp.rd);*/
+ close(fdp.rd); /* should close fd, to not confuse exec'ed PROG */
}
if (need_mount) {
* that'll become PID 1 in this new namespace.
*/
if (opts & OPT_fork) {
- pid_t pid = xfork();
- if (pid > 0) {
- /* Parent */
- int exit_status = wait_for_exitstatus(pid);
- if (WIFSIGNALED(exit_status))
- kill_myself_with_sig(WTERMSIG(exit_status));
- return WEXITSTATUS(exit_status);
- }
+ xvfork_parent_waits_and_exits();
/* Child continues */
}
mount_or_die("proc", proc_mnt_target, "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV);
}
- if (argv[0]) {
- BB_EXECVP_or_die(argv);
- }
- /* unshare from util-linux 2.27.1, despite not documenting it,
- * runs a login shell (argv0="-sh") if no PROG is given
- */
- run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL);
+ exec_prog_or_SHELL(argv);
}