/****************************************************************************
 * Copyright (C) 1998 WIDE Project. All rights reserved.
 * Copyright (C) 1999,2000,2001,2002 University of Tromso. All rights reserved.
 * Copyright (C) 2002 Invenia Innovation AS. All rights reserved.
 *
 * Author: Feike W. Dillema, feico@pasta.cs.uit.no.
 *         based on newbie code by Yusuke DOI, Keio Univ. Murai Lab.
 ****************************************************************************/

/*
 * <$Id: ev_signal.c,v 3.21 2005/06/19 20:09:13 dillema Exp $>
 */

#include "totd.h"

static void ev_signal_initiator_generic (int sig);
static void ev_handler_sigusr1 (void);
static void ev_handler_sigusr2 (void);
static void ev_handler_cleanup (void);

/* event initiator (== signal handler) matrix */
const struct {
	int signal_id;		/* signal id */
	void (*initiator) (int);/* event initiator */
	void (*handler) (void);	/* event handler */
}   Ev_matrix[] = {
	{
		SIGINT, ev_signal_initiator_generic, ev_handler_cleanup
	},
	{
		SIGHUP, SIG_IGN, NULL
	},
	{
		SIGTERM, ev_signal_initiator_generic, ev_handler_cleanup
	},
	{
		SIGUSR1, ev_signal_initiator_generic, ev_handler_sigusr1
	},
	{
		SIGUSR2, ev_signal_initiator_generic, ev_handler_sigusr2
	},
	{
		-1, NULL, NULL
	}			/* <- terminator -- don't forget */
};

/* signal event queue */
static Q_Set *Ev_signal_queue = NULL;

/*
 * (private) generic event initiator(== signal handler)
 */
static void ev_signal_initiator_generic (int sig) {
	int i;
	Ev_Sig_Data *sd_tmp;

	if (T.debug > 2) {
		syslog (LOG_DEBUG, "ev_signal_initiator_generic(): start.");
	}

	if (!Ev_signal_queue) {
		syslog (LOG_ERR, "ev_signal_initiator_generic(): no queue to process.");
		return;
	}
	for (i = 0; Ev_matrix[i].signal_id > 0 && Ev_matrix[i].signal_id != sig; i++);

	sd_tmp = malloc (sizeof (Ev_Sig_Data));
	if (!sd_tmp) {
		syslog (LOG_WARNING, "ev_signal_initiator_generic(): memory exhausted");
		return;
	}
	sd_tmp->handler = Ev_matrix[i].handler;

	if (enqueue (Ev_signal_queue, (void *) sd_tmp) < 0)
		syslog (LOG_WARNING, "ev_signal_initiator_generic(): signal queue full?");

	return;
}

/*
 * event handlers
 */
void ev_handler_sigusr1 (void) {
	syslog (LOG_INFO, "ev_handler_sigusr1(): processing SIGUSR1");
}

void ev_handler_sigusr2 (void) {
	syslog (LOG_INFO, "ev_handler_sigusr2(): processing SIGUSR2");
}

void ev_handler_cleanup (void) {
	totd_exit (0);
}

/* == end of private section == */

/*
 * event initializer
 */
int ev_signal_init (void) {
	int i;

	/* set event initiator */
	for (i = 0; Ev_matrix[i].signal_id > 0; i++)
		signal (Ev_matrix[i].signal_id, Ev_matrix[i].initiator);

	/* initialize queue */
	Ev_signal_queue = queue_create ();
	if (!Ev_signal_queue)
		return -1;

	return 0;
}

/*
 * event dequeue/process
 */
void ev_signal_process (void) {
	Ev_Sig_Data *sd_tmp;

	if (Ev_signal_queue)
		while ((sd_tmp = (Ev_Sig_Data *) dequeue (Ev_signal_queue))) {
			(sd_tmp->handler) ();	/* process event */
			free (sd_tmp);
		}
	else
		syslog (LOG_ERR, "ev_signal_process(): no queue to process.");
}

/*
 * finish signal routine
 */
void ev_signal_finish (void) {
	/* don't process signal. It may cause event loop */
	queue_destroy (Ev_signal_queue, free);
	Ev_signal_queue = NULL;
}


syntax highlighted by Code2HTML, v. 0.9.1