#ifndef __supervise_h
#define __supervise_h

#include "config.h"

#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

#ifndef HAVE_SYSLOG
static void inline supervise(char *x)
{
	fatal("You probably don't want to supervise when you cannot log");
}
#else
static int supervised_pid = -1;
static int supervised_quit = 0;
static void handle_sign(int signo)
{
	if (supervised_pid != -1) {
		kill(supervised_pid, signo);
		supervised_quit = 1;
	}
}
static void inline supervise(char *x)
{
	int fd, status;
	int super_pid;
	/* GOOD DAEMON PRACTICES */

	/* do first fork */
	signal(SIGCHLD, SIG_IGN);
	switch (fork()) {
	case -1: cfatal("fork: %s");
	case 0: break;
	default: exit(0);
	};

	/* be a proper daemon */
	fd = open("/dev/null", O_RDWR);
	if (fd != 0) { close(0); dup2(fd, 0); }
	if (fd != 1) { close(1); dup2(fd, 1); }
	if (fd != 2) { close(2); dup2(fd, 2); }
	if (fd > 2) { close(fd); }

	super_pid = getpid();
#ifdef HAVE_SETSID
	/* change session ID if possible */
	(void) setsid();
#endif
	/* signore Sigpipe */
	signal(SIGPIPE, SIG_IGN);

	/* we want child notification */
	signal(SIGCHLD, SIG_DFL);

	/* setup other signals */
	signal(SIGSTOP, handle_sign);
	signal(SIGCONT, handle_sign);
	signal(SIGTERM, handle_sign);
	signal(SIGHUP, handle_sign);
	signal(SIGINT, handle_sign);

	/* do second fork */
restart_from_child_l:
	switch ((supervised_pid = fork())) {
	case -1: cfatal("fork: %s");
	case 0: /* child */ return;
	};

	/* pid file */
	if (x && *x == '/') {
		FILE *fp;

		fp = fopen(x, "w");
		fprintf(fp, "%d\n", super_pid);
		fclose(fp);
	}

wait_some_more_l:
#ifdef HAVE_WAITPID
	waitpid(supervised_pid, &status, 0);
#else
#ifdef HAVE_WAIT4
	wait4(supervised_pid, &status, 0, NULL);
#else
	while (wait(&status) != supervised_pid);
#endif
#endif
	if (kill(supervised_pid, 0) == -1) {
		sleep(1); /* go to sleep for 1 second */
		if ((volatile)supervised_quit)
			exit(0);
		/* wasn't supposed to be dead yet... */
		goto restart_from_child_l;
	}
	supervised_quit = 0;
	goto wait_some_more_l;
}
#endif

#endif


syntax highlighted by Code2HTML, v. 0.9.1