Home | History | Annotate | Line # | Download | only in master
      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