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