1 /* Copyright 1993-95 by Carl Harris, Jr.
4 * Distribute freely, except: don't remove my name from the source or
5 * documentation (don't take credit for my work), mark your changes (don't
6 * get me blamed for your possible bugs), don't alter or remove this
7 * notice. May be sold if buildable source is provided to buyer. No
8 * warrantee of any kind, express or implied, is included with this
9 * software; use at your own risk, responsibility for damages (if any) to
10 * anyone resulting from the use of this software rests entirely with the
13 * Send bug reports, bug fixes, enhancements, requests, flames, etc., and
14 * I'll try to keep a version up to date. I can be reached as follows:
15 * Carl Harris <ceharris@mal.com>
19 /***********************************************************************
22 programmer: Carl Harris, ceharris@mal.com
23 description: This module contains all of the code needed to
24 turn a process into a daemon for POSIX, SysV, and
28 Revision 1.1 1996/06/25 14:32:01 esr
31 Revision 1.1 1995/08/14 18:36:38 ceharris
32 Patches to support POP3's LAST command.
33 Final revisions for beta3 release.
35 ***********************************************************************/
41 #include <sys/types.h>
46 #if defined(HAVE_SYS_WAIT_H)
47 # include <sys/wait.h>
50 #if defined(HAVE_UNISTD_H)
55 #include "popclient.h"
58 /******************************************************************
59 function: sigchld_handler
60 description: Process the SIGCHLD (a.k.a SIGCLD) signal by calling
61 a wait() variant to obtain the exit code of the
64 ret. value: none (or undefined if REGSIGTYPE is int).
67 *****************************************************************/
74 #if defined(HAVE_UNION_WAIT)
80 #if defined(HAVE_WAIT3)
81 while ((pid = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0)
82 ; /* swallow 'em up. */
83 #elif defined(HAVE_WAITPID)
84 while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
85 ; /* swallow 'em up. */
86 #else /* Zooks! Nothing to do but wait(), and hope we don't block... */
94 /******************************************************************
96 description: become a daemon process; i.e. detach from the
97 control terminal, don't reacquire a control terminal,
98 become process group leader of our own process group,
99 and set up to catch child process termination signals.
101 options command-line options.
104 globals: refers to the address of sigchld_handler().
106 *****************************************************************/
110 struct optrec *options;
114 RETSIGTYPE sigchild_handler();
116 /* if we are started by init (process 1) via /etc/inittab we needn't
117 bother to detach from our process group context */
122 /* Ignore BSD terminal stop signals */
124 signal(SIGTTOU, SIG_IGN);
127 signal(SIGTTIN, SIG_IGN);
130 signal(SIGTSTP, SIG_IGN);
133 /* In case we were not started in the background, fork and let
134 the parent exit. Guarantees that the child is not a process
137 if ((childpid = fork()) < 0) {
141 else if (childpid > 0)
142 exit(0); /* parent */
145 /* Make ourselves the leader of a new process group with no
146 controlling terminal */
148 #if defined(HAVE_SETSID) /* POSIX */
149 /* POSIX makes this soooo easy to do */
154 #elif defined(SIGTSTP) /* BSD */
155 /* change process group */
156 setpgrp(0, getpid());
158 /* lose controlling tty */
159 if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
160 ioctl(fd, TIOCNOTTY, (char *) 0);
163 #else /* SVR3 and older */
164 /* change process group */
167 /* lose controlling tty */
168 signal(SIGHUP, SIG_IGN);
169 if ((childpid = fork) < 0) {
173 else if (childpid > 0) {
174 exit(0); /* parent */
180 /* Close any/all open file descriptors */
181 #if defined(HAVE_GETDTABLESIZE)
182 for (fd = getdtablesize()-1; fd >= 0; fd--)
183 #elif defined(NOFILE)
184 for (fd = NOFILE-1; fd >= 0; fd--)
185 #else /* make an educated guess */
186 for (fd = 19; fd >= 0; fd--)
192 /* Reopen stdin descriptor on /dev/null */
193 if ((fd = open("/dev/null", O_RDWR)) < 0) { /* stdin */
194 perror("open: /dev/null");
199 if (dup(fd) < 0) { /* stdout */
203 if (dup(fd) < 0) { /* stderr */
208 /* move to root directory, so we don't prevent filesystem unmounts */
211 /* set our umask to something reasonable (we hope) */
212 #if defined(DEF_UMASK)
218 /* set up to catch child process termination signals */
219 signal(SIGCLD, sigchild_handler);