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 recieved. 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 sensitivly 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
;
280 int old_exit_value
, *token_state
;
281 WORD_LIST
*save_subst_varlist
;
282 #if defined (ARRAY_VARS)
286 if (catch_flag
== 0) /* simple optimization */
289 catch_flag
= trapped_signal_received
= 0;
291 /* Preserve $? when running trap. */
292 old_exit_value
= last_command_exit_value
;
293 #if defined (ARRAY_VARS)
294 ps
= save_pipestatus_array ();
297 for (sig
= 1; sig
< NSIG
; sig
++)
299 /* XXX this could be made into a counter by using
300 while (pending_traps[sig]--) instead of the if statement. */
301 if (pending_traps
[sig
])
305 BLOCK_SIGNAL (sig
, set
, oset
);
309 run_interrupt_trap ();
312 #if defined (JOB_CONTROL) && defined (SIGCHLD)
313 else if (sig
== SIGCHLD
&&
314 trap_list
[SIGCHLD
] != (char *)IMPOSSIBLE_TRAP_HANDLER
&&
315 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) == 0)
317 sigmodes
[SIGCHLD
] |= SIG_INPROGRESS
;
318 run_sigchld_trap (pending_traps
[sig
]); /* use as counter */
319 sigmodes
[SIGCHLD
] &= ~SIG_INPROGRESS
;
321 else if (sig
== SIGCHLD
&&
322 trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
&&
323 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) != 0)
325 /* This can happen when run_pending_traps is called while
326 running a SIGCHLD trap handler. */
327 UNBLOCK_SIGNAL (oset
);
331 else if (trap_list
[sig
] == (char *)DEFAULT_SIG
||
332 trap_list
[sig
] == (char *)IGNORE_SIG
||
333 trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
335 /* This is possible due to a race condition. Say a bash
336 process has SIGTERM trapped. A subshell is spawned
337 using { list; } & and the parent does something and kills
338 the subshell with SIGTERM. It's possible for the subshell
339 to set pending_traps[SIGTERM] to 1 before the code in
340 execute_cmd.c eventually calls restore_original_signals
341 to reset the SIGTERM signal handler in the subshell. The
342 next time run_pending_traps is called, pending_traps[SIGTERM]
343 will be 1, but the trap handler in trap_list[SIGTERM] will
344 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
345 Unless we catch this, the subshell will dump core when
346 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
348 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
349 sig
, trap_list
[sig
]);
350 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
352 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig
, signal_name (sig
));
353 kill (getpid (), sig
);
358 token_state
= save_token_state ();
359 save_subst_varlist
= subst_assign_varlist
;
360 subst_assign_varlist
= 0;
362 evalstring (savestring (trap_list
[sig
]), "trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
363 restore_token_state (token_state
);
366 subst_assign_varlist
= save_subst_varlist
;
369 pending_traps
[sig
] = 0;
371 UNBLOCK_SIGNAL (oset
);
375 #if defined (ARRAY_VARS)
376 restore_pipestatus_array (ps
);
378 last_command_exit_value
= old_exit_value
;
387 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
390 internal_warning ("trap_handler: signal %d: signal not trapped", sig
);
396 (trap_list
[sig
] == (char *)DEFAULT_SIG
) ||
397 (trap_list
[sig
] == (char *)IGNORE_SIG
))
398 programming_error (_("trap_handler: bad signal %d"), sig
);
402 #if defined (MUST_REINSTALL_SIGHANDLERS)
403 # if defined (JOB_CONTROL) && defined (SIGCHLD)
405 # endif /* JOB_CONTROL && SIGCHLD */
406 set_signal_handler (sig
, trap_handler
);
407 #endif /* MUST_REINSTALL_SIGHANDLERS */
410 pending_traps
[sig
]++;
412 trapped_signal_received
= sig
;
414 if (this_shell_builtin
&& (this_shell_builtin
== wait_builtin
))
416 wait_signal_received
= sig
;
417 if (interrupt_immediately
)
418 longjmp (wait_intr_buf
, 1);
421 #if defined (READLINE)
422 /* Set the event hook so readline will call it after the signal handlers
423 finish executing, so if this interrupted character input we can get
425 if (RL_ISSTATE (RL_STATE_SIGHANDLER
) && interrupt_immediately
== 0)
426 bashline_set_event_hook ();
429 if (interrupt_immediately
)
430 run_pending_traps ();
439 first_pending_trap ()
443 for (i
= 1; i
< NSIG
; i
++)
444 if (pending_traps
[i
])
450 any_signals_trapped ()
454 for (i
= 1; i
< NSIG
; i
++)
455 if (sigmodes
[i
] & SIG_TRAPPED
)
463 CHECK_ALRM
; /* set by the read builtin */
467 /* Convenience functions the rest of the shell can use */
469 check_signals_and_traps ()
473 run_pending_traps ();
476 #if defined (JOB_CONTROL) && defined (SIGCHLD)
478 #ifdef INCLUDE_UNUSED
479 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
481 set_sigchld_trap (command_string
)
482 char *command_string
;
484 set_signal (SIGCHLD
, command_string
);
488 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
489 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
490 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
491 reset the disposition to the default and not have the original signal
492 accidentally restored, undoing the user's command. */
494 maybe_set_sigchld_trap (command_string
)
495 char *command_string
;
497 if ((sigmodes
[SIGCHLD
] & SIG_TRAPPED
) == 0 && trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
498 set_signal (SIGCHLD
, command_string
);
501 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
502 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
503 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
505 set_impossible_sigchld_trap ()
507 restore_default_signal (SIGCHLD
);
508 change_signal (SIGCHLD
, (char *)IMPOSSIBLE_TRAP_HANDLER
);
509 sigmodes
[SIGCHLD
] &= ~SIG_TRAPPED
; /* maybe_set_sigchld_trap checks this */
512 /* Act as if we received SIGCHLD NCHILD times and increment
513 pending_traps[SIGCHLD] by that amount. This allows us to still run the
514 SIGCHLD trap once for each exited child. */
516 queue_sigchld_trap (nchild
)
522 pending_traps
[SIGCHLD
] += nchild
;
523 trapped_signal_received
= SIGCHLD
;
526 #endif /* JOB_CONTROL && SIGCHLD */
529 set_debug_trap (command
)
532 set_signal (DEBUG_TRAP
, command
);
536 set_error_trap (command
)
539 set_signal (ERROR_TRAP
, command
);
543 set_return_trap (command
)
546 set_signal (RETURN_TRAP
, command
);
549 #ifdef INCLUDE_UNUSED
551 set_sigint_trap (command
)
554 set_signal (SIGINT
, command
);
558 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
559 things, like waiting for command substitution or executing commands
560 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
562 set_sigint_handler ()
564 if (sigmodes
[SIGINT
] & SIG_HARD_IGNORE
)
565 return ((SigHandler
*)SIG_IGN
);
567 else if (sigmodes
[SIGINT
] & SIG_IGNORED
)
568 return ((SigHandler
*)set_signal_handler (SIGINT
, SIG_IGN
)); /* XXX */
570 else if (sigmodes
[SIGINT
] & SIG_TRAPPED
)
571 return ((SigHandler
*)set_signal_handler (SIGINT
, trap_handler
));
573 /* The signal is not trapped, so set the handler to the shell's special
574 interrupt handler. */
575 else if (interactive
) /* XXX - was interactive_shell */
576 return (set_signal_handler (SIGINT
, sigint_sighandler
));
578 return (set_signal_handler (SIGINT
, termsig_sighandler
));
581 /* Return the correct handler for signal SIG according to the values in
584 trap_to_sighandler (sig
)
587 if (sigmodes
[sig
] & (SIG_IGNORED
|SIG_HARD_IGNORE
))
589 else if (sigmodes
[sig
] & SIG_TRAPPED
)
590 return (trap_handler
);
595 /* Set SIG to call STRING as a command. */
597 set_signal (sig
, string
)
603 if (SPECIAL_TRAP (sig
))
605 change_signal (sig
, savestring (string
));
606 if (sig
== EXIT_TRAP
&& interactive
== 0)
607 initialize_terminating_signals ();
611 /* A signal ignored on entry to the shell cannot be trapped or reset, but
612 no error is reported when attempting to do so. -- Posix.2 */
613 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
616 /* Make sure we have original_signals[sig] if the signal has not yet
618 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
620 /* If we aren't sure of the original value, check it. */
621 if (original_signals
[sig
] == IMPOSSIBLE_TRAP_HANDLER
)
623 if (original_signals
[sig
] == SIG_IGN
)
627 /* Only change the system signal handler if SIG_NO_TRAP is not set.
628 The trap command string is changed in either case. The shell signal
629 handlers for SIGINT and SIGCHLD run the user specified traps in an
630 environment in which it is safe to do so. */
631 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
633 BLOCK_SIGNAL (sig
, set
, oset
);
634 change_signal (sig
, savestring (string
));
635 set_signal_handler (sig
, trap_handler
);
636 UNBLOCK_SIGNAL (oset
);
639 change_signal (sig
, savestring (string
));
643 free_trap_command (sig
)
646 if ((sigmodes
[sig
] & SIG_TRAPPED
) && trap_list
[sig
] &&
647 (trap_list
[sig
] != (char *)IGNORE_SIG
) &&
648 (trap_list
[sig
] != (char *)DEFAULT_SIG
) &&
649 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
))
650 free (trap_list
[sig
]);
653 /* If SIG has a string assigned to it, get rid of it. Then give it
656 change_signal (sig
, value
)
660 if ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
661 free_trap_command (sig
);
662 trap_list
[sig
] = value
;
664 sigmodes
[sig
] |= SIG_TRAPPED
;
665 if (value
== (char *)IGNORE_SIG
)
666 sigmodes
[sig
] |= SIG_IGNORED
;
668 sigmodes
[sig
] &= ~SIG_IGNORED
;
669 if (sigmodes
[sig
] & SIG_INPROGRESS
)
670 sigmodes
[sig
] |= SIG_CHANGED
;
674 get_original_signal (sig
)
677 /* If we aren't sure the of the original value, then get it. */
678 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
683 get_all_original_signals ()
687 for (i
= 1; i
< NSIG
; i
++)
688 GET_ORIGINAL_SIGNAL (i
);
692 set_original_signal (sig
, handler
)
696 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
697 SETORIGSIG (sig
, handler
);
700 /* Restore the default action for SIG; i.e., the action the shell
701 would have taken before you used the trap command. This is called
702 from trap_builtin (), which takes care to restore the handlers for
703 the signals the shell treats specially. */
705 restore_default_signal (sig
)
708 if (SPECIAL_TRAP (sig
))
710 if ((sig
!= DEBUG_TRAP
&& sig
!= ERROR_TRAP
&& sig
!= RETURN_TRAP
) ||
711 (sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
712 free_trap_command (sig
);
713 trap_list
[sig
] = (char *)NULL
;
714 sigmodes
[sig
] &= ~SIG_TRAPPED
;
715 if (sigmodes
[sig
] & SIG_INPROGRESS
)
716 sigmodes
[sig
] |= SIG_CHANGED
;
720 GET_ORIGINAL_SIGNAL (sig
);
722 /* A signal ignored on entry to the shell cannot be trapped or reset, but
723 no error is reported when attempting to do so. Thanks Posix.2. */
724 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
727 /* If we aren't trapping this signal, don't bother doing anything else. */
728 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
731 /* Only change the signal handler for SIG if it allows it. */
732 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
733 set_signal_handler (sig
, original_signals
[sig
]);
735 /* Change the trap command in either case. */
736 change_signal (sig
, (char *)DEFAULT_SIG
);
738 /* Mark the signal as no longer trapped. */
739 sigmodes
[sig
] &= ~SIG_TRAPPED
;
742 /* Make this signal be ignored. */
747 if (SPECIAL_TRAP (sig
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
749 change_signal (sig
, (char *)IGNORE_SIG
);
753 GET_ORIGINAL_SIGNAL (sig
);
755 /* A signal ignored on entry to the shell cannot be trapped or reset.
756 No error is reported when the user attempts to do so. */
757 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
760 /* If already trapped and ignored, no change necessary. */
761 if (sigmodes
[sig
] & SIG_IGNORED
)
764 /* Only change the signal handler for SIG if it allows it. */
765 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
766 set_signal_handler (sig
, SIG_IGN
);
768 /* Change the trap command in either case. */
769 change_signal (sig
, (char *)IGNORE_SIG
);
772 /* Handle the calling of "trap 0". The only sticky situation is when
773 the command to be executed includes an "exit". This is why we have
774 to provide our own place for top_level to jump to. */
779 int code
, function_code
, retval
;
780 #if defined (ARRAY_VARS)
784 trap_saved_exit_value
= last_command_exit_value
;
785 #if defined (ARRAY_VARS)
786 ps
= save_pipestatus_array ();
790 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
791 currently running in the trap handler (call to exit in the list of
792 commands given to trap 0). */
793 if ((sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
) &&
794 (sigmodes
[EXIT_TRAP
] & (SIG_IGNORED
|SIG_INPROGRESS
)) == 0)
796 trap_command
= savestring (trap_list
[EXIT_TRAP
]);
797 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
798 sigmodes
[EXIT_TRAP
] |= SIG_INPROGRESS
;
800 retval
= trap_saved_exit_value
;
803 code
= setjmp_nosigs (top_level
);
805 /* If we're in a function, make sure return longjmps come here, too. */
806 if (return_catch_flag
)
807 function_code
= setjmp_nosigs (return_catch
);
809 if (code
== 0 && function_code
== 0)
812 parse_and_execute (trap_command
, "exit trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
814 else if (code
== ERREXIT
)
815 retval
= last_command_exit_value
;
816 else if (code
== EXITPROG
)
817 retval
= last_command_exit_value
;
818 else if (function_code
!= 0)
819 retval
= return_catch_value
;
821 retval
= trap_saved_exit_value
;
827 #if defined (ARRAY_VARS)
828 restore_pipestatus_array (ps
);
830 return (trap_saved_exit_value
);
834 run_trap_cleanup (sig
)
837 sigmodes
[sig
] &= ~(SIG_INPROGRESS
|SIG_CHANGED
);
840 /* Run a trap command for SIG. SIG is one of the signals the shell treats
841 specially. Returns the exit status of the executed trap command list. */
843 _run_trap_internal (sig
, tag
)
847 char *trap_command
, *old_trap
;
848 int trap_exit_value
, *token_state
;
849 volatile int save_return_catch_flag
, function_code
;
851 procenv_t save_return_catch
;
852 WORD_LIST
*save_subst_varlist
;
853 #if defined (ARRAY_VARS)
857 trap_exit_value
= function_code
= 0;
858 /* Run the trap only if SIG is trapped and not ignored, and we are not
859 currently executing in the trap handler. */
860 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0) &&
861 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
) &&
862 ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0))
864 old_trap
= trap_list
[sig
];
865 sigmodes
[sig
] |= SIG_INPROGRESS
;
866 sigmodes
[sig
] &= ~SIG_CHANGED
; /* just to be sure */
867 trap_command
= savestring (old_trap
);
869 running_trap
= sig
+ 1;
870 trap_saved_exit_value
= last_command_exit_value
;
871 #if defined (ARRAY_VARS)
872 ps
= save_pipestatus_array ();
875 token_state
= save_token_state ();
876 save_subst_varlist
= subst_assign_varlist
;
877 subst_assign_varlist
= 0;
879 /* If we're in a function, make sure return longjmps come here, too. */
880 save_return_catch_flag
= return_catch_flag
;
881 if (return_catch_flag
)
883 COPY_PROCENV (return_catch
, save_return_catch
);
884 function_code
= setjmp_nosigs (return_catch
);
887 flags
= SEVAL_NONINT
|SEVAL_NOHIST
;
888 if (sig
!= DEBUG_TRAP
&& sig
!= RETURN_TRAP
&& sig
!= ERROR_TRAP
)
889 flags
|= SEVAL_RESETLINE
;
890 if (function_code
== 0)
891 parse_and_execute (trap_command
, tag
, flags
);
893 restore_token_state (token_state
);
896 subst_assign_varlist
= save_subst_varlist
;
898 trap_exit_value
= last_command_exit_value
;
899 last_command_exit_value
= trap_saved_exit_value
;
900 #if defined (ARRAY_VARS)
901 restore_pipestatus_array (ps
);
905 sigmodes
[sig
] &= ~SIG_INPROGRESS
;
907 if (sigmodes
[sig
] & SIG_CHANGED
)
910 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
911 the places where they can be changed using unwind-protects. For
912 example, look at execute_cmd.c:execute_function(). */
913 if (SPECIAL_TRAP (sig
) == 0)
916 sigmodes
[sig
] &= ~SIG_CHANGED
;
919 if (save_return_catch_flag
)
921 return_catch_flag
= save_return_catch_flag
;
922 return_catch_value
= trap_exit_value
;
923 COPY_PROCENV (save_return_catch
, return_catch
);
925 longjmp (return_catch
, 1);
929 return trap_exit_value
;
939 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
941 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[DEBUG_TRAP
] & SIG_IGNORED
) == 0) && ((sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
) == 0))
943 #if defined (JOB_CONTROL)
944 save_pgrp
= pipeline_pgrp
;
947 # if defined (PGRP_PIPE)
948 save_pgrp_pipe (save_pipe
, 1);
950 stop_making_children ();
953 trap_exit_value
= _run_trap_internal (DEBUG_TRAP
, "debug trap");
955 #if defined (JOB_CONTROL)
956 pipeline_pgrp
= save_pgrp
;
957 restore_pipeline (1);
958 # if defined (PGRP_PIPE)
960 restore_pgrp_pipe (save_pipe
);
962 if (pipeline_pgrp
> 0)
963 give_terminal_to (pipeline_pgrp
, 1);
964 notify_and_cleanup ();
967 #if defined (DEBUGGER)
968 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
969 a function or sourced script, we force a `return'. */
970 if (debugging_mode
&& trap_exit_value
== 2 && return_catch_flag
)
972 return_catch_value
= trap_exit_value
;
973 longjmp (return_catch
, 1);
977 return trap_exit_value
;
983 if ((sigmodes
[ERROR_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[ERROR_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[ERROR_TRAP
] & SIG_INPROGRESS
) == 0)
984 _run_trap_internal (ERROR_TRAP
, "error trap");
993 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && (sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
))
997 if ((sigmodes
[RETURN_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[RETURN_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[RETURN_TRAP
] & SIG_INPROGRESS
) == 0)
999 old_exit_value
= last_command_exit_value
;
1000 _run_trap_internal (RETURN_TRAP
, "return trap");
1001 last_command_exit_value
= old_exit_value
;
1005 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1006 declared here to localize the trap functions. */
1008 run_interrupt_trap ()
1010 _run_trap_internal (SIGINT
, "interrupt trap");
1013 /* Free all the allocated strings in the list of traps and reset the trap
1014 values to the default. Intended to be called from subshells that want
1015 to complete work done by reset_signal_handlers upon execution of a
1016 subsequent `trap' command that changes a signal's disposition. We need
1017 to make sure that we duplicate the behavior of
1018 reset_or_restore_signal_handlers and not change the disposition of signals
1019 that are set to be ignored. */
1021 free_trap_strings ()
1025 for (i
= 0; i
< BASH_NSIG
; i
++)
1027 if (trap_list
[i
] != (char *)IGNORE_SIG
)
1028 free_trap_string (i
);
1030 trap_list
[DEBUG_TRAP
] = trap_list
[EXIT_TRAP
] = trap_list
[ERROR_TRAP
] = trap_list
[RETURN_TRAP
] = (char *)NULL
;
1033 /* Free a trap command string associated with SIG without changing signal
1034 disposition. Intended to be called from free_trap_strings() */
1036 free_trap_string (sig
)
1039 change_signal (sig
, (char *)DEFAULT_SIG
);
1040 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1043 /* Reset the handler for SIG to the original value but leave the trap string
1049 set_signal_handler (sig
, original_signals
[sig
]);
1050 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1053 /* Set the handler signal SIG to the original and free any trap
1054 command associated with it. */
1056 restore_signal (sig
)
1059 set_signal_handler (sig
, original_signals
[sig
]);
1060 change_signal (sig
, (char *)DEFAULT_SIG
);
1061 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1065 reset_or_restore_signal_handlers (reset
)
1066 sh_resetsig_func_t
*reset
;
1070 /* Take care of the exit trap first */
1071 if (sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
)
1073 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
1074 if (reset
!= reset_signal
)
1076 free_trap_command (EXIT_TRAP
);
1077 trap_list
[EXIT_TRAP
] = (char *)NULL
;
1081 for (i
= 1; i
< NSIG
; i
++)
1083 if (sigmodes
[i
] & SIG_TRAPPED
)
1085 if (trap_list
[i
] == (char *)IGNORE_SIG
)
1086 set_signal_handler (i
, SIG_IGN
);
1090 else if (sigmodes
[i
] & SIG_SPECIAL
)
1094 /* Command substitution and other child processes don't inherit the
1095 debug, error, or return traps. If we're in the debugger, and the
1096 `functrace' or `errtrace' options have been set, then let command
1097 substitutions inherit them. Let command substitution inherit the
1098 RETURN trap if we're in the debugger and tracing functions. */
1099 if (function_trace_mode
== 0)
1101 sigmodes
[DEBUG_TRAP
] &= ~SIG_TRAPPED
;
1102 sigmodes
[RETURN_TRAP
] &= ~SIG_TRAPPED
;
1104 if (error_trace_mode
== 0)
1105 sigmodes
[ERROR_TRAP
] &= ~SIG_TRAPPED
;
1108 /* Reset trapped signals to their original values, but don't free the
1109 trap strings. Called by the command substitution code and other places
1110 that create a "subshell environment". */
1112 reset_signal_handlers ()
1114 reset_or_restore_signal_handlers (reset_signal
);
1117 /* Reset all trapped signals to their original values. Signals set to be
1118 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1119 are. Called by child processes after they are forked. */
1121 restore_original_signals ()
1123 reset_or_restore_signal_handlers (restore_signal
);
1126 /* If a trap handler exists for signal SIG, then call it; otherwise just
1127 return failure. Returns 1 if it called the trap handler. */
1129 maybe_call_trap_handler (sig
)
1132 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
1133 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
1138 run_interrupt_trap ();
1160 signal_is_trapped (sig
)
1163 return (sigmodes
[sig
] & SIG_TRAPPED
);
1167 signal_is_pending (sig
)
1170 return (pending_traps
[sig
]);
1174 signal_is_special (sig
)
1177 return (sigmodes
[sig
] & SIG_SPECIAL
);
1181 signal_is_ignored (sig
)
1184 return (sigmodes
[sig
] & SIG_IGNORED
);
1188 signal_is_hard_ignored (sig
)
1191 return (sigmodes
[sig
] & SIG_HARD_IGNORE
);
1195 set_signal_ignored (sig
)
1198 sigmodes
[sig
] |= SIG_HARD_IGNORE
;
1199 original_signals
[sig
] = SIG_IGN
;
1203 signal_in_progress (sig
)
1206 return (sigmodes
[sig
] & SIG_INPROGRESS
);