/* * Initialize a daemon process. */ #include #include #include #include extern int errno; #ifdef SIGTSTP /* true if BSD system */ #include #include #endif /* * Detach a daemon process from login session context. */ daemon_start(ignsigcld) int ignsigcld; /* nonzero -> handle SIGCLDs so zombies don't clog */ { register int childpid, fd; /* * If we were started by init (process 1) from the /etc/inittab file * there's no need to detach. * This test is unreliable due to an unavoidable ambiguity * if the process is started by some other process and orphaned * (i.e., if the parent process terminates before we are started). */ if (getppid() == 1) goto out; /* * Ignore the terminal stop signals (BSD). */ #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif /* * If we were not started in the background, fork and * let the parent exit. This also guarantees the first child * is not a process group leader. */ if ( (childpid = fork()) < 0) err_sys("can't fork first child"); else if (childpid > 0) exit(0); /* parent */ /* * First child process. * * Disassociate from controlling terminal and process group. * Ensure the process can't reacquire a new controlling terminal. */ #ifdef SIGTSTP /* BSD */ if (setpgrp(0, getpid()) == -1) err_sys("can't change process group"); if ( (fd = open("/dev/tty", O_RDWR)) >= 0) { ioctl(fd, TIOCNOTTY, (char *)NULL); /* lose controlling tty */ close(fd); } #else /* System V */ if (setpgrp() == -1) err_sys("can't change process group"); signal(SIGHUP, SIG_IGN); /* immune from pgrp leader death */ if ( (childpid = fork()) < 0) err_sys("can't fork second child"); else if (childpid > 0) exit(0); /* first child */ /* second child */ #endif out: /* * Close any open files descriptors. */ for (fd = 0; fd < NOFILE; fd++) close(fd); errno = 0; /* probably got set to EBADF from a close */ /* * Move the current directory to root, to make sure we * aren't on a mounted filesystem. */ chdir("/"); /* * Clear any inherited file mode creation mask. */ umask(0); /* * See if the caller isn't interested in the exit status of its * children, and doesn't want to have them become zombies and * clog up the system. * With System V all we need do is ignore the signal. * With BSD, however, we have to catch each signal * and execute the wait3() system call. */ if (ignsigcld) { #ifdef SIGTSTP int sig_child(); signal(SIGCLD, sig_child); /* BSD */ #else signal(SIGCLD, SIG_IGN); /* System V */ #endif } }