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