]> Pileus Git - ~andy/fetchmail/blob - daemon.c
Remove all those obnoxious block comments.
[~andy/fetchmail] / daemon.c
1 /*
2  * damemon.c -- turn a process into a daemon under POSIX, SYSV, BSD.
3  *
4  * For license terms, see the file COPYING in this directory.
5  */
6
7 #include <config.h>
8
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <sys/file.h>
12 #include <signal.h>
13 #include <fcntl.h>
14
15 #if defined(HAVE_SYS_WAIT_H)
16 #  include <sys/wait.h>
17 #endif
18
19 #if defined(HAVE_UNISTD_H)
20 #  include <unistd.h>
21 #endif
22
23 #if defined(QNX)
24 #  include <unix.h>
25 #endif
26
27 /* BSD portability hack */
28 #if !defined(SIGCLD) && defined(SIGCHLD)
29 #define SIGCLD  SIGCHLD
30 #endif
31
32 #include "fetchmail.h"
33
34 RETSIGTYPE
35 sigchld_handler ()
36 /* process SIGCHLD/SIGCLD to obtain the exit code of the terminating process */
37 {
38   pid_t pid;
39
40 #if defined(HAVE_UNION_WAIT)
41   union wait status;
42 #else
43   int status;
44 #endif
45
46 #if     defined(HAVE_WAIT3)
47   while ((pid = wait3(&status, WNOHANG, (struct rusage *) 0)) > 0)
48     ; /* swallow 'em up. */
49 #elif   defined(HAVE_WAITPID)
50   while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
51     ; /* swallow 'em up. */
52 #else   /* Zooks! Nothing to do but wait(), and hope we don't block... */
53   wait(&status);
54 #endif
55
56 }
57
58 int
59 daemonize (logfile, termhook)
60 /* detach from control TTY, become process group leader, catch SIGCHLD */
61 const char *logfile;
62 void (*termhook)(int);
63 {
64   int fd;
65   pid_t childpid;
66   RETSIGTYPE sigchld_handler();
67
68   /* if we are started by init (process 1) via /etc/inittab we needn't 
69      bother to detach from our process group context */
70
71   if (getppid() == 1) 
72     goto nottyDetach;
73
74   /* Ignore BSD terminal stop signals */
75 #ifdef  SIGTTOU
76   signal(SIGTTOU, SIG_IGN);
77 #endif
78 #ifdef  SIGTTIN
79   signal(SIGTTIN, SIG_IGN);
80 #endif
81 #ifdef  SIGTSTP
82   signal(SIGTSTP, SIG_IGN);
83 #endif
84
85   /* In case we were not started in the background, fork and let
86      the parent exit.  Guarantees that the child is not a process
87      group leader */
88
89   if ((childpid = fork()) < 0) {
90     perror("fork");
91     return(PS_IOERR);
92   }
93   else if (childpid > 0) 
94     exit(0);  /* parent */
95
96   
97   /* Make ourselves the leader of a new process group with no
98      controlling terminal */
99
100 #if     defined(HAVE_SETSID)            /* POSIX */
101   /* POSIX makes this soooo easy to do */
102   if (setsid() < 0) {
103     perror("setsid");
104     return(PS_IOERR);
105   }
106 #elif   defined(SIGTSTP)                /* BSD */
107   /* change process group */
108   setpgrp(0, getpid());
109
110   /* lose controlling tty */
111   if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
112     ioctl(fd, TIOCNOTTY, (char *) 0);
113     close(fd);
114   }
115 #else                                   /* SVR3 and older */
116   /* change process group */
117   setpgrp();
118   
119   /* lose controlling tty */
120   signal(SIGHUP, SIG_IGN);
121   if ((childpid = fork) < 0) {
122     perror("fork");
123     return(PS_IOERR);
124   }
125   else if (childpid > 0) {
126     exit(0);    /* parent */
127   }
128 #endif
129
130 nottyDetach:
131
132   /* Close any/all open file descriptors */
133 #if     defined(HAVE_GETDTABLESIZE)
134   for (fd = getdtablesize()-1;  fd >= 0;  fd--)
135 #elif   defined(NOFILE)
136   for (fd = NOFILE-1;  fd >= 0;  fd--)
137 #else           /* make an educated guess */
138   for (fd = 19;  fd >= 0;  fd--)
139 #endif
140   {
141     close(fd);
142   }
143
144   /* Reopen stdin descriptor on /dev/null */
145   if ((fd = open("/dev/null", O_RDWR)) < 0) {   /* stdin */
146     perror("open: /dev/null");
147     return(PS_IOERR);
148   }
149
150   if (logfile)
151     fd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, 0777);        /* stdout */
152   else
153     if (dup(fd) < 0) {                          /* stdout */
154       perror("dup");
155       return(PS_IOERR);
156     }
157   if (dup(fd) < 0) {                            /* stderr */
158     perror("dup");
159     return(PS_IOERR);
160   }
161
162   /* move to root directory, so we don't prevent filesystem unmounts */
163   chdir("/");
164
165   /* set our umask to something reasonable (we hope) */
166 #if defined(DEF_UMASK)
167   umask(DEF_UMASK);
168 #else
169   umask(022);
170 #endif
171
172   /* set up to catch child process termination signals */ 
173   signal(SIGCLD, sigchld_handler); 
174 #if defined(SIGPWR)
175   signal(SIGPWR, sigchld_handler); 
176 #endif
177 }
178
179 /* daemon.c ends here */