/** * \file sig.c * * \brief Signal handling routines for PennMUSH. * * */ #include "config.h" #include <signal.h> #include "conf.h" #include "externs.h" #include "confmagic.h" #ifndef HAS_SIGPROCMASK static Sigfunc saved_handlers[NSIG]; #endif /** Our own version of signal(). * We're going to rewrite the signal() function in terms of * sigaction, where available, to ensure consistent semantics. * We want signal handlers to remain installed, and we want * signals (except SIGALRM) to restart system calls which they * interrupt. This is how bsd signals work, and what we'd like. * This function is essentially example 10.12 from Stevens' * _Advanced Programming in the Unix Environment_. * \param signo signal number. * \param func signal handler function to install. * \return former signal handler for signo. */ Sigfunc install_sig_handler(int signo, Sigfunc func) { #ifdef HAS_SIGACTION struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; #ifdef SA_RESTART act.sa_flags |= SA_RESTART; #endif if (sigaction(signo, &act, &oact) < 0) return SIG_ERR; return oact.sa_handler; #else /* No sigaction, drat. */ return signal(signo, func); #endif } /** Reinstall a signal handler. * \param signo the signal number. * \param func signal handler function to reload. */ void reload_sig_handler(int signo __attribute__ ((__unused__)), Sigfunc func __attribute__ ((__unused__))) { #if !(defined(HAS_SIGACTION) || defined(SIGNALS_KEPT)) signal(signo, func); #endif } /** Set a signal to be ignored. * \param signo signal number to ignore. */ void ignore_signal(int signo) { #ifdef HAS_SIGACTION struct sigaction act; act.sa_handler = SIG_IGN; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(signo, &act, NULL); #else /* No sigaction, drat. */ signal(signo, SIG_IGN); #endif } /** Set a signal to block. * These don't really work right without sigprocmask(), but we try. * \param signo signal number to block. */ void block_a_signal(int signo) { #ifdef HAS_SIGPROCMASK sigset_t mask; sigemptyset(&mask); sigaddset(&mask, signo); sigprocmask(SIG_BLOCK, &mask, NULL); #else if (signo > 0 && signo < NSIG) saved_handlers[signo] = signal(signo, SIG_IGN); #endif } /** Unblock a signal. * These don't really work right without sigprocmask(), but we try. * \param signo signal number to unblock. */ void unblock_a_signal(int signo) { #ifdef HAS_SIGPROCMASK sigset_t mask; if (signo >= 0 && signo < NSIG) { sigemptyset(&mask); sigaddset(&mask, signo); sigprocmask(SIG_UNBLOCK, &mask, NULL); } #else if (signo >= 0 && signo < NSIG) signal(signo, saved_handlers[signo]); #endif } /** Block all signals. */ void block_signals(void) { #ifdef HAS_SIGPROCMASK sigset_t mask; sigfillset(&mask); sigprocmask(SIG_BLOCK, &mask, NULL); #else int i; for (i = 0; i < NSIG; i++) signal(i, SIG_IGN); #endif }