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