1 /* Copyright 1993-95 by Carl Harris, Jr. Copyright 1996 by Eric S. Raymond
3 * For license terms, see the file COPYING in this directory.
7 /***********************************************************************
10 programmer: Carl Harris, ceharris@mal.com
11 description: This module contains all of the code needed to
12 turn a process into a daemon for POSIX, SysV, and
15 ***********************************************************************/
21 #include <sys/types.h>
26 #if defined(HAVE_SYS_WAIT_H)
27 # include <sys/wait.h>
30 #if defined(HAVE_UNISTD_H)
35 #include "popclient.h"
37 /******************************************************************
38 function: sigchld_handler
39 description: Process the SIGCHLD (a.k.a SIGCLD) signal by calling
40 a wait() variant to obtain the exit code of the
43 ret. value: none (or undefined if REGSIGTYPE is int).
46 *****************************************************************/
53 #if defined(HAVE_UNION_WAIT)
59 #if defined(HAVE_WAIT3)
60 while ((pid = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0)
61 ; /* swallow 'em up. */
62 #elif defined(HAVE_WAITPID)
63 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
64 ; /* swallow 'em up. */
65 #else /* Zooks! Nothing to do but wait(), and hope we don't block... */
73 /******************************************************************
75 description: become a daemon process; i.e. detach from the
76 control terminal, don't reacquire a control terminal,
77 become process group leader of our own process group,
78 and set up to catch child process termination signals.
80 logfile file to direct stdout and stderr to, if non-NULL.
83 globals: termhook, sigchld_handler().
85 *****************************************************************/
88 daemonize (logfile, termhook)
90 void (*termhook)(int);
94 RETSIGTYPE sigchld_handler();
96 /* if we are started by init (process 1) via /etc/inittab we needn't
97 bother to detach from our process group context */
102 /* Ignore BSD terminal stop signals */
104 signal(SIGTTOU, SIG_IGN);
107 signal(SIGTTIN, SIG_IGN);
110 signal(SIGTSTP, SIG_IGN);
113 /* In case we were not started in the background, fork and let
114 the parent exit. Guarantees that the child is not a process
117 if ((childpid = fork()) < 0) {
121 else if (childpid > 0)
122 exit(0); /* parent */
125 /* Make ourselves the leader of a new process group with no
126 controlling terminal */
128 #if defined(HAVE_SETSID) /* POSIX */
129 /* POSIX makes this soooo easy to do */
134 #elif defined(SIGTSTP) /* BSD */
135 /* change process group */
136 setpgrp(0, getpid());
138 /* lose controlling tty */
139 if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
140 ioctl(fd, TIOCNOTTY, (char *) 0);
143 #else /* SVR3 and older */
144 /* change process group */
147 /* lose controlling tty */
148 signal(SIGHUP, SIG_IGN);
149 if ((childpid = fork) < 0) {
153 else if (childpid > 0) {
154 exit(0); /* parent */
160 /* Close any/all open file descriptors */
161 #if defined(HAVE_GETDTABLESIZE)
162 for (fd = getdtablesize()-1; fd >= 0; fd--)
163 #elif defined(NOFILE)
164 for (fd = NOFILE-1; fd >= 0; fd--)
165 #else /* make an educated guess */
166 for (fd = 19; fd >= 0; fd--)
172 /* Reopen stdin descriptor on /dev/null */
173 if ((fd = open("/dev/null", O_RDWR)) < 0) { /* stdin */
174 perror("open: /dev/null");
179 fd = open(logfile, O_CREAT|O_WRONLY, 0777); /* stdout */
181 if (dup(fd) < 0) { /* stdout */
185 if (dup(fd) < 0) { /* stderr */
190 /* move to root directory, so we don't prevent filesystem unmounts */
193 /* set our umask to something reasonable (we hope) */
194 #if defined(DEF_UMASK)
200 /* set up to catch child process termination signals */
201 signal(SIGCLD, sigchld_handler);