]> git.ipfire.org Git - thirdparty/bash.git/blame - trap.c
Imported from ../bash-2.01.tar.gz.
[thirdparty/bash.git] / trap.c
CommitLineData
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
4/* Copyright (C) 1987, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 1, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
ccc6cda3
JA
22#include "config.h"
23
726f6388
JA
24#include <stdio.h>
25
26#include "bashtypes.h"
27#include "trap.h"
28
d166f048 29#include "bashansi.h"
726f6388 30
ccc6cda3
JA
31#if defined (HAVE_UNISTD_H)
32# include <unistd.h>
33#endif
34
726f6388
JA
35#include "shell.h"
36#include "signames.h"
ccc6cda3 37#include "builtins/common.h"
726f6388
JA
38
39/* Flags which describe the current handling state of a signal. */
40#define SIG_INHERITED 0x0 /* Value inherited from parent. */
41#define SIG_TRAPPED 0x1 /* Currently trapped. */
42#define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
43#define SIG_SPECIAL 0x4 /* Treat this signal specially. */
44#define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
ccc6cda3
JA
45#define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
46#define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
47#define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
726f6388
JA
48
49/* An array of such flags, one for each signal, describing what the
ccc6cda3
JA
50 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
51 assumes this. */
52static int sigmodes[NSIG+1];
726f6388
JA
53
54static void change_signal (), restore_signal ();
55
56/* Variables used here but defined in other files. */
57extern int interactive_shell, interactive;
58extern int interrupt_immediately;
59extern int last_command_exit_value;
d166f048 60extern int line_number;
726f6388
JA
61
62/* The list of things to do originally, before we started trapping. */
63SigHandler *original_signals[NSIG];
64
65/* For each signal, a slot for a string, which is a command to be
66 executed when that signal is recieved. The slot can also contain
67 DEFAULT_SIG, which means do whatever you were going to do before
68 you were so rudely interrupted, or IGNORE_SIG, which says ignore
69 this signal. */
ccc6cda3 70char *trap_list[NSIG+1];
726f6388
JA
71
72/* A bitmap of signals received for which we have trap handlers. */
73int pending_traps[NSIG];
74
ccc6cda3
JA
75/* Set to the number of the signal we're running the trap for + 1.
76 Used in execute_cmd.c and builtins/common.c to clean up when
77 parse_and_execute does not return normally after executing the
78 trap command (e.g., when `return' is executed in the trap command). */
79int running_trap;
80
d166f048
JA
81/* The value of line_number when the trap started executing, since
82 parse_and_execute resets it to 1 and the trap command might want
83 it. */
84int trap_line_number;
85
726f6388
JA
86/* A value which can never be the target of a trap handler. */
87#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
88
89void
90initialize_traps ()
91{
92 register int i;
93
ccc6cda3
JA
94 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = (char *)NULL;
95 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = SIG_INHERITED;
96 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
726f6388
JA
97
98 for (i = 1; i < NSIG; i++)
99 {
100 pending_traps[i] = 0;
101 trap_list[i] = (char *)DEFAULT_SIG;
102 sigmodes[i] = SIG_INHERITED;
103 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
104 }
105
106 /* Show which signals are treated specially by the shell. */
107#if defined (SIGCHLD)
ccc6cda3
JA
108 original_signals[SIGCHLD] =
109 (SigHandler *) set_signal_handler (SIGCHLD, SIG_DFL);
726f6388
JA
110 set_signal_handler (SIGCHLD, original_signals[SIGCHLD]);
111 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
112#endif /* SIGCHLD */
113
114 original_signals[SIGINT] =
115 (SigHandler *) set_signal_handler (SIGINT, SIG_DFL);
116 set_signal_handler (SIGINT, original_signals[SIGINT]);
117 sigmodes[SIGINT] |= SIG_SPECIAL;
118
119 original_signals[SIGQUIT] =
120 (SigHandler *) set_signal_handler (SIGQUIT, SIG_DFL);
121 set_signal_handler (SIGQUIT, original_signals[SIGQUIT]);
122 sigmodes[SIGQUIT] |= SIG_SPECIAL;
123
124 if (interactive)
125 {
ccc6cda3
JA
126 original_signals[SIGTERM] =
127 (SigHandler *)set_signal_handler (SIGTERM, SIG_DFL);
726f6388
JA
128 set_signal_handler (SIGTERM, original_signals[SIGTERM]);
129 sigmodes[SIGTERM] |= SIG_SPECIAL;
130 }
131}
132
133/* Return the print name of this signal. */
134char *
135signal_name (sig)
136 int sig;
137{
ccc6cda3 138 return ((sig > NSIG || sig < 0) ? "bad signal number" : signal_names[sig]);
726f6388
JA
139}
140
141/* Turn a string into a signal number, or a number into
142 a signal number. If STRING is "2", "SIGINT", or "INT",
143 then (int)2 is returned. Return NO_SIG if STRING doesn't
144 contain a valid signal descriptor. */
145int
146decode_signal (string)
147 char *string;
148{
ccc6cda3 149 long sig;
726f6388 150
ccc6cda3
JA
151 if (legal_number (string, &sig))
152 return ((sig >= 0 && sig <= NSIG) ? (int)sig : NO_SIG);
726f6388 153
ccc6cda3
JA
154 for (sig = 0; sig <= NSIG; sig++)
155 if (strcasecmp (string, signal_names[sig]) == 0 ||
156 strcasecmp (string, &(signal_names[sig])[3]) == 0)
157 return ((int)sig);
726f6388
JA
158
159 return (NO_SIG);
160}
161
162/* Non-zero when we catch a trapped signal. */
ccc6cda3 163static int catch_flag;
726f6388
JA
164
165void
166run_pending_traps ()
167{
168 register int sig;
169 int old_exit_value;
170
171 if (catch_flag == 0) /* simple optimization */
172 return;
173
174 catch_flag = 0;
175
176 /* Preserve $? when running trap. */
177 old_exit_value = last_command_exit_value;
178
179 for (sig = 1; sig < NSIG; sig++)
180 {
181 /* XXX this could be made into a counter by using
182 while (pending_traps[sig]--) instead of the if statement. */
183 if (pending_traps[sig])
184 {
ccc6cda3 185#if defined (HAVE_POSIX_SIGNALS)
726f6388
JA
186 sigset_t set, oset;
187
188 sigemptyset (&set);
189 sigemptyset (&oset);
190
191 sigaddset (&set, sig);
192 sigprocmask (SIG_BLOCK, &set, &oset);
193#else
194# if defined (HAVE_BSD_SIGNALS)
195 int oldmask = sigblock (sigmask (sig));
196# endif
ccc6cda3 197#endif /* HAVE_POSIX_SIGNALS */
726f6388
JA
198
199 if (sig == SIGINT)
200 {
201 run_interrupt_trap ();
ccc6cda3 202 CLRINTERRUPT;
726f6388
JA
203 }
204 else
d166f048 205 parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST);
726f6388
JA
206
207 pending_traps[sig] = 0;
208
ccc6cda3 209#if defined (HAVE_POSIX_SIGNALS)
726f6388
JA
210 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
211#else
212# if defined (HAVE_BSD_SIGNALS)
213 sigsetmask (oldmask);
214# endif
215#endif /* POSIX_VERSION */
216 }
217 }
218
219 last_command_exit_value = old_exit_value;
220}
221
222sighandler
223trap_handler (sig)
224 int sig;
225{
226 if ((sig >= NSIG) ||
227 (trap_list[sig] == (char *)DEFAULT_SIG) ||
228 (trap_list[sig] == (char *)IGNORE_SIG))
ccc6cda3 229 programming_error ("trap_handler: bad signal %d", sig);
726f6388
JA
230 else
231 {
ccc6cda3 232#if defined (MUST_REINSTALL_SIGHANDLERS)
726f6388 233 set_signal_handler (sig, trap_handler);
ccc6cda3 234#endif /* MUST_REINSTALL_SIGHANDLERS */
726f6388
JA
235
236 catch_flag = 1;
237 pending_traps[sig]++;
238
239 if (interrupt_immediately)
240 run_pending_traps ();
241 }
ccc6cda3
JA
242
243 SIGRETURN (0);
726f6388
JA
244}
245
246#if defined (JOB_CONTROL) && defined (SIGCHLD)
247/* Make COMMAND_STRING be executed when SIGCHLD is caught. */
248void
249set_sigchld_trap (command_string)
250 char *command_string;
251{
726f6388
JA
252 set_signal (SIGCHLD, command_string);
253}
254
255/* Make COMMAND_STRING be executed when SIGCHLD is caught iff the current
256 SIGCHLD trap handler is DEFAULT_SIG. */
257void
258maybe_set_sigchld_trap (command_string)
259 char *command_string;
260{
726f6388
JA
261 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
262 set_signal (SIGCHLD, command_string);
263}
264#endif /* JOB_CONTROL && SIGCHLD */
265
ccc6cda3
JA
266void
267set_debug_trap (command)
726f6388
JA
268 char *command;
269{
ccc6cda3
JA
270 set_signal (DEBUG_TRAP, command);
271}
726f6388 272
ccc6cda3
JA
273void
274set_sigint_trap (command)
275 char *command;
276{
726f6388
JA
277 set_signal (SIGINT, command);
278}
279
280/* Reset the SIGINT handler so that subshells that are doing `shellsy'
281 things, like waiting for command substitution or executing commands
282 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
283SigHandler *
284set_sigint_handler ()
285{
286 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
287 return ((SigHandler *)SIG_IGN);
288
289 else if (sigmodes[SIGINT] & SIG_IGNORED)
ccc6cda3
JA
290 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
291
726f6388
JA
292 else if (sigmodes[SIGINT] & SIG_TRAPPED)
293 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
294
295 /* The signal is not trapped, so set the handler to the shell's special
296 interrupt handler. */
297 else if (interactive) /* XXX - was interactive_shell */
298 return (set_signal_handler (SIGINT, sigint_sighandler));
299 else
300 return (set_signal_handler (SIGINT, termination_unwind_protect));
301}
302
303/* Set SIG to call STRING as a command. */
304void
305set_signal (sig, string)
306 int sig;
307 char *string;
308{
ccc6cda3
JA
309 if (sig == DEBUG_TRAP || sig == EXIT_TRAP)
310 {
311 change_signal (sig, savestring (string));
d166f048
JA
312 if (sig == EXIT_TRAP && interactive == 0)
313 initialize_terminating_signals ();
ccc6cda3
JA
314 return;
315 }
316
726f6388
JA
317 /* A signal ignored on entry to the shell cannot be trapped or reset, but
318 no error is reported when attempting to do so. -- Posix.2 */
319 if (sigmodes[sig] & SIG_HARD_IGNORE)
320 return;
321
322 /* Make sure we have original_signals[sig] if the signal has not yet
323 been trapped. */
324 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
325 {
326 /* If we aren't sure of the original value, check it. */
327 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
328 {
329 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
330 set_signal_handler (sig, original_signals[sig]);
331 }
332
333 /* Signals ignored on entry to the shell cannot be trapped or reset. */
334 if (original_signals[sig] == SIG_IGN)
335 {
336 sigmodes[sig] |= SIG_HARD_IGNORE;
337 return;
338 }
339 }
340
341 /* Only change the system signal handler if SIG_NO_TRAP is not set.
342 The trap command string is changed in either case. The shell signal
343 handlers for SIGINT and SIGCHLD run the user specified traps in an
344 environment in which it is safe to do so. */
345 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
346 {
347 set_signal_handler (sig, SIG_IGN);
348 change_signal (sig, savestring (string));
349 set_signal_handler (sig, trap_handler);
350 }
351 else
352 change_signal (sig, savestring (string));
353}
354
355static void
356free_trap_command (sig)
357 int sig;
358{
359 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
360 (trap_list[sig] != (char *)IGNORE_SIG) &&
361 (trap_list[sig] != (char *)DEFAULT_SIG) &&
362 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
363 free (trap_list[sig]);
364}
ccc6cda3 365
726f6388
JA
366/* If SIG has a string assigned to it, get rid of it. Then give it
367 VALUE. */
368static void
369change_signal (sig, value)
370 int sig;
371 char *value;
372{
d166f048
JA
373 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
374 free_trap_command (sig);
726f6388
JA
375 trap_list[sig] = value;
376
377 sigmodes[sig] |= SIG_TRAPPED;
378 if (value == (char *)IGNORE_SIG)
379 sigmodes[sig] |= SIG_IGNORED;
380 else
381 sigmodes[sig] &= ~SIG_IGNORED;
382 if (sigmodes[sig] & SIG_INPROGRESS)
383 sigmodes[sig] |= SIG_CHANGED;
384}
385
386#define GET_ORIGINAL_SIGNAL(sig) \
387 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
388 get_original_signal (sig)
389
390static void
391get_original_signal (sig)
392 int sig;
393{
394 /* If we aren't sure the of the original value, then get it. */
395 if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
396 {
397 original_signals[sig] =
398 (SigHandler *) set_signal_handler (sig, SIG_DFL);
399 set_signal_handler (sig, original_signals[sig]);
400
401 /* Signals ignored on entry to the shell cannot be trapped. */
402 if (original_signals[sig] == SIG_IGN)
403 sigmodes[sig] |= SIG_HARD_IGNORE;
404 }
405}
406
407/* Restore the default action for SIG; i.e., the action the shell
408 would have taken before you used the trap command. This is called
409 from trap_builtin (), which takes care to restore the handlers for
410 the signals the shell treats specially. */
411void
412restore_default_signal (sig)
413 int sig;
414{
ccc6cda3 415 if (sig == DEBUG_TRAP || sig == EXIT_TRAP)
726f6388 416 {
d166f048
JA
417 if ((sig != DEBUG_TRAP) || (sigmodes[sig] & SIG_INPROGRESS) == 0)
418 free_trap_command (sig);
726f6388
JA
419 trap_list[sig] = (char *)NULL;
420 sigmodes[sig] &= ~SIG_TRAPPED;
d166f048
JA
421 if (sigmodes[sig] & SIG_INPROGRESS)
422 sigmodes[sig] |= SIG_CHANGED;
726f6388
JA
423 return;
424 }
425
426 GET_ORIGINAL_SIGNAL (sig);
427
428 /* A signal ignored on entry to the shell cannot be trapped or reset, but
429 no error is reported when attempting to do so. Thanks Posix.2. */
430 if (sigmodes[sig] & SIG_HARD_IGNORE)
431 return;
432
433 /* If we aren't trapping this signal, don't bother doing anything else. */
ccc6cda3 434 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
726f6388
JA
435 return;
436
437 /* Only change the signal handler for SIG if it allows it. */
ccc6cda3 438 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
726f6388
JA
439 set_signal_handler (sig, original_signals[sig]);
440
441 /* Change the trap command in either case. */
442 change_signal (sig, (char *)DEFAULT_SIG);
443
444 /* Mark the signal as no longer trapped. */
445 sigmodes[sig] &= ~SIG_TRAPPED;
446}
447
448/* Make this signal be ignored. */
449void
450ignore_signal (sig)
451 int sig;
452{
ccc6cda3
JA
453 if ((sig == EXIT_TRAP || sig == DEBUG_TRAP) && ((sigmodes[sig] & SIG_IGNORED) == 0))
454 {
455 change_signal (sig, (char *)IGNORE_SIG);
456 return;
457 }
458
726f6388
JA
459 GET_ORIGINAL_SIGNAL (sig);
460
461 /* A signal ignored on entry to the shell cannot be trapped or reset.
ccc6cda3 462 No error is reported when the user attempts to do so. */
726f6388
JA
463 if (sigmodes[sig] & SIG_HARD_IGNORE)
464 return;
465
466 /* If already trapped and ignored, no change necessary. */
ccc6cda3 467 if (sigmodes[sig] & SIG_IGNORED)
726f6388
JA
468 return;
469
470 /* Only change the signal handler for SIG if it allows it. */
ccc6cda3 471 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
726f6388
JA
472 set_signal_handler (sig, SIG_IGN);
473
474 /* Change the trap command in either case. */
475 change_signal (sig, (char *)IGNORE_SIG);
476}
477
478/* Handle the calling of "trap 0". The only sticky situation is when
479 the command to be executed includes an "exit". This is why we have
480 to provide our own place for top_level to jump to. */
481int
482run_exit_trap ()
483{
ccc6cda3
JA
484 char *trap_command;
485 int code, old_exit_value;
726f6388
JA
486
487 old_exit_value = last_command_exit_value;
488
ccc6cda3
JA
489 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
490 currently running in the trap handler (call to exit in the list of
491 commands given to trap 0). */
492 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
493 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
726f6388 494 {
ccc6cda3
JA
495 trap_command = savestring (trap_list[EXIT_TRAP]);
496 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
497 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
726f6388
JA
498
499 code = setjmp (top_level);
500
501 if (code == 0)
d166f048 502 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST);
726f6388 503 else if (code == EXITPROG)
ccc6cda3 504 return (last_command_exit_value);
726f6388
JA
505 else
506 return (old_exit_value);
507 }
508
509 return (old_exit_value);
510}
511
ccc6cda3
JA
512void
513run_trap_cleanup (sig)
514 int sig;
515{
516 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
517}
518
519/* Run a trap command for SIG. SIG is one of the signals the shell treats
520 specially. */
726f6388 521static void
ccc6cda3 522_run_trap_internal (sig, tag)
726f6388 523 int sig;
ccc6cda3 524 char *tag;
726f6388 525{
ccc6cda3 526 char *trap_command, *old_trap;
d166f048 527 int old_exit_value, old_line_number;
ccc6cda3
JA
528
529 /* Run the trap only if SIG is trapped and not ignored, and we are not
530 currently executing in the trap handler. */
531 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
532 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
533 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
534 {
535 old_trap = trap_list[sig];
536 sigmodes[sig] |= SIG_INPROGRESS;
537 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
538 trap_command = savestring (old_trap);
539
540 running_trap = sig + 1;
541 old_exit_value = last_command_exit_value;
d166f048
JA
542 /* Need to copy the value of line_number because parse_and_execute
543 resets it to 1, and the trap command might want it. */
544 trap_line_number = line_number;
545 parse_and_execute (trap_command, tag, SEVAL_NONINT|SEVAL_NOHIST);
ccc6cda3
JA
546 last_command_exit_value = old_exit_value;
547 running_trap = 0;
548
549 sigmodes[sig] &= ~SIG_INPROGRESS;
550
551 if (sigmodes[sig] & SIG_CHANGED)
552 {
553 free (old_trap);
554 sigmodes[sig] &= ~SIG_CHANGED;
555 }
556 }
557}
558
559void
560run_debug_trap ()
561{
562 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0)
563 _run_trap_internal (DEBUG_TRAP, "debug trap");
564}
565
566/* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
567 declared here to localize the trap functions. */
568void
569run_interrupt_trap ()
570{
571 _run_trap_internal (SIGINT, "interrupt trap");
726f6388
JA
572}
573
574/* Free all the allocated strings in the list of traps and reset the trap
575 values to the default. */
576void
577free_trap_strings ()
578{
579 register int i;
580
ccc6cda3 581 for (i = 0; i < NSIG+1; i++)
726f6388
JA
582 {
583 free_trap_command (i);
584 trap_list[i] = (char *)DEFAULT_SIG;
585 sigmodes[i] &= ~SIG_TRAPPED;
586 }
ccc6cda3 587 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = (char *)NULL;
726f6388
JA
588}
589
590/* Reset the handler for SIG to the original value. */
591static void
592reset_signal (sig)
593 int sig;
594{
595 set_signal_handler (sig, original_signals[sig]);
596}
597
ccc6cda3
JA
598/* Set the handler signal SIG to the original and free any trap
599 command associated with it. */
600static void
601restore_signal (sig)
602 int sig;
726f6388 603{
ccc6cda3
JA
604 set_signal_handler (sig, original_signals[sig]);
605 change_signal (sig, (char *)DEFAULT_SIG);
606 sigmodes[sig] &= ~SIG_TRAPPED;
726f6388
JA
607}
608
ccc6cda3
JA
609static void
610reset_or_restore_signal_handlers (reset)
611 VFunction *reset;
726f6388
JA
612{
613 register int i;
614
ccc6cda3
JA
615 /* Take care of the exit trap first */
616 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
726f6388 617 {
ccc6cda3
JA
618 free_trap_command (EXIT_TRAP);
619 trap_list[EXIT_TRAP] = (char *)NULL;
620 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
726f6388 621 }
726f6388
JA
622 for (i = 1; i < NSIG; i++)
623 {
ccc6cda3 624 if (sigmodes[i] & SIG_TRAPPED)
726f6388
JA
625 {
626 if (trap_list[i] == (char *)IGNORE_SIG)
627 set_signal_handler (i, SIG_IGN);
628 else
ccc6cda3 629 (*reset) (i);
726f6388 630 }
ccc6cda3
JA
631 else if (sigmodes[i] & SIG_SPECIAL)
632 (*reset) (i);
726f6388
JA
633 }
634}
635
726f6388 636void
ccc6cda3 637reset_signal_handlers ()
726f6388 638{
ccc6cda3
JA
639 reset_or_restore_signal_handlers (reset_signal);
640}
726f6388 641
ccc6cda3
JA
642/* Reset all trapped signals to their original values. Signals set to be
643 ignored with trap '' SIGNAL should be ignored, so we make sure that they
644 are. Called by child processes after they are forked. */
645void
646restore_original_signals ()
647{
648 reset_or_restore_signal_handlers (restore_signal);
726f6388
JA
649}
650
651/* If a trap handler exists for signal SIG, then call it; otherwise just
652 return failure. */
653int
654maybe_call_trap_handler (sig)
655 int sig;
656{
657 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
ccc6cda3 658 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
726f6388
JA
659 {
660 switch (sig)
661 {
662 case SIGINT:
663 run_interrupt_trap ();
664 break;
ccc6cda3 665 case EXIT_TRAP:
726f6388
JA
666 run_exit_trap ();
667 break;
ccc6cda3
JA
668 case DEBUG_TRAP:
669 run_debug_trap ();
670 break;
726f6388
JA
671 default:
672 trap_handler (sig);
673 break;
674 }
675 return (1);
676 }
677 else
678 return (0);
679}
680
681int
682signal_is_trapped (sig)
683 int sig;
684{
685 return (sigmodes[sig] & SIG_TRAPPED);
686}
687
688int
689signal_is_special (sig)
690 int sig;
691{
692 return (sigmodes[sig] & SIG_SPECIAL);
693}
694
695int
696signal_is_ignored (sig)
697 int sig;
698{
699 return (sigmodes[sig] & SIG_IGNORED);
700}
701
702void
703set_signal_ignored (sig)
704 int sig;
705{
706 sigmodes[sig] |= SIG_HARD_IGNORE;
ccc6cda3 707 original_signals[sig] = SIG_IGN;
726f6388 708}