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)
38 /* BSD portability hack */
39 #if !defined(SIGCLD) && defined(SIGCHLD)
40 #define SIGCLD SIGCHLD
43 #include "popclient.h"
45 /******************************************************************
46 function: sigchld_handler
47 description: Process the SIGCHLD (a.k.a SIGCLD) signal by calling
48 a wait() variant to obtain the exit code of the
51 ret. value: none (or undefined if REGSIGTYPE is int).
54 *****************************************************************/
61 #if defined(HAVE_UNION_WAIT)
67 #if defined(HAVE_WAIT3)
68 while ((pid = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0)
69 ; /* swallow 'em up. */
70 #elif defined(HAVE_WAITPID)
71 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
72 ; /* swallow 'em up. */
73 #else /* Zooks! Nothing to do but wait(), and hope we don't block... */
81 /******************************************************************
83 description: become a daemon process; i.e. detach from the
84 control terminal, don't reacquire a control terminal,
85 become process group leader of our own process group,
86 and set up to catch child process termination signals.
88 logfile file to direct stdout and stderr to, if non-NULL.
91 globals: termhook, sigchld_handler().
93 *****************************************************************/
96 daemonize (logfile, termhook)
98 void (*termhook)(int);
102 RETSIGTYPE sigchld_handler();
104 /* if we are started by init (process 1) via /etc/inittab we needn't
105 bother to detach from our process group context */
110 /* Ignore BSD terminal stop signals */
112 signal(SIGTTOU, SIG_IGN);
115 signal(SIGTTIN, SIG_IGN);
118 signal(SIGTSTP, SIG_IGN);
121 /* In case we were not started in the background, fork and let
122 the parent exit. Guarantees that the child is not a process
125 if ((childpid = fork()) < 0) {
129 else if (childpid > 0)
130 exit(0); /* parent */
133 /* Make ourselves the leader of a new process group with no
134 controlling terminal */
136 #if defined(HAVE_SETSID) /* POSIX */
137 /* POSIX makes this soooo easy to do */
142 #elif defined(SIGTSTP) /* BSD */
143 /* change process group */
144 setpgrp(0, getpid());
146 /* lose controlling tty */
147 if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
148 ioctl(fd, TIOCNOTTY, (char *) 0);
151 #else /* SVR3 and older */
152 /* change process group */
155 /* lose controlling tty */
156 signal(SIGHUP, SIG_IGN);
157 if ((childpid = fork) < 0) {
161 else if (childpid > 0) {
162 exit(0); /* parent */
168 /* Close any/all open file descriptors */
169 #if defined(HAVE_GETDTABLESIZE)
170 for (fd = getdtablesize()-1; fd >= 0; fd--)
171 #elif defined(NOFILE)
172 for (fd = NOFILE-1; fd >= 0; fd--)
173 #else /* make an educated guess */
174 for (fd = 19; fd >= 0; fd--)
180 /* Reopen stdin descriptor on /dev/null */
181 if ((fd = open("/dev/null", O_RDWR)) < 0) { /* stdin */
182 perror("open: /dev/null");
187 fd = open(logfile, O_CREAT|O_WRONLY, 0777); /* stdout */
189 if (dup(fd) < 0) { /* stdout */
193 if (dup(fd) < 0) { /* stderr */
198 /* move to root directory, so we don't prevent filesystem unmounts */
201 /* set our umask to something reasonable (we hope) */
202 #if defined(DEF_UMASK)
208 /* set up to catch child process termination signals */
209 signal(SIGCLD, sigchld_handler);
211 signal(SIGPWR, sigchld_handler);