Commit 5a79e104 5a79e104e2b745587db5532ec730d1c99384d111 by Alain Magloire

Most daemon will share the same code to daemonize(), we use

	a generic one, lib/daemon.c, so any bug fix will impact the
	others and reduce maintainance/duplication.

	* lib/Makefile.am: Addition daemon.c
	* lib/daemon.c: New file.
	* pop3d/pop3d.c (pop3d_daemon_init): Use lib/daemon.c:daemon() code
	instead.
	* imap4d/imap4d.c (imap4d_daemon_init): Use lib/daemon.c:daemon code
	instead.
	* comstat/comstat.c (comstat_daemon_init): Use lib/daemon.c:daemon code
	instead. Remove trailing spaces.
1 parent 97f85b62
1 2001-11-11 Alain Magloire
2
3 Most daemon will share the same code to daemonize(), we use
4 a generic one, lib/daemon.c, so any bug fix will impact the
5 others and reduce maintainance/duplication.
6
7 * lib/Makefile.am: Addition daemon.c
8 * lib/daemon.c: New file.
9 * pop3d/pop3d.c (pop3d_daemon_init): Use lib/daemon.c:daemon() code
10 instead.
11 * imap4d/imap4d.c (imap4d_daemon_init): Use lib/daemon.c:daemon code
12 instead.
13 * comstat/comstat.c (comstat_daemon_init): Use lib/daemon.c:daemon code
14 instead. Remove trailing spaces.
15
1 2001-11-11 Sergey Poznyakoff 16 2001-11-11 Sergey Poznyakoff
2 17
3 * comsat/action.c: (new) User-defined actions for comsat. 18 * comsat/action.c: (new) User-defined actions for comsat.
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
21 21
22 #ifndef PATH_DEV 22 #ifndef PATH_DEV
23 # define PATH_DEV "/dev" 23 # define PATH_DEV "/dev"
24 #endif 24 #endif
25 #ifndef PATH_TTY_PFX 25 #ifndef PATH_TTY_PFX
26 # define PATH_TTY_PFX PATH_DEV 26 # define PATH_TTY_PFX PATH_DEV
27 #endif 27 #endif
...@@ -96,7 +96,7 @@ main(int argc, char **argv) ...@@ -96,7 +96,7 @@ main(int argc, char **argv)
96 { 96 {
97 int c; 97 int c;
98 char *config_file = NULL; 98 char *config_file = NULL;
99 99
100 while ((c = getopt_long (argc, argv, short_options, long_options, NULL)) 100 while ((c = getopt_long (argc, argv, short_options, long_options, NULL))
101 != -1) 101 != -1)
102 { 102 {
...@@ -171,7 +171,7 @@ sig_hup (int sig) ...@@ -171,7 +171,7 @@ sig_hup (int sig)
171 syslog (LOG_ERR, "can't restart: not started with absolute pathname"); 171 syslog (LOG_ERR, "can't restart: not started with absolute pathname");
172 else 172 else
173 execvp (xargv[0], xargv); 173 execvp (xargv[0], xargv);
174 174
175 signal (sig, sig_hup); 175 signal (sig, sig_hup);
176 } 176 }
177 177
...@@ -185,7 +185,7 @@ comsat_init () ...@@ -185,7 +185,7 @@ comsat_init ()
185 list_append (bookie, path_record); 185 list_append (bookie, path_record);
186 186
187 gethostname (hostname, sizeof hostname); 187 gethostname (hostname, sizeof hostname);
188 188
189 /* Set signal handlers */ 189 /* Set signal handlers */
190 signal (SIGTTOU, SIG_IGN); 190 signal (SIGTTOU, SIG_IGN);
191 signal (SIGCHLD, SIG_IGN); 191 signal (SIGCHLD, SIG_IGN);
...@@ -196,46 +196,15 @@ comsat_init () ...@@ -196,46 +196,15 @@ comsat_init ()
196 static void 196 static void
197 comsat_daemon_init (void) 197 comsat_daemon_init (void)
198 { 198 {
199 pid_t pid; 199 extern int daemon (int, int);
200
201 pid = fork ();
202 if (pid == -1)
203 {
204 perror ("fork failed:");
205 exit (EXIT_FAILURE);
206 }
207 else if (pid > 0)
208 exit (EXIT_SUCCESS); /* Parent exits. */
209
210 /* Child: */
211 signal (SIGHUP, sig_hup);
212 200
213 setsid (); /* Become session leader. */ 201 /* Become a daemon. Take care to close inherited fds and to hold
214 202 first three one, in, out, err. Do not do the chdir("/"). */
215 /* The second fork is to guarantee that the daemon cannot acquire a 203 if (daemon (1, 0) < 0)
216 controlling terminal. */
217 pid = fork ();
218 if (pid == -1)
219 { 204 {
220 perror("fork failed"); 205 perror ("failed to become a daemon:");
221 exit (EXIT_FAILURE); 206 exit (EXIT_FAILURE);
222 } 207 }
223 else if (pid > 0)
224 exit (EXIT_SUCCESS); /* Parent exits. */
225
226 /* Close inherited file descriptors. */
227 {
228 size_t i, fdmax;
229 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
230 fdmax = sysconf(_SC_OPEN_MAX);
231 #elif defined(HAVE_GETDTABLESIZE)
232 fdmax = getdtablesize ();*/
233 #else
234 fdmax = 64;
235 #endif
236 for (i = 0; i < fdmax; ++i)
237 close (i);
238 }
239 } 208 }
240 209
241 unsigned maxrequests = 16; /* Maximum number of request allowed per 210 unsigned maxrequests = 16; /* Maximum number of request allowed per
...@@ -256,14 +225,14 @@ comsat_daemon (int port) ...@@ -256,14 +225,14 @@ comsat_daemon (int port)
256 unsigned overflow_count = 0; /* Number of overflows achieved during 225 unsigned overflow_count = 0; /* Number of overflows achieved during
257 the current interval */ 226 the current interval */
258 time_t now; 227 time_t now;
259 228
260 fd = socket (AF_INET, SOCK_DGRAM, 0); 229 fd = socket (AF_INET, SOCK_DGRAM, 0);
261 if (fd == -1) 230 if (fd == -1)
262 { 231 {
263 syslog (LOG_CRIT, "socket: %m"); 232 syslog (LOG_CRIT, "socket: %m");
264 exit (1); 233 exit (1);
265 } 234 }
266 235
267 memset (&local_sin, 0, sizeof local_sin); 236 memset (&local_sin, 0, sizeof local_sin);
268 local_sin.sin_family = AF_INET; 237 local_sin.sin_family = AF_INET;
269 local_sin.sin_addr.s_addr = INADDR_ANY; /*FIXME*/ 238 local_sin.sin_addr.s_addr = INADDR_ANY; /*FIXME*/
...@@ -276,13 +245,13 @@ comsat_daemon (int port) ...@@ -276,13 +245,13 @@ comsat_daemon (int port)
276 } 245 }
277 246
278 syslog (LOG_NOTICE, "GNU comsat started"); 247 syslog (LOG_NOTICE, "GNU comsat started");
279 248
280 last_request_time = last_overflow_time = time (NULL); 249 last_request_time = last_overflow_time = time (NULL);
281 while (1) 250 while (1)
282 { 251 {
283 fd_set fdset; 252 fd_set fdset;
284 int rc; 253 int rc;
285 254
286 FD_ZERO (&fdset); 255 FD_ZERO (&fdset);
287 FD_SET (fd, &fdset); 256 FD_SET (fd, &fdset);
288 rc = select (fd+1, &fdset, NULL, NULL, NULL); 257 rc = select (fd+1, &fdset, NULL, NULL, NULL);
...@@ -316,7 +285,7 @@ comsat_daemon (int port) ...@@ -316,7 +285,7 @@ comsat_daemon (int port)
316 overflow_count = 0; 285 overflow_count = 0;
317 last_overflow_time = time (NULL); 286 last_overflow_time = time (NULL);
318 } 287 }
319 288
320 if (now - last_request_time <= request_control_interval) 289 if (now - last_request_time <= request_control_interval)
321 reqcount++; 290 reqcount++;
322 else 291 else
...@@ -341,7 +310,7 @@ comsat_main (int fd) ...@@ -341,7 +310,7 @@ comsat_main (int fd)
341 char *p, *endp; 310 char *p, *endp;
342 size_t offset; 311 size_t offset;
343 char *path = NULL; 312 char *path = NULL;
344 313
345 len = sizeof sin_from; 314 len = sizeof sin_from;
346 rdlen = recvfrom (fd, buffer, sizeof buffer, 0, 315 rdlen = recvfrom (fd, buffer, sizeof buffer, 0,
347 (struct sockaddr*)&sin_from, &len); 316 (struct sockaddr*)&sin_from, &len);
...@@ -359,9 +328,9 @@ comsat_main (int fd) ...@@ -359,9 +328,9 @@ comsat_main (int fd)
359 inet_ntoa (sin_from.sin_addr)); 328 inet_ntoa (sin_from.sin_addr));
360 return 1; 329 return 1;
361 } 330 }
362 331
363 syslog (LOG_INFO, "%d bytes from %s", rdlen, inet_ntoa (sin_from.sin_addr)); 332 syslog (LOG_INFO, "%d bytes from %s", rdlen, inet_ntoa (sin_from.sin_addr));
364 333
365 buffer[rdlen] = 0; 334 buffer[rdlen] = 0;
366 335
367 /* Parse the buffer */ 336 /* Parse the buffer */
...@@ -399,7 +368,7 @@ comsat_main (int fd) ...@@ -399,7 +368,7 @@ comsat_main (int fd)
399 syslog (LOG_ERR, "fork: %m"); 368 syslog (LOG_ERR, "fork: %m");
400 return 1; 369 return 1;
401 } 370 }
402 371
403 if (pid > 0) 372 if (pid > 0)
404 { 373 {
405 struct timeval tv; 374 struct timeval tv;
...@@ -408,7 +377,7 @@ comsat_main (int fd) ...@@ -408,7 +377,7 @@ comsat_main (int fd)
408 select (0, NULL, NULL, NULL, &tv); 377 select (0, NULL, NULL, NULL, &tv);
409 kill (pid, SIGKILL); /* Just in case the child is hung */ 378 kill (pid, SIGKILL); /* Just in case the child is hung */
410 return 0; 379 return 0;
411 } 380 }
412 381
413 /* Child: do actual I/O */ 382 /* Child: do actual I/O */
414 notify_user (buffer, tty, path, offset); 383 notify_user (buffer, tty, path, offset);
...@@ -420,7 +389,7 @@ get_newline_str (FILE *fp) ...@@ -420,7 +389,7 @@ get_newline_str (FILE *fp)
420 { 389 {
421 #if defined(OPOST) && defined(ONLCR) 390 #if defined(OPOST) && defined(ONLCR)
422 struct termios tbuf; 391 struct termios tbuf;
423 392
424 tcgetattr (fileno (fp), &tbuf); 393 tcgetattr (fileno (fp), &tbuf);
425 if ((tbuf.c_oflag & OPOST) && (tbuf.c_oflag & ONLCR)) 394 if ((tbuf.c_oflag & OPOST) && (tbuf.c_oflag & ONLCR))
426 return "\n"; 395 return "\n";
...@@ -484,7 +453,7 @@ notify_user (char *user, char *device, char *path, off_t offset) ...@@ -484,7 +453,7 @@ notify_user (char *user, char *device, char *path, off_t offset)
484 path, strerror (status)); 453 path, strerror (status));
485 return; 454 return;
486 } 455 }
487 456
488 /* Read headers */ 457 /* Read headers */
489 size -= offset; 458 size -= offset;
490 blurb = malloc (size + 1); 459 blurb = malloc (size + 1);
...@@ -514,7 +483,7 @@ notify_user (char *user, char *device, char *path, off_t offset) ...@@ -514,7 +483,7 @@ notify_user (char *user, char *device, char *path, off_t offset)
514 mailbox_set_stream (tmp, stream); 483 mailbox_set_stream (tmp, stream);
515 mailbox_messages_count (tmp, &count); 484 mailbox_messages_count (tmp, &count);
516 mailbox_get_message (tmp, 1, &msg); 485 mailbox_get_message (tmp, 1, &msg);
517 486
518 run_user_action (fp, cr, msg); 487 run_user_action (fp, cr, msg);
519 fclose (fp); 488 fclose (fp);
520 } 489 }
...@@ -624,7 +593,7 @@ mailbox_path (const char *user) ...@@ -624,7 +593,7 @@ mailbox_path (const char *user)
624 { 593 {
625 struct passwd *pw; 594 struct passwd *pw;
626 char *mailbox_name; 595 char *mailbox_name;
627 596
628 pw = mu_getpwnam (user); 597 pw = mu_getpwnam (user);
629 if (!pw) 598 if (!pw)
630 { 599 {
...@@ -638,7 +607,7 @@ mailbox_path (const char *user) ...@@ -638,7 +607,7 @@ mailbox_path (const char *user)
638 + strlen (pw->pw_name) + 1, 1); 607 + strlen (pw->pw_name) + 1, 1);
639 sprintf (mailbox_name, "%s/%s", _PATH_MAILDIR, pw->pw_name); 608 sprintf (mailbox_name, "%s/%s", _PATH_MAILDIR, pw->pw_name);
640 } 609 }
641 else 610 else
642 { 611 {
643 mailbox_name = calloc (strlen (pw->pw_dir) + strlen ("/INBOX"), 1); 612 mailbox_name = calloc (strlen (pw->pw_dir) + strlen ("/INBOX"), 1);
644 sprintf (mailbox_name, "%s/INBOX", pw->pw_dir); 613 sprintf (mailbox_name, "%s/INBOX", pw->pw_dir);
......
...@@ -102,7 +102,7 @@ main (int argc, char **argv) ...@@ -102,7 +102,7 @@ main (int argc, char **argv)
102 case 'S': 102 case 'S':
103 set_namespace (NS_SHARED, optarg); 103 set_namespace (NS_SHARED, optarg);
104 break; 104 break;
105 105
106 case 't': 106 case 't':
107 timeout = strtoul (optarg, NULL, 10); 107 timeout = strtoul (optarg, NULL, 10);
108 break; 108 break;
...@@ -145,7 +145,7 @@ main (int argc, char **argv) ...@@ -145,7 +145,7 @@ main (int argc, char **argv)
145 #ifdef USE_VIRTUAL_DOMAINS 145 #ifdef USE_VIRTUAL_DOMAINS
146 mu_register_getpwnam (getpwnam_virtual); 146 mu_register_getpwnam (getpwnam_virtual);
147 #endif 147 #endif
148 148
149 /* Set the signal handlers. */ 149 /* Set the signal handlers. */
150 signal (SIGINT, imap4d_signal); 150 signal (SIGINT, imap4d_signal);
151 signal (SIGQUIT, imap4d_signal); 151 signal (SIGQUIT, imap4d_signal);
...@@ -161,9 +161,11 @@ main (int argc, char **argv) ...@@ -161,9 +161,11 @@ main (int argc, char **argv)
161 161
162 if (mode == DAEMON) 162 if (mode == DAEMON)
163 imap4d_daemon_init (); 163 imap4d_daemon_init ();
164 164 else
165 /* Make sure we are in the root. */ 165 {
166 chdir ("/"); 166 /* Make sure we are in the root. */
167 chdir ("/");
168 }
167 169
168 /* Set up for syslog. */ 170 /* Set up for syslog. */
169 openlog ("gnu-imap4d", LOG_PID, LOG_FACILITY); 171 openlog ("gnu-imap4d", LOG_PID, LOG_FACILITY);
...@@ -203,7 +205,7 @@ imap4d_mainloop (int infile, int outfile) ...@@ -203,7 +205,7 @@ imap4d_mainloop (int infile, int outfile)
203 imap4d_bye (ERR_NO_OFILE); 205 imap4d_bye (ERR_NO_OFILE);
204 206
205 setvbuf(ofile, NULL, _IOLBF, 0); 207 setvbuf(ofile, NULL, _IOLBF, 0);
206 208
207 syslog (LOG_INFO, "Incoming connection opened"); 209 syslog (LOG_INFO, "Incoming connection opened");
208 210
209 /* log information on the connecting client */ 211 /* log information on the connecting client */
...@@ -240,43 +242,15 @@ imap4d_mainloop (int infile, int outfile) ...@@ -240,43 +242,15 @@ imap4d_mainloop (int infile, int outfile)
240 static void 242 static void
241 imap4d_daemon_init (void) 243 imap4d_daemon_init (void)
242 { 244 {
243 pid_t pid; 245 extern int daemon (int, int);
244 246
245 pid = fork (); 247 /* Become a daemon. Take care to close inherited fds and to hold
246 if (pid == -1) 248 first three one, in, out, err */
247 { 249 if (daemon (0, 0) < 0)
248 perror ("fork failed:");
249 exit (1);
250 }
251 else if (pid > 0)
252 exit (0); /* Parent exits. */
253
254 setsid (); /* Become session leader. */
255
256 signal (SIGHUP, SIG_IGN); /* Ignore SIGHUP. */
257
258 /* The second fork is to guarantee that the daemon cannot acquire a
259 controlling terminal. */
260 pid = fork ();
261 if (pid == -1)
262 { 250 {
263 perror("fork failed:"); 251 perror("fork failed:");
264 exit (1); 252 exit (1);
265 } 253 }
266 else if (pid > 0)
267 exit (0); /* Parent exits. */
268
269 /* Close inherited file descriptors. */
270 {
271 size_t i;
272 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
273 size_t fdlimit = sysconf(_SC_OPEN_MAX);
274 #else
275 size_t fdlimit = 64;
276 #endif
277 for (i = 0; i < fdlimit; ++i)
278 close (i);
279 }
280 254
281 /* SIGCHLD is not ignore but rather use to do some simple load balancing. */ 255 /* SIGCHLD is not ignore but rather use to do some simple load balancing. */
282 #ifdef HAVE_SIGACTION 256 #ifdef HAVE_SIGACTION
......
...@@ -3,9 +3,9 @@ noinst_LIBRARIES = libmailutils.a ...@@ -3,9 +3,9 @@ noinst_LIBRARIES = libmailutils.a
3 3
4 SUBDIRS = posix 4 SUBDIRS = posix
5 5
6 INCLUDES = -I${top_srcdir}/include 6 INCLUDES = -I${top_srcdir}/include
7 libmailutils_a_SOURCES = basename.c getopt.c getopt1.c md5.c mu_dbm.c getline.c \ 7 libmailutils_a_SOURCES = basename.c daemon.c getopt.c getopt1.c md5.c \
8 xstrdup.c xmalloc.c argcv.c 8 mu_dbm.c getline.c xstrdup.c xmalloc.c argcv.c
9 9
10 EXTRA_DIST = alloca.c fnmatch.c setenv.c snprintf.c strchrnul.c strndup.c \ 10 EXTRA_DIST = alloca.c fnmatch.c setenv.c snprintf.c strchrnul.c strndup.c \
11 strnlen.c strtok_r.c strsignal.c xstrtol.c vasprintf.c malloc.c realloc.c \ 11 strnlen.c strtok_r.c strsignal.c xstrtol.c vasprintf.c malloc.c realloc.c \
......
1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <config.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <signal.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36
37 #ifdef HAVE_PATHS_H
38 # include <paths.h>
39 #endif
40
41 #ifndef _PATH_DEVNULL
42 # define _PATH_DEVNULL "/dev/null"
43 #endif
44
45 /*
46 According to Unix-FAQ maintained by Andrew Gierth:
47
48 1.fork() so the parent can exit, this returns control to the command
49 line or shell invoking your program. This step is required so that the
50 new process is guaranteed not to be a process group leader. The next
51 step, setsid(), fails if you're a process group leader.
52
53 2.setsid() to become a process group and session group leader. Since a
54 controlling terminal is associated with a session, and this new session
55 has not yet acquired a controlling terminal our process now has no
56 controlling terminal, which is a Good Thing for daemons.
57
58 3.fork() again so the parent, (the session group leader), can exit. This
59 means that we, as a non-session group leader, can never regain a
60 controlling terminal.
61
62 4.chdir("/") to ensure that our process doesn't keep any directory in use.
63 Failure to do this could make it so that an administrator couldn't unmount
64 a filesystem, because it was our current directory.
65 [Equivalently, we could change to any directory containing files important
66 to the daemon's operation.]
67
68 5.umask(0) so that we have complete control over the permissions of
69 anything we write. We don't know what umask we may have inherited.
70 [This step is optional]
71
72 6.close() fds 0, 1, and 2. This releases the standard in, out, and error
73 we inherited from our parent process. We have no way of knowing where
74 these fds might have been redirected to. Note that many daemons use
75 sysconf() to determine the limit _SC_OPEN_MAX. _SC_OPEN_MAX tells you the
76 maximun open files/process. Then in a loop, the daemon can close all
77 possible file descriptors. You have to decide if you need to do this or not.
78 If you think that there might be file-descriptors open you should close
79 them, since there's a limit on number of concurrent file descriptors.
80
81 7.Establish new open descriptors for stdin, stdout and stderr. Even if
82 you don't plan to use them, it is still a good idea to have them open.
83 The precise handling of these is a matter of taste; if you have a logfile,
84 for example, you might wish to open it as stdout or stderr, and open
85 `/dev/null' as stdin; alternatively, you could open `/dev/console' as
86 stderr and/or stdout, and `/dev/null' as stdin, or any other combination
87 that makes sense for your particular daemon. */
88
89 #define MAXFD 64
90
91 void
92 waitdaemon_timeout (int signo)
93 {
94 int left;
95
96 (void)signo;
97 left = alarm (0);
98 signal (SIGALRM, SIG_DFL);
99 if (left == 0)
100 errx (1, "timed out waiting for child");
101 }
102
103 /* waitdaemon is like daemon, but optionally the parent pause up
104 until maxwait before exiting. Return -1, on error, otherwise
105 waitdaemon will return the pid of the parent. */
106
107 int
108 waitdaemon (int nochdir, int noclose, int maxwait)
109 {
110 int fd;
111 pid_t childpid;
112 pid_t ppid;
113
114 ppid = getpid ();
115
116 switch (childpid = fork ())
117 {
118 case -1: /* Something went wrong. */
119 return (-1);
120
121 case 0: /* In the child. */
122 break;
123
124 default: /* In the parent. */
125 if (maxwait > 0)
126 {
127 signal (SIGALRM, waitdaemon_timeout);
128 alarm (maxwait);
129 pause ();
130 }
131 _exit(0);
132 }
133
134 if (setsid () == -1)
135 return -1;
136
137 /* SIGHUP is ignore because when the session leader terminates
138 all process in the session (the second child) are sent the SIGHUP. */
139 signal (SIGHUP, SIG_IGN);
140
141 switch (fork ())
142 {
143 case 0:
144 break;
145
146 case -1:
147 return -1;
148
149 default:
150 _exit (0);
151 }
152
153 if (!nochdir)
154 chdir ("/");
155
156 if (!noclose)
157 {
158 int i;
159 long fdlimit = -1;
160
161 #if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
162 fdlimit = sysconf (_SC_OPEN_MAX);
163 #elif defined (HAVE_GETDTABLESIZE)
164 fdlimit = getdtablesize ();
165 #endif
166
167 if (fdlimit == -1)
168 fdlimit = MAXFD;
169
170 for (i = 0; i < fdlimit; i++)
171 close (i);
172
173 fd = open (_PATH_DEVNULL, O_RDWR, 0);
174 if (fd != -1)
175 {
176 dup2 (fd, STDIN_FILENO);
177 dup2 (fd, STDOUT_FILENO);
178 dup2 (fd, STDERR_FILENO);
179 if (fd > 2)
180 close (fd);
181 }
182 }
183 return ppid;
184 }
185
186 int
187 daemon (int nochdir, int noclose)
188 {
189 return (waitdaemon (nochdir, noclose, 0) == -1) ? -1 : 0;
190 }
...@@ -151,9 +151,11 @@ main (int argc, char **argv) ...@@ -151,9 +151,11 @@ main (int argc, char **argv)
151 151
152 if (mode == DAEMON) 152 if (mode == DAEMON)
153 pop3d_daemon_init (); 153 pop3d_daemon_init ();
154 154 else
155 /* Make sure we are in the root directory. */ 155 {
156 chdir ("/"); 156 /* Make sure we are in the root directory. */
157 chdir ("/");
158 }
157 159
158 /* Set up for syslog. */ 160 /* Set up for syslog. */
159 openlog ("gnu-pop3d", LOG_PID, LOG_FACILITY); 161 openlog ("gnu-pop3d", LOG_PID, LOG_FACILITY);
...@@ -179,43 +181,15 @@ main (int argc, char **argv) ...@@ -179,43 +181,15 @@ main (int argc, char **argv)
179 static void 181 static void
180 pop3d_daemon_init (void) 182 pop3d_daemon_init (void)
181 { 183 {
182 pid_t pid; 184 extern int daemon (int, int);
183
184 pid = fork ();
185 if (pid == -1)
186 {
187 perror ("fork failed:");
188 exit (EXIT_FAILURE);
189 }
190 else if (pid > 0)
191 exit (EXIT_SUCCESS); /* Parent exits. */
192
193 setsid (); /* Become session leader. */
194 185
195 signal (SIGHUP, SIG_IGN); /* Ignore SIGHUP. */ 186 /* Become a daemon. Take care to close inherited fds and to hold
196 187 first three one, in, out, err */
197 /* The second fork is to guarantee that the daemon cannot acquire a 188 if (daemon (0, 0) < 0)
198 controlling terminal. */
199 pid = fork ();
200 if (pid == -1)
201 { 189 {
202 perror("fork failed:"); 190 perror ("failed to become a daemon:");
203 exit (EXIT_FAILURE); 191 exit (EXIT_FAILURE);
204 } 192 }
205 else if (pid > 0)
206 exit (EXIT_SUCCESS); /* Parent exits. */
207
208 /* Close inherited file descriptors. */
209 {
210 size_t i;
211 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
212 size_t fdlimit = sysconf(_SC_OPEN_MAX);
213 #else
214 size_t fdlimit = 64;
215 #endif
216 for (i = 0; i < fdlimit; ++i)
217 close (i);
218 }
219 193
220 /* SIGCHLD is not ignore but rather use to do some simple load balancing. */ 194 /* SIGCHLD is not ignore but rather use to do some simple load balancing. */
221 #ifdef HAVE_SIGACTION 195 #ifdef HAVE_SIGACTION
......