1 /* trap.c -- Not the trap command, but useful functions for manipulating
2 those objects. The trap command is in builtins/trap.def. */
4 /* Copyright (C) 1987-2003 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
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 2, or (at your option) any later
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
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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
24 #if defined (HAVE_UNISTD_H)
28 #include "bashtypes.h"
40 #include "input.h" /* for save_token_state, restore_token_state */
43 #include "builtins/common.h"
44 #include "builtins/builtext.h"
50 /* Flags which describe the current handling state of a signal. */
51 #define SIG_INHERITED 0x0 /* Value inherited from parent. */
52 #define SIG_TRAPPED 0x1 /* Currently trapped. */
53 #define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
54 #define SIG_SPECIAL 0x4 /* Treat this signal specially. */
55 #define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
56 #define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
57 #define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
58 #define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
60 #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
62 /* An array of such flags, one for each signal, describing what the
63 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
65 static int sigmodes[BASH_NSIG];
67 static void free_trap_command __P((int));
68 static void change_signal __P((int, char *));
70 static void get_original_signal __P((int));
72 static int _run_trap_internal __P((int, char *));
74 static void reset_signal __P((int));
75 static void restore_signal __P((int));
76 static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
78 /* Variables used here but defined in other files. */
79 extern int interrupt_immediately;
80 extern int last_command_exit_value;
81 extern int line_number;
83 extern char *this_command_name;
84 extern sh_builtin_func_t *this_shell_builtin;
85 extern procenv_t wait_intr_buf;
86 extern int return_catch_flag, return_catch_value;
87 extern int subshell_level;
89 /* The list of things to do originally, before we started trapping. */
90 SigHandler *original_signals[NSIG];
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
97 char *trap_list[BASH_NSIG];
99 /* A bitmap of signals received for which we have trap handlers. */
100 int pending_traps[NSIG];
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). */
108 /* Set to last_command_exit_value before running a trap. */
109 int trap_saved_exit_value;
111 /* The (trapped) signal received while executing in the `wait' builtin */
112 int wait_signal_received;
114 /* A value which can never be the target of a trap handler. */
115 #define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
122 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
123 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
124 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
126 for (i = 1; i < NSIG; i++)
128 pending_traps[i] = 0;
129 trap_list[i] = (char *)DEFAULT_SIG;
130 sigmodes[i] = SIG_INHERITED;
131 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
134 /* Show which signals are treated specially by the shell. */
135 #if defined (SIGCHLD)
136 original_signals[SIGCHLD] =
137 (SigHandler *) set_signal_handler (SIGCHLD, SIG_DFL);
138 set_signal_handler (SIGCHLD, original_signals[SIGCHLD]);
139 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
142 original_signals[SIGINT] =
143 (SigHandler *) set_signal_handler (SIGINT, SIG_DFL);
144 set_signal_handler (SIGINT, original_signals[SIGINT]);
145 sigmodes[SIGINT] |= SIG_SPECIAL;
147 #if defined (__BEOS__)
148 /* BeOS sets SIGINT to SIG_IGN! */
149 original_signals[SIGINT] = SIG_DFL;
152 original_signals[SIGQUIT] =
153 (SigHandler *) set_signal_handler (SIGQUIT, SIG_DFL);
154 set_signal_handler (SIGQUIT, original_signals[SIGQUIT]);
155 sigmodes[SIGQUIT] |= SIG_SPECIAL;
159 original_signals[SIGTERM] =
160 (SigHandler *)set_signal_handler (SIGTERM, SIG_DFL);
161 set_signal_handler (SIGTERM, original_signals[SIGTERM]);
162 sigmodes[SIGTERM] |= SIG_SPECIAL;
166 #ifdef INCLUDE_UNUSED
167 /* Return a printable representation of the trap handler for SIG. */
169 trap_handler_string (sig)
172 if (trap_list[sig] == (char *)DEFAULT_SIG)
173 return "DEFAULT_SIG";
174 else if (trap_list[sig] == (char *)IGNORE_SIG)
176 else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
177 return "IMPOSSIBLE_TRAP_HANDLER";
178 else if (trap_list[sig])
179 return trap_list[sig];
185 /* Return the print name of this signal. */
192 /* on cygwin32, signal_names[sig] could be null */
193 ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
194 ? _("invalid signal number")
200 /* Turn a string into a signal number, or a number into
201 a signal number. If STRING is "2", "SIGINT", or "INT",
202 then (int)2 is returned. Return NO_SIG if STRING doesn't
203 contain a valid signal descriptor. */
205 decode_signal (string, flags)
212 if (legal_number (string, &sig))
213 return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
215 /* A leading `SIG' may be omitted. */
216 for (sig = 0; sig < BASH_NSIG; sig++)
218 name = signal_names[sig];
219 if (name == 0 || name[0] == '\0')
222 /* Check name without the SIG prefix first case sensitivly or
223 insensitively depending on whether flags includes DSIG_NOCASE */
224 if (STREQN (name, "SIG", 3))
228 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
230 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
232 /* If we can't use the `SIG' prefix to match, punt on this
234 else if ((flags & DSIG_SIGPREFIX) == 0)
238 /* Check name with SIG prefix case sensitively or insensitively
239 depending on whether flags includes DSIG_NOCASE */
240 name = signal_names[sig];
241 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
243 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
250 /* Non-zero when we catch a trapped signal. */
251 static int catch_flag;
257 int old_exit_value, *token_state;
259 if (catch_flag == 0) /* simple optimization */
264 /* Preserve $? when running trap. */
265 old_exit_value = last_command_exit_value;
267 for (sig = 1; sig < NSIG; sig++)
269 /* XXX this could be made into a counter by using
270 while (pending_traps[sig]--) instead of the if statement. */
271 if (pending_traps[sig])
273 #if defined (HAVE_POSIX_SIGNALS)
279 sigaddset (&set, sig);
280 sigprocmask (SIG_BLOCK, &set, &oset);
282 # if defined (HAVE_BSD_SIGNALS)
283 int oldmask = sigblock (sigmask (sig));
285 #endif /* HAVE_POSIX_SIGNALS */
289 run_interrupt_trap ();
292 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
293 trap_list[sig] == (char *)IGNORE_SIG ||
294 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
296 /* This is possible due to a race condition. Say a bash
297 process has SIGTERM trapped. A subshell is spawned
298 using { list; } & and the parent does something and kills
299 the subshell with SIGTERM. It's possible for the subshell
300 to set pending_traps[SIGTERM] to 1 before the code in
301 execute_cmd.c eventually calls restore_original_signals
302 to reset the SIGTERM signal handler in the subshell. The
303 next time run_pending_traps is called, pending_traps[SIGTERM]
304 will be 1, but the trap handler in trap_list[SIGTERM] will
305 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
306 Unless we catch this, the subshell will dump core when
307 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
309 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
310 sig, trap_list[sig]);
311 if (trap_list[sig] == (char *)DEFAULT_SIG)
313 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
314 kill (getpid (), sig);
319 token_state = save_token_state ();
320 parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST);
321 restore_token_state (token_state);
325 pending_traps[sig] = 0;
327 #if defined (HAVE_POSIX_SIGNALS)
328 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
330 # if defined (HAVE_BSD_SIGNALS)
331 sigsetmask (oldmask);
333 #endif /* POSIX_VERSION */
337 last_command_exit_value = old_exit_value;
347 (trap_list[sig] == (char *)DEFAULT_SIG) ||
348 (trap_list[sig] == (char *)IGNORE_SIG))
349 programming_error (_("trap_handler: bad signal %d"), sig);
353 #if defined (MUST_REINSTALL_SIGHANDLERS)
354 set_signal_handler (sig, trap_handler);
355 #endif /* MUST_REINSTALL_SIGHANDLERS */
358 pending_traps[sig]++;
360 if (interrupt_immediately && this_shell_builtin && (this_shell_builtin == wait_builtin))
362 wait_signal_received = sig;
363 longjmp (wait_intr_buf, 1);
366 if (interrupt_immediately)
367 run_pending_traps ();
375 #if defined (JOB_CONTROL) && defined (SIGCHLD)
377 #ifdef INCLUDE_UNUSED
378 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
380 set_sigchld_trap (command_string)
381 char *command_string;
383 set_signal (SIGCHLD, command_string);
387 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff the current
388 SIGCHLD trap handler is DEFAULT_SIG. */
390 maybe_set_sigchld_trap (command_string)
391 char *command_string;
393 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
394 set_signal (SIGCHLD, command_string);
396 #endif /* JOB_CONTROL && SIGCHLD */
399 set_debug_trap (command)
402 set_signal (DEBUG_TRAP, command);
406 set_error_trap (command)
409 set_signal (ERROR_TRAP, command);
413 set_return_trap (command)
416 set_signal (RETURN_TRAP, command);
419 #ifdef INCLUDE_UNUSED
421 set_sigint_trap (command)
424 set_signal (SIGINT, command);
428 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
429 things, like waiting for command substitution or executing commands
430 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
432 set_sigint_handler ()
434 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
435 return ((SigHandler *)SIG_IGN);
437 else if (sigmodes[SIGINT] & SIG_IGNORED)
438 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
440 else if (sigmodes[SIGINT] & SIG_TRAPPED)
441 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
443 /* The signal is not trapped, so set the handler to the shell's special
444 interrupt handler. */
445 else if (interactive) /* XXX - was interactive_shell */
446 return (set_signal_handler (SIGINT, sigint_sighandler));
448 return (set_signal_handler (SIGINT, termination_unwind_protect));
451 /* Return the correct handler for signal SIG according to the values in
454 trap_to_sighandler (sig)
457 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
459 else if (sigmodes[sig] & SIG_TRAPPED)
460 return (trap_handler);
465 /* Set SIG to call STRING as a command. */
467 set_signal (sig, string)
471 if (SPECIAL_TRAP (sig))
473 change_signal (sig, savestring (string));
474 if (sig == EXIT_TRAP && interactive == 0)
475 initialize_terminating_signals ();
479 /* A signal ignored on entry to the shell cannot be trapped or reset, but
480 no error is reported when attempting to do so. -- Posix.2 */
481 if (sigmodes[sig] & SIG_HARD_IGNORE)
484 /* Make sure we have original_signals[sig] if the signal has not yet
486 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
488 /* If we aren't sure of the original value, check it. */
489 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
491 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
492 set_signal_handler (sig, original_signals[sig]);
495 /* Signals ignored on entry to the shell cannot be trapped or reset. */
496 if (original_signals[sig] == SIG_IGN)
498 sigmodes[sig] |= SIG_HARD_IGNORE;
503 /* Only change the system signal handler if SIG_NO_TRAP is not set.
504 The trap command string is changed in either case. The shell signal
505 handlers for SIGINT and SIGCHLD run the user specified traps in an
506 environment in which it is safe to do so. */
507 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
509 set_signal_handler (sig, SIG_IGN);
510 change_signal (sig, savestring (string));
511 set_signal_handler (sig, trap_handler);
514 change_signal (sig, savestring (string));
518 free_trap_command (sig)
521 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
522 (trap_list[sig] != (char *)IGNORE_SIG) &&
523 (trap_list[sig] != (char *)DEFAULT_SIG) &&
524 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
525 free (trap_list[sig]);
528 /* If SIG has a string assigned to it, get rid of it. Then give it
531 change_signal (sig, value)
535 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
536 free_trap_command (sig);
537 trap_list[sig] = value;
539 sigmodes[sig] |= SIG_TRAPPED;
540 if (value == (char *)IGNORE_SIG)
541 sigmodes[sig] |= SIG_IGNORED;
543 sigmodes[sig] &= ~SIG_IGNORED;
544 if (sigmodes[sig] & SIG_INPROGRESS)
545 sigmodes[sig] |= SIG_CHANGED;
548 #define GET_ORIGINAL_SIGNAL(sig) \
549 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
550 get_original_signal (sig)
553 get_original_signal (sig)
556 /* If we aren't sure the of the original value, then get it. */
557 if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
559 original_signals[sig] =
560 (SigHandler *) set_signal_handler (sig, SIG_DFL);
561 set_signal_handler (sig, original_signals[sig]);
563 /* Signals ignored on entry to the shell cannot be trapped. */
564 if (original_signals[sig] == SIG_IGN)
565 sigmodes[sig] |= SIG_HARD_IGNORE;
569 /* Restore the default action for SIG; i.e., the action the shell
570 would have taken before you used the trap command. This is called
571 from trap_builtin (), which takes care to restore the handlers for
572 the signals the shell treats specially. */
574 restore_default_signal (sig)
577 if (SPECIAL_TRAP (sig))
579 if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
580 (sigmodes[sig] & SIG_INPROGRESS) == 0)
581 free_trap_command (sig);
582 trap_list[sig] = (char *)NULL;
583 sigmodes[sig] &= ~SIG_TRAPPED;
584 if (sigmodes[sig] & SIG_INPROGRESS)
585 sigmodes[sig] |= SIG_CHANGED;
589 GET_ORIGINAL_SIGNAL (sig);
591 /* A signal ignored on entry to the shell cannot be trapped or reset, but
592 no error is reported when attempting to do so. Thanks Posix.2. */
593 if (sigmodes[sig] & SIG_HARD_IGNORE)
596 /* If we aren't trapping this signal, don't bother doing anything else. */
597 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
600 /* Only change the signal handler for SIG if it allows it. */
601 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
602 set_signal_handler (sig, original_signals[sig]);
604 /* Change the trap command in either case. */
605 change_signal (sig, (char *)DEFAULT_SIG);
607 /* Mark the signal as no longer trapped. */
608 sigmodes[sig] &= ~SIG_TRAPPED;
611 /* Make this signal be ignored. */
616 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
618 change_signal (sig, (char *)IGNORE_SIG);
622 GET_ORIGINAL_SIGNAL (sig);
624 /* A signal ignored on entry to the shell cannot be trapped or reset.
625 No error is reported when the user attempts to do so. */
626 if (sigmodes[sig] & SIG_HARD_IGNORE)
629 /* If already trapped and ignored, no change necessary. */
630 if (sigmodes[sig] & SIG_IGNORED)
633 /* Only change the signal handler for SIG if it allows it. */
634 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
635 set_signal_handler (sig, SIG_IGN);
637 /* Change the trap command in either case. */
638 change_signal (sig, (char *)IGNORE_SIG);
641 /* Handle the calling of "trap 0". The only sticky situation is when
642 the command to be executed includes an "exit". This is why we have
643 to provide our own place for top_level to jump to. */
648 int code, function_code, retval;
650 trap_saved_exit_value = last_command_exit_value;
653 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
654 currently running in the trap handler (call to exit in the list of
655 commands given to trap 0). */
656 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
657 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
659 trap_command = savestring (trap_list[EXIT_TRAP]);
660 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
661 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
663 retval = trap_saved_exit_value;
666 code = setjmp (top_level);
668 /* If we're in a function, make sure return longjmps come here, too. */
669 if (return_catch_flag)
670 function_code = setjmp (return_catch);
672 if (code == 0 && function_code == 0)
675 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST);
677 else if (code == ERREXIT)
678 retval = last_command_exit_value;
679 else if (code == EXITPROG)
680 retval = last_command_exit_value;
681 else if (function_code != 0)
682 retval = return_catch_value;
684 retval = trap_saved_exit_value;
690 return (trap_saved_exit_value);
694 run_trap_cleanup (sig)
697 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
700 /* Run a trap command for SIG. SIG is one of the signals the shell treats
701 specially. Returns the exit status of the executed trap command list. */
703 _run_trap_internal (sig, tag)
707 char *trap_command, *old_trap;
708 int trap_exit_value, *token_state;
709 int save_return_catch_flag, function_code;
710 procenv_t save_return_catch;
712 trap_exit_value = function_code = 0;
713 /* Run the trap only if SIG is trapped and not ignored, and we are not
714 currently executing in the trap handler. */
715 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
716 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
717 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
719 old_trap = trap_list[sig];
720 sigmodes[sig] |= SIG_INPROGRESS;
721 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
722 trap_command = savestring (old_trap);
724 running_trap = sig + 1;
725 trap_saved_exit_value = last_command_exit_value;
727 token_state = save_token_state ();
729 /* If we're in a function, make sure return longjmps come here, too. */
730 save_return_catch_flag = return_catch_flag;
731 if (return_catch_flag)
733 COPY_PROCENV (return_catch, save_return_catch);
734 function_code = setjmp (return_catch);
737 if (function_code == 0)
738 parse_and_execute (trap_command, tag, SEVAL_NONINT|SEVAL_NOHIST);
740 restore_token_state (token_state);
743 trap_exit_value = last_command_exit_value;
744 last_command_exit_value = trap_saved_exit_value;
747 sigmodes[sig] &= ~SIG_INPROGRESS;
749 if (sigmodes[sig] & SIG_CHANGED)
752 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
753 the places where they can be changed using unwind-protects. For
754 example, look at execute_cmd.c:execute_function(). */
755 if (SPECIAL_TRAP (sig) == 0)
758 sigmodes[sig] &= ~SIG_CHANGED;
761 if (save_return_catch_flag)
763 return_catch_flag = save_return_catch_flag;
764 return_catch_value = trap_exit_value;
765 COPY_PROCENV (save_return_catch, return_catch);
767 longjmp (return_catch, 1);
771 return trap_exit_value;
779 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
781 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
783 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
785 #if defined (DEBUGGER)
786 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
787 a function or sourced script, we force a `return'. */
788 if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
790 return_catch_value = trap_exit_value;
791 longjmp (return_catch, 1);
795 return trap_exit_value;
801 if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
802 _run_trap_internal (ERROR_TRAP, "error trap");
810 if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
812 old_exit_value = last_command_exit_value;
813 _run_trap_internal (RETURN_TRAP, "return trap");
814 last_command_exit_value = old_exit_value;
818 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
819 declared here to localize the trap functions. */
821 run_interrupt_trap ()
823 _run_trap_internal (SIGINT, "interrupt trap");
826 #ifdef INCLUDE_UNUSED
827 /* Free all the allocated strings in the list of traps and reset the trap
828 values to the default. */
834 for (i = 0; i < BASH_NSIG; i++)
836 free_trap_command (i);
837 trap_list[i] = (char *)DEFAULT_SIG;
838 sigmodes[i] &= ~SIG_TRAPPED;
840 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
844 /* Reset the handler for SIG to the original value. */
849 set_signal_handler (sig, original_signals[sig]);
850 sigmodes[sig] &= ~SIG_TRAPPED;
853 /* Set the handler signal SIG to the original and free any trap
854 command associated with it. */
859 set_signal_handler (sig, original_signals[sig]);
860 change_signal (sig, (char *)DEFAULT_SIG);
861 sigmodes[sig] &= ~SIG_TRAPPED;
865 reset_or_restore_signal_handlers (reset)
866 sh_resetsig_func_t *reset;
870 /* Take care of the exit trap first */
871 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
873 free_trap_command (EXIT_TRAP);
874 trap_list[EXIT_TRAP] = (char *)NULL;
875 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
878 for (i = 1; i < NSIG; i++)
880 if (sigmodes[i] & SIG_TRAPPED)
882 if (trap_list[i] == (char *)IGNORE_SIG)
883 set_signal_handler (i, SIG_IGN);
887 else if (sigmodes[i] & SIG_SPECIAL)
891 /* Command substitution and other child processes don't inherit the
892 debug, error, or return traps. If we're in the debugger, and the
893 `functrace' or `errtrace' options have been set, then let command
894 substitutions inherit them. Let command substitution inherit the
895 RETURN trap if we're in the debugger and tracing functions. */
896 #if defined (DEBUGGER)
897 if (debugging_mode == 0 || function_trace_mode == 0)
899 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
900 #if defined (DEBUGGER)
901 if (debugging_mode == 0 || error_trace_mode == 0)
903 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
904 #if defined (DEBUGGER)
905 if (debugging_mode == 0 || function_trace_mode == 0)
906 sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
910 /* Reset trapped signals to their original values, but don't free the
911 trap strings. Called by the command substitution code. */
913 reset_signal_handlers ()
915 reset_or_restore_signal_handlers (reset_signal);
918 /* Reset all trapped signals to their original values. Signals set to be
919 ignored with trap '' SIGNAL should be ignored, so we make sure that they
920 are. Called by child processes after they are forked. */
922 restore_original_signals ()
924 reset_or_restore_signal_handlers (restore_signal);
927 /* If a trap handler exists for signal SIG, then call it; otherwise just
930 maybe_call_trap_handler (sig)
933 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
934 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
939 run_interrupt_trap ();
961 signal_is_trapped (sig)
964 return (sigmodes[sig] & SIG_TRAPPED);
968 signal_is_special (sig)
971 return (sigmodes[sig] & SIG_SPECIAL);
975 signal_is_ignored (sig)
978 return (sigmodes[sig] & SIG_IGNORED);
982 set_signal_ignored (sig)
985 sigmodes[sig] |= SIG_HARD_IGNORE;
986 original_signals[sig] = SIG_IGN;