/* Due to a #define in libbb.h on MMU systems we actually have 1 argument - * char **argv "vanishes" */ void FAST_FUNC bb_daemonize_or_rexec(int flags, char **argv) { int fd; if (flags & DAEMON_CHDIR_ROOT) xchdir("/"); if (flags & DAEMON_DEVNULL_STDIO) { close(0); close(1); close(2); } fd = open(bb_dev_null, O_RDWR); if (fd < 0) { /* NB: we can be called as bb_sanitize_stdio() from init * or mdev, and there /dev/null may legitimately not (yet) exist! * Do not use xopen above, but obtain _ANY_ open descriptor, * even bogus one as below. */ fd = xopen("/", O_RDONLY); /* don't believe this can fail */ } while ((unsigned)fd < 2) fd = dup(fd); /* have 0,1,2 open at least to /dev/null */ if (!(flags & DAEMON_ONLY_SANITIZE)) { if (fork_or_rexec(argv)) exit(EXIT_SUCCESS); /* parent */ /* if daemonizing, detach from stdio & ctty */ setsid(); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); if (flags & DAEMON_DOUBLE_FORK) { /* On Linux, session leader can acquire ctty * unknowingly, by opening a tty. * Prevent this: stop being a session leader. */ if (fork_or_rexec(argv)) exit(EXIT_SUCCESS); /* parent */ } } while (fd > 2) { close(fd--); if (!(flags & DAEMON_CLOSE_EXTRA_FDS)) return; /* else close everything after fd#2 */ } }
int setsid_main(int argc UNUSED_PARAM, char **argv) { if (!argv[1]) bb_show_usage(); /* setsid() is allowed only when we are not a process group leader. * Otherwise our PID serves as PGID of some existing process group * and cannot be used as PGID of a new process group. */ if (getpgrp() == getpid()) if (fork_or_rexec(argv)) exit(EXIT_SUCCESS); /* parent */ setsid(); /* no error possible */ BB_EXECVP(argv[1], argv + 1); bb_simple_perror_msg_and_die(argv[1]); }