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