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-2009 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"
40 #include "input.h" /* for save_token_state, restore_token_state */
44 #include "builtins/common.h"
45 #include "builtins/builtext.h"
51 /* Flags which describe the current handling state of a signal. */
52 #define SIG_INHERITED 0x0 /* Value inherited from parent. */
53 #define SIG_TRAPPED 0x1 /* Currently trapped. */
54 #define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
55 #define SIG_SPECIAL 0x4 /* Treat this signal specially. */
56 #define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
57 #define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
58 #define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
59 #define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
61 #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
63 /* An array of such flags, one for each signal, describing what the
64 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
66 static int sigmodes
[BASH_NSIG
];
68 static void free_trap_command
__P((int));
69 static void change_signal
__P((int, char *));
71 static void get_original_signal
__P((int));
73 static int _run_trap_internal
__P((int, char *));
75 static void free_trap_string
__P((int));
76 static void reset_signal
__P((int));
77 static void restore_signal
__P((int));
78 static void reset_or_restore_signal_handlers
__P((sh_resetsig_func_t
*));
80 /* Variables used here but defined in other files. */
81 extern int last_command_exit_value
;
82 extern int line_number
;
84 extern char *this_command_name
;
85 extern sh_builtin_func_t
*this_shell_builtin
;
86 extern procenv_t wait_intr_buf
;
87 extern int return_catch_flag
, return_catch_value
;
88 extern int subshell_level
;
89 extern WORD_LIST
*subst_assign_varlist
;
91 /* The list of things to do originally, before we started trapping. */
92 SigHandler
*original_signals
[NSIG
];
94 /* For each signal, a slot for a string, which is a command to be
95 executed when that signal is recieved. The slot can also contain
96 DEFAULT_SIG, which means do whatever you were going to do before
97 you were so rudely interrupted, or IGNORE_SIG, which says ignore
99 char *trap_list
[BASH_NSIG
];
101 /* A bitmap of signals received for which we have trap handlers. */
102 int pending_traps
[NSIG
];
104 /* Set to the number of the signal we're running the trap for + 1.
105 Used in execute_cmd.c and builtins/common.c to clean up when
106 parse_and_execute does not return normally after executing the
107 trap command (e.g., when `return' is executed in the trap command). */
110 /* Set to last_command_exit_value before running a trap. */
111 int trap_saved_exit_value
;
113 /* The (trapped) signal received while executing in the `wait' builtin */
114 int wait_signal_received
;
116 /* A value which can never be the target of a trap handler. */
117 #define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
119 #define GETORIGSIG(sig) \
121 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
122 set_signal_handler (sig, original_signals[sig]); \
123 if (original_signals[sig] == SIG_IGN) \
124 sigmodes[sig] |= SIG_HARD_IGNORE; \
127 #define GET_ORIGINAL_SIGNAL(sig) \
128 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
136 initialize_signames();
138 trap_list
[EXIT_TRAP
] = trap_list
[DEBUG_TRAP
] = trap_list
[ERROR_TRAP
] = trap_list
[RETURN_TRAP
] = (char *)NULL
;
139 sigmodes
[EXIT_TRAP
] = sigmodes
[DEBUG_TRAP
] = sigmodes
[ERROR_TRAP
] = sigmodes
[RETURN_TRAP
] = SIG_INHERITED
;
140 original_signals
[EXIT_TRAP
] = IMPOSSIBLE_TRAP_HANDLER
;
142 for (i
= 1; i
< NSIG
; i
++)
144 pending_traps
[i
] = 0;
145 trap_list
[i
] = (char *)DEFAULT_SIG
;
146 sigmodes
[i
] = SIG_INHERITED
;
147 original_signals
[i
] = IMPOSSIBLE_TRAP_HANDLER
;
150 /* Show which signals are treated specially by the shell. */
151 #if defined (SIGCHLD)
152 GETORIGSIG (SIGCHLD
);
153 sigmodes
[SIGCHLD
] |= (SIG_SPECIAL
| SIG_NO_TRAP
);
157 sigmodes
[SIGINT
] |= SIG_SPECIAL
;
159 #if defined (__BEOS__)
160 /* BeOS sets SIGINT to SIG_IGN! */
161 original_signals
[SIGINT
] = SIG_DFL
;
162 sigmodes
[SIGINT
] &= ~SIG_HARD_IGNORE
;
165 GETORIGSIG (SIGQUIT
);
166 sigmodes
[SIGQUIT
] |= SIG_SPECIAL
;
170 GETORIGSIG (SIGTERM
);
171 sigmodes
[SIGTERM
] |= SIG_SPECIAL
;
175 #ifdef INCLUDE_UNUSED
176 /* Return a printable representation of the trap handler for SIG. */
178 trap_handler_string (sig
)
181 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
182 return "DEFAULT_SIG";
183 else if (trap_list
[sig
] == (char *)IGNORE_SIG
)
185 else if (trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
186 return "IMPOSSIBLE_TRAP_HANDLER";
187 else if (trap_list
[sig
])
188 return trap_list
[sig
];
194 /* Return the print name of this signal. */
201 /* on cygwin32, signal_names[sig] could be null */
202 ret
= (sig
>= BASH_NSIG
|| sig
< 0 || signal_names
[sig
] == NULL
)
203 ? _("invalid signal number")
209 /* Turn a string into a signal number, or a number into
210 a signal number. If STRING is "2", "SIGINT", or "INT",
211 then (int)2 is returned. Return NO_SIG if STRING doesn't
212 contain a valid signal descriptor. */
214 decode_signal (string
, flags
)
221 if (legal_number (string
, &sig
))
222 return ((sig
>= 0 && sig
< NSIG
) ? (int)sig
: NO_SIG
);
224 /* A leading `SIG' may be omitted. */
225 for (sig
= 0; sig
< BASH_NSIG
; sig
++)
227 name
= signal_names
[sig
];
228 if (name
== 0 || name
[0] == '\0')
231 /* Check name without the SIG prefix first case sensitivly or
232 insensitively depending on whether flags includes DSIG_NOCASE */
233 if (STREQN (name
, "SIG", 3))
237 if ((flags
& DSIG_NOCASE
) && strcasecmp (string
, name
) == 0)
239 else if ((flags
& DSIG_NOCASE
) == 0 && strcmp (string
, name
) == 0)
241 /* If we can't use the `SIG' prefix to match, punt on this
243 else if ((flags
& DSIG_SIGPREFIX
) == 0)
247 /* Check name with SIG prefix case sensitively or insensitively
248 depending on whether flags includes DSIG_NOCASE */
249 name
= signal_names
[sig
];
250 if ((flags
& DSIG_NOCASE
) && strcasecmp (string
, name
) == 0)
252 else if ((flags
& DSIG_NOCASE
) == 0 && strcmp (string
, name
) == 0)
259 /* Non-zero when we catch a trapped signal. */
260 static int catch_flag
;
266 int old_exit_value
, *token_state
;
267 WORD_LIST
*save_subst_varlist
;
269 if (catch_flag
== 0) /* simple optimization */
274 /* Preserve $? when running trap. */
275 old_exit_value
= last_command_exit_value
;
277 for (sig
= 1; sig
< NSIG
; sig
++)
279 /* XXX this could be made into a counter by using
280 while (pending_traps[sig]--) instead of the if statement. */
281 if (pending_traps
[sig
])
283 #if defined (HAVE_POSIX_SIGNALS)
289 sigaddset (&set
, sig
);
290 sigprocmask (SIG_BLOCK
, &set
, &oset
);
292 # if defined (HAVE_BSD_SIGNALS)
293 int oldmask
= sigblock (sigmask (sig
));
295 #endif /* HAVE_POSIX_SIGNALS */
299 run_interrupt_trap ();
302 #if defined (JOB_CONTROL) && defined (SIGCHLD)
303 else if (sig
== SIGCHLD
&&
304 trap_list
[SIGCHLD
] != (char *)IMPOSSIBLE_TRAP_HANDLER
&&
305 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) == 0)
307 run_sigchld_trap (pending_traps
[sig
]); /* use as counter */
310 else if (trap_list
[sig
] == (char *)DEFAULT_SIG
||
311 trap_list
[sig
] == (char *)IGNORE_SIG
||
312 trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
314 /* This is possible due to a race condition. Say a bash
315 process has SIGTERM trapped. A subshell is spawned
316 using { list; } & and the parent does something and kills
317 the subshell with SIGTERM. It's possible for the subshell
318 to set pending_traps[SIGTERM] to 1 before the code in
319 execute_cmd.c eventually calls restore_original_signals
320 to reset the SIGTERM signal handler in the subshell. The
321 next time run_pending_traps is called, pending_traps[SIGTERM]
322 will be 1, but the trap handler in trap_list[SIGTERM] will
323 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
324 Unless we catch this, the subshell will dump core when
325 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
327 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
328 sig
, trap_list
[sig
]);
329 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
331 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig
, signal_name (sig
));
332 kill (getpid (), sig
);
337 token_state
= save_token_state ();
338 save_subst_varlist
= subst_assign_varlist
;
339 subst_assign_varlist
= 0;
341 parse_and_execute (savestring (trap_list
[sig
]), "trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
342 restore_token_state (token_state
);
345 subst_assign_varlist
= save_subst_varlist
;
348 pending_traps
[sig
] = 0;
350 #if defined (HAVE_POSIX_SIGNALS)
351 sigprocmask (SIG_SETMASK
, &oset
, (sigset_t
*)NULL
);
353 # if defined (HAVE_BSD_SIGNALS)
354 sigsetmask (oldmask
);
356 #endif /* POSIX_VERSION */
360 last_command_exit_value
= old_exit_value
;
369 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
372 internal_warning ("trap_handler: signal %d: signal not trapped", sig
);
378 (trap_list
[sig
] == (char *)DEFAULT_SIG
) ||
379 (trap_list
[sig
] == (char *)IGNORE_SIG
))
380 programming_error (_("trap_handler: bad signal %d"), sig
);
384 #if defined (MUST_REINSTALL_SIGHANDLERS)
385 # if defined (JOB_CONTROL) && defined (SIGCHLD)
387 # endif /* JOB_CONTROL && SIGCHLD */
388 set_signal_handler (sig
, trap_handler
);
389 #endif /* MUST_REINSTALL_SIGHANDLERS */
392 pending_traps
[sig
]++;
394 if (interrupt_immediately
&& this_shell_builtin
&& (this_shell_builtin
== wait_builtin
))
396 wait_signal_received
= sig
;
397 longjmp (wait_intr_buf
, 1);
400 if (interrupt_immediately
)
401 run_pending_traps ();
409 #if defined (JOB_CONTROL) && defined (SIGCHLD)
411 #ifdef INCLUDE_UNUSED
412 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
414 set_sigchld_trap (command_string
)
415 char *command_string
;
417 set_signal (SIGCHLD
, command_string
);
421 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
422 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
423 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
424 reset the disposition to the default and not have the original signal
425 accidentally restored, undoing the user's command. */
427 maybe_set_sigchld_trap (command_string
)
428 char *command_string
;
430 if ((sigmodes
[SIGCHLD
] & SIG_TRAPPED
) == 0 && trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
431 set_signal (SIGCHLD
, command_string
);
434 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
435 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
436 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
438 set_impossible_sigchld_trap ()
440 restore_default_signal (SIGCHLD
);
441 change_signal (SIGCHLD
, (char *)IMPOSSIBLE_TRAP_HANDLER
);
442 sigmodes
[SIGCHLD
] &= ~SIG_TRAPPED
; /* maybe_set_sigchld_trap checks this */
444 #endif /* JOB_CONTROL && SIGCHLD */
447 set_debug_trap (command
)
450 set_signal (DEBUG_TRAP
, command
);
454 set_error_trap (command
)
457 set_signal (ERROR_TRAP
, command
);
461 set_return_trap (command
)
464 set_signal (RETURN_TRAP
, command
);
467 #ifdef INCLUDE_UNUSED
469 set_sigint_trap (command
)
472 set_signal (SIGINT
, command
);
476 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
477 things, like waiting for command substitution or executing commands
478 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
480 set_sigint_handler ()
482 if (sigmodes
[SIGINT
] & SIG_HARD_IGNORE
)
483 return ((SigHandler
*)SIG_IGN
);
485 else if (sigmodes
[SIGINT
] & SIG_IGNORED
)
486 return ((SigHandler
*)set_signal_handler (SIGINT
, SIG_IGN
)); /* XXX */
488 else if (sigmodes
[SIGINT
] & SIG_TRAPPED
)
489 return ((SigHandler
*)set_signal_handler (SIGINT
, trap_handler
));
491 /* The signal is not trapped, so set the handler to the shell's special
492 interrupt handler. */
493 else if (interactive
) /* XXX - was interactive_shell */
494 return (set_signal_handler (SIGINT
, sigint_sighandler
));
496 return (set_signal_handler (SIGINT
, termsig_sighandler
));
499 /* Return the correct handler for signal SIG according to the values in
502 trap_to_sighandler (sig
)
505 if (sigmodes
[sig
] & (SIG_IGNORED
|SIG_HARD_IGNORE
))
507 else if (sigmodes
[sig
] & SIG_TRAPPED
)
508 return (trap_handler
);
513 /* Set SIG to call STRING as a command. */
515 set_signal (sig
, string
)
519 if (SPECIAL_TRAP (sig
))
521 change_signal (sig
, savestring (string
));
522 if (sig
== EXIT_TRAP
&& interactive
== 0)
523 initialize_terminating_signals ();
527 /* A signal ignored on entry to the shell cannot be trapped or reset, but
528 no error is reported when attempting to do so. -- Posix.2 */
529 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
532 /* Make sure we have original_signals[sig] if the signal has not yet
534 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
536 /* If we aren't sure of the original value, check it. */
537 if (original_signals
[sig
] == IMPOSSIBLE_TRAP_HANDLER
)
539 if (original_signals
[sig
] == SIG_IGN
)
543 /* Only change the system signal handler if SIG_NO_TRAP is not set.
544 The trap command string is changed in either case. The shell signal
545 handlers for SIGINT and SIGCHLD run the user specified traps in an
546 environment in which it is safe to do so. */
547 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
549 set_signal_handler (sig
, SIG_IGN
);
550 change_signal (sig
, savestring (string
));
551 set_signal_handler (sig
, trap_handler
);
554 change_signal (sig
, savestring (string
));
558 free_trap_command (sig
)
561 if ((sigmodes
[sig
] & SIG_TRAPPED
) && trap_list
[sig
] &&
562 (trap_list
[sig
] != (char *)IGNORE_SIG
) &&
563 (trap_list
[sig
] != (char *)DEFAULT_SIG
) &&
564 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
))
565 free (trap_list
[sig
]);
568 /* If SIG has a string assigned to it, get rid of it. Then give it
571 change_signal (sig
, value
)
575 if ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
576 free_trap_command (sig
);
577 trap_list
[sig
] = value
;
579 sigmodes
[sig
] |= SIG_TRAPPED
;
580 if (value
== (char *)IGNORE_SIG
)
581 sigmodes
[sig
] |= SIG_IGNORED
;
583 sigmodes
[sig
] &= ~SIG_IGNORED
;
584 if (sigmodes
[sig
] & SIG_INPROGRESS
)
585 sigmodes
[sig
] |= SIG_CHANGED
;
589 get_original_signal (sig
)
592 /* If we aren't sure the of the original value, then get it. */
593 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
597 /* Restore the default action for SIG; i.e., the action the shell
598 would have taken before you used the trap command. This is called
599 from trap_builtin (), which takes care to restore the handlers for
600 the signals the shell treats specially. */
602 restore_default_signal (sig
)
605 if (SPECIAL_TRAP (sig
))
607 if ((sig
!= DEBUG_TRAP
&& sig
!= ERROR_TRAP
&& sig
!= RETURN_TRAP
) ||
608 (sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
609 free_trap_command (sig
);
610 trap_list
[sig
] = (char *)NULL
;
611 sigmodes
[sig
] &= ~SIG_TRAPPED
;
612 if (sigmodes
[sig
] & SIG_INPROGRESS
)
613 sigmodes
[sig
] |= SIG_CHANGED
;
617 GET_ORIGINAL_SIGNAL (sig
);
619 /* A signal ignored on entry to the shell cannot be trapped or reset, but
620 no error is reported when attempting to do so. Thanks Posix.2. */
621 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
624 /* If we aren't trapping this signal, don't bother doing anything else. */
625 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
628 /* Only change the signal handler for SIG if it allows it. */
629 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
630 set_signal_handler (sig
, original_signals
[sig
]);
632 /* Change the trap command in either case. */
633 change_signal (sig
, (char *)DEFAULT_SIG
);
635 /* Mark the signal as no longer trapped. */
636 sigmodes
[sig
] &= ~SIG_TRAPPED
;
639 /* Make this signal be ignored. */
644 if (SPECIAL_TRAP (sig
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
646 change_signal (sig
, (char *)IGNORE_SIG
);
650 GET_ORIGINAL_SIGNAL (sig
);
652 /* A signal ignored on entry to the shell cannot be trapped or reset.
653 No error is reported when the user attempts to do so. */
654 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
657 /* If already trapped and ignored, no change necessary. */
658 if (sigmodes
[sig
] & SIG_IGNORED
)
661 /* Only change the signal handler for SIG if it allows it. */
662 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
663 set_signal_handler (sig
, SIG_IGN
);
665 /* Change the trap command in either case. */
666 change_signal (sig
, (char *)IGNORE_SIG
);
669 /* Handle the calling of "trap 0". The only sticky situation is when
670 the command to be executed includes an "exit". This is why we have
671 to provide our own place for top_level to jump to. */
676 int code
, function_code
, retval
;
678 trap_saved_exit_value
= last_command_exit_value
;
681 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
682 currently running in the trap handler (call to exit in the list of
683 commands given to trap 0). */
684 if ((sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
) &&
685 (sigmodes
[EXIT_TRAP
] & (SIG_IGNORED
|SIG_INPROGRESS
)) == 0)
687 trap_command
= savestring (trap_list
[EXIT_TRAP
]);
688 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
689 sigmodes
[EXIT_TRAP
] |= SIG_INPROGRESS
;
691 retval
= trap_saved_exit_value
;
694 code
= setjmp (top_level
);
696 /* If we're in a function, make sure return longjmps come here, too. */
697 if (return_catch_flag
)
698 function_code
= setjmp (return_catch
);
700 if (code
== 0 && function_code
== 0)
703 parse_and_execute (trap_command
, "exit trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
705 else if (code
== ERREXIT
)
706 retval
= last_command_exit_value
;
707 else if (code
== EXITPROG
)
708 retval
= last_command_exit_value
;
709 else if (function_code
!= 0)
710 retval
= return_catch_value
;
712 retval
= trap_saved_exit_value
;
718 return (trap_saved_exit_value
);
722 run_trap_cleanup (sig
)
725 sigmodes
[sig
] &= ~(SIG_INPROGRESS
|SIG_CHANGED
);
728 /* Run a trap command for SIG. SIG is one of the signals the shell treats
729 specially. Returns the exit status of the executed trap command list. */
731 _run_trap_internal (sig
, tag
)
735 char *trap_command
, *old_trap
;
736 int trap_exit_value
, *token_state
;
737 int save_return_catch_flag
, function_code
, flags
;
738 procenv_t save_return_catch
;
739 WORD_LIST
*save_subst_varlist
;
741 trap_exit_value
= function_code
= 0;
742 /* Run the trap only if SIG is trapped and not ignored, and we are not
743 currently executing in the trap handler. */
744 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0) &&
745 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
) &&
746 ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0))
748 old_trap
= trap_list
[sig
];
749 sigmodes
[sig
] |= SIG_INPROGRESS
;
750 sigmodes
[sig
] &= ~SIG_CHANGED
; /* just to be sure */
751 trap_command
= savestring (old_trap
);
753 running_trap
= sig
+ 1;
754 trap_saved_exit_value
= last_command_exit_value
;
756 token_state
= save_token_state ();
757 save_subst_varlist
= subst_assign_varlist
;
758 subst_assign_varlist
= 0;
760 /* If we're in a function, make sure return longjmps come here, too. */
761 save_return_catch_flag
= return_catch_flag
;
762 if (return_catch_flag
)
764 COPY_PROCENV (return_catch
, save_return_catch
);
765 function_code
= setjmp (return_catch
);
768 flags
= SEVAL_NONINT
|SEVAL_NOHIST
;
769 if (sig
!= DEBUG_TRAP
&& sig
!= RETURN_TRAP
&& sig
!= ERROR_TRAP
)
770 flags
|= SEVAL_RESETLINE
;
771 if (function_code
== 0)
772 parse_and_execute (trap_command
, tag
, flags
);
774 restore_token_state (token_state
);
777 subst_assign_varlist
= save_subst_varlist
;
779 trap_exit_value
= last_command_exit_value
;
780 last_command_exit_value
= trap_saved_exit_value
;
783 sigmodes
[sig
] &= ~SIG_INPROGRESS
;
785 if (sigmodes
[sig
] & SIG_CHANGED
)
788 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
789 the places where they can be changed using unwind-protects. For
790 example, look at execute_cmd.c:execute_function(). */
791 if (SPECIAL_TRAP (sig
) == 0)
794 sigmodes
[sig
] &= ~SIG_CHANGED
;
797 if (save_return_catch_flag
)
799 return_catch_flag
= save_return_catch_flag
;
800 return_catch_value
= trap_exit_value
;
801 COPY_PROCENV (save_return_catch
, return_catch
);
803 longjmp (return_catch
, 1);
807 return trap_exit_value
;
817 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
819 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[DEBUG_TRAP
] & SIG_IGNORED
) == 0) && ((sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
) == 0))
821 #if defined (JOB_CONTROL)
822 save_pgrp
= pipeline_pgrp
;
825 # if defined (PGRP_PIPE)
826 save_pgrp_pipe (save_pipe
, 1);
828 stop_making_children ();
831 trap_exit_value
= _run_trap_internal (DEBUG_TRAP
, "debug trap");
833 #if defined (JOB_CONTROL)
834 pipeline_pgrp
= save_pgrp
;
835 restore_pipeline (1);
836 # if defined (PGRP_PIPE)
838 restore_pgrp_pipe (save_pipe
);
840 if (pipeline_pgrp
> 0)
841 give_terminal_to (pipeline_pgrp
, 1);
842 notify_and_cleanup ();
845 #if defined (DEBUGGER)
846 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
847 a function or sourced script, we force a `return'. */
848 if (debugging_mode
&& trap_exit_value
== 2 && return_catch_flag
)
850 return_catch_value
= trap_exit_value
;
851 longjmp (return_catch
, 1);
855 return trap_exit_value
;
861 if ((sigmodes
[ERROR_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[ERROR_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[ERROR_TRAP
] & SIG_INPROGRESS
) == 0)
862 _run_trap_internal (ERROR_TRAP
, "error trap");
871 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && (sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
))
875 if ((sigmodes
[RETURN_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[RETURN_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[RETURN_TRAP
] & SIG_INPROGRESS
) == 0)
877 old_exit_value
= last_command_exit_value
;
878 _run_trap_internal (RETURN_TRAP
, "return trap");
879 last_command_exit_value
= old_exit_value
;
883 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
884 declared here to localize the trap functions. */
886 run_interrupt_trap ()
888 _run_trap_internal (SIGINT
, "interrupt trap");
891 #ifdef INCLUDE_UNUSED
892 /* Free all the allocated strings in the list of traps and reset the trap
893 values to the default. Intended to be called from subshells that want
894 to complete work done by reset_signal_handlers upon execution of a
895 subsequent `trap' command that changes a signal's disposition. */
901 for (i
= 0; i
< BASH_NSIG
; i
++)
902 free_trap_string (i
);
903 trap_list
[DEBUG_TRAP
] = trap_list
[EXIT_TRAP
] = trap_list
[ERROR_TRAP
] = trap_list
[RETURN_TRAP
] = (char *)NULL
;
906 /* Free a trap command string associated with SIG without changing signal
907 disposition. Intended to be called from free_trap_strings() */
909 free_trap_string (sig
)
912 change_signal (sig
, (char *)DEFAULT_SIG
);
913 sigmodes
[sig
] &= ~SIG_TRAPPED
;
917 /* Reset the handler for SIG to the original value. */
922 set_signal_handler (sig
, original_signals
[sig
]);
923 sigmodes
[sig
] &= ~SIG_TRAPPED
;
926 /* Set the handler signal SIG to the original and free any trap
927 command associated with it. */
932 set_signal_handler (sig
, original_signals
[sig
]);
933 change_signal (sig
, (char *)DEFAULT_SIG
);
934 sigmodes
[sig
] &= ~SIG_TRAPPED
;
938 reset_or_restore_signal_handlers (reset
)
939 sh_resetsig_func_t
*reset
;
943 /* Take care of the exit trap first */
944 if (sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
)
946 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
947 if (reset
!= reset_signal
)
949 free_trap_command (EXIT_TRAP
);
950 trap_list
[EXIT_TRAP
] = (char *)NULL
;
954 for (i
= 1; i
< NSIG
; i
++)
956 if (sigmodes
[i
] & SIG_TRAPPED
)
958 if (trap_list
[i
] == (char *)IGNORE_SIG
)
959 set_signal_handler (i
, SIG_IGN
);
963 else if (sigmodes
[i
] & SIG_SPECIAL
)
967 /* Command substitution and other child processes don't inherit the
968 debug, error, or return traps. If we're in the debugger, and the
969 `functrace' or `errtrace' options have been set, then let command
970 substitutions inherit them. Let command substitution inherit the
971 RETURN trap if we're in the debugger and tracing functions. */
972 if (function_trace_mode
== 0)
974 sigmodes
[DEBUG_TRAP
] &= ~SIG_TRAPPED
;
975 sigmodes
[RETURN_TRAP
] &= ~SIG_TRAPPED
;
977 if (error_trace_mode
== 0)
978 sigmodes
[ERROR_TRAP
] &= ~SIG_TRAPPED
;
981 /* Reset trapped signals to their original values, but don't free the
982 trap strings. Called by the command substitution code. */
984 reset_signal_handlers ()
986 reset_or_restore_signal_handlers (reset_signal
);
989 /* Reset all trapped signals to their original values. Signals set to be
990 ignored with trap '' SIGNAL should be ignored, so we make sure that they
991 are. Called by child processes after they are forked. */
993 restore_original_signals ()
995 reset_or_restore_signal_handlers (restore_signal
);
998 /* If a trap handler exists for signal SIG, then call it; otherwise just
1001 maybe_call_trap_handler (sig
)
1004 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
1005 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
1010 run_interrupt_trap ();
1032 signal_is_trapped (sig
)
1035 return (sigmodes
[sig
] & SIG_TRAPPED
);
1039 signal_is_special (sig
)
1042 return (sigmodes
[sig
] & SIG_SPECIAL
);
1046 signal_is_ignored (sig
)
1049 return (sigmodes
[sig
] & SIG_IGNORED
);
1053 set_signal_ignored (sig
)
1056 sigmodes
[sig
] |= SIG_HARD_IGNORE
;
1057 original_signals
[sig
] = SIG_IGN
;
1061 signal_in_progress (sig
)
1064 return (sigmodes
[sig
] & SIG_INPROGRESS
);