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