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-2013 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
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.
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.
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/>.
24 #if defined (HAVE_UNISTD_H)
28 #include "bashtypes.h"
42 #include "input.h" /* for save_token_state, restore_token_state */
46 #include "builtins/common.h"
47 #include "builtins/builtext.h"
49 #if defined (READLINE)
50 # include <readline/readline.h>
51 # include "bashline.h"
58 /* Flags which describe the current handling state of a signal. */
59 #define SIG_INHERITED 0x0 /* Value inherited from parent. */
60 #define SIG_TRAPPED 0x1 /* Currently trapped. */
61 #define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
62 #define SIG_SPECIAL 0x4 /* Treat this signal specially. */
63 #define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
64 #define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
65 #define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
66 #define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
68 #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
70 /* An array of such flags, one for each signal, describing what the
71 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
73 static int sigmodes[BASH_NSIG];
75 static void free_trap_command __P((int));
76 static void change_signal __P((int, char *));
78 static int _run_trap_internal __P((int, char *));
80 static void free_trap_string __P((int));
81 static void reset_signal __P((int));
82 static void restore_signal __P((int));
83 static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
85 /* Variables used here but defined in other files. */
86 extern int last_command_exit_value;
87 extern int line_number;
89 extern int sigalrm_seen;
90 extern procenv_t alrmbuf;
92 extern char *this_command_name;
93 extern sh_builtin_func_t *this_shell_builtin;
94 extern procenv_t wait_intr_buf;
95 extern int return_catch_flag, return_catch_value;
96 extern int subshell_level;
97 extern WORD_LIST *subst_assign_varlist;
99 /* The list of things to do originally, before we started trapping. */
100 SigHandler *original_signals[NSIG];
102 /* For each signal, a slot for a string, which is a command to be
103 executed when that signal is received. The slot can also contain
104 DEFAULT_SIG, which means do whatever you were going to do before
105 you were so rudely interrupted, or IGNORE_SIG, which says ignore
107 char *trap_list[BASH_NSIG];
109 /* A bitmap of signals received for which we have trap handlers. */
110 int pending_traps[NSIG];
112 /* Set to the number of the signal we're running the trap for + 1.
113 Used in execute_cmd.c and builtins/common.c to clean up when
114 parse_and_execute does not return normally after executing the
115 trap command (e.g., when `return' is executed in the trap command). */
118 /* Set to last_command_exit_value before running a trap. */
119 int trap_saved_exit_value;
121 /* The (trapped) signal received while executing in the `wait' builtin */
122 int wait_signal_received;
124 int trapped_signal_received;
126 #define GETORIGSIG(sig) \
128 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
129 set_signal_handler (sig, original_signals[sig]); \
130 if (original_signals[sig] == SIG_IGN) \
131 sigmodes[sig] |= SIG_HARD_IGNORE; \
134 #define SETORIGSIG(sig,handler) \
136 original_signals[sig] = handler; \
137 if (original_signals[sig] == SIG_IGN) \
138 sigmodes[sig] |= SIG_HARD_IGNORE; \
141 #define GET_ORIGINAL_SIGNAL(sig) \
142 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
150 initialize_signames();
152 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
153 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
154 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
156 for (i = 1; i < NSIG; i++)
158 pending_traps[i] = 0;
159 trap_list[i] = (char *)DEFAULT_SIG;
160 sigmodes[i] = SIG_INHERITED; /* XXX - only set, not used */
161 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
164 /* Show which signals are treated specially by the shell. */
165 #if defined (SIGCHLD)
166 GETORIGSIG (SIGCHLD);
167 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
171 sigmodes[SIGINT] |= SIG_SPECIAL;
173 #if defined (__BEOS__)
174 /* BeOS sets SIGINT to SIG_IGN! */
175 original_signals[SIGINT] = SIG_DFL;
176 sigmodes[SIGINT] &= ~SIG_HARD_IGNORE;
179 GETORIGSIG (SIGQUIT);
180 sigmodes[SIGQUIT] |= SIG_SPECIAL;
184 GETORIGSIG (SIGTERM);
185 sigmodes[SIGTERM] |= SIG_SPECIAL;
190 /* Return a printable representation of the trap handler for SIG. */
192 trap_handler_string (sig)
195 if (trap_list[sig] == (char *)DEFAULT_SIG)
196 return "DEFAULT_SIG";
197 else if (trap_list[sig] == (char *)IGNORE_SIG)
199 else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
200 return "IMPOSSIBLE_TRAP_HANDLER";
201 else if (trap_list[sig])
202 return trap_list[sig];
208 /* Return the print name of this signal. */
215 /* on cygwin32, signal_names[sig] could be null */
216 ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
217 ? _("invalid signal number")
223 /* Turn a string into a signal number, or a number into
224 a signal number. If STRING is "2", "SIGINT", or "INT",
225 then (int)2 is returned. Return NO_SIG if STRING doesn't
226 contain a valid signal descriptor. */
228 decode_signal (string, flags)
235 if (legal_number (string, &sig))
236 return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
238 /* A leading `SIG' may be omitted. */
239 for (sig = 0; sig < BASH_NSIG; sig++)
241 name = signal_names[sig];
242 if (name == 0 || name[0] == '\0')
245 /* Check name without the SIG prefix first case sensitively or
246 insensitively depending on whether flags includes DSIG_NOCASE */
247 if (STREQN (name, "SIG", 3))
251 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
253 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
255 /* If we can't use the `SIG' prefix to match, punt on this
257 else if ((flags & DSIG_SIGPREFIX) == 0)
261 /* Check name with SIG prefix case sensitively or insensitively
262 depending on whether flags includes DSIG_NOCASE */
263 name = signal_names[sig];
264 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
266 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
273 /* Non-zero when we catch a trapped signal. */
274 static int catch_flag;
281 WORD_LIST *save_subst_varlist;
282 sh_parser_state_t pstate;
283 #if defined (ARRAY_VARS)
287 if (catch_flag == 0) /* simple optimization */
290 if (running_trap > 0)
293 internal_warning ("run_pending_traps: recursive invocation while running trap for signal %d", running_trap-1);
296 return; /* no recursive trap invocations */
302 catch_flag = trapped_signal_received = 0;
304 /* Preserve $? when running trap. */
305 old_exit_value = last_command_exit_value;
306 #if defined (ARRAY_VARS)
307 ps = save_pipestatus_array ();
310 for (sig = 1; sig < NSIG; sig++)
312 /* XXX this could be made into a counter by using
313 while (pending_traps[sig]--) instead of the if statement. */
314 if (pending_traps[sig])
316 if (running_trap == sig+1)
319 running_trap = sig + 1;
323 pending_traps[sig] = 0; /* XXX */
324 run_interrupt_trap ();
327 #if defined (JOB_CONTROL) && defined (SIGCHLD)
328 else if (sig == SIGCHLD &&
329 trap_list[SIGCHLD] != (char *)IMPOSSIBLE_TRAP_HANDLER &&
330 (sigmodes[SIGCHLD] & SIG_INPROGRESS) == 0)
332 sigmodes[SIGCHLD] |= SIG_INPROGRESS;
333 run_sigchld_trap (pending_traps[sig]); /* use as counter */
334 sigmodes[SIGCHLD] &= ~SIG_INPROGRESS;
336 else if (sig == SIGCHLD &&
337 trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER &&
338 (sigmodes[SIGCHLD] & SIG_INPROGRESS) != 0)
340 /* This can happen when run_pending_traps is called while
341 running a SIGCHLD trap handler. */
343 /* want to leave pending_traps[SIGCHLD] alone here */
346 else if (sig == SIGCHLD && (sigmodes[SIGCHLD] & SIG_INPROGRESS))
348 /* whoops -- print warning? */
349 running_trap = 0; /* XXX */
350 /* want to leave pending_traps[SIGCHLD] alone here */
354 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
355 trap_list[sig] == (char *)IGNORE_SIG ||
356 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
358 /* This is possible due to a race condition. Say a bash
359 process has SIGTERM trapped. A subshell is spawned
360 using { list; } & and the parent does something and kills
361 the subshell with SIGTERM. It's possible for the subshell
362 to set pending_traps[SIGTERM] to 1 before the code in
363 execute_cmd.c eventually calls restore_original_signals
364 to reset the SIGTERM signal handler in the subshell. The
365 next time run_pending_traps is called, pending_traps[SIGTERM]
366 will be 1, but the trap handler in trap_list[SIGTERM] will
367 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
368 Unless we catch this, the subshell will dump core when
369 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
371 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
372 sig, trap_list[sig]);
373 if (trap_list[sig] == (char *)DEFAULT_SIG)
375 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
376 kill (getpid (), sig);
381 /* XXX - should we use save_parser_state/restore_parser_state? */
382 save_parser_state (&pstate);
383 save_subst_varlist = subst_assign_varlist;
384 subst_assign_varlist = 0;
386 #if defined (JOB_CONTROL)
387 save_pipeline (1); /* XXX only provides one save level */
389 /* XXX - set pending_traps[sig] = 0 here? */
390 pending_traps[sig] = 0;
391 evalstring (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
392 #if defined (JOB_CONTROL)
393 restore_pipeline (1);
396 subst_assign_varlist = save_subst_varlist;
397 restore_parser_state (&pstate);
400 pending_traps[sig] = 0; /* XXX - move before evalstring? */
405 #if defined (ARRAY_VARS)
406 restore_pipestatus_array (ps);
408 last_command_exit_value = old_exit_value;
417 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
420 internal_warning ("trap_handler: signal %d: signal not trapped", sig);
426 (trap_list[sig] == (char *)DEFAULT_SIG) ||
427 (trap_list[sig] == (char *)IGNORE_SIG))
428 programming_error (_("trap_handler: bad signal %d"), sig);
432 #if defined (MUST_REINSTALL_SIGHANDLERS)
433 # if defined (JOB_CONTROL) && defined (SIGCHLD)
435 # endif /* JOB_CONTROL && SIGCHLD */
436 set_signal_handler (sig, trap_handler);
437 #endif /* MUST_REINSTALL_SIGHANDLERS */
440 pending_traps[sig]++;
442 trapped_signal_received = sig;
444 if (this_shell_builtin && (this_shell_builtin == wait_builtin))
446 wait_signal_received = sig;
447 if (interrupt_immediately)
448 longjmp (wait_intr_buf, 1);
451 #if defined (READLINE)
452 /* Set the event hook so readline will call it after the signal handlers
453 finish executing, so if this interrupted character input we can get
455 if (RL_ISSTATE (RL_STATE_SIGHANDLER) && interrupt_immediately == 0)
456 bashline_set_event_hook ();
459 if (interrupt_immediately)
460 run_pending_traps ();
469 first_pending_trap ()
473 for (i = 1; i < NSIG; i++)
474 if (pending_traps[i])
480 any_signals_trapped ()
484 for (i = 1; i < NSIG; i++)
485 if (sigmodes[i] & SIG_TRAPPED)
493 CHECK_ALRM; /* set by the read builtin */
497 /* Convenience functions the rest of the shell can use */
499 check_signals_and_traps ()
503 run_pending_traps ();
506 #if defined (JOB_CONTROL) && defined (SIGCHLD)
508 #ifdef INCLUDE_UNUSED
509 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
511 set_sigchld_trap (command_string)
512 char *command_string;
514 set_signal (SIGCHLD, command_string);
518 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
519 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
520 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
521 reset the disposition to the default and not have the original signal
522 accidentally restored, undoing the user's command. */
524 maybe_set_sigchld_trap (command_string)
525 char *command_string;
527 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER)
528 set_signal (SIGCHLD, command_string);
531 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
532 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
533 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
535 set_impossible_sigchld_trap ()
537 restore_default_signal (SIGCHLD);
538 change_signal (SIGCHLD, (char *)IMPOSSIBLE_TRAP_HANDLER);
539 sigmodes[SIGCHLD] &= ~SIG_TRAPPED; /* maybe_set_sigchld_trap checks this */
542 /* Act as if we received SIGCHLD NCHILD times and increment
543 pending_traps[SIGCHLD] by that amount. This allows us to still run the
544 SIGCHLD trap once for each exited child. */
546 queue_sigchld_trap (nchild)
552 pending_traps[SIGCHLD] += nchild;
553 trapped_signal_received = SIGCHLD;
556 #endif /* JOB_CONTROL && SIGCHLD */
559 set_debug_trap (command)
562 set_signal (DEBUG_TRAP, command);
566 set_error_trap (command)
569 set_signal (ERROR_TRAP, command);
573 set_return_trap (command)
576 set_signal (RETURN_TRAP, command);
579 #ifdef INCLUDE_UNUSED
581 set_sigint_trap (command)
584 set_signal (SIGINT, command);
588 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
589 things, like waiting for command substitution or executing commands
590 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
592 set_sigint_handler ()
594 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
595 return ((SigHandler *)SIG_IGN);
597 else if (sigmodes[SIGINT] & SIG_IGNORED)
598 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
600 else if (sigmodes[SIGINT] & SIG_TRAPPED)
601 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
603 /* The signal is not trapped, so set the handler to the shell's special
604 interrupt handler. */
605 else if (interactive) /* XXX - was interactive_shell */
606 return (set_signal_handler (SIGINT, sigint_sighandler));
608 return (set_signal_handler (SIGINT, termsig_sighandler));
611 /* Return the correct handler for signal SIG according to the values in
614 trap_to_sighandler (sig)
617 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
619 else if (sigmodes[sig] & SIG_TRAPPED)
620 return (trap_handler);
625 /* Set SIG to call STRING as a command. */
627 set_signal (sig, string)
633 if (SPECIAL_TRAP (sig))
635 change_signal (sig, savestring (string));
636 if (sig == EXIT_TRAP && interactive == 0)
637 initialize_terminating_signals ();
641 /* A signal ignored on entry to the shell cannot be trapped or reset, but
642 no error is reported when attempting to do so. -- Posix.2 */
643 if (sigmodes[sig] & SIG_HARD_IGNORE)
646 /* Make sure we have original_signals[sig] if the signal has not yet
648 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
650 /* If we aren't sure of the original value, check it. */
651 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
653 if (original_signals[sig] == SIG_IGN)
657 /* Only change the system signal handler if SIG_NO_TRAP is not set.
658 The trap command string is changed in either case. The shell signal
659 handlers for SIGINT and SIGCHLD run the user specified traps in an
660 environment in which it is safe to do so. */
661 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
663 BLOCK_SIGNAL (sig, set, oset);
664 change_signal (sig, savestring (string));
665 set_signal_handler (sig, trap_handler);
666 UNBLOCK_SIGNAL (oset);
669 change_signal (sig, savestring (string));
673 free_trap_command (sig)
676 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
677 (trap_list[sig] != (char *)IGNORE_SIG) &&
678 (trap_list[sig] != (char *)DEFAULT_SIG) &&
679 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
680 free (trap_list[sig]);
683 /* If SIG has a string assigned to it, get rid of it. Then give it
686 change_signal (sig, value)
690 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
691 free_trap_command (sig);
692 trap_list[sig] = value;
694 sigmodes[sig] |= SIG_TRAPPED;
695 if (value == (char *)IGNORE_SIG)
696 sigmodes[sig] |= SIG_IGNORED;
698 sigmodes[sig] &= ~SIG_IGNORED;
699 if (sigmodes[sig] & SIG_INPROGRESS)
700 sigmodes[sig] |= SIG_CHANGED;
704 get_original_signal (sig)
707 /* If we aren't sure the of the original value, then get it. */
708 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
713 get_all_original_signals ()
717 for (i = 1; i < NSIG; i++)
718 GET_ORIGINAL_SIGNAL (i);
722 set_original_signal (sig, handler)
726 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
727 SETORIGSIG (sig, handler);
730 /* Restore the default action for SIG; i.e., the action the shell
731 would have taken before you used the trap command. This is called
732 from trap_builtin (), which takes care to restore the handlers for
733 the signals the shell treats specially. */
735 restore_default_signal (sig)
738 if (SPECIAL_TRAP (sig))
740 if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
741 (sigmodes[sig] & SIG_INPROGRESS) == 0)
742 free_trap_command (sig);
743 trap_list[sig] = (char *)NULL;
744 sigmodes[sig] &= ~SIG_TRAPPED;
745 if (sigmodes[sig] & SIG_INPROGRESS)
746 sigmodes[sig] |= SIG_CHANGED;
750 GET_ORIGINAL_SIGNAL (sig);
752 /* A signal ignored on entry to the shell cannot be trapped or reset, but
753 no error is reported when attempting to do so. Thanks Posix.2. */
754 if (sigmodes[sig] & SIG_HARD_IGNORE)
757 /* If we aren't trapping this signal, don't bother doing anything else. */
758 /* We special-case SIGCHLD and IMPOSSIBLE_TRAP_HANDLER (see above) as a
759 sentinel to determine whether or not disposition is reset to the default
760 while the trap handler is executing. */
761 if (((sigmodes[sig] & SIG_TRAPPED) == 0) &&
762 (sig != SIGCHLD || (sigmodes[sig] & SIG_INPROGRESS) == 0 || trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
765 /* Only change the signal handler for SIG if it allows it. */
766 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
767 set_signal_handler (sig, original_signals[sig]);
769 /* Change the trap command in either case. */
770 change_signal (sig, (char *)DEFAULT_SIG);
772 /* Mark the signal as no longer trapped. */
773 sigmodes[sig] &= ~SIG_TRAPPED;
776 /* Make this signal be ignored. */
781 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
783 change_signal (sig, (char *)IGNORE_SIG);
787 GET_ORIGINAL_SIGNAL (sig);
789 /* A signal ignored on entry to the shell cannot be trapped or reset.
790 No error is reported when the user attempts to do so. */
791 if (sigmodes[sig] & SIG_HARD_IGNORE)
794 /* If already trapped and ignored, no change necessary. */
795 if (sigmodes[sig] & SIG_IGNORED)
798 /* Only change the signal handler for SIG if it allows it. */
799 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
800 set_signal_handler (sig, SIG_IGN);
802 /* Change the trap command in either case. */
803 change_signal (sig, (char *)IGNORE_SIG);
806 /* Handle the calling of "trap 0". The only sticky situation is when
807 the command to be executed includes an "exit". This is why we have
808 to provide our own place for top_level to jump to. */
813 int code, function_code, retval;
814 #if defined (ARRAY_VARS)
818 trap_saved_exit_value = last_command_exit_value;
819 #if defined (ARRAY_VARS)
820 ps = save_pipestatus_array ();
824 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
825 currently running in the trap handler (call to exit in the list of
826 commands given to trap 0). */
827 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
828 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
830 trap_command = savestring (trap_list[EXIT_TRAP]);
831 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
832 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
834 retval = trap_saved_exit_value;
837 code = setjmp_nosigs (top_level);
839 /* If we're in a function, make sure return longjmps come here, too. */
840 if (return_catch_flag)
841 function_code = setjmp_nosigs (return_catch);
843 if (code == 0 && function_code == 0)
846 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
848 else if (code == ERREXIT)
849 retval = last_command_exit_value;
850 else if (code == EXITPROG)
851 retval = last_command_exit_value;
852 else if (function_code != 0)
853 retval = return_catch_value;
855 retval = trap_saved_exit_value;
861 #if defined (ARRAY_VARS)
862 restore_pipestatus_array (ps);
864 return (trap_saved_exit_value);
868 run_trap_cleanup (sig)
871 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
874 #define RECURSIVE_SIG(s) (SPECIAL_TRAP(s) == 0)
876 /* Run a trap command for SIG. SIG is one of the signals the shell treats
877 specially. Returns the exit status of the executed trap command list. */
879 _run_trap_internal (sig, tag)
883 char *trap_command, *old_trap;
884 int trap_exit_value, *token_state;
885 volatile int save_return_catch_flag, function_code;
887 procenv_t save_return_catch;
888 WORD_LIST *save_subst_varlist;
889 sh_parser_state_t pstate;
890 #if defined (ARRAY_VARS)
894 trap_exit_value = function_code = 0;
895 /* Run the trap only if SIG is trapped and not ignored, and we are not
896 currently executing in the trap handler. */
897 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
898 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
900 /* Uncomment this to allow some special signals to recursively execute
902 (RECURSIVE_SIG (sig) || (sigmodes[sig] & SIG_INPROGRESS) == 0))
904 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
907 old_trap = trap_list[sig];
908 sigmodes[sig] |= SIG_INPROGRESS;
909 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
910 trap_command = savestring (old_trap);
912 running_trap = sig + 1;
914 #if defined (ARRAY_VARS)
915 ps = save_pipestatus_array ();
918 save_parser_state (&pstate);
919 save_subst_varlist = subst_assign_varlist;
920 subst_assign_varlist = 0;
922 #if defined (JOB_CONTROL)
923 if (sig != DEBUG_TRAP) /* run_debug_trap does this */
924 save_pipeline (1); /* XXX only provides one save level */
927 /* If we're in a function, make sure return longjmps come here, too. */
928 save_return_catch_flag = return_catch_flag;
929 if (return_catch_flag)
931 COPY_PROCENV (return_catch, save_return_catch);
932 function_code = setjmp_nosigs (return_catch);
935 flags = SEVAL_NONINT|SEVAL_NOHIST;
936 if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
937 flags |= SEVAL_RESETLINE;
938 if (function_code == 0)
939 parse_and_execute (trap_command, tag, flags);
941 trap_exit_value = last_command_exit_value;
943 #if defined (JOB_CONTROL)
944 if (sig != DEBUG_TRAP) /* run_debug_trap does this */
945 restore_pipeline (1);
948 subst_assign_varlist = save_subst_varlist;
949 restore_parser_state (&pstate);
951 #if defined (ARRAY_VARS)
952 restore_pipestatus_array (ps);
956 sigmodes[sig] &= ~SIG_INPROGRESS;
958 if (sigmodes[sig] & SIG_CHANGED)
961 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
962 the places where they can be changed using unwind-protects. For
963 example, look at execute_cmd.c:execute_function(). */
964 if (SPECIAL_TRAP (sig) == 0)
967 sigmodes[sig] &= ~SIG_CHANGED;
970 if (save_return_catch_flag)
972 return_catch_flag = save_return_catch_flag;
973 return_catch_value = trap_exit_value;
974 COPY_PROCENV (save_return_catch, return_catch);
976 longjmp (return_catch, 1);
980 return trap_exit_value;
990 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
992 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
994 #if defined (JOB_CONTROL)
995 save_pgrp = pipeline_pgrp;
998 # if defined (PGRP_PIPE)
999 save_pgrp_pipe (save_pipe, 1);
1001 stop_making_children ();
1004 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
1006 #if defined (JOB_CONTROL)
1007 pipeline_pgrp = save_pgrp;
1008 restore_pipeline (1);
1009 # if defined (PGRP_PIPE)
1011 restore_pgrp_pipe (save_pipe);
1013 if (pipeline_pgrp > 0)
1014 give_terminal_to (pipeline_pgrp, 1);
1015 notify_and_cleanup ();
1018 #if defined (DEBUGGER)
1019 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
1020 a function or sourced script, we force a `return'. */
1021 if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
1023 return_catch_value = trap_exit_value;
1024 longjmp (return_catch, 1);
1028 return trap_exit_value;
1034 if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
1035 _run_trap_internal (ERROR_TRAP, "error trap");
1044 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
1048 if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
1050 old_exit_value = last_command_exit_value;
1051 _run_trap_internal (RETURN_TRAP, "return trap");
1052 last_command_exit_value = old_exit_value;
1056 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1057 declared here to localize the trap functions. */
1059 run_interrupt_trap ()
1061 _run_trap_internal (SIGINT, "interrupt trap");
1064 /* Free all the allocated strings in the list of traps and reset the trap
1065 values to the default. Intended to be called from subshells that want
1066 to complete work done by reset_signal_handlers upon execution of a
1067 subsequent `trap' command that changes a signal's disposition. We need
1068 to make sure that we duplicate the behavior of
1069 reset_or_restore_signal_handlers and not change the disposition of signals
1070 that are set to be ignored. */
1072 free_trap_strings ()
1076 for (i = 0; i < BASH_NSIG; i++)
1078 if (trap_list[i] != (char *)IGNORE_SIG)
1079 free_trap_string (i);
1081 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
1084 /* Free a trap command string associated with SIG without changing signal
1085 disposition. Intended to be called from free_trap_strings() */
1087 free_trap_string (sig)
1090 change_signal (sig, (char *)DEFAULT_SIG);
1091 sigmodes[sig] &= ~SIG_TRAPPED;
1094 /* Reset the handler for SIG to the original value but leave the trap string
1100 set_signal_handler (sig, original_signals[sig]);
1101 sigmodes[sig] &= ~SIG_TRAPPED;
1104 /* Set the handler signal SIG to the original and free any trap
1105 command associated with it. */
1107 restore_signal (sig)
1110 set_signal_handler (sig, original_signals[sig]);
1111 change_signal (sig, (char *)DEFAULT_SIG);
1112 sigmodes[sig] &= ~SIG_TRAPPED;
1116 reset_or_restore_signal_handlers (reset)
1117 sh_resetsig_func_t *reset;
1121 /* Take care of the exit trap first */
1122 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
1124 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
1125 if (reset != reset_signal)
1127 free_trap_command (EXIT_TRAP);
1128 trap_list[EXIT_TRAP] = (char *)NULL;
1132 for (i = 1; i < NSIG; i++)
1134 if (sigmodes[i] & SIG_TRAPPED)
1136 if (trap_list[i] == (char *)IGNORE_SIG)
1137 set_signal_handler (i, SIG_IGN);
1141 else if (sigmodes[i] & SIG_SPECIAL)
1145 /* Command substitution and other child processes don't inherit the
1146 debug, error, or return traps. If we're in the debugger, and the
1147 `functrace' or `errtrace' options have been set, then let command
1148 substitutions inherit them. Let command substitution inherit the
1149 RETURN trap if we're in the debugger and tracing functions. */
1150 if (function_trace_mode == 0)
1152 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
1153 sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
1155 if (error_trace_mode == 0)
1156 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
1159 /* Reset trapped signals to their original values, but don't free the
1160 trap strings. Called by the command substitution code and other places
1161 that create a "subshell environment". */
1163 reset_signal_handlers ()
1165 reset_or_restore_signal_handlers (reset_signal);
1168 /* Reset all trapped signals to their original values. Signals set to be
1169 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1170 are. Called by child processes after they are forked. */
1172 restore_original_signals ()
1174 reset_or_restore_signal_handlers (restore_signal);
1177 /* If a trap handler exists for signal SIG, then call it; otherwise just
1178 return failure. Returns 1 if it called the trap handler. */
1180 maybe_call_trap_handler (sig)
1183 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
1184 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
1189 run_interrupt_trap ();
1211 signal_is_trapped (sig)
1214 return (sigmodes[sig] & SIG_TRAPPED);
1218 signal_is_pending (sig)
1221 return (pending_traps[sig]);
1225 signal_is_special (sig)
1228 return (sigmodes[sig] & SIG_SPECIAL);
1232 signal_is_ignored (sig)
1235 return (sigmodes[sig] & SIG_IGNORED);
1239 signal_is_hard_ignored (sig)
1242 return (sigmodes[sig] & SIG_HARD_IGNORE);
1246 set_signal_hard_ignored (sig)
1249 sigmodes[sig] |= SIG_HARD_IGNORE;
1250 original_signals[sig] = SIG_IGN;
1254 set_signal_ignored (sig)
1257 original_signals[sig] = SIG_IGN;
1261 signal_in_progress (sig)
1264 return (sigmodes[sig] & SIG_INPROGRESS);