]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | /* trap.c -- Not the trap command, but useful functions for manipulating |
2 | those objects. The trap command is in builtins/trap.def. */ | |
3 | ||
3185942a | 4 | /* Copyright (C) 1987-2009 Free Software Foundation, Inc. |
726f6388 JA |
5 | |
6 | This file is part of GNU Bash, the Bourne Again SHell. | |
7 | ||
3185942a JA |
8 | Bash is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation, either version 3 of the License, or | |
11 | (at your option) any later version. | |
726f6388 | 12 | |
3185942a JA |
13 | Bash is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
726f6388 | 17 | |
3185942a JA |
18 | You should have received a copy of the GNU General Public License |
19 | along with Bash. If not, see <http://www.gnu.org/licenses/>. | |
20 | */ | |
726f6388 | 21 | |
ccc6cda3 JA |
22 | #include "config.h" |
23 | ||
e8ce775d JA |
24 | #if defined (HAVE_UNISTD_H) |
25 | # include <unistd.h> | |
26 | #endif | |
27 | ||
726f6388 | 28 | #include "bashtypes.h" |
d166f048 | 29 | #include "bashansi.h" |
726f6388 | 30 | |
cce855bc | 31 | #include <stdio.h> |
bb70624e | 32 | #include <errno.h> |
cce855bc | 33 | |
b80f6443 JA |
34 | #include "bashintl.h" |
35 | ||
cce855bc JA |
36 | #include "trap.h" |
37 | ||
726f6388 | 38 | #include "shell.h" |
b80f6443 | 39 | #include "flags.h" |
bb70624e | 40 | #include "input.h" /* for save_token_state, restore_token_state */ |
3185942a | 41 | #include "jobs.h" |
726f6388 | 42 | #include "signames.h" |
7117c2d2 | 43 | #include "builtins.h" |
ccc6cda3 | 44 | #include "builtins/common.h" |
7117c2d2 | 45 | #include "builtins/builtext.h" |
726f6388 | 46 | |
bb70624e JA |
47 | #ifndef errno |
48 | extern int errno; | |
49 | #endif | |
50 | ||
726f6388 JA |
51 | /* Flags which describe the current handling state of a signal. */ |
52 | #define SIG_INHERITED 0x0 /* Value inherited from parent. */ | |
53 | #define SIG_TRAPPED 0x1 /* Currently trapped. */ | |
54 | #define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */ | |
55 | #define SIG_SPECIAL 0x4 /* Treat this signal specially. */ | |
56 | #define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */ | |
ccc6cda3 JA |
57 | #define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */ |
58 | #define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */ | |
59 | #define SIG_IGNORED 0x40 /* The signal is currently being ignored. */ | |
726f6388 | 60 | |
b80f6443 | 61 | #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP) |
f73dda09 | 62 | |
726f6388 | 63 | /* An array of such flags, one for each signal, describing what the |
ccc6cda3 JA |
64 | shell will do with a signal. DEBUG_TRAP == NSIG; some code below |
65 | assumes this. */ | |
f73dda09 JA |
66 | static int sigmodes[BASH_NSIG]; |
67 | ||
68 | static void free_trap_command __P((int)); | |
69 | static void change_signal __P((int, char *)); | |
70 | ||
71 | static void get_original_signal __P((int)); | |
72 | ||
b80f6443 | 73 | static int _run_trap_internal __P((int, char *)); |
726f6388 | 74 | |
f73dda09 JA |
75 | static void reset_signal __P((int)); |
76 | static void restore_signal __P((int)); | |
77 | static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *)); | |
726f6388 JA |
78 | |
79 | /* Variables used here but defined in other files. */ | |
726f6388 | 80 | extern int last_command_exit_value; |
d166f048 | 81 | extern int line_number; |
726f6388 | 82 | |
b80f6443 | 83 | extern char *this_command_name; |
7117c2d2 JA |
84 | extern sh_builtin_func_t *this_shell_builtin; |
85 | extern procenv_t wait_intr_buf; | |
b80f6443 JA |
86 | extern int return_catch_flag, return_catch_value; |
87 | extern int subshell_level; | |
7117c2d2 | 88 | |
726f6388 JA |
89 | /* The list of things to do originally, before we started trapping. */ |
90 | SigHandler *original_signals[NSIG]; | |
91 | ||
92 | /* For each signal, a slot for a string, which is a command to be | |
93 | executed when that signal is recieved. The slot can also contain | |
94 | DEFAULT_SIG, which means do whatever you were going to do before | |
95 | you were so rudely interrupted, or IGNORE_SIG, which says ignore | |
96 | this signal. */ | |
f73dda09 | 97 | char *trap_list[BASH_NSIG]; |
726f6388 JA |
98 | |
99 | /* A bitmap of signals received for which we have trap handlers. */ | |
100 | int pending_traps[NSIG]; | |
101 | ||
ccc6cda3 JA |
102 | /* Set to the number of the signal we're running the trap for + 1. |
103 | Used in execute_cmd.c and builtins/common.c to clean up when | |
104 | parse_and_execute does not return normally after executing the | |
105 | trap command (e.g., when `return' is executed in the trap command). */ | |
106 | int running_trap; | |
107 | ||
b80f6443 JA |
108 | /* Set to last_command_exit_value before running a trap. */ |
109 | int trap_saved_exit_value; | |
d166f048 | 110 | |
7117c2d2 JA |
111 | /* The (trapped) signal received while executing in the `wait' builtin */ |
112 | int wait_signal_received; | |
113 | ||
726f6388 JA |
114 | /* A value which can never be the target of a trap handler. */ |
115 | #define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps | |
116 | ||
0628567a JA |
117 | #define GETORIGSIG(sig) \ |
118 | do { \ | |
119 | original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \ | |
120 | set_signal_handler (sig, original_signals[sig]); \ | |
121 | if (original_signals[sig] == SIG_IGN) \ | |
122 | sigmodes[sig] |= SIG_HARD_IGNORE; \ | |
123 | } while (0) | |
124 | ||
125 | #define GET_ORIGINAL_SIGNAL(sig) \ | |
126 | if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \ | |
127 | GETORIGSIG(sig) | |
128 | ||
726f6388 JA |
129 | void |
130 | initialize_traps () | |
131 | { | |
132 | register int i; | |
133 | ||
0628567a JA |
134 | initialize_signames(); |
135 | ||
b80f6443 JA |
136 | trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL; |
137 | sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED; | |
ccc6cda3 | 138 | original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER; |
726f6388 JA |
139 | |
140 | for (i = 1; i < NSIG; i++) | |
141 | { | |
142 | pending_traps[i] = 0; | |
143 | trap_list[i] = (char *)DEFAULT_SIG; | |
144 | sigmodes[i] = SIG_INHERITED; | |
145 | original_signals[i] = IMPOSSIBLE_TRAP_HANDLER; | |
146 | } | |
147 | ||
148 | /* Show which signals are treated specially by the shell. */ | |
149 | #if defined (SIGCHLD) | |
0628567a | 150 | GETORIGSIG (SIGCHLD); |
726f6388 JA |
151 | sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP); |
152 | #endif /* SIGCHLD */ | |
153 | ||
0628567a | 154 | GETORIGSIG (SIGINT); |
726f6388 JA |
155 | sigmodes[SIGINT] |= SIG_SPECIAL; |
156 | ||
b72432fd JA |
157 | #if defined (__BEOS__) |
158 | /* BeOS sets SIGINT to SIG_IGN! */ | |
159 | original_signals[SIGINT] = SIG_DFL; | |
0628567a | 160 | sigmodes[SIGINT] &= ~SIG_HARD_IGNORE; |
b72432fd JA |
161 | #endif |
162 | ||
0628567a | 163 | GETORIGSIG (SIGQUIT); |
726f6388 JA |
164 | sigmodes[SIGQUIT] |= SIG_SPECIAL; |
165 | ||
166 | if (interactive) | |
167 | { | |
0628567a | 168 | GETORIGSIG (SIGTERM); |
726f6388 JA |
169 | sigmodes[SIGTERM] |= SIG_SPECIAL; |
170 | } | |
171 | } | |
172 | ||
bb70624e JA |
173 | #ifdef INCLUDE_UNUSED |
174 | /* Return a printable representation of the trap handler for SIG. */ | |
175 | static char * | |
176 | trap_handler_string (sig) | |
177 | int sig; | |
178 | { | |
179 | if (trap_list[sig] == (char *)DEFAULT_SIG) | |
180 | return "DEFAULT_SIG"; | |
181 | else if (trap_list[sig] == (char *)IGNORE_SIG) | |
182 | return "IGNORE_SIG"; | |
183 | else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER) | |
184 | return "IMPOSSIBLE_TRAP_HANDLER"; | |
185 | else if (trap_list[sig]) | |
186 | return trap_list[sig]; | |
187 | else | |
188 | return "NULL"; | |
189 | } | |
190 | #endif | |
191 | ||
726f6388 JA |
192 | /* Return the print name of this signal. */ |
193 | char * | |
194 | signal_name (sig) | |
195 | int sig; | |
196 | { | |
cce855bc JA |
197 | char *ret; |
198 | ||
199 | /* on cygwin32, signal_names[sig] could be null */ | |
b80f6443 JA |
200 | ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL) |
201 | ? _("invalid signal number") | |
202 | : signal_names[sig]; | |
203 | ||
cce855bc | 204 | return ret; |
726f6388 JA |
205 | } |
206 | ||
207 | /* Turn a string into a signal number, or a number into | |
208 | a signal number. If STRING is "2", "SIGINT", or "INT", | |
209 | then (int)2 is returned. Return NO_SIG if STRING doesn't | |
210 | contain a valid signal descriptor. */ | |
211 | int | |
b80f6443 | 212 | decode_signal (string, flags) |
726f6388 | 213 | char *string; |
b80f6443 | 214 | int flags; |
726f6388 | 215 | { |
7117c2d2 | 216 | intmax_t sig; |
b80f6443 | 217 | char *name; |
726f6388 | 218 | |
ccc6cda3 | 219 | if (legal_number (string, &sig)) |
f73dda09 | 220 | return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG); |
726f6388 | 221 | |
e8ce775d | 222 | /* A leading `SIG' may be omitted. */ |
f73dda09 | 223 | for (sig = 0; sig < BASH_NSIG; sig++) |
b72432fd | 224 | { |
b80f6443 JA |
225 | name = signal_names[sig]; |
226 | if (name == 0 || name[0] == '\0') | |
b72432fd | 227 | continue; |
b80f6443 JA |
228 | |
229 | /* Check name without the SIG prefix first case sensitivly or | |
230 | insensitively depending on whether flags includes DSIG_NOCASE */ | |
231 | if (STREQN (name, "SIG", 3)) | |
232 | { | |
233 | name += 3; | |
234 | ||
235 | if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0) | |
236 | return ((int)sig); | |
237 | else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0) | |
238 | return ((int)sig); | |
239 | /* If we can't use the `SIG' prefix to match, punt on this | |
240 | name now. */ | |
241 | else if ((flags & DSIG_SIGPREFIX) == 0) | |
242 | continue; | |
243 | } | |
244 | ||
245 | /* Check name with SIG prefix case sensitively or insensitively | |
246 | depending on whether flags includes DSIG_NOCASE */ | |
247 | name = signal_names[sig]; | |
248 | if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0) | |
249 | return ((int)sig); | |
250 | else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0) | |
b72432fd JA |
251 | return ((int)sig); |
252 | } | |
726f6388 JA |
253 | |
254 | return (NO_SIG); | |
255 | } | |
256 | ||
257 | /* Non-zero when we catch a trapped signal. */ | |
ccc6cda3 | 258 | static int catch_flag; |
726f6388 JA |
259 | |
260 | void | |
261 | run_pending_traps () | |
262 | { | |
263 | register int sig; | |
bb70624e | 264 | int old_exit_value, *token_state; |
726f6388 JA |
265 | |
266 | if (catch_flag == 0) /* simple optimization */ | |
267 | return; | |
268 | ||
269 | catch_flag = 0; | |
270 | ||
271 | /* Preserve $? when running trap. */ | |
272 | old_exit_value = last_command_exit_value; | |
273 | ||
274 | for (sig = 1; sig < NSIG; sig++) | |
275 | { | |
276 | /* XXX this could be made into a counter by using | |
28ef6c31 | 277 | while (pending_traps[sig]--) instead of the if statement. */ |
726f6388 JA |
278 | if (pending_traps[sig]) |
279 | { | |
ccc6cda3 | 280 | #if defined (HAVE_POSIX_SIGNALS) |
726f6388 JA |
281 | sigset_t set, oset; |
282 | ||
283 | sigemptyset (&set); | |
284 | sigemptyset (&oset); | |
285 | ||
286 | sigaddset (&set, sig); | |
287 | sigprocmask (SIG_BLOCK, &set, &oset); | |
288 | #else | |
289 | # if defined (HAVE_BSD_SIGNALS) | |
290 | int oldmask = sigblock (sigmask (sig)); | |
291 | # endif | |
ccc6cda3 | 292 | #endif /* HAVE_POSIX_SIGNALS */ |
726f6388 JA |
293 | |
294 | if (sig == SIGINT) | |
295 | { | |
296 | run_interrupt_trap (); | |
ccc6cda3 | 297 | CLRINTERRUPT; |
726f6388 | 298 | } |
3185942a JA |
299 | #if defined (JOB_CONTROL) && defined (SIGCHLD) |
300 | else if (sig == SIGCHLD && | |
301 | trap_list[SIGCHLD] != (char *)IMPOSSIBLE_TRAP_HANDLER && | |
302 | (sigmodes[SIGCHLD] & SIG_INPROGRESS) == 0) | |
303 | { | |
304 | run_sigchld_trap (pending_traps[sig]); /* use as counter */ | |
305 | } | |
306 | #endif | |
bb70624e JA |
307 | else if (trap_list[sig] == (char *)DEFAULT_SIG || |
308 | trap_list[sig] == (char *)IGNORE_SIG || | |
309 | trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER) | |
310 | { | |
311 | /* This is possible due to a race condition. Say a bash | |
312 | process has SIGTERM trapped. A subshell is spawned | |
313 | using { list; } & and the parent does something and kills | |
314 | the subshell with SIGTERM. It's possible for the subshell | |
315 | to set pending_traps[SIGTERM] to 1 before the code in | |
316 | execute_cmd.c eventually calls restore_original_signals | |
317 | to reset the SIGTERM signal handler in the subshell. The | |
318 | next time run_pending_traps is called, pending_traps[SIGTERM] | |
319 | will be 1, but the trap handler in trap_list[SIGTERM] will | |
320 | be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG). | |
321 | Unless we catch this, the subshell will dump core when | |
322 | trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is | |
323 | usually 0x0. */ | |
b80f6443 | 324 | internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"), |
f73dda09 | 325 | sig, trap_list[sig]); |
bb70624e JA |
326 | if (trap_list[sig] == (char *)DEFAULT_SIG) |
327 | { | |
b80f6443 | 328 | internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig)); |
bb70624e JA |
329 | kill (getpid (), sig); |
330 | } | |
331 | } | |
726f6388 | 332 | else |
bb70624e JA |
333 | { |
334 | token_state = save_token_state (); | |
17345e5a | 335 | parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE); |
bb70624e JA |
336 | restore_token_state (token_state); |
337 | free (token_state); | |
338 | } | |
726f6388 JA |
339 | |
340 | pending_traps[sig] = 0; | |
341 | ||
ccc6cda3 | 342 | #if defined (HAVE_POSIX_SIGNALS) |
726f6388 JA |
343 | sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); |
344 | #else | |
345 | # if defined (HAVE_BSD_SIGNALS) | |
346 | sigsetmask (oldmask); | |
347 | # endif | |
348 | #endif /* POSIX_VERSION */ | |
349 | } | |
350 | } | |
351 | ||
352 | last_command_exit_value = old_exit_value; | |
353 | } | |
354 | ||
355 | sighandler | |
356 | trap_handler (sig) | |
357 | int sig; | |
358 | { | |
bb70624e JA |
359 | int oerrno; |
360 | ||
3185942a JA |
361 | if ((sigmodes[sig] & SIG_TRAPPED) == 0) |
362 | { | |
363 | #if defined (DEBUG) | |
364 | internal_warning ("trap_handler: signal %d: signal not trapped", sig); | |
365 | #endif | |
366 | SIGRETURN (0); | |
367 | } | |
368 | ||
726f6388 JA |
369 | if ((sig >= NSIG) || |
370 | (trap_list[sig] == (char *)DEFAULT_SIG) || | |
371 | (trap_list[sig] == (char *)IGNORE_SIG)) | |
b80f6443 | 372 | programming_error (_("trap_handler: bad signal %d"), sig); |
726f6388 JA |
373 | else |
374 | { | |
28ef6c31 | 375 | oerrno = errno; |
ccc6cda3 | 376 | #if defined (MUST_REINSTALL_SIGHANDLERS) |
3185942a JA |
377 | # if defined (JOB_CONTROL) && defined (SIGCHLD) |
378 | if (sig != SIGCHLD) | |
379 | # endif /* JOB_CONTROL && SIGCHLD */ | |
726f6388 | 380 | set_signal_handler (sig, trap_handler); |
ccc6cda3 | 381 | #endif /* MUST_REINSTALL_SIGHANDLERS */ |
726f6388 JA |
382 | |
383 | catch_flag = 1; | |
384 | pending_traps[sig]++; | |
385 | ||
7117c2d2 JA |
386 | if (interrupt_immediately && this_shell_builtin && (this_shell_builtin == wait_builtin)) |
387 | { | |
388 | wait_signal_received = sig; | |
389 | longjmp (wait_intr_buf, 1); | |
390 | } | |
391 | ||
726f6388 JA |
392 | if (interrupt_immediately) |
393 | run_pending_traps (); | |
bb70624e JA |
394 | |
395 | errno = oerrno; | |
726f6388 | 396 | } |
ccc6cda3 JA |
397 | |
398 | SIGRETURN (0); | |
726f6388 JA |
399 | } |
400 | ||
401 | #if defined (JOB_CONTROL) && defined (SIGCHLD) | |
cce855bc JA |
402 | |
403 | #ifdef INCLUDE_UNUSED | |
726f6388 JA |
404 | /* Make COMMAND_STRING be executed when SIGCHLD is caught. */ |
405 | void | |
406 | set_sigchld_trap (command_string) | |
407 | char *command_string; | |
408 | { | |
726f6388 JA |
409 | set_signal (SIGCHLD, command_string); |
410 | } | |
cce855bc | 411 | #endif |
726f6388 | 412 | |
95732b49 | 413 | /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD |
3185942a JA |
414 | is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel |
415 | to make sure that a SIGCHLD trap handler run via run_sigchld_trap can | |
416 | reset the disposition to the default and not have the original signal | |
417 | accidentally restored, undoing the user's command. */ | |
726f6388 JA |
418 | void |
419 | maybe_set_sigchld_trap (command_string) | |
420 | char *command_string; | |
421 | { | |
3185942a | 422 | if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER) |
726f6388 JA |
423 | set_signal (SIGCHLD, command_string); |
424 | } | |
3185942a JA |
425 | |
426 | /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used | |
427 | as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether | |
428 | or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */ | |
429 | void | |
430 | set_impossible_sigchld_trap () | |
431 | { | |
432 | restore_default_signal (SIGCHLD); | |
433 | change_signal (SIGCHLD, (char *)IMPOSSIBLE_TRAP_HANDLER); | |
434 | sigmodes[SIGCHLD] &= ~SIG_TRAPPED; /* maybe_set_sigchld_trap checks this */ | |
435 | } | |
726f6388 JA |
436 | #endif /* JOB_CONTROL && SIGCHLD */ |
437 | ||
ccc6cda3 JA |
438 | void |
439 | set_debug_trap (command) | |
726f6388 JA |
440 | char *command; |
441 | { | |
ccc6cda3 JA |
442 | set_signal (DEBUG_TRAP, command); |
443 | } | |
726f6388 | 444 | |
f73dda09 JA |
445 | void |
446 | set_error_trap (command) | |
447 | char *command; | |
448 | { | |
449 | set_signal (ERROR_TRAP, command); | |
450 | } | |
451 | ||
b80f6443 JA |
452 | void |
453 | set_return_trap (command) | |
454 | char *command; | |
455 | { | |
456 | set_signal (RETURN_TRAP, command); | |
457 | } | |
458 | ||
cce855bc | 459 | #ifdef INCLUDE_UNUSED |
ccc6cda3 JA |
460 | void |
461 | set_sigint_trap (command) | |
462 | char *command; | |
463 | { | |
726f6388 JA |
464 | set_signal (SIGINT, command); |
465 | } | |
cce855bc | 466 | #endif |
726f6388 JA |
467 | |
468 | /* Reset the SIGINT handler so that subshells that are doing `shellsy' | |
469 | things, like waiting for command substitution or executing commands | |
470 | in explicit subshells ( ( cmd ) ), can catch interrupts properly. */ | |
471 | SigHandler * | |
472 | set_sigint_handler () | |
473 | { | |
474 | if (sigmodes[SIGINT] & SIG_HARD_IGNORE) | |
475 | return ((SigHandler *)SIG_IGN); | |
476 | ||
477 | else if (sigmodes[SIGINT] & SIG_IGNORED) | |
ccc6cda3 JA |
478 | return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */ |
479 | ||
726f6388 JA |
480 | else if (sigmodes[SIGINT] & SIG_TRAPPED) |
481 | return ((SigHandler *)set_signal_handler (SIGINT, trap_handler)); | |
482 | ||
483 | /* The signal is not trapped, so set the handler to the shell's special | |
484 | interrupt handler. */ | |
485 | else if (interactive) /* XXX - was interactive_shell */ | |
486 | return (set_signal_handler (SIGINT, sigint_sighandler)); | |
487 | else | |
0628567a | 488 | return (set_signal_handler (SIGINT, termsig_sighandler)); |
726f6388 JA |
489 | } |
490 | ||
e8ce775d JA |
491 | /* Return the correct handler for signal SIG according to the values in |
492 | sigmodes[SIG]. */ | |
493 | SigHandler * | |
494 | trap_to_sighandler (sig) | |
495 | int sig; | |
496 | { | |
497 | if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE)) | |
498 | return (SIG_IGN); | |
499 | else if (sigmodes[sig] & SIG_TRAPPED) | |
500 | return (trap_handler); | |
501 | else | |
502 | return (SIG_DFL); | |
503 | } | |
504 | ||
726f6388 JA |
505 | /* Set SIG to call STRING as a command. */ |
506 | void | |
507 | set_signal (sig, string) | |
508 | int sig; | |
509 | char *string; | |
510 | { | |
f73dda09 | 511 | if (SPECIAL_TRAP (sig)) |
ccc6cda3 JA |
512 | { |
513 | change_signal (sig, savestring (string)); | |
d166f048 JA |
514 | if (sig == EXIT_TRAP && interactive == 0) |
515 | initialize_terminating_signals (); | |
ccc6cda3 JA |
516 | return; |
517 | } | |
518 | ||
726f6388 JA |
519 | /* A signal ignored on entry to the shell cannot be trapped or reset, but |
520 | no error is reported when attempting to do so. -- Posix.2 */ | |
521 | if (sigmodes[sig] & SIG_HARD_IGNORE) | |
522 | return; | |
523 | ||
524 | /* Make sure we have original_signals[sig] if the signal has not yet | |
525 | been trapped. */ | |
526 | if ((sigmodes[sig] & SIG_TRAPPED) == 0) | |
527 | { | |
528 | /* If we aren't sure of the original value, check it. */ | |
529 | if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) | |
0628567a | 530 | GETORIGSIG (sig); |
726f6388 | 531 | if (original_signals[sig] == SIG_IGN) |
0628567a | 532 | return; |
726f6388 JA |
533 | } |
534 | ||
535 | /* Only change the system signal handler if SIG_NO_TRAP is not set. | |
536 | The trap command string is changed in either case. The shell signal | |
537 | handlers for SIGINT and SIGCHLD run the user specified traps in an | |
538 | environment in which it is safe to do so. */ | |
539 | if ((sigmodes[sig] & SIG_NO_TRAP) == 0) | |
540 | { | |
541 | set_signal_handler (sig, SIG_IGN); | |
542 | change_signal (sig, savestring (string)); | |
543 | set_signal_handler (sig, trap_handler); | |
544 | } | |
545 | else | |
546 | change_signal (sig, savestring (string)); | |
547 | } | |
548 | ||
549 | static void | |
550 | free_trap_command (sig) | |
551 | int sig; | |
552 | { | |
553 | if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] && | |
554 | (trap_list[sig] != (char *)IGNORE_SIG) && | |
555 | (trap_list[sig] != (char *)DEFAULT_SIG) && | |
556 | (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER)) | |
557 | free (trap_list[sig]); | |
558 | } | |
ccc6cda3 | 559 | |
726f6388 JA |
560 | /* If SIG has a string assigned to it, get rid of it. Then give it |
561 | VALUE. */ | |
562 | static void | |
563 | change_signal (sig, value) | |
564 | int sig; | |
565 | char *value; | |
566 | { | |
d166f048 JA |
567 | if ((sigmodes[sig] & SIG_INPROGRESS) == 0) |
568 | free_trap_command (sig); | |
726f6388 JA |
569 | trap_list[sig] = value; |
570 | ||
571 | sigmodes[sig] |= SIG_TRAPPED; | |
572 | if (value == (char *)IGNORE_SIG) | |
573 | sigmodes[sig] |= SIG_IGNORED; | |
574 | else | |
575 | sigmodes[sig] &= ~SIG_IGNORED; | |
576 | if (sigmodes[sig] & SIG_INPROGRESS) | |
577 | sigmodes[sig] |= SIG_CHANGED; | |
578 | } | |
579 | ||
726f6388 JA |
580 | static void |
581 | get_original_signal (sig) | |
582 | int sig; | |
583 | { | |
584 | /* If we aren't sure the of the original value, then get it. */ | |
585 | if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER) | |
0628567a | 586 | GETORIGSIG (sig); |
726f6388 JA |
587 | } |
588 | ||
589 | /* Restore the default action for SIG; i.e., the action the shell | |
590 | would have taken before you used the trap command. This is called | |
591 | from trap_builtin (), which takes care to restore the handlers for | |
592 | the signals the shell treats specially. */ | |
593 | void | |
594 | restore_default_signal (sig) | |
595 | int sig; | |
596 | { | |
f73dda09 | 597 | if (SPECIAL_TRAP (sig)) |
726f6388 | 598 | { |
b80f6443 JA |
599 | if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) || |
600 | (sigmodes[sig] & SIG_INPROGRESS) == 0) | |
d166f048 | 601 | free_trap_command (sig); |
726f6388 JA |
602 | trap_list[sig] = (char *)NULL; |
603 | sigmodes[sig] &= ~SIG_TRAPPED; | |
d166f048 JA |
604 | if (sigmodes[sig] & SIG_INPROGRESS) |
605 | sigmodes[sig] |= SIG_CHANGED; | |
726f6388 JA |
606 | return; |
607 | } | |
608 | ||
609 | GET_ORIGINAL_SIGNAL (sig); | |
610 | ||
611 | /* A signal ignored on entry to the shell cannot be trapped or reset, but | |
612 | no error is reported when attempting to do so. Thanks Posix.2. */ | |
613 | if (sigmodes[sig] & SIG_HARD_IGNORE) | |
614 | return; | |
615 | ||
616 | /* If we aren't trapping this signal, don't bother doing anything else. */ | |
ccc6cda3 | 617 | if ((sigmodes[sig] & SIG_TRAPPED) == 0) |
726f6388 JA |
618 | return; |
619 | ||
620 | /* Only change the signal handler for SIG if it allows it. */ | |
ccc6cda3 | 621 | if ((sigmodes[sig] & SIG_NO_TRAP) == 0) |
726f6388 JA |
622 | set_signal_handler (sig, original_signals[sig]); |
623 | ||
624 | /* Change the trap command in either case. */ | |
625 | change_signal (sig, (char *)DEFAULT_SIG); | |
626 | ||
627 | /* Mark the signal as no longer trapped. */ | |
628 | sigmodes[sig] &= ~SIG_TRAPPED; | |
629 | } | |
630 | ||
631 | /* Make this signal be ignored. */ | |
632 | void | |
633 | ignore_signal (sig) | |
634 | int sig; | |
635 | { | |
f73dda09 | 636 | if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0)) |
ccc6cda3 JA |
637 | { |
638 | change_signal (sig, (char *)IGNORE_SIG); | |
639 | return; | |
640 | } | |
641 | ||
726f6388 JA |
642 | GET_ORIGINAL_SIGNAL (sig); |
643 | ||
644 | /* A signal ignored on entry to the shell cannot be trapped or reset. | |
ccc6cda3 | 645 | No error is reported when the user attempts to do so. */ |
726f6388 JA |
646 | if (sigmodes[sig] & SIG_HARD_IGNORE) |
647 | return; | |
648 | ||
649 | /* If already trapped and ignored, no change necessary. */ | |
ccc6cda3 | 650 | if (sigmodes[sig] & SIG_IGNORED) |
726f6388 JA |
651 | return; |
652 | ||
653 | /* Only change the signal handler for SIG if it allows it. */ | |
ccc6cda3 | 654 | if ((sigmodes[sig] & SIG_NO_TRAP) == 0) |
726f6388 JA |
655 | set_signal_handler (sig, SIG_IGN); |
656 | ||
657 | /* Change the trap command in either case. */ | |
658 | change_signal (sig, (char *)IGNORE_SIG); | |
659 | } | |
660 | ||
661 | /* Handle the calling of "trap 0". The only sticky situation is when | |
662 | the command to be executed includes an "exit". This is why we have | |
663 | to provide our own place for top_level to jump to. */ | |
664 | int | |
665 | run_exit_trap () | |
666 | { | |
ccc6cda3 | 667 | char *trap_command; |
b80f6443 | 668 | int code, function_code, retval; |
726f6388 | 669 | |
b80f6443 JA |
670 | trap_saved_exit_value = last_command_exit_value; |
671 | function_code = 0; | |
726f6388 | 672 | |
ccc6cda3 JA |
673 | /* Run the trap only if signal 0 is trapped and not ignored, and we are not |
674 | currently running in the trap handler (call to exit in the list of | |
675 | commands given to trap 0). */ | |
676 | if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) && | |
677 | (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0) | |
726f6388 | 678 | { |
ccc6cda3 JA |
679 | trap_command = savestring (trap_list[EXIT_TRAP]); |
680 | sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED; | |
681 | sigmodes[EXIT_TRAP] |= SIG_INPROGRESS; | |
726f6388 | 682 | |
b80f6443 JA |
683 | retval = trap_saved_exit_value; |
684 | running_trap = 1; | |
685 | ||
726f6388 JA |
686 | code = setjmp (top_level); |
687 | ||
b80f6443 JA |
688 | /* If we're in a function, make sure return longjmps come here, too. */ |
689 | if (return_catch_flag) | |
690 | function_code = setjmp (return_catch); | |
691 | ||
692 | if (code == 0 && function_code == 0) | |
cce855bc JA |
693 | { |
694 | reset_parser (); | |
17345e5a | 695 | parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE); |
cce855bc | 696 | } |
b80f6443 JA |
697 | else if (code == ERREXIT) |
698 | retval = last_command_exit_value; | |
726f6388 | 699 | else if (code == EXITPROG) |
b80f6443 JA |
700 | retval = last_command_exit_value; |
701 | else if (function_code != 0) | |
702 | retval = return_catch_value; | |
726f6388 | 703 | else |
b80f6443 JA |
704 | retval = trap_saved_exit_value; |
705 | ||
706 | running_trap = 0; | |
707 | return retval; | |
726f6388 JA |
708 | } |
709 | ||
b80f6443 | 710 | return (trap_saved_exit_value); |
726f6388 JA |
711 | } |
712 | ||
ccc6cda3 JA |
713 | void |
714 | run_trap_cleanup (sig) | |
715 | int sig; | |
716 | { | |
717 | sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED); | |
718 | } | |
719 | ||
720 | /* Run a trap command for SIG. SIG is one of the signals the shell treats | |
b80f6443 JA |
721 | specially. Returns the exit status of the executed trap command list. */ |
722 | static int | |
ccc6cda3 | 723 | _run_trap_internal (sig, tag) |
726f6388 | 724 | int sig; |
ccc6cda3 | 725 | char *tag; |
726f6388 | 726 | { |
ccc6cda3 | 727 | char *trap_command, *old_trap; |
b80f6443 | 728 | int trap_exit_value, *token_state; |
17345e5a | 729 | int save_return_catch_flag, function_code, flags; |
b80f6443 | 730 | procenv_t save_return_catch; |
ccc6cda3 | 731 | |
b80f6443 | 732 | trap_exit_value = function_code = 0; |
ccc6cda3 JA |
733 | /* Run the trap only if SIG is trapped and not ignored, and we are not |
734 | currently executing in the trap handler. */ | |
735 | if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) && | |
736 | (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) && | |
737 | ((sigmodes[sig] & SIG_INPROGRESS) == 0)) | |
738 | { | |
739 | old_trap = trap_list[sig]; | |
740 | sigmodes[sig] |= SIG_INPROGRESS; | |
741 | sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */ | |
742 | trap_command = savestring (old_trap); | |
743 | ||
744 | running_trap = sig + 1; | |
b80f6443 | 745 | trap_saved_exit_value = last_command_exit_value; |
bb70624e JA |
746 | |
747 | token_state = save_token_state (); | |
b80f6443 JA |
748 | |
749 | /* If we're in a function, make sure return longjmps come here, too. */ | |
750 | save_return_catch_flag = return_catch_flag; | |
751 | if (return_catch_flag) | |
752 | { | |
753 | COPY_PROCENV (return_catch, save_return_catch); | |
754 | function_code = setjmp (return_catch); | |
755 | } | |
756 | ||
17345e5a | 757 | flags = SEVAL_NONINT|SEVAL_NOHIST; |
89a92869 | 758 | if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP) |
17345e5a | 759 | flags |= SEVAL_RESETLINE; |
b80f6443 | 760 | if (function_code == 0) |
17345e5a | 761 | parse_and_execute (trap_command, tag, flags); |
b80f6443 | 762 | |
bb70624e JA |
763 | restore_token_state (token_state); |
764 | free (token_state); | |
765 | ||
b80f6443 JA |
766 | trap_exit_value = last_command_exit_value; |
767 | last_command_exit_value = trap_saved_exit_value; | |
ccc6cda3 JA |
768 | running_trap = 0; |
769 | ||
770 | sigmodes[sig] &= ~SIG_INPROGRESS; | |
771 | ||
772 | if (sigmodes[sig] & SIG_CHANGED) | |
773 | { | |
b80f6443 JA |
774 | #if 0 |
775 | /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in | |
776 | the places where they can be changed using unwind-protects. For | |
777 | example, look at execute_cmd.c:execute_function(). */ | |
778 | if (SPECIAL_TRAP (sig) == 0) | |
779 | #endif | |
780 | free (old_trap); | |
ccc6cda3 JA |
781 | sigmodes[sig] &= ~SIG_CHANGED; |
782 | } | |
b80f6443 JA |
783 | |
784 | if (save_return_catch_flag) | |
785 | { | |
786 | return_catch_flag = save_return_catch_flag; | |
787 | return_catch_value = trap_exit_value; | |
788 | COPY_PROCENV (save_return_catch, return_catch); | |
789 | if (function_code) | |
790 | longjmp (return_catch, 1); | |
791 | } | |
ccc6cda3 | 792 | } |
b80f6443 JA |
793 | |
794 | return trap_exit_value; | |
ccc6cda3 JA |
795 | } |
796 | ||
b80f6443 | 797 | int |
ccc6cda3 JA |
798 | run_debug_trap () |
799 | { | |
b80f6443 | 800 | int trap_exit_value; |
89a92869 CR |
801 | pid_t save_pgrp; |
802 | int save_pipe[2]; | |
b80f6443 JA |
803 | |
804 | /* XXX - question: should the DEBUG trap inherit the RETURN trap? */ | |
805 | trap_exit_value = 0; | |
806 | if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0)) | |
807 | { | |
89a92869 CR |
808 | #if defined (JOB_CONTROL) |
809 | save_pgrp = pipeline_pgrp; | |
810 | pipeline_pgrp = 0; | |
811 | save_pipeline (1); | |
812 | # if defined (PGRP_PIPE) | |
813 | save_pgrp_pipe (save_pipe, 1); | |
814 | # endif | |
815 | stop_making_children (); | |
816 | #endif | |
817 | ||
b80f6443 | 818 | trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap"); |
89a92869 CR |
819 | |
820 | #if defined (JOB_CONTROL) | |
821 | pipeline_pgrp = save_pgrp; | |
822 | restore_pipeline (1); | |
823 | # if defined (PGRP_PIPE) | |
824 | close_pgrp_pipe (); | |
825 | restore_pgrp_pipe (save_pipe); | |
826 | # endif | |
827 | if (pipeline_pgrp > 0) | |
828 | give_terminal_to (pipeline_pgrp, 1); | |
829 | notify_and_cleanup (); | |
830 | #endif | |
b80f6443 JA |
831 | |
832 | #if defined (DEBUGGER) | |
833 | /* If we're in the debugger and the DEBUG trap returns 2 while we're in | |
834 | a function or sourced script, we force a `return'. */ | |
835 | if (debugging_mode && trap_exit_value == 2 && return_catch_flag) | |
836 | { | |
837 | return_catch_value = trap_exit_value; | |
838 | longjmp (return_catch, 1); | |
839 | } | |
840 | #endif | |
841 | } | |
842 | return trap_exit_value; | |
ccc6cda3 JA |
843 | } |
844 | ||
f73dda09 JA |
845 | void |
846 | run_error_trap () | |
847 | { | |
b80f6443 | 848 | if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0) |
f73dda09 JA |
849 | _run_trap_internal (ERROR_TRAP, "error trap"); |
850 | } | |
851 | ||
b80f6443 JA |
852 | void |
853 | run_return_trap () | |
854 | { | |
855 | int old_exit_value; | |
856 | ||
95732b49 JA |
857 | #if 0 |
858 | if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS)) | |
859 | return; | |
860 | #endif | |
861 | ||
b80f6443 JA |
862 | if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0) |
863 | { | |
864 | old_exit_value = last_command_exit_value; | |
865 | _run_trap_internal (RETURN_TRAP, "return trap"); | |
866 | last_command_exit_value = old_exit_value; | |
867 | } | |
868 | } | |
869 | ||
ccc6cda3 JA |
870 | /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and |
871 | declared here to localize the trap functions. */ | |
872 | void | |
873 | run_interrupt_trap () | |
874 | { | |
875 | _run_trap_internal (SIGINT, "interrupt trap"); | |
726f6388 JA |
876 | } |
877 | ||
cce855bc | 878 | #ifdef INCLUDE_UNUSED |
726f6388 JA |
879 | /* Free all the allocated strings in the list of traps and reset the trap |
880 | values to the default. */ | |
881 | void | |
882 | free_trap_strings () | |
883 | { | |
884 | register int i; | |
885 | ||
f73dda09 | 886 | for (i = 0; i < BASH_NSIG; i++) |
726f6388 JA |
887 | { |
888 | free_trap_command (i); | |
889 | trap_list[i] = (char *)DEFAULT_SIG; | |
890 | sigmodes[i] &= ~SIG_TRAPPED; | |
891 | } | |
b80f6443 | 892 | trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL; |
726f6388 | 893 | } |
cce855bc | 894 | #endif |
726f6388 JA |
895 | |
896 | /* Reset the handler for SIG to the original value. */ | |
897 | static void | |
898 | reset_signal (sig) | |
899 | int sig; | |
900 | { | |
901 | set_signal_handler (sig, original_signals[sig]); | |
7117c2d2 | 902 | sigmodes[sig] &= ~SIG_TRAPPED; |
726f6388 JA |
903 | } |
904 | ||
ccc6cda3 JA |
905 | /* Set the handler signal SIG to the original and free any trap |
906 | command associated with it. */ | |
907 | static void | |
908 | restore_signal (sig) | |
909 | int sig; | |
726f6388 | 910 | { |
ccc6cda3 JA |
911 | set_signal_handler (sig, original_signals[sig]); |
912 | change_signal (sig, (char *)DEFAULT_SIG); | |
913 | sigmodes[sig] &= ~SIG_TRAPPED; | |
726f6388 JA |
914 | } |
915 | ||
ccc6cda3 JA |
916 | static void |
917 | reset_or_restore_signal_handlers (reset) | |
f73dda09 | 918 | sh_resetsig_func_t *reset; |
726f6388 JA |
919 | { |
920 | register int i; | |
921 | ||
ccc6cda3 JA |
922 | /* Take care of the exit trap first */ |
923 | if (sigmodes[EXIT_TRAP] & SIG_TRAPPED) | |
726f6388 | 924 | { |
ccc6cda3 | 925 | sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED; |
95732b49 JA |
926 | if (reset != reset_signal) |
927 | { | |
928 | free_trap_command (EXIT_TRAP); | |
929 | trap_list[EXIT_TRAP] = (char *)NULL; | |
930 | } | |
726f6388 | 931 | } |
b80f6443 | 932 | |
726f6388 JA |
933 | for (i = 1; i < NSIG; i++) |
934 | { | |
ccc6cda3 | 935 | if (sigmodes[i] & SIG_TRAPPED) |
726f6388 JA |
936 | { |
937 | if (trap_list[i] == (char *)IGNORE_SIG) | |
938 | set_signal_handler (i, SIG_IGN); | |
939 | else | |
ccc6cda3 | 940 | (*reset) (i); |
726f6388 | 941 | } |
ccc6cda3 JA |
942 | else if (sigmodes[i] & SIG_SPECIAL) |
943 | (*reset) (i); | |
726f6388 | 944 | } |
f73dda09 JA |
945 | |
946 | /* Command substitution and other child processes don't inherit the | |
b80f6443 JA |
947 | debug, error, or return traps. If we're in the debugger, and the |
948 | `functrace' or `errtrace' options have been set, then let command | |
949 | substitutions inherit them. Let command substitution inherit the | |
950 | RETURN trap if we're in the debugger and tracing functions. */ | |
0628567a JA |
951 | if (function_trace_mode == 0) |
952 | { | |
953 | sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED; | |
954 | sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED; | |
955 | } | |
956 | if (error_trace_mode == 0) | |
b80f6443 | 957 | sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED; |
726f6388 JA |
958 | } |
959 | ||
f73dda09 JA |
960 | /* Reset trapped signals to their original values, but don't free the |
961 | trap strings. Called by the command substitution code. */ | |
726f6388 | 962 | void |
ccc6cda3 | 963 | reset_signal_handlers () |
726f6388 | 964 | { |
ccc6cda3 JA |
965 | reset_or_restore_signal_handlers (reset_signal); |
966 | } | |
726f6388 | 967 | |
ccc6cda3 JA |
968 | /* Reset all trapped signals to their original values. Signals set to be |
969 | ignored with trap '' SIGNAL should be ignored, so we make sure that they | |
970 | are. Called by child processes after they are forked. */ | |
971 | void | |
972 | restore_original_signals () | |
973 | { | |
974 | reset_or_restore_signal_handlers (restore_signal); | |
726f6388 JA |
975 | } |
976 | ||
977 | /* If a trap handler exists for signal SIG, then call it; otherwise just | |
978 | return failure. */ | |
979 | int | |
980 | maybe_call_trap_handler (sig) | |
981 | int sig; | |
982 | { | |
983 | /* Call the trap handler for SIG if the signal is trapped and not ignored. */ | |
ccc6cda3 | 984 | if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0)) |
726f6388 JA |
985 | { |
986 | switch (sig) | |
987 | { | |
988 | case SIGINT: | |
989 | run_interrupt_trap (); | |
990 | break; | |
ccc6cda3 | 991 | case EXIT_TRAP: |
726f6388 JA |
992 | run_exit_trap (); |
993 | break; | |
ccc6cda3 JA |
994 | case DEBUG_TRAP: |
995 | run_debug_trap (); | |
996 | break; | |
f73dda09 JA |
997 | case ERROR_TRAP: |
998 | run_error_trap (); | |
999 | break; | |
726f6388 JA |
1000 | default: |
1001 | trap_handler (sig); | |
1002 | break; | |
1003 | } | |
1004 | return (1); | |
1005 | } | |
1006 | else | |
1007 | return (0); | |
1008 | } | |
1009 | ||
1010 | int | |
1011 | signal_is_trapped (sig) | |
1012 | int sig; | |
1013 | { | |
1014 | return (sigmodes[sig] & SIG_TRAPPED); | |
1015 | } | |
1016 | ||
1017 | int | |
1018 | signal_is_special (sig) | |
1019 | int sig; | |
1020 | { | |
1021 | return (sigmodes[sig] & SIG_SPECIAL); | |
1022 | } | |
1023 | ||
1024 | int | |
1025 | signal_is_ignored (sig) | |
1026 | int sig; | |
1027 | { | |
1028 | return (sigmodes[sig] & SIG_IGNORED); | |
1029 | } | |
1030 | ||
1031 | void | |
1032 | set_signal_ignored (sig) | |
1033 | int sig; | |
1034 | { | |
1035 | sigmodes[sig] |= SIG_HARD_IGNORE; | |
ccc6cda3 | 1036 | original_signals[sig] = SIG_IGN; |
726f6388 | 1037 | } |
95732b49 JA |
1038 | |
1039 | int | |
1040 | signal_in_progress (sig) | |
1041 | int sig; | |
1042 | { | |
1043 | return (sigmodes[sig] & SIG_INPROGRESS); | |
1044 | } |