1/* signal.c 2 Signal handling routines. 3 4 Copyright (C) 1992 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP package. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#include "uudefs.h" 28#include "sysdep.h" 29#include "system.h" 30 31#include <errno.h> 32 33/* Signal handling routines. When we catch a signal, we want to set 34 the appropriate elements of afSignal and afLog_signal to TRUE. If 35 we are on a system which restarts system calls, we may also want to 36 longjmp out. On a system which does not restart system calls, 37 these signal handling routines are well-defined by ANSI C. */ 38 39#if HAVE_RESTARTABLE_SYSCALLS 40volatile sig_atomic_t fSjmp; 41volatile jmp_buf sSjmp_buf; 42#endif /* HAVE_RESTARTABLE_SYSCALLS */ 43 44/* Some systems, such as SunOS, have a SA_INTERRUPT bit that must be 45 set in the sigaction structure to force system calls to be 46 interrupted. */ 47#ifndef SA_INTERRUPT 48#define SA_INTERRUPT 0 49#endif 50 51/* The SVR3 sigset function can be called just like signal, unless 52 system calls are restarted which is extremely unlikely; we prevent 53 this case in sysh.unx. */ 54#if HAVE_SIGSET && ! HAVE_SIGACTION && ! HAVE_SIGVEC 55#define signal sigset 56#endif 57 58/* The sigvec structure changed from 4.2BSD to 4.3BSD. These macros 59 make the 4.3 code backward compatible. */ 60#ifndef SV_INTERRUPT 61#define SV_INTERRUPT 0 62#endif 63#if ! HAVE_SIGVEC_SV_FLAGS 64#define sv_flags sv_onstack 65#endif 66 67/* Catch a signal. Reinstall the signal handler if necessary, set the 68 appropriate variables, and do a longjmp if necessary. */ 69 70RETSIGTYPE 71ussignal (isig) 72 int isig; 73{ 74 int iindex; 75 76#if ! HAVE_SIGACTION && ! HAVE_SIGVEC && ! HAVE_SIGSET 77 (void) signal (isig, ussignal); 78#endif 79 80 switch (isig) 81 { 82 default: iindex = INDEXSIG_SIGHUP; break; 83#ifdef SIGINT 84 case SIGINT: iindex = INDEXSIG_SIGINT; break; 85#endif 86#ifdef SIGQUIT 87 case SIGQUIT: iindex = INDEXSIG_SIGQUIT; break; 88#endif 89#ifdef SIGTERM 90 case SIGTERM: iindex = INDEXSIG_SIGTERM; break; 91#endif 92#ifdef SIGPIPE 93 case SIGPIPE: iindex = INDEXSIG_SIGPIPE; break; 94#endif 95 } 96 97 afSignal[iindex] = TRUE; 98 afLog_signal[iindex] = TRUE; 99 100#if HAVE_RESTARTABLE_SYSCALLS 101 if (fSjmp) 102 longjmp (sSjmp_buf, 1); 103#endif /* HAVE_RESTARTABLE_SYSCALLS */ 104} 105 106/* Prepare to catch a signal. This is basically the ANSI C routine 107 signal, but it uses sigaction or sigvec instead if they are 108 available. If fforce is FALSE, we do not set the signal if it is 109 currently being ignored. If pfignored is not NULL and fforce is 110 FALSE, then *pfignored will be set to TRUE if the signal was 111 previously being ignored (if fforce is TRUE the value returned in 112 *pfignored is meaningless). If we can't change the signal handler 113 we give a fatal error. */ 114 115void 116usset_signal (isig, pfn, fforce, pfignored) 117 int isig; 118 RETSIGTYPE (*pfn) P((int)); 119 boolean fforce; 120 boolean *pfignored; 121{ 122#if HAVE_SIGACTION 123 124 struct sigaction s; 125 126 if (! fforce) 127 { 128 (void) (sigemptyset (&s.sa_mask)); 129 if (sigaction (isig, (struct sigaction *) NULL, &s) != 0) 130 ulog (LOG_FATAL, "sigaction (%d): %s", isig, strerror (errno)); 131 132 if (s.sa_handler == SIG_IGN) 133 { 134 if (pfignored != NULL) 135 *pfignored = TRUE; 136 return; 137 } 138 139 if (pfignored != NULL) 140 *pfignored = FALSE; 141 } 142 143 s.sa_handler = pfn; 144 (void) (sigemptyset (&s.sa_mask)); 145 s.sa_flags = SA_INTERRUPT; 146 147 if (sigaction (isig, &s, (struct sigaction *) NULL) != 0) 148 ulog (LOG_FATAL, "sigaction (%d): %s", isig, strerror (errno)); 149 150#else /* ! HAVE_SIGACTION */ 151#if HAVE_SIGVEC 152 153 struct sigvec s; 154 155 if (! fforce) 156 { 157 if (sigvec (isig, (struct sigvec *) NULL, &s) != 0) 158 ulog (LOG_FATAL, "sigvec (%d): %s", isig, strerror (errno)); 159 160 if (s.sv_handler == SIG_IGN) 161 { 162 if (pfignored != NULL) 163 *pfignored = TRUE; 164 return; 165 } 166 167 if (pfignored != NULL) 168 *pfignored = FALSE; 169 } 170 171 s.sv_handler = pfn; 172 s.sv_mask = 0; 173 s.sv_flags = SV_INTERRUPT; 174 175 if (sigvec (isig, &s, (struct sigvec *) NULL) != 0) 176 ulog (LOG_FATAL, "sigvec (%d): %s", isig, strerror (errno)); 177 178#else /* ! HAVE_SIGVEC */ 179 180 if (! fforce) 181 { 182 if (signal (isig, SIG_IGN) == SIG_IGN) 183 { 184 if (pfignored != NULL) 185 *pfignored = TRUE; 186 return; 187 } 188 189 if (pfignored != NULL) 190 *pfignored = FALSE; 191 } 192 193 (void) signal (isig, pfn); 194 195#endif /* ! HAVE_SIGVEC */ 196#endif /* ! HAVE_SIGACTION */ 197} 198 199/* The routine called by the system independent code, which always 200 uses the same signal handler. */ 201 202void 203usysdep_signal (isig) 204 int isig; 205{ 206 usset_signal (isig, ussignal, FALSE, (boolean *) NULL); 207} 208