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 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