1/* vi: set sw=4 ts=4: */ 2/* 3 * Rexec program for system have fork() as vfork() with foreground option 4 * 5 * Copyright (C) Vladimir N. Oleynik <dzo@simtreas.ru> 6 * Copyright (C) 2003 Russ Dill <Russ.Dill@asu.edu> 7 * 8 * daemon() portion taken from uClibc: 9 * 10 * Copyright (c) 1991, 1993 11 * The Regents of the University of California. All rights reserved. 12 * 13 * Modified for uClibc by Erik Andersen <andersee@debian.org> 14 * 15 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 16 */ 17 18#include <paths.h> 19#include "busybox.h" /* for struct bb_applet */ 20 21/* This does a fork/exec in one call, using vfork(). Returns PID of new child, 22 * -1 for failure. Runs argv[0], searching path if that has no / in it. */ 23pid_t spawn(char **argv) 24{ 25 /* Compiler should not optimize stores here */ 26 volatile int failed; 27 pid_t pid; 28 29// Ain't it a good place to fflush(NULL)? 30 31 /* Be nice to nommu machines. */ 32 failed = 0; 33 pid = vfork(); 34 if (pid < 0) /* error */ 35 return pid; 36 if (!pid) { /* child */ 37 /* This macro is ok - it doesn't do NOEXEC/NOFORK tricks */ 38 BB_EXECVP(argv[0], argv); 39 40 /* We are (maybe) sharing a stack with blocked parent, 41 * let parent know we failed and then exit to unblock parent 42 * (but don't run atexit() stuff, which would screw up parent.) 43 */ 44 failed = errno; 45 _exit(111); 46 } 47 /* parent */ 48 /* Unfortunately, this is not reliable: according to standards 49 * vfork() can be equivalent to fork() and we won't see value 50 * of 'failed'. 51 * Interested party can wait on pid and learn exit code. 52 * If 111 - then it (most probably) failed to exec */ 53 if (failed) { 54 errno = failed; 55 return -1; 56 } 57 return pid; 58} 59 60/* Die with an error message if we can't spawn a child process. */ 61pid_t xspawn(char **argv) 62{ 63 pid_t pid = spawn(argv); 64 if (pid < 0) 65 bb_perror_msg_and_die("%s", *argv); 66 return pid; 67} 68 69// Wait for the specified child PID to exit, returning child's error return. 70int wait4pid(int pid) 71{ 72 int status; 73 74 if (pid <= 0) { 75 /*errno = ECHILD; -- wrong. */ 76 /* we expect errno to be already set from failed [v]fork/exec */ 77 return -1; 78 } 79 if (waitpid(pid, &status, 0) == -1) 80 return -1; 81 if (WIFEXITED(status)) 82 return WEXITSTATUS(status); 83 if (WIFSIGNALED(status)) 84 return WTERMSIG(status) + 1000; 85 return 0; 86} 87 88int wait_nohang(int *wstat) 89{ 90 return waitpid(-1, wstat, WNOHANG); 91} 92 93int wait_pid(int *wstat, int pid) 94{ 95 int r; 96 97 do 98 r = waitpid(pid, wstat, 0); 99 while ((r == -1) && (errno == EINTR)); 100 return r; 101} 102 103#if ENABLE_FEATURE_PREFER_APPLETS 104void save_nofork_data(struct nofork_save_area *save) 105{ 106 memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); 107 save->current_applet = current_applet; 108 save->xfunc_error_retval = xfunc_error_retval; 109 save->option_mask32 = option_mask32; 110 save->die_sleep = die_sleep; 111 save->saved = 1; 112} 113 114void restore_nofork_data(struct nofork_save_area *save) 115{ 116 memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); 117 current_applet = save->current_applet; 118 xfunc_error_retval = save->xfunc_error_retval; 119 option_mask32 = save->option_mask32; 120 die_sleep = save->die_sleep; 121 122 applet_name = current_applet->name; 123} 124 125int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv) 126{ 127 int rc, argc; 128 129 current_applet = a; 130 applet_name = a->name; 131 xfunc_error_retval = EXIT_FAILURE; 132 /*option_mask32 = 0; - not needed */ 133 /* special flag for xfunc_die(). If xfunc will "die" 134 * in NOFORK applet, xfunc_die() sees negative 135 * die_sleep and longjmp here instead. */ 136 die_sleep = -1; 137 138 argc = 1; 139 while (argv[argc]) 140 argc++; 141 142 rc = setjmp(die_jmp); 143 if (!rc) { 144 /* Some callers (xargs) 145 * need argv untouched because they free argv[i]! */ 146 char *tmp_argv[argc+1]; 147 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); 148 /* Finally we can call NOFORK applet's main() */ 149 rc = a->main(argc, tmp_argv); 150 } else { /* xfunc died in NOFORK applet */ 151 /* in case they meant to return 0... */ 152 if (rc == -2222) 153 rc = 0; 154 } 155 156 /* Restoring globals */ 157 restore_nofork_data(old); 158 return rc; 159} 160 161int run_nofork_applet(const struct bb_applet *a, char **argv) 162{ 163 struct nofork_save_area old; 164 165 /* Saving globals */ 166 save_nofork_data(&old); 167 return run_nofork_applet_prime(&old, a, argv); 168} 169#endif /* FEATURE_PREFER_APPLETS */ 170 171int spawn_and_wait(char **argv) 172{ 173 int rc; 174#if ENABLE_FEATURE_PREFER_APPLETS 175 const struct bb_applet *a = find_applet_by_name(argv[0]); 176 177 if (a && (a->nofork 178#if BB_MMU 179 || a->noexec /* NOEXEC trick needs fork() */ 180#endif 181 )) { 182#if BB_MMU 183 if (a->nofork) 184#endif 185 { 186 return run_nofork_applet(a, argv); 187 } 188#if BB_MMU 189 /* MMU only */ 190 /* a->noexec is true */ 191 rc = fork(); 192 if (rc) /* parent or error */ 193 return wait4pid(rc); 194 /* child */ 195 xfunc_error_retval = EXIT_FAILURE; 196 current_applet = a; 197 run_current_applet_and_exit(argv); 198#endif 199 } 200#endif /* FEATURE_PREFER_APPLETS */ 201 rc = spawn(argv); 202 return wait4pid(rc); 203} 204 205#if !BB_MMU 206void re_exec(char **argv) 207{ 208 /* high-order bit of first char in argv[0] is a hidden 209 * "we have (already) re-execed, don't do it again" flag */ 210 argv[0][0] |= 0x80; 211 execv(bb_busybox_exec_path, argv); 212 bb_perror_msg_and_die("exec %s", bb_busybox_exec_path); 213} 214 215void forkexit_or_rexec(char **argv) 216{ 217 pid_t pid; 218 /* Maybe we are already re-execed and come here again? */ 219 if (re_execed) 220 return; 221 222 pid = vfork(); 223 if (pid < 0) /* wtf? */ 224 bb_perror_msg_and_die("vfork"); 225 if (pid) /* parent */ 226 exit(0); 227 /* child - re-exec ourself */ 228 re_exec(argv); 229} 230#else 231/* Dance around (void)...*/ 232#undef forkexit_or_rexec 233void forkexit_or_rexec(void) 234{ 235 pid_t pid; 236 pid = fork(); 237 if (pid < 0) /* wtf? */ 238 bb_perror_msg_and_die("fork"); 239 if (pid) /* parent */ 240 exit(0); 241 /* child */ 242} 243#define forkexit_or_rexec(argv) forkexit_or_rexec() 244#endif 245 246/* Due to a #define in libbb.h on MMU systems we actually have 1 argument - 247 * char **argv "vanishes" */ 248void bb_daemonize_or_rexec(int flags, char **argv) 249{ 250 int fd; 251 252 if (flags & DAEMON_CHDIR_ROOT) 253 xchdir("/"); 254 255 if (flags & DAEMON_DEVNULL_STDIO) { 256 close(0); 257 close(1); 258 close(2); 259 } 260 261 fd = xopen(bb_dev_null, O_RDWR); 262 263 while ((unsigned)fd < 2) 264 fd = dup(fd); /* have 0,1,2 open at least to /dev/null */ 265 266 if (!(flags & DAEMON_ONLY_SANITIZE)) { 267 forkexit_or_rexec(argv); 268 /* if daemonizing, make sure we detach from stdio & ctty */ 269 setsid(); 270 dup2(fd, 0); 271 dup2(fd, 1); 272 dup2(fd, 2); 273 } 274 while (fd > 2) { 275 close(fd--); 276 if (!(flags & DAEMON_CLOSE_EXTRA_FDS)) 277 return; 278 /* else close everything after fd#2 */ 279 } 280} 281 282void bb_sanitize_stdio(void) 283{ 284 bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE, NULL); 285} 286