diff options
| author | svn2git <svn2git@FreeBSD.org> | 1994-05-01 08:00:00 +0000 |
|---|---|---|
| committer | svn2git <svn2git@FreeBSD.org> | 1994-05-01 08:00:00 +0000 |
| commit | a16f65c7d117419bd266c28a1901ef129a337569 (patch) | |
| tree | 2626602f66dc3551e7a7c7bc9ad763c3bc7ab40a /gnu/libexec/uucp/libunix/signal.c | |
| parent | 8503f4f13f77abf7adc8f7e329c6f9c1d52b6a20 (diff) | |
Diffstat (limited to 'gnu/libexec/uucp/libunix/signal.c')
| -rw-r--r-- | gnu/libexec/uucp/libunix/signal.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libunix/signal.c b/gnu/libexec/uucp/libunix/signal.c new file mode 100644 index 000000000000..33e24a724574 --- /dev/null +++ b/gnu/libexec/uucp/libunix/signal.c @@ -0,0 +1,208 @@ +/* signal.c + Signal handling routines. + + Copyright (C) 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program 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 of the + License, or (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#include "uudefs.h" +#include "sysdep.h" +#include "system.h" + +#include <errno.h> + +/* Signal handling routines. When we catch a signal, we want to set + the appropriate elements of afSignal and afLog_signal to TRUE. If + we are on a system which restarts system calls, we may also want to + longjmp out. On a system which does not restart system calls, + these signal handling routines are well-defined by ANSI C. */ + +#if HAVE_RESTARTABLE_SYSCALLS +volatile sig_atomic_t fSjmp; +volatile jmp_buf sSjmp_buf; +#endif /* HAVE_RESTARTABLE_SYSCALLS */ + +/* Some systems, such as SunOS, have a SA_INTERRUPT bit that must be + set in the sigaction structure to force system calls to be + interrupted. */ +#ifndef SA_INTERRUPT +#define SA_INTERRUPT 0 +#endif + +/* The SVR3 sigset function can be called just like signal, unless + system calls are restarted which is extremely unlikely; we prevent + this case in sysh.unx. */ +#if HAVE_SIGSET && ! HAVE_SIGACTION && ! HAVE_SIGVEC +#define signal sigset +#endif + +/* The sigvec structure changed from 4.2BSD to 4.3BSD. These macros + make the 4.3 code backward compatible. */ +#ifndef SV_INTERRUPT +#define SV_INTERRUPT 0 +#endif +#if ! HAVE_SIGVEC_SV_FLAGS +#define sv_flags sv_onstack +#endif + +/* Catch a signal. Reinstall the signal handler if necessary, set the + appropriate variables, and do a longjmp if necessary. */ + +RETSIGTYPE +ussignal (isig) + int isig; +{ + int iindex; + +#if ! HAVE_SIGACTION && ! HAVE_SIGVEC && ! HAVE_SIGSET + (void) signal (isig, ussignal); +#endif + + switch (isig) + { + default: iindex = INDEXSIG_SIGHUP; break; +#ifdef SIGINT + case SIGINT: iindex = INDEXSIG_SIGINT; break; +#endif +#ifdef SIGQUIT + case SIGQUIT: iindex = INDEXSIG_SIGQUIT; break; +#endif +#ifdef SIGTERM + case SIGTERM: iindex = INDEXSIG_SIGTERM; break; +#endif +#ifdef SIGPIPE + case SIGPIPE: iindex = INDEXSIG_SIGPIPE; break; +#endif + } + + afSignal[iindex] = TRUE; + afLog_signal[iindex] = TRUE; + +#if HAVE_RESTARTABLE_SYSCALLS + if (fSjmp) + longjmp (sSjmp_buf, 1); +#endif /* HAVE_RESTARTABLE_SYSCALLS */ +} + +/* Prepare to catch a signal. This is basically the ANSI C routine + signal, but it uses sigaction or sigvec instead if they are + available. If fforce is FALSE, we do not set the signal if it is + currently being ignored. If pfignored is not NULL and fforce is + FALSE, then *pfignored will be set to TRUE if the signal was + previously being ignored (if fforce is TRUE the value returned in + *pfignored is meaningless). If we can't change the signal handler + we give a fatal error. */ + +void +usset_signal (isig, pfn, fforce, pfignored) + int isig; + RETSIGTYPE (*pfn) P((int)); + boolean fforce; + boolean *pfignored; +{ +#if HAVE_SIGACTION + + struct sigaction s; + + if (! fforce) + { + (void) (sigemptyset (&s.sa_mask)); + if (sigaction (isig, (struct sigaction *) NULL, &s) != 0) + ulog (LOG_FATAL, "sigaction (%d): %s", isig, strerror (errno)); + + if (s.sa_handler == SIG_IGN) + { + if (pfignored != NULL) + *pfignored = TRUE; + return; + } + + if (pfignored != NULL) + *pfignored = FALSE; + } + + s.sa_handler = pfn; + (void) (sigemptyset (&s.sa_mask)); + s.sa_flags = SA_INTERRUPT; + + if (sigaction (isig, &s, (struct sigaction *) NULL) != 0) + ulog (LOG_FATAL, "sigaction (%d): %s", isig, strerror (errno)); + +#else /* ! HAVE_SIGACTION */ +#if HAVE_SIGVEC + + struct sigvec s; + + if (! fforce) + { + if (sigvec (isig, (struct sigvec *) NULL, &s) != 0) + ulog (LOG_FATAL, "sigvec (%d): %s", isig, strerror (errno)); + + if (s.sv_handler == SIG_IGN) + { + if (pfignored != NULL) + *pfignored = TRUE; + return; + } + + if (pfignored != NULL) + *pfignored = FALSE; + } + + s.sv_handler = pfn; + s.sv_mask = 0; + s.sv_flags = SV_INTERRUPT; + + if (sigvec (isig, &s, (struct sigvec *) NULL) != 0) + ulog (LOG_FATAL, "sigvec (%d): %s", isig, strerror (errno)); + +#else /* ! HAVE_SIGVEC */ + + if (! fforce) + { + if (signal (isig, SIG_IGN) == SIG_IGN) + { + if (pfignored != NULL) + *pfignored = TRUE; + return; + } + + if (pfignored != NULL) + *pfignored = FALSE; + } + + (void) signal (isig, pfn); + +#endif /* ! HAVE_SIGVEC */ +#endif /* ! HAVE_SIGACTION */ +} + +/* The routine called by the system independent code, which always + uses the same signal handler. */ + +void +usysdep_signal (isig) + int isig; +{ + usset_signal (isig, ussignal, FALSE, (boolean *) NULL); +} |
