diff options
-rw-r--r-- | lib/ChangeLog | 5 | ||||
-rw-r--r-- | lib/sigevent.c | 147 | ||||
-rw-r--r-- | lib/sigevent.h | 49 |
3 files changed, 201 insertions, 0 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog index 2533c75c..ab2489d0 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,8 @@ +2004-01-19 Paul Jakma <paul@dishone.st> + + * sigevent.{c,h}: New files, implement event handled signals. + see signal_init() in sigevent.h. + 2003-12-23 Vincent Jardin <jardin@6wind.com> * {command.c, memory.c, vty.c, zebra.h}: Add isisd support diff --git a/lib/sigevent.c b/lib/sigevent.c new file mode 100644 index 00000000..fa5edf4a --- /dev/null +++ b/lib/sigevent.c @@ -0,0 +1,147 @@ +/* Quagga signal handling functions. + * Copyright (C) 2004 Paul Jakma, + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <zebra.h> +#include <sigevent.h> +#include <log.h> + +struct quagga_sigevent_master_t +{ + struct thread_master *tm; + struct thread *t; + + struct quagga_signal_t *signals; + int sigc; + +} sigmaster; + +/* Generic signal handler + * Schedules signal event thread + */ +void +quagga_signal_handler (int signo) +{ + int i; + struct quagga_signal_t *sig; + + for (i = 0; i < sigmaster.sigc; i++) + { + sig = &(sigmaster.signals[i]); + + if (sig->signal == signo) + sig->caught++; + } +} + +int +quagga_signal_timer (struct thread *t) +{ + sigset_t newmask, oldmask; + struct quagga_sigevent_master_t *sigm; + struct quagga_signal_t *sig; + int i; + + sigm = THREAD_ARG (t); + + /* block all signals */ + sigfillset (&newmask); + if ( (sigprocmask (SIG_BLOCK, &newmask, &oldmask)) < 0) + { + zlog_err ("quagga_signal_timer: couldnt block signals!"); + sigm->t = thread_add_timer (sigm->tm, quagga_signal_timer, + &sigmaster, QUAGGA_SIGNAL_TIMER_INTERVAL); + return -1; + } + + for (i = 0; i < sigm->sigc; i++) + { + sig = &(sigm->signals[i]); + if (sig->caught > 0) + { + sig->caught = 0; + sig->handler(); + } + } + + sigm->t = thread_add_timer (sigm->tm, quagga_signal_timer, &sigmaster, + QUAGGA_SIGNAL_TIMER_INTERVAL); + + if ( sigprocmask (SIG_UNBLOCK, &oldmask, NULL) < 0 ); + return -1; + + return 0; +} + +/* Initialization of signal handles. */ +/* Signale wrapper. */ +int +signal_set (int signo) +{ + int ret; + struct sigaction sig; + struct sigaction osig; + + sig.sa_handler = &quagga_signal_handler; + sigfillset (&sig.sa_mask); + sig.sa_flags = 0; + if (signo == SIGALRM) { +#ifdef SA_INTERRUPT + sig.sa_flags |= SA_INTERRUPT; /* SunOS */ +#endif + } else { +#ifdef SA_RESTART + sig.sa_flags |= SA_RESTART; +#endif /* SA_RESTART */ + } + + ret = sigaction (signo, &sig, &osig); + if (ret < 0) + return ret; + else + return 0; +} + +void +signal_init (struct thread_master *m, + int sigc, struct quagga_signal_t signals[]) +{ + + int i = 0; + struct quagga_signal_t *sig; + + while (i < sigc) + { + sig = &signals[i]; + if ( signal_set (sig->signal) < 0 ) + exit (-1); + i++; + } + + sigmaster.sigc = sigc; + sigmaster.signals = signals; + sigmaster.tm = m; + + sigmaster.t = + thread_add_timer (m, quagga_signal_timer, &sigmaster, + QUAGGA_SIGNAL_TIMER_INTERVAL); + +} + diff --git a/lib/sigevent.h b/lib/sigevent.h new file mode 100644 index 00000000..6296736a --- /dev/null +++ b/lib/sigevent.h @@ -0,0 +1,49 @@ +/* + * Quagga Signal handling header. + * + * Copyright (C) 2004 Paul Jakma. + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _QUAGGA_SIGNAL_H +#define _QUAGGA_SIGNAL_H +#include <thread.h> + +#define QUAGGA_SIGNAL_TIMER_INTERVAL 2L +#define Q_SIGC(sig) (sizeof(sig)/sizeof(sig[0])) + +struct quagga_signal_t +{ + int signal; /* signal number */ + void (*handler) (void); /* handler to call */ + + volatile sig_atomic_t caught; /* private member */ +}; + +/* initialise sigevent system + * takes: + * - pointer to valid struct thread_master + * - number of elements in passed in signals array + * - array of quagga_signal_t's describing signals to handle + * and handlers to use for each signal + */ +void signal_init (struct thread_master *m, int sigc, + struct quagga_signal_t *signals); + +#endif /* _QUAGGA_SIGNAL_H */ |