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