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)
34 /* BSD portability hack */
35 #if !defined(SIGCLD) && defined(SIGCHLD)
36 #define SIGCLD SIGCHLD
39 #include "popclient.h"
41 /******************************************************************
42 function: sigchld_handler
43 description: Process the SIGCHLD (a.k.a SIGCLD) signal by calling
44 a wait() variant to obtain the exit code of the
47 ret. value: none (or undefined if REGSIGTYPE is int).
50 *****************************************************************/
57 #if defined(HAVE_UNION_WAIT)
63 #if defined(HAVE_WAIT3)
64 while ((pid = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0)
65 ; /* swallow 'em up. */
66 #elif defined(HAVE_WAITPID)
67 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
68 ; /* swallow 'em up. */
69 #else /* Zooks! Nothing to do but wait(), and hope we don't block... */
77 /******************************************************************
79 description: become a daemon process; i.e. detach from the
80 control terminal, don't reacquire a control terminal,
81 become process group leader of our own process group,
82 and set up to catch child process termination signals.
84 logfile file to direct stdout and stderr to, if non-NULL.
87 globals: termhook, sigchld_handler().
89 *****************************************************************/
92 daemonize (logfile, termhook)
94 void (*termhook)(int);
98 RETSIGTYPE sigchld_handler();
100 /* if we are started by init (process 1) via /etc/inittab we needn't
101 bother to detach from our process group context */
106 /* Ignore BSD terminal stop signals */
108 signal(SIGTTOU, SIG_IGN);
111 signal(SIGTTIN, SIG_IGN);
114 signal(SIGTSTP, SIG_IGN);
117 /* In case we were not started in the background, fork and let
118 the parent exit. Guarantees that the child is not a process
121 if ((childpid = fork()) < 0) {
125 else if (childpid > 0)
126 exit(0); /* parent */
129 /* Make ourselves the leader of a new process group with no
130 controlling terminal */
132 #if defined(HAVE_SETSID) /* POSIX */
133 /* POSIX makes this soooo easy to do */
138 #elif defined(SIGTSTP) /* BSD */
139 /* change process group */
140 setpgrp(0, getpid());
142 /* lose controlling tty */
143 if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
144 ioctl(fd, TIOCNOTTY, (char *) 0);
147 #else /* SVR3 and older */
148 /* change process group */
151 /* lose controlling tty */
152 signal(SIGHUP, SIG_IGN);
153 if ((childpid = fork) < 0) {
157 else if (childpid > 0) {
158 exit(0); /* parent */
164 /* Close any/all open file descriptors */
165 #if defined(HAVE_GETDTABLESIZE)
166 for (fd = getdtablesize()-1; fd >= 0; fd--)
167 #elif defined(NOFILE)
168 for (fd = NOFILE-1; fd >= 0; fd--)
169 #else /* make an educated guess */
170 for (fd = 19; fd >= 0; fd--)
176 /* Reopen stdin descriptor on /dev/null */
177 if ((fd = open("/dev/null", O_RDWR)) < 0) { /* stdin */
178 perror("open: /dev/null");
183 fd = open(logfile, O_CREAT|O_WRONLY, 0777); /* stdout */
185 if (dup(fd) < 0) { /* stdout */
189 if (dup(fd) < 0) { /* stderr */
194 /* move to root directory, so we don't prevent filesystem unmounts */
197 /* set our umask to something reasonable (we hope) */
198 #if defined(DEF_UMASK)
204 /* set up to catch child process termination signals */
205 signal(SIGCLD, sigchld_handler);