1 /*++
2 /* NAME
3 /* master_monitor 3
4 /* SUMMARY
5 /* Postfix master - start-up monitoring
6 /* SYNOPSIS
7 /* #include "master.h"
8 /*
9 /* int master_monitor(time_limit)
10 /* int time_limit;
11 /* DESCRIPTION
12 /* master_monitor() forks off a background child process, and
13 /* returns in the child. The result value is the file descriptor
14 /* on which the child process must write one byte after it
15 /* completes successful initialization as a daemon process.
16 /*
17 /* The foreground process waits for the child's completion for
18 /* a limited amount of time. It terminates with exit status 0
19 /* in case of success, non-zero otherwise.
20 /* DIAGNOSTICS
21 /* Fatal errors: system call failure.
22 /* BUGS
23 /* SEE ALSO
24 /* LICENSE
25 /* .ad
26 /* .fi
27 /* The Secure Mailer license must be distributed with this software.
28 /* AUTHOR(S)
29 /* Wietse Venema
30 /* IBM T.J. Watson Research
31 /* P.O. Box 704
32 /* Yorktown Heights, NY 10598, USA
33 /*--*/
34
35 /* System library. */
36
37 #include <sys_defs.h>
38 #include <signal.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41
42 /* Utility library. */
43
44 #include <msg.h>
45 #include <iostuff.h>
46
47 /* Application-specific. */
48
49 #include <master.h>
50
51 /* master_monitor - fork off a foreground monitor process */
52
master_monitor(int time_limit)53 int master_monitor(int time_limit)
54 {
55 pid_t pid;
56 int pipes[2];
57 char buf[1];
58
59 /*
60 * Sanity check.
61 */
62 if (time_limit <= 0)
63 msg_panic("master_monitor: bad time limit: %d", time_limit);
64
65 /*
66 * Set up the plumbing for child-to-parent communication.
67 */
68 if (pipe(pipes) < 0)
69 msg_fatal("pipe: %m");
70 close_on_exec(pipes[0], CLOSE_ON_EXEC);
71 close_on_exec(pipes[1], CLOSE_ON_EXEC);
72
73 /*
74 * Fork the child, and wait for it to report successful initialization.
75 */
76 switch (pid = fork()) {
77 case -1:
78 /* Error. */
79 msg_fatal("fork: %m");
80 case 0:
81 /* Child. Initialize as daemon in the background. */
82 close(pipes[0]);
83 return (pipes[1]);
84 default:
85 /* Parent. Monitor the child in the foreground. */
86 close(pipes[1]);
87 switch (timed_read(pipes[0], buf, 1, time_limit, (void *) 0)) {
88 default:
89 /* The child process still runs, but something is wrong. */
90 (void) kill(pid, SIGKILL);
91 /* FALLTHROUGH */
92 case 0:
93 /* The child process exited prematurely. */
94 msg_fatal("daemon initialization failure");
95 case 1:
96 /* The child process initialized successfully. */
97 exit(0);
98 }
99 }
100 }
101