/* 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]);
}