xref: /netbsd-src/external/ibm-public/postfix/dist/src/master/master_monitor.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /*	$NetBSD: master_monitor.c,v 1.1.1.1 2013/09/25 19:06:32 tron 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 
37 /* System library. */
38 
39 #include <sys_defs.h>
40 #include <signal.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 
44 /* Utility library. */
45 
46 #include <msg.h>
47 #include <iostuff.h>
48 
49 /* Application-specific. */
50 
51 #include <master.h>
52 
53 /* master_monitor - fork off a foreground monitor process */
54 
55 int     master_monitor(int time_limit)
56 {
57     pid_t   pid;
58     int     pipes[2];
59     char    buf[1];
60 
61     /*
62      * Sanity check.
63      */
64     if (time_limit <= 0)
65 	msg_panic("master_monitor: bad time limit: %d", time_limit);
66 
67     /*
68      * Set up the plumbing for child-to-parent communication.
69      */
70     if (pipe(pipes) < 0)
71 	msg_fatal("pipe: %m");
72     close_on_exec(pipes[0], CLOSE_ON_EXEC);
73     close_on_exec(pipes[1], CLOSE_ON_EXEC);
74 
75     /*
76      * Fork the child, and wait for it to report successful initialization.
77      */
78     switch (pid = fork()) {
79     case -1:
80 	/* Error. */
81 	msg_fatal("fork: %m");
82     case 0:
83 	/* Child. Initialize as daemon in the background. */
84 	close(pipes[0]);
85 	return (pipes[1]);
86     default:
87 	/* Parent. Monitor the child in the foreground. */
88 	close(pipes[1]);
89 	switch (timed_read(pipes[0], buf, 1, time_limit, (char *) 0)) {
90 	default:
91 	    /* The child process still runs, but something is wrong. */
92 	    (void) kill(pid, SIGKILL);
93 	    /* FALLTHROUGH */
94 	case 0:
95 	    /* The child process exited prematurely. */
96 	    msg_fatal("daemon initialization failure");
97 	case 1:
98 	    /* The child process initialized successfully. */
99 	    exit(0);
100 	}
101     }
102 }
103