117721Speter/* sighandle.c -- Library routines for manipulating chains of signal handlers 217721Speter Copyright (C) 1992 Free Software Foundation, Inc. 317721Speter 417721Speter This program is free software; you can redistribute it and/or modify 517721Speter it under the terms of the GNU General Public License as published by 617721Speter the Free Software Foundation; either version 2, or (at your option) 717721Speter any later version. 817721Speter 917721Speter This program is distributed in the hope that it will be useful, 1017721Speter but WITHOUT ANY WARRANTY; without even the implied warranty of 1117721Speter MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1225839Speter GNU General Public License for more details. */ 1317721Speter 1417721Speter/* Written by Paul Sander, HaL Computer Systems, Inc. <paul@hal.com> 1517721Speter Brian Berliner <berliner@Sun.COM> added POSIX support */ 1617721Speter 1717721Speter/************************************************************************* 1817721Speter * 1917721Speter * signal.c -- This file contains code that manipulates chains of signal 2017721Speter * handlers. 2117721Speter * 2217721Speter * Facilities are provided to register a signal handler for 2317721Speter * any specific signal. When a signal is received, all of the 2417721Speter * registered signal handlers are invoked in the reverse order 2517721Speter * in which they are registered. Note that the signal handlers 2617721Speter * must not themselves make calls to the signal handling 2717721Speter * facilities. 2817721Speter * 2917721Speter *************************************************************************/ 3017721Speter 3117721Speter#ifdef HAVE_CONFIG_H 3217721Speter#include "config.h" 3317721Speter#endif 3417721Speter#include "system.h" 3517721Speter 3617721Speter#include <sys/types.h> 3717721Speter#include <stdio.h> 3817721Speter#include <signal.h> 3917721Speter 4017721Speter/* Add prototype support. */ 4117721Speter#ifndef PROTO 4217721Speter#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) 4317721Speter#define PROTO(ARGS) ARGS 4417721Speter#else 4517721Speter#define PROTO(ARGS) () 4617721Speter#endif 4717721Speter#endif 4817721Speter 4917721Speter#ifdef STDC_HEADERS 5017721Speter#include <stdlib.h> 5117721Speter#else 5217721Speter#if __STDC__ 5317721Speterchar *calloc(unsigned nelem, unsigned size); 5417721Speterchar *malloc(unsigned size); 5517721Speter#else 5617721Speterchar *calloc(); 5717721Speterchar *malloc(); 5817721Speter#endif /* __STDC__ */ 5917721Speter#endif /* STDC_HEADERS */ 6017721Speter 6117721Speter/* Define the highest signal number (usually) */ 6217721Speter#ifndef SIGMAX 6317721Speter#define SIGMAX 64 6417721Speter#endif 6517721Speter 6617721Speter/* Define linked list of signal handlers structure */ 6717721Speterstruct SIG_hlist { 6817721Speter RETSIGTYPE (*handler)(); 6917721Speter struct SIG_hlist *next; 7017721Speter}; 7117721Speter 7217721Speter/* 7317721Speter * Define array of lists of signal handlers. Note that this depends on 7417721Speter * the implementation to initialize each element to a null pointer. 7517721Speter */ 7617721Speter 7717721Speterstatic struct SIG_hlist **SIG_handlers; 7817721Speter 7917721Speter/* Define array of default signal vectors */ 8017721Speter 8117721Speter#ifdef POSIX_SIGNALS 8217721Speterstatic struct sigaction *SIG_defaults; 8317721Speter#else 8417721Speter#ifdef BSD_SIGNALS 8517721Speterstatic struct sigvec *SIG_defaults; 8617721Speter#else 8717721Speterstatic RETSIGTYPE (**SIG_defaults) PROTO ((int)); 8817721Speter#endif 8917721Speter#endif 9017721Speter 9117721Speter/* Critical section housekeeping */ 9217721Speterstatic int SIG_crSectNest = 0; /* Nesting level */ 9317721Speter#ifdef POSIX_SIGNALS 9417721Speterstatic sigset_t SIG_crSectMask; /* Signal mask */ 9517721Speter#else 9617721Speterstatic int SIG_crSectMask; /* Signal mask */ 9717721Speter#endif 9817721Speter 9917721Speter/* 10017721Speter * Initialize the signal handler arrays 10117721Speter */ 10217721Speter 10317721Speterstatic int SIG_init() 10417721Speter{ 10517721Speter int i; 10617721Speter#ifdef POSIX_SIGNALS 10717721Speter sigset_t sigset_test; 10817721Speter#endif 10917721Speter 11017721Speter if (SIG_defaults && SIG_handlers) /* already allocated */ 11117721Speter return (0); 11217721Speter 11317721Speter#ifdef POSIX_SIGNALS 11417721Speter (void) sigfillset(&sigset_test); 11517721Speter for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++) 11617721Speter ; 11717721Speter if (i < SIGMAX) 11817721Speter i = SIGMAX; 11917721Speter i++; 12017721Speter if (!SIG_defaults) 12117721Speter SIG_defaults = (struct sigaction *) 12217721Speter calloc(i, sizeof(struct sigaction)); 12317721Speter (void) sigemptyset(&SIG_crSectMask); 12417721Speter#else 12517721Speter i = SIGMAX+1; 12617721Speter#ifdef BSD_SIGNALS 12717721Speter if (!SIG_defaults) 12817721Speter SIG_defaults = (struct sigvec *) 12917721Speter calloc(i, sizeof(struct sigvec)); 13017721Speter#else 13117721Speter if (!SIG_defaults) 13217721Speter SIG_defaults = (RETSIGTYPE (**) PROTO ((int)) ) 13317721Speter calloc(i, sizeof(RETSIGTYPE (**) PROTO ((int)) )); 13417721Speter#endif 13517721Speter SIG_crSectMask = 0; 13617721Speter#endif 13717721Speter if (!SIG_handlers) 13817721Speter SIG_handlers = (struct SIG_hlist **) 13917721Speter calloc(i, sizeof(struct SIG_hlist *)); 14017721Speter return (!SIG_defaults || !SIG_handlers); 14117721Speter} 14217721Speter 14317721Speter/* 14417721Speter * The following invokes each signal handler in the reverse order in which 14517721Speter * they were registered. 14617721Speter */ 14717721Speterstatic RETSIGTYPE SIG_handle PROTO ((int)); 14817721Speter 14917721Speterstatic RETSIGTYPE SIG_handle(sig) 15017721Speterint sig; 15117721Speter{ 15217721Speter struct SIG_hlist *this; 15317721Speter 15417721Speter /* Dispatch signal handlers */ 15517721Speter this = SIG_handlers[sig]; 15617721Speter while (this != (struct SIG_hlist *) NULL) 15717721Speter { 15817721Speter (*this->handler)(sig); 15917721Speter this = this->next; 16017721Speter } 16117721Speter 16217721Speter return; 16317721Speter} 16417721Speter 16517721Speter/* 16617721Speter * The following registers a signal handler. If the handler is already 16717721Speter * registered, it is not registered twice, nor is the order in which signal 16817721Speter * handlers are invoked changed. If this is the first signal handler 16917721Speter * registered for a given signal, the old sigvec structure is saved for 17017721Speter * restoration later. 17117721Speter */ 17217721Speter 17317721Speterint SIG_register(sig,fn) 17417721Speterint sig; 17517721SpeterRETSIGTYPE (*fn)(); 17617721Speter{ 17717721Speter int val; 17817721Speter struct SIG_hlist *this; 17917721Speter#ifdef POSIX_SIGNALS 18017721Speter struct sigaction act; 18117721Speter sigset_t sigset_mask, sigset_omask; 18217721Speter#else 18317721Speter#ifdef BSD_SIGNALS 18417721Speter struct sigvec vec; 18517721Speter int mask; 18617721Speter#endif 18717721Speter#endif 18817721Speter 18917721Speter /* Initialize */ 19017721Speter if (SIG_init() != 0) 19117721Speter return (-1); 19217721Speter val = 0; 19317721Speter 19417721Speter /* Block this signal while we look at handler chain */ 19517721Speter#ifdef POSIX_SIGNALS 19617721Speter (void) sigemptyset(&sigset_mask); 19717721Speter (void) sigaddset(&sigset_mask, sig); 19817721Speter (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask); 19917721Speter#else 20017721Speter#ifdef BSD_SIGNALS 20117721Speter mask = sigblock(sigmask(sig)); 20217721Speter#endif 20317721Speter#endif 20417721Speter 20517721Speter /* See if this handler was already registered */ 20617721Speter this = SIG_handlers[sig]; 20717721Speter while (this != (struct SIG_hlist *) NULL) 20817721Speter { 20917721Speter if (this->handler == fn) break; 21017721Speter this = this->next; 21117721Speter } 21217721Speter 21317721Speter /* Register the new handler only if it is not already registered. */ 21417721Speter if (this == (struct SIG_hlist *) NULL) 21517721Speter { 21617721Speter 21717721Speter /* 21817721Speter * If this is the first handler registered for this signal, 21917721Speter * set up the signal handler dispatcher 22017721Speter */ 22117721Speter 22217721Speter if (SIG_handlers[sig] == (struct SIG_hlist *) NULL) 22317721Speter { 22417721Speter#ifdef POSIX_SIGNALS 22517721Speter act.sa_handler = SIG_handle; 22617721Speter (void) sigemptyset(&act.sa_mask); 22717721Speter act.sa_flags = 0; 22817721Speter val = sigaction(sig, &act, &SIG_defaults[sig]); 22917721Speter#else 23017721Speter#ifdef BSD_SIGNALS 23117721Speter memset (&vec, 0, sizeof (vec)); 23217721Speter vec.sv_handler = SIG_handle; 23317721Speter val = sigvec(sig, &vec, &SIG_defaults[sig]); 23417721Speter#else 23517721Speter if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR) 23617721Speter val = -1; 23717721Speter#endif 23817721Speter#endif 23917721Speter } 24017721Speter 24117721Speter /* If not, register it */ 24217721Speter if ((val == 0) && (this == (struct SIG_hlist *) NULL)) 24317721Speter { 24417721Speter this = (struct SIG_hlist *) 24517721Speter malloc(sizeof(struct SIG_hlist)); 24617721Speter if (this == NULL) 24717721Speter { 24817721Speter val = -1; 24917721Speter } 25017721Speter else 25117721Speter { 25217721Speter this->handler = fn; 25317721Speter this->next = SIG_handlers[sig]; 25417721Speter SIG_handlers[sig] = this; 25517721Speter } 25617721Speter } 25717721Speter } 25817721Speter 25917721Speter /* Unblock the signal */ 26017721Speter#ifdef POSIX_SIGNALS 26117721Speter (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL); 26217721Speter#else 26317721Speter#ifdef BSD_SIGNALS 26417721Speter (void) sigsetmask(mask); 26517721Speter#endif 26617721Speter#endif 26717721Speter 26817721Speter return val; 26917721Speter} 27017721Speter 27117721Speter/* 27217721Speter * The following deregisters a signal handler. If the last signal handler for 27317721Speter * a given signal is deregistered, the default sigvec information is restored. 27417721Speter */ 27517721Speter 27617721Speterint SIG_deregister(sig,fn) 27717721Speterint sig; 27817721SpeterRETSIGTYPE (*fn)(); 27917721Speter{ 28017721Speter int val; 28117721Speter struct SIG_hlist *this; 28217721Speter struct SIG_hlist *last; 28317721Speter#ifdef POSIX_SIGNALS 28417721Speter sigset_t sigset_mask, sigset_omask; 28517721Speter#else 28617721Speter#ifdef BSD_SIGNALS 28717721Speter int mask; 28817721Speter#endif 28917721Speter#endif 29017721Speter 29117721Speter /* Initialize */ 29217721Speter if (SIG_init() != 0) 29317721Speter return (-1); 29417721Speter val = 0; 29517721Speter last = (struct SIG_hlist *) NULL; 29617721Speter 29717721Speter /* Block this signal while we look at handler chain */ 29817721Speter#ifdef POSIX_SIGNALS 29917721Speter (void) sigemptyset(&sigset_mask); 30017721Speter (void) sigaddset(&sigset_mask, sig); 30117721Speter (void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask); 30217721Speter#else 30317721Speter#ifdef BSD_SIGNALS 30417721Speter mask = sigblock(sigmask(sig)); 30517721Speter#endif 30617721Speter#endif 30717721Speter 30817721Speter /* Search for the signal handler */ 30917721Speter this = SIG_handlers[sig]; 31017721Speter while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn)) 31117721Speter { 31217721Speter last = this; 31317721Speter this = this->next; 31417721Speter } 31517721Speter 31617721Speter /* If it was registered, remove it */ 31717721Speter if (this != (struct SIG_hlist *) NULL) 31817721Speter { 31917721Speter if (last == (struct SIG_hlist *) NULL) 32017721Speter { 32117721Speter SIG_handlers[sig] = this->next; 32217721Speter } 32317721Speter else 32417721Speter { 32517721Speter last->next = this->next; 32617721Speter } 32717721Speter free((char *) this); 32817721Speter } 32917721Speter 33017721Speter /* Restore default behavior if there are no registered handlers */ 33117721Speter if (SIG_handlers[sig] == (struct SIG_hlist *) NULL) 33217721Speter { 33317721Speter#ifdef POSIX_SIGNALS 33417721Speter val = sigaction(sig, &SIG_defaults[sig], 33517721Speter (struct sigaction *) NULL); 33617721Speter#else 33717721Speter#ifdef BSD_SIGNALS 33817721Speter val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL); 33917721Speter#else 34017721Speter if (signal(sig, SIG_defaults[sig]) == SIG_ERR) 34117721Speter val = -1; 34217721Speter#endif 34317721Speter#endif 34417721Speter } 34517721Speter 34617721Speter /* Unblock the signal */ 34717721Speter#ifdef POSIX_SIGNALS 34817721Speter (void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL); 34917721Speter#else 35017721Speter#ifdef BSD_SIGNALS 35117721Speter (void) sigsetmask(mask); 35217721Speter#endif 35317721Speter#endif 35417721Speter 35517721Speter return val; 35617721Speter} 35717721Speter 35817721Speter/* 35917721Speter * The following begins a critical section. 36017721Speter */ 36117721Speter 36217721Spetervoid SIG_beginCrSect() 36317721Speter{ 36417721Speter if (SIG_init() == 0) 36517721Speter { 36617721Speter if (SIG_crSectNest == 0) 36717721Speter { 36817721Speter#ifdef POSIX_SIGNALS 36917721Speter sigset_t sigset_mask; 37017721Speter 37117721Speter (void) sigfillset(&sigset_mask); 37217721Speter (void) sigprocmask(SIG_SETMASK, 37317721Speter &sigset_mask, &SIG_crSectMask); 37417721Speter#else 37517721Speter#ifdef BSD_SIGNALS 37617721Speter SIG_crSectMask = sigblock(~0); 37717721Speter#else 37817721Speter /* TBD */ 37917721Speter#endif 38017721Speter#endif 38117721Speter } 38217721Speter SIG_crSectNest++; 38317721Speter } 38417721Speter} 38517721Speter 38617721Speter/* 38766525Speter * Return nonzero if currently in a critical section. 38866525Speter * Otherwise return zero. 38966525Speter */ 39066525Speter 39166525Speterint SIG_inCrSect() 39266525Speter{ 39366525Speter return SIG_crSectNest > 0; 39466525Speter} 39566525Speter 39666525Speter/* 39717721Speter * The following ends a critical section. 39817721Speter */ 39917721Speter 40017721Spetervoid SIG_endCrSect() 40117721Speter{ 40217721Speter if (SIG_init() == 0) 40317721Speter { 40417721Speter SIG_crSectNest--; 40517721Speter if (SIG_crSectNest == 0) 40617721Speter { 40717721Speter#ifdef POSIX_SIGNALS 40817721Speter (void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL); 40917721Speter#else 41017721Speter#ifdef BSD_SIGNALS 41117721Speter (void) sigsetmask(SIG_crSectMask); 41217721Speter#else 41317721Speter /* TBD */ 41417721Speter#endif 41517721Speter#endif 41617721Speter } 41717721Speter } 41817721Speter} 419