Home | History | Annotate | Line # | Download | only in lib
sighandle.c revision 1.1.1.1.26.1
      1           1.1  christos /* sighandle.c -- Library routines for manipulating chains of signal handlers
      2           1.1  christos    Copyright (C) 1992 Free Software Foundation, Inc.
      3           1.1  christos 
      4           1.1  christos    This program is free software; you can redistribute it and/or modify
      5           1.1  christos    it under the terms of the GNU General Public License as published by
      6           1.1  christos    the Free Software Foundation; either version 2, or (at your option)
      7           1.1  christos    any later version.
      8           1.1  christos 
      9           1.1  christos    This program is distributed in the hope that it will be useful,
     10           1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11           1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12           1.1  christos    GNU General Public License for more details.  */
     13  1.1.1.1.26.1       snj #include <sys/cdefs.h>
     14  1.1.1.1.26.1       snj __RCSID("$NetBSD: sighandle.c,v 1.1.1.1.26.1 2017/05/13 06:23:23 snj Exp $");
     15           1.1  christos 
     16           1.1  christos /* Written by Paul Sander, HaL Computer Systems, Inc. <paul (at) hal.com>
     17           1.1  christos    Brian Berliner <berliner (at) Sun.COM> added POSIX support */
     18           1.1  christos 
     19           1.1  christos /*************************************************************************
     20           1.1  christos  *
     21           1.1  christos  * signal.c -- This file contains code that manipulates chains of signal
     22           1.1  christos  *             handlers.
     23           1.1  christos  *
     24           1.1  christos  *             Facilities are provided to register a signal handler for
     25           1.1  christos  *             any specific signal.  When a signal is received, all of the
     26           1.1  christos  *             registered signal handlers are invoked in the reverse order
     27           1.1  christos  *             in which they are registered.  Note that the signal handlers
     28           1.1  christos  *             must not themselves make calls to the signal handling
     29           1.1  christos  *             facilities.
     30           1.1  christos  *
     31           1.1  christos  *************************************************************************/
     32           1.1  christos 
     33           1.1  christos #ifdef HAVE_CONFIG_H
     34           1.1  christos #include "config.h"
     35           1.1  christos #endif
     36           1.1  christos #include "system.h"
     37           1.1  christos 
     38           1.1  christos #include <sys/types.h>
     39           1.1  christos #include <stdio.h>
     40           1.1  christos #include <signal.h>
     41           1.1  christos 
     42           1.1  christos #ifdef STDC_HEADERS
     43           1.1  christos #include <stdlib.h>
     44           1.1  christos #else
     45           1.1  christos #if __STDC__
     46           1.1  christos char *calloc(unsigned nelem, unsigned size);
     47           1.1  christos char *malloc(unsigned size);
     48           1.1  christos #else
     49           1.1  christos char *calloc();
     50           1.1  christos char *malloc();
     51           1.1  christos #endif /* __STDC__ */
     52           1.1  christos #endif /* STDC_HEADERS */
     53           1.1  christos 
     54           1.1  christos /* Define the highest signal number (usually) */
     55           1.1  christos #ifndef SIGMAX
     56           1.1  christos #define	SIGMAX	64
     57           1.1  christos #endif
     58           1.1  christos 
     59           1.1  christos /* Define linked list of signal handlers structure */
     60           1.1  christos struct SIG_hlist {
     61           1.1  christos 	RETSIGTYPE		(*handler)();
     62           1.1  christos 	struct SIG_hlist	*next;
     63           1.1  christos };
     64           1.1  christos 
     65           1.1  christos /*
     66           1.1  christos  * Define array of lists of signal handlers.  Note that this depends on
     67           1.1  christos  * the implementation to initialize each element to a null pointer.
     68           1.1  christos  */
     69           1.1  christos 
     70           1.1  christos static	struct SIG_hlist	**SIG_handlers;
     71           1.1  christos 
     72           1.1  christos /* Define array of default signal vectors */
     73           1.1  christos 
     74           1.1  christos #ifdef POSIX_SIGNALS
     75           1.1  christos static	struct sigaction	*SIG_defaults;
     76           1.1  christos #else
     77           1.1  christos #ifdef BSD_SIGNALS
     78           1.1  christos static	struct sigvec		*SIG_defaults;
     79           1.1  christos #else
     80           1.1  christos static	RETSIGTYPE		(**SIG_defaults) (int);
     81           1.1  christos #endif
     82           1.1  christos #endif
     83           1.1  christos 
     84           1.1  christos /* Critical section housekeeping */
     85           1.1  christos static	int		SIG_crSectNest = 0;	/* Nesting level */
     86           1.1  christos #ifdef POSIX_SIGNALS
     87           1.1  christos static	sigset_t	SIG_crSectMask;		/* Signal mask */
     88           1.1  christos #else
     89           1.1  christos static	int		SIG_crSectMask;		/* Signal mask */
     90           1.1  christos #endif
     91           1.1  christos 
     92           1.1  christos /*
     94           1.1  christos  * Initialize the signal handler arrays
     95           1.1  christos  */
     96           1.1  christos 
     97           1.1  christos static int SIG_init()
     98           1.1  christos {
     99           1.1  christos 	int i;
    100           1.1  christos #ifdef POSIX_SIGNALS
    101           1.1  christos 	sigset_t sigset_test;
    102           1.1  christos #endif
    103           1.1  christos 
    104           1.1  christos 	if (SIG_defaults && SIG_handlers)	/* already allocated */
    105           1.1  christos 		return (0);
    106           1.1  christos 
    107           1.1  christos #ifdef POSIX_SIGNALS
    108           1.1  christos 	(void) sigfillset(&sigset_test);
    109           1.1  christos 	for (i = 1; i < SIGMAX && sigismember(&sigset_test, i) == 1; i++)
    110           1.1  christos 		;
    111           1.1  christos 	if (i < SIGMAX)
    112           1.1  christos 		i = SIGMAX;
    113           1.1  christos 	i++;
    114           1.1  christos 	if (!SIG_defaults)
    115           1.1  christos 		SIG_defaults = (struct sigaction *)
    116           1.1  christos 			calloc(i, sizeof(struct sigaction));
    117           1.1  christos 	(void) sigemptyset(&SIG_crSectMask);
    118           1.1  christos #else
    119           1.1  christos 	i = SIGMAX+1;
    120           1.1  christos #ifdef BSD_SIGNALS
    121           1.1  christos 	if (!SIG_defaults)
    122           1.1  christos 		SIG_defaults = (struct sigvec *)
    123           1.1  christos 			calloc(i, sizeof(struct sigvec));
    124           1.1  christos #else
    125           1.1  christos 	if (!SIG_defaults)
    126           1.1  christos 		SIG_defaults = ( RETSIGTYPE (**) (int) )
    127           1.1  christos 			calloc( i, sizeof( RETSIGTYPE (**) (int) ) );
    128           1.1  christos #endif
    129           1.1  christos 	SIG_crSectMask = 0;
    130           1.1  christos #endif
    131           1.1  christos 	if (!SIG_handlers)
    132           1.1  christos 		SIG_handlers = (struct SIG_hlist **)
    133           1.1  christos 			calloc(i, sizeof(struct SIG_hlist *));
    134           1.1  christos 	return (!SIG_defaults || !SIG_handlers);
    135           1.1  christos }
    136           1.1  christos 
    137           1.1  christos 
    138           1.1  christos 
    139           1.1  christos /*
    140           1.1  christos  * The following begins a critical section.
    141           1.1  christos  */
    142           1.1  christos void SIG_beginCrSect (void)
    143           1.1  christos {
    144           1.1  christos 	if (SIG_init() == 0)
    145           1.1  christos 	{
    146           1.1  christos 		if (SIG_crSectNest == 0)
    147           1.1  christos 		{
    148           1.1  christos #ifdef POSIX_SIGNALS
    149           1.1  christos 			sigset_t sigset_mask;
    150           1.1  christos 
    151           1.1  christos 			(void) sigfillset(&sigset_mask);
    152           1.1  christos 			(void) sigprocmask(SIG_SETMASK,
    153           1.1  christos 					   &sigset_mask, &SIG_crSectMask);
    154           1.1  christos #else
    155           1.1  christos #ifdef BSD_SIGNALS
    156           1.1  christos 			SIG_crSectMask = sigblock(~0);
    157           1.1  christos #else
    158           1.1  christos 			/* TBD */
    159           1.1  christos #endif
    160           1.1  christos #endif
    161           1.1  christos 		}
    162           1.1  christos 		SIG_crSectNest++;
    163           1.1  christos 	}
    164           1.1  christos }
    165           1.1  christos 
    166           1.1  christos 
    167           1.1  christos 
    168           1.1  christos /*
    169           1.1  christos  * The following ends a critical section.
    170           1.1  christos  */
    171           1.1  christos void SIG_endCrSect (void)
    172           1.1  christos {
    173           1.1  christos 	if (SIG_init() == 0)
    174           1.1  christos 	{
    175           1.1  christos 		SIG_crSectNest--;
    176           1.1  christos 		if (SIG_crSectNest == 0)
    177           1.1  christos 		{
    178           1.1  christos #ifdef POSIX_SIGNALS
    179           1.1  christos 			(void) sigprocmask(SIG_SETMASK, &SIG_crSectMask, NULL);
    180           1.1  christos #else
    181           1.1  christos #ifdef BSD_SIGNALS
    182           1.1  christos 			(void) sigsetmask(SIG_crSectMask);
    183           1.1  christos #else
    184           1.1  christos 			/* TBD */
    185           1.1  christos #endif
    186           1.1  christos #endif
    187           1.1  christos 		}
    188           1.1  christos 	}
    189           1.1  christos }
    190           1.1  christos 
    191           1.1  christos 
    192           1.1  christos 
    193           1.1  christos /*
    194           1.1  christos  * The following invokes each signal handler in the reverse order in which
    195           1.1  christos  * they were registered.
    196           1.1  christos  */
    197           1.1  christos static RETSIGTYPE SIG_handle (int sig)
    198           1.1  christos {
    199           1.1  christos 	struct SIG_hlist	*this;
    200           1.1  christos 
    201           1.1  christos 	/* Dispatch signal handlers */
    202           1.1  christos 	/* This crit section stuff is a CVSism - we know that our interrupt
    203           1.1  christos 	 * handlers will always end up exiting and we don't want them to be
    204           1.1  christos 	 * interrupted themselves.
    205           1.1  christos 	 */
    206           1.1  christos 	SIG_beginCrSect();
    207           1.1  christos 	this = SIG_handlers[sig];
    208           1.1  christos 	while (this != (struct SIG_hlist *) NULL)
    209           1.1  christos 	{
    210           1.1  christos 		(*this->handler)(sig);
    211           1.1  christos 		this = this->next;
    212           1.1  christos 	}
    213           1.1  christos 	SIG_endCrSect();
    214           1.1  christos 
    215           1.1  christos 	return;
    216           1.1  christos }
    217           1.1  christos 
    218           1.1  christos /*
    220           1.1  christos  * The following registers a signal handler.  If the handler is already
    221           1.1  christos  * registered, it is not registered twice, nor is the order in which signal
    222           1.1  christos  * handlers are invoked changed.  If this is the first signal handler
    223           1.1  christos  * registered for a given signal, the old sigvec structure is saved for
    224           1.1  christos  * restoration later.
    225           1.1  christos  */
    226           1.1  christos 
    227           1.1  christos int SIG_register(int sig, RETSIGTYPE (*fn)())
    228           1.1  christos {
    229           1.1  christos 	int			val;
    230           1.1  christos 	struct SIG_hlist	*this;
    231           1.1  christos #ifdef POSIX_SIGNALS
    232           1.1  christos 	struct sigaction	act;
    233           1.1  christos 	sigset_t		sigset_mask, sigset_omask;
    234           1.1  christos #else
    235           1.1  christos #ifdef BSD_SIGNALS
    236           1.1  christos 	struct sigvec		vec;
    237           1.1  christos 	int			mask;
    238           1.1  christos #endif
    239           1.1  christos #endif
    240           1.1  christos 
    241           1.1  christos 	/* Initialize */
    242           1.1  christos 	if (SIG_init() != 0)
    243           1.1  christos 		return (-1);
    244           1.1  christos 	val = 0;
    245           1.1  christos 
    246           1.1  christos 	/* Block this signal while we look at handler chain */
    247           1.1  christos #ifdef POSIX_SIGNALS
    248           1.1  christos 	(void) sigemptyset(&sigset_mask);
    249           1.1  christos 	(void) sigaddset(&sigset_mask, sig);
    250           1.1  christos 	(void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
    251           1.1  christos #else
    252           1.1  christos #ifdef BSD_SIGNALS
    253           1.1  christos 	mask = sigblock(sigmask(sig));
    254           1.1  christos #endif
    255           1.1  christos #endif
    256           1.1  christos 
    257           1.1  christos 	/* See if this handler was already registered */
    258           1.1  christos 	this = SIG_handlers[sig];
    259           1.1  christos 	while (this != (struct SIG_hlist *) NULL)
    260           1.1  christos 	{
    261           1.1  christos 		if (this->handler == fn) break;
    262           1.1  christos 		this = this->next;
    263           1.1  christos 	}
    264           1.1  christos 
    265           1.1  christos 	/* Register the new handler only if it is not already registered. */
    266           1.1  christos 	if (this == (struct SIG_hlist *) NULL)
    267           1.1  christos 	{
    268           1.1  christos 
    269           1.1  christos 		/*
    270           1.1  christos 		 * If this is the first handler registered for this signal,
    271           1.1  christos 		 * set up the signal handler dispatcher
    272           1.1  christos 		 */
    273           1.1  christos 
    274           1.1  christos 		if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
    275           1.1  christos 		{
    276           1.1  christos #ifdef POSIX_SIGNALS
    277           1.1  christos 			act.sa_handler = SIG_handle;
    278           1.1  christos 			(void) sigemptyset(&act.sa_mask);
    279           1.1  christos 			act.sa_flags = 0;
    280           1.1  christos 			val = sigaction(sig, &act, &SIG_defaults[sig]);
    281           1.1  christos #else
    282           1.1  christos #ifdef BSD_SIGNALS
    283           1.1  christos 			memset (&vec, 0, sizeof (vec));
    284           1.1  christos 			vec.sv_handler = SIG_handle;
    285           1.1  christos 			val = sigvec(sig, &vec, &SIG_defaults[sig]);
    286           1.1  christos #else
    287           1.1  christos 			if ((SIG_defaults[sig] = signal(sig, SIG_handle)) == SIG_ERR)
    288           1.1  christos 				val = -1;
    289           1.1  christos #endif
    290           1.1  christos #endif
    291           1.1  christos 		}
    292           1.1  christos 
    293           1.1  christos 		/* If not, register it */
    294           1.1  christos 		if ((val == 0) && (this == (struct SIG_hlist *) NULL))
    295           1.1  christos 		{
    296           1.1  christos 			this = (struct SIG_hlist *)
    297           1.1  christos 			                      malloc(sizeof(struct SIG_hlist));
    298           1.1  christos 			if (this == NULL)
    299           1.1  christos 			{
    300           1.1  christos 				val = -1;
    301           1.1  christos 			}
    302           1.1  christos 			else
    303           1.1  christos 			{
    304           1.1  christos 				this->handler = fn;
    305           1.1  christos 				this->next = SIG_handlers[sig];
    306           1.1  christos 				SIG_handlers[sig] = this;
    307           1.1  christos 			}
    308           1.1  christos 		}
    309           1.1  christos 	}
    310           1.1  christos 
    311           1.1  christos 	/* Unblock the signal */
    312           1.1  christos #ifdef POSIX_SIGNALS
    313           1.1  christos 	(void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
    314           1.1  christos #else
    315           1.1  christos #ifdef BSD_SIGNALS
    316           1.1  christos 	(void) sigsetmask(mask);
    317           1.1  christos #endif
    318           1.1  christos #endif
    319           1.1  christos 
    320           1.1  christos 	return val;
    321           1.1  christos }
    322           1.1  christos 
    323           1.1  christos 
    324           1.1  christos 
    325           1.1  christos /*
    326           1.1  christos  * The following deregisters a signal handler.  If the last signal handler for
    327           1.1  christos  * a given signal is deregistered, the default sigvec information is restored.
    328           1.1  christos  */
    329           1.1  christos 
    330           1.1  christos int SIG_deregister(int sig, RETSIGTYPE (*fn)())
    331           1.1  christos {
    332           1.1  christos 	int			val;
    333           1.1  christos 	struct SIG_hlist	*this;
    334           1.1  christos 	struct SIG_hlist	*last;
    335           1.1  christos #ifdef POSIX_SIGNALS
    336           1.1  christos 	sigset_t		sigset_mask, sigset_omask;
    337           1.1  christos #else
    338           1.1  christos #ifdef BSD_SIGNALS
    339           1.1  christos 	int			mask;
    340           1.1  christos #endif
    341           1.1  christos #endif
    342           1.1  christos 
    343           1.1  christos 	/* Initialize */
    344           1.1  christos 	if (SIG_init() != 0)
    345           1.1  christos 		return (-1);
    346           1.1  christos 	val = 0;
    347           1.1  christos 	last = (struct SIG_hlist *) NULL;
    348           1.1  christos 
    349           1.1  christos 	/* Block this signal while we look at handler chain */
    350           1.1  christos #ifdef POSIX_SIGNALS
    351           1.1  christos 	(void) sigemptyset(&sigset_mask);
    352           1.1  christos 	(void) sigaddset(&sigset_mask, sig);
    353           1.1  christos 	(void) sigprocmask(SIG_BLOCK, &sigset_mask, &sigset_omask);
    354           1.1  christos #else
    355           1.1  christos #ifdef BSD_SIGNALS
    356           1.1  christos 	mask = sigblock(sigmask(sig));
    357           1.1  christos #endif
    358           1.1  christos #endif
    359           1.1  christos 
    360           1.1  christos 	/* Search for the signal handler */
    361           1.1  christos 	this = SIG_handlers[sig];
    362           1.1  christos 	while ((this != (struct SIG_hlist *) NULL) && (this->handler != fn))
    363           1.1  christos 	{
    364           1.1  christos 		last = this;
    365           1.1  christos 		this = this->next;
    366           1.1  christos 	}
    367           1.1  christos 
    368           1.1  christos 	/* If it was registered, remove it */
    369           1.1  christos 	if (this != (struct SIG_hlist *) NULL)
    370           1.1  christos 	{
    371           1.1  christos 		if (last == (struct SIG_hlist *) NULL)
    372           1.1  christos 		{
    373           1.1  christos 			SIG_handlers[sig] = this->next;
    374           1.1  christos 		}
    375           1.1  christos 		else
    376           1.1  christos 		{
    377           1.1  christos 			last->next = this->next;
    378           1.1  christos 		}
    379           1.1  christos 		free((char *) this);
    380           1.1  christos 	}
    381           1.1  christos 
    382           1.1  christos 	/* Restore default behavior if there are no registered handlers */
    383           1.1  christos 	if (SIG_handlers[sig] == (struct SIG_hlist *) NULL)
    384           1.1  christos 	{
    385           1.1  christos #ifdef POSIX_SIGNALS
    386           1.1  christos 		val = sigaction(sig, &SIG_defaults[sig],
    387           1.1  christos 				(struct sigaction *) NULL);
    388           1.1  christos #else
    389           1.1  christos #ifdef BSD_SIGNALS
    390           1.1  christos 		val = sigvec(sig, &SIG_defaults[sig], (struct sigvec *) NULL);
    391           1.1  christos #else
    392           1.1  christos 		if (signal(sig, SIG_defaults[sig]) == SIG_ERR)
    393           1.1  christos 			val = -1;
    394           1.1  christos #endif
    395           1.1  christos #endif
    396           1.1  christos 	}
    397           1.1  christos 
    398           1.1  christos 	/* Unblock the signal */
    399           1.1  christos #ifdef POSIX_SIGNALS
    400           1.1  christos 	(void) sigprocmask(SIG_SETMASK, &sigset_omask, NULL);
    401           1.1  christos #else
    402           1.1  christos #ifdef BSD_SIGNALS
    403           1.1  christos 	(void) sigsetmask(mask);
    404           1.1  christos #endif
    405           1.1  christos #endif
    406           1.1  christos 
    407           1.1  christos 	return val;
    408           1.1  christos }
    409           1.1  christos 
    410           1.1  christos 
    411           1.1  christos 
    412           1.1  christos /*
    413           1.1  christos  * Return nonzero if currently in a critical section.
    414           1.1  christos  * Otherwise return zero.
    415           1.1  christos  */
    416           1.1  christos 
    417           1.1  christos int SIG_inCrSect (void)
    418           1.1  christos {
    419                         	return SIG_crSectNest > 0;
    420                         }
    421