/* signal handlers are crazy...
 * apparently only a very limited number of functions are 
 * safe to be used inside a signal handler.
 *
 * If this file is compiled with BROKEN defined,
 * the fork/execed childs SIGHUP signal handler will never be called.
 * (first sighup will work, then nothing....)
 *
 * see signal(7) for the list of "Async-signal-safe functions".
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <sys/types.h>
#include <unistd.h>


#if !defined(BROKEN)
static int reexec = 0;
#endif

static char **args;

void signal_handler (int signum)
{
	printf("Received signal %d\n", signum);

	if (signum == SIGHUP) {
#if defined (BROKEN)
		int pid = fork();
		if (pid == 0) {
			execvp(args[0], args);
			/* never reached? */
			exit(-1);
		} else {
			printf("SIGHUP received, child started: %d\n", pid);
		}
#else
		reexec = 1;
		return;
#endif
	}

	printf("Shutting down...\n");
	exit(0);
}

int main (int argc, char **argv)
{
	static struct sigaction sa;

	args = argv;

	sa.sa_handler = signal_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;

	if (sigaction (SIGINT, &sa, NULL) < 0) perror ("sigaction SIGINT");
	if (sigaction (SIGHUP, &sa, NULL) < 0) perror ("sigaction SIGHUP");

	printf("Started up with pid %d\n", getpid());

	while (1)
	{
		struct sigaction old;

#if !defined(BROKEN)
		if (reexec == 1)
		{
			int pid = fork();
			if (pid == 0) {
				execvp(args[0], args);
				/* never reached? */
				exit(-1);
			} else {
				printf("SIGHUP received, child started: %d\n", pid);
				exit(0);
			}
		}
#endif
		printf("zZzzzZzzz....\n");
		sleep(3);
		sigaction(SIGHUP, NULL, &old);
		if (old.sa_handler == signal_handler)
			printf("SIGHUP is handled by signal_handler\n");
		else if (old.sa_handler = SIG_DFL)
			printf("SIGHUP is handled by SIG_DFL\n");
		else
			printf("SIGHUP has unknown handler\n");

	}

	return 0;
}
