xref: /netbsd-src/external/ibm-public/postfix/dist/src/master/master_monitor.c (revision 67b9b338a7386232ac596b5fd0cd5a9cc8a03c71)
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