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