78ed81a3 |
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., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | |
22 | The author of the program may be contacted at ian@airs.com or |
23 | c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. |
24 | */ |
25 | |
26 | #include "uucp.h" |
27 | |
28 | #include "uudefs.h" |
29 | #include "sysdep.h" |
30 | #include "system.h" |
31 | |
32 | #include <errno.h> |
33 | \f |
34 | /* Signal handling routines. When we catch a signal, we want to set |
35 | the appropriate elements of afSignal and afLog_signal to TRUE. If |
36 | we are on a system which restarts system calls, we may also want to |
37 | longjmp out. On a system which does not restart system calls, |
38 | these signal handling routines are well-defined by ANSI C. */ |
39 | |
40 | #if HAVE_RESTARTABLE_SYSCALLS |
41 | volatile sig_atomic_t fSjmp; |
42 | volatile jmp_buf sSjmp_buf; |
43 | #endif /* HAVE_RESTARTABLE_SYSCALLS */ |
44 | |
45 | /* Some systems, such as SunOS, have a SA_INTERRUPT bit that must be |
46 | set in the sigaction structure to force system calls to be |
47 | interrupted. */ |
48 | #ifndef SA_INTERRUPT |
49 | #define SA_INTERRUPT 0 |
50 | #endif |
51 | |
52 | /* The SVR3 sigset function can be called just like signal, unless |
53 | system calls are restarted which is extremely unlikely; we prevent |
54 | this case in sysh.unx. */ |
55 | #if HAVE_SIGSET && ! HAVE_SIGACTION && ! HAVE_SIGVEC |
56 | #define signal sigset |
57 | #endif |
58 | |
59 | /* The sigvec structure changed from 4.2BSD to 4.3BSD. These macros |
60 | make the 4.3 code backward compatible. */ |
61 | #ifndef SV_INTERRUPT |
62 | #define SV_INTERRUPT 0 |
63 | #endif |
64 | #if ! HAVE_SIGVEC_SV_FLAGS |
65 | #define sv_flags sv_onstack |
66 | #endif |
67 | |
68 | /* Catch a signal. Reinstall the signal handler if necessary, set the |
69 | appropriate variables, and do a longjmp if necessary. */ |
70 | |
71 | RETSIGTYPE |
72 | ussignal (isig) |
73 | int isig; |
74 | { |
75 | int iindex; |
76 | |
77 | #if ! HAVE_SIGACTION && ! HAVE_SIGVEC && ! HAVE_SIGSET |
78 | (void) signal (isig, ussignal); |
79 | #endif |
80 | |
81 | switch (isig) |
82 | { |
83 | default: iindex = INDEXSIG_SIGHUP; break; |
84 | #ifdef SIGINT |
85 | case SIGINT: iindex = INDEXSIG_SIGINT; break; |
86 | #endif |
87 | #ifdef SIGQUIT |
88 | case SIGQUIT: iindex = INDEXSIG_SIGQUIT; break; |
89 | #endif |
90 | #ifdef SIGTERM |
91 | case SIGTERM: iindex = INDEXSIG_SIGTERM; break; |
92 | #endif |
93 | #ifdef SIGPIPE |
94 | case SIGPIPE: iindex = INDEXSIG_SIGPIPE; break; |
95 | #endif |
96 | } |
97 | |
98 | afSignal[iindex] = TRUE; |
99 | afLog_signal[iindex] = TRUE; |
100 | |
101 | #if HAVE_RESTARTABLE_SYSCALLS |
102 | if (fSjmp) |
103 | longjmp (sSjmp_buf, 1); |
104 | #endif /* HAVE_RESTARTABLE_SYSCALLS */ |
105 | } |
106 | |
107 | /* Prepare to catch a signal. This is basically the ANSI C routine |
108 | signal, but it uses sigaction or sigvec instead if they are |
109 | available. If fforce is FALSE, we do not set the signal if it is |
110 | currently being ignored. If pfignored is not NULL and fforce is |
111 | FALSE, then *pfignored will be set to TRUE if the signal was |
112 | previously being ignored (if fforce is TRUE the value returned in |
113 | *pfignored is meaningless). If we can't change the signal handler |
114 | we give a fatal error. */ |
115 | |
116 | void |
117 | usset_signal (isig, pfn, fforce, pfignored) |
118 | int isig; |
119 | RETSIGTYPE (*pfn) P((int)); |
120 | boolean fforce; |
121 | boolean *pfignored; |
122 | { |
123 | #if HAVE_SIGACTION |
124 | |
125 | struct sigaction s; |
126 | |
127 | if (! fforce) |
128 | { |
129 | (void) (sigemptyset (&s.sa_mask)); |
130 | if (sigaction (isig, (struct sigaction *) NULL, &s) != 0) |
131 | ulog (LOG_FATAL, "sigaction (%d): %s", isig, strerror (errno)); |
132 | |
133 | if (s.sa_handler == SIG_IGN) |
134 | { |
135 | if (pfignored != NULL) |
136 | *pfignored = TRUE; |
137 | return; |
138 | } |
139 | |
140 | if (pfignored != NULL) |
141 | *pfignored = FALSE; |
142 | } |
143 | |
144 | s.sa_handler = pfn; |
145 | (void) (sigemptyset (&s.sa_mask)); |
146 | s.sa_flags = SA_INTERRUPT; |
147 | |
148 | if (sigaction (isig, &s, (struct sigaction *) NULL) != 0) |
149 | ulog (LOG_FATAL, "sigaction (%d): %s", isig, strerror (errno)); |
150 | |
151 | #else /* ! HAVE_SIGACTION */ |
152 | #if HAVE_SIGVEC |
153 | |
154 | struct sigvec s; |
155 | |
156 | if (! fforce) |
157 | { |
158 | if (sigvec (isig, (struct sigvec *) NULL, &s) != 0) |
159 | ulog (LOG_FATAL, "sigvec (%d): %s", isig, strerror (errno)); |
160 | |
161 | if (s.sv_handler == SIG_IGN) |
162 | { |
163 | if (pfignored != NULL) |
164 | *pfignored = TRUE; |
165 | return; |
166 | } |
167 | |
168 | if (pfignored != NULL) |
169 | *pfignored = FALSE; |
170 | } |
171 | |
172 | s.sv_handler = pfn; |
173 | s.sv_mask = 0; |
174 | s.sv_flags = SV_INTERRUPT; |
175 | |
176 | if (sigvec (isig, &s, (struct sigvec *) NULL) != 0) |
177 | ulog (LOG_FATAL, "sigvec (%d): %s", isig, strerror (errno)); |
178 | |
179 | #else /* ! HAVE_SIGVEC */ |
180 | |
181 | if (! fforce) |
182 | { |
183 | if (signal (isig, SIG_IGN) == SIG_IGN) |
184 | { |
185 | if (pfignored != NULL) |
186 | *pfignored = TRUE; |
187 | return; |
188 | } |
189 | |
190 | if (pfignored != NULL) |
191 | *pfignored = FALSE; |
192 | } |
193 | |
194 | (void) signal (isig, pfn); |
195 | |
196 | #endif /* ! HAVE_SIGVEC */ |
197 | #endif /* ! HAVE_SIGACTION */ |
198 | } |
199 | |
200 | /* The routine called by the system independent code, which always |
201 | uses the same signal handler. */ |
202 | |
203 | void |
204 | usysdep_signal (isig) |
205 | int isig; |
206 | { |
207 | usset_signal (isig, ussignal, FALSE, (boolean *) NULL); |
208 | } |