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
40 volatile sig_atomic_t fSjmp;
41 volatile 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
70 RETSIGTYPE
ussignal(isig)71 ussignal (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
115 void
usset_signal(isig,pfn,fforce,pfignored)116 usset_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
202 void
usysdep_signal(isig)203 usysdep_signal (isig)
204 int isig;
205 {
206 usset_signal (isig, ussignal, FALSE, (boolean *) NULL);
207 }
208