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