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 if (running_trap
> 0)
290 return; /* no recursive trap invocations */
292 catch_flag
= trapped_signal_received
= 0;
294 /* Preserve $? when running trap. */
295 old_exit_value
= last_command_exit_value
;
296 #if defined (ARRAY_VARS)
297 ps
= save_pipestatus_array ();
300 for (sig
= 1; sig
< NSIG
; sig
++)
302 /* XXX this could be made into a counter by using
303 while (pending_traps[sig]--) instead of the if statement. */
304 if (pending_traps
[sig
])
308 BLOCK_SIGNAL (sig
, set
, oset
);
310 running_trap
= sig
+ 1;
314 run_interrupt_trap ();
317 #if defined (JOB_CONTROL) && defined (SIGCHLD)
318 else if (sig
== SIGCHLD
&&
319 trap_list
[SIGCHLD
] != (char *)IMPOSSIBLE_TRAP_HANDLER
&&
320 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) == 0)
322 sigmodes
[SIGCHLD
] |= SIG_INPROGRESS
;
323 run_sigchld_trap (pending_traps
[sig
]); /* use as counter */
324 sigmodes
[SIGCHLD
] &= ~SIG_INPROGRESS
;
326 else if (sig
== SIGCHLD
&&
327 trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
&&
328 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) != 0)
330 /* This can happen when run_pending_traps is called while
331 running a SIGCHLD trap handler. */
333 UNBLOCK_SIGNAL (oset
);
337 else if (trap_list
[sig
] == (char *)DEFAULT_SIG
||
338 trap_list
[sig
] == (char *)IGNORE_SIG
||
339 trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
341 /* This is possible due to a race condition. Say a bash
342 process has SIGTERM trapped. A subshell is spawned
343 using { list; } & and the parent does something and kills
344 the subshell with SIGTERM. It's possible for the subshell
345 to set pending_traps[SIGTERM] to 1 before the code in
346 execute_cmd.c eventually calls restore_original_signals
347 to reset the SIGTERM signal handler in the subshell. The
348 next time run_pending_traps is called, pending_traps[SIGTERM]
349 will be 1, but the trap handler in trap_list[SIGTERM] will
350 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
351 Unless we catch this, the subshell will dump core when
352 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
354 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
355 sig
, trap_list
[sig
]);
356 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
358 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig
, signal_name (sig
));
359 kill (getpid (), sig
);
364 /* XXX - should we use save_parser_state/restore_parser_state? */
365 token_state
= save_token_state ();
366 save_subst_varlist
= subst_assign_varlist
;
367 subst_assign_varlist
= 0;
369 #if defined (JOB_CONTROL)
370 save_pipeline (1); /* XXX only provides one save level */
372 evalstring (savestring (trap_list
[sig
]), "trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
373 #if defined (JOB_CONTROL)
374 restore_pipeline (1);
377 restore_token_state (token_state
);
380 subst_assign_varlist
= save_subst_varlist
;
383 pending_traps
[sig
] = 0;
386 UNBLOCK_SIGNAL (oset
);
390 #if defined (ARRAY_VARS)
391 restore_pipestatus_array (ps
);
393 last_command_exit_value
= old_exit_value
;
402 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
405 internal_warning ("trap_handler: signal %d: signal not trapped", sig
);
411 (trap_list
[sig
] == (char *)DEFAULT_SIG
) ||
412 (trap_list
[sig
] == (char *)IGNORE_SIG
))
413 programming_error (_("trap_handler: bad signal %d"), sig
);
417 #if defined (MUST_REINSTALL_SIGHANDLERS)
418 # if defined (JOB_CONTROL) && defined (SIGCHLD)
420 # endif /* JOB_CONTROL && SIGCHLD */
421 set_signal_handler (sig
, trap_handler
);
422 #endif /* MUST_REINSTALL_SIGHANDLERS */
425 pending_traps
[sig
]++;
427 trapped_signal_received
= sig
;
429 if (this_shell_builtin
&& (this_shell_builtin
== wait_builtin
))
431 wait_signal_received
= sig
;
432 if (interrupt_immediately
)
433 longjmp (wait_intr_buf
, 1);
436 #if defined (READLINE)
437 /* Set the event hook so readline will call it after the signal handlers
438 finish executing, so if this interrupted character input we can get
440 if (RL_ISSTATE (RL_STATE_SIGHANDLER
) && interrupt_immediately
== 0)
441 bashline_set_event_hook ();
444 if (interrupt_immediately
)
445 run_pending_traps ();
454 first_pending_trap ()
458 for (i
= 1; i
< NSIG
; i
++)
459 if (pending_traps
[i
])
465 any_signals_trapped ()
469 for (i
= 1; i
< NSIG
; i
++)
470 if (sigmodes
[i
] & SIG_TRAPPED
)
478 CHECK_ALRM
; /* set by the read builtin */
482 /* Convenience functions the rest of the shell can use */
484 check_signals_and_traps ()
488 run_pending_traps ();
491 #if defined (JOB_CONTROL) && defined (SIGCHLD)
493 #ifdef INCLUDE_UNUSED
494 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
496 set_sigchld_trap (command_string
)
497 char *command_string
;
499 set_signal (SIGCHLD
, command_string
);
503 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
504 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
505 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
506 reset the disposition to the default and not have the original signal
507 accidentally restored, undoing the user's command. */
509 maybe_set_sigchld_trap (command_string
)
510 char *command_string
;
512 if ((sigmodes
[SIGCHLD
] & SIG_TRAPPED
) == 0 && trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
513 set_signal (SIGCHLD
, command_string
);
516 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
517 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
518 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
520 set_impossible_sigchld_trap ()
522 restore_default_signal (SIGCHLD
);
523 change_signal (SIGCHLD
, (char *)IMPOSSIBLE_TRAP_HANDLER
);
524 sigmodes
[SIGCHLD
] &= ~SIG_TRAPPED
; /* maybe_set_sigchld_trap checks this */
527 /* Act as if we received SIGCHLD NCHILD times and increment
528 pending_traps[SIGCHLD] by that amount. This allows us to still run the
529 SIGCHLD trap once for each exited child. */
531 queue_sigchld_trap (nchild
)
537 pending_traps
[SIGCHLD
] += nchild
;
538 trapped_signal_received
= SIGCHLD
;
541 #endif /* JOB_CONTROL && SIGCHLD */
544 set_debug_trap (command
)
547 set_signal (DEBUG_TRAP
, command
);
551 set_error_trap (command
)
554 set_signal (ERROR_TRAP
, command
);
558 set_return_trap (command
)
561 set_signal (RETURN_TRAP
, command
);
564 #ifdef INCLUDE_UNUSED
566 set_sigint_trap (command
)
569 set_signal (SIGINT
, command
);
573 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
574 things, like waiting for command substitution or executing commands
575 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
577 set_sigint_handler ()
579 if (sigmodes
[SIGINT
] & SIG_HARD_IGNORE
)
580 return ((SigHandler
*)SIG_IGN
);
582 else if (sigmodes
[SIGINT
] & SIG_IGNORED
)
583 return ((SigHandler
*)set_signal_handler (SIGINT
, SIG_IGN
)); /* XXX */
585 else if (sigmodes
[SIGINT
] & SIG_TRAPPED
)
586 return ((SigHandler
*)set_signal_handler (SIGINT
, trap_handler
));
588 /* The signal is not trapped, so set the handler to the shell's special
589 interrupt handler. */
590 else if (interactive
) /* XXX - was interactive_shell */
591 return (set_signal_handler (SIGINT
, sigint_sighandler
));
593 return (set_signal_handler (SIGINT
, termsig_sighandler
));
596 /* Return the correct handler for signal SIG according to the values in
599 trap_to_sighandler (sig
)
602 if (sigmodes
[sig
] & (SIG_IGNORED
|SIG_HARD_IGNORE
))
604 else if (sigmodes
[sig
] & SIG_TRAPPED
)
605 return (trap_handler
);
610 /* Set SIG to call STRING as a command. */
612 set_signal (sig
, string
)
618 if (SPECIAL_TRAP (sig
))
620 change_signal (sig
, savestring (string
));
621 if (sig
== EXIT_TRAP
&& interactive
== 0)
622 initialize_terminating_signals ();
626 /* A signal ignored on entry to the shell cannot be trapped or reset, but
627 no error is reported when attempting to do so. -- Posix.2 */
628 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
631 /* Make sure we have original_signals[sig] if the signal has not yet
633 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
635 /* If we aren't sure of the original value, check it. */
636 if (original_signals
[sig
] == IMPOSSIBLE_TRAP_HANDLER
)
638 if (original_signals
[sig
] == SIG_IGN
)
642 /* Only change the system signal handler if SIG_NO_TRAP is not set.
643 The trap command string is changed in either case. The shell signal
644 handlers for SIGINT and SIGCHLD run the user specified traps in an
645 environment in which it is safe to do so. */
646 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
648 BLOCK_SIGNAL (sig
, set
, oset
);
649 change_signal (sig
, savestring (string
));
650 set_signal_handler (sig
, trap_handler
);
651 UNBLOCK_SIGNAL (oset
);
654 change_signal (sig
, savestring (string
));
658 free_trap_command (sig
)
661 if ((sigmodes
[sig
] & SIG_TRAPPED
) && trap_list
[sig
] &&
662 (trap_list
[sig
] != (char *)IGNORE_SIG
) &&
663 (trap_list
[sig
] != (char *)DEFAULT_SIG
) &&
664 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
))
665 free (trap_list
[sig
]);
668 /* If SIG has a string assigned to it, get rid of it. Then give it
671 change_signal (sig
, value
)
675 if ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
676 free_trap_command (sig
);
677 trap_list
[sig
] = value
;
679 sigmodes
[sig
] |= SIG_TRAPPED
;
680 if (value
== (char *)IGNORE_SIG
)
681 sigmodes
[sig
] |= SIG_IGNORED
;
683 sigmodes
[sig
] &= ~SIG_IGNORED
;
684 if (sigmodes
[sig
] & SIG_INPROGRESS
)
685 sigmodes
[sig
] |= SIG_CHANGED
;
689 get_original_signal (sig
)
692 /* If we aren't sure the of the original value, then get it. */
693 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
698 get_all_original_signals ()
702 for (i
= 1; i
< NSIG
; i
++)
703 GET_ORIGINAL_SIGNAL (i
);
707 set_original_signal (sig
, handler
)
711 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
712 SETORIGSIG (sig
, handler
);
715 /* Restore the default action for SIG; i.e., the action the shell
716 would have taken before you used the trap command. This is called
717 from trap_builtin (), which takes care to restore the handlers for
718 the signals the shell treats specially. */
720 restore_default_signal (sig
)
723 if (SPECIAL_TRAP (sig
))
725 if ((sig
!= DEBUG_TRAP
&& sig
!= ERROR_TRAP
&& sig
!= RETURN_TRAP
) ||
726 (sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
727 free_trap_command (sig
);
728 trap_list
[sig
] = (char *)NULL
;
729 sigmodes
[sig
] &= ~SIG_TRAPPED
;
730 if (sigmodes
[sig
] & SIG_INPROGRESS
)
731 sigmodes
[sig
] |= SIG_CHANGED
;
735 GET_ORIGINAL_SIGNAL (sig
);
737 /* A signal ignored on entry to the shell cannot be trapped or reset, but
738 no error is reported when attempting to do so. Thanks Posix.2. */
739 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
742 /* If we aren't trapping this signal, don't bother doing anything else. */
743 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
746 /* Only change the signal handler for SIG if it allows it. */
747 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
748 set_signal_handler (sig
, original_signals
[sig
]);
750 /* Change the trap command in either case. */
751 change_signal (sig
, (char *)DEFAULT_SIG
);
753 /* Mark the signal as no longer trapped. */
754 sigmodes
[sig
] &= ~SIG_TRAPPED
;
757 /* Make this signal be ignored. */
762 if (SPECIAL_TRAP (sig
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
764 change_signal (sig
, (char *)IGNORE_SIG
);
768 GET_ORIGINAL_SIGNAL (sig
);
770 /* A signal ignored on entry to the shell cannot be trapped or reset.
771 No error is reported when the user attempts to do so. */
772 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
775 /* If already trapped and ignored, no change necessary. */
776 if (sigmodes
[sig
] & SIG_IGNORED
)
779 /* Only change the signal handler for SIG if it allows it. */
780 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
781 set_signal_handler (sig
, SIG_IGN
);
783 /* Change the trap command in either case. */
784 change_signal (sig
, (char *)IGNORE_SIG
);
787 /* Handle the calling of "trap 0". The only sticky situation is when
788 the command to be executed includes an "exit". This is why we have
789 to provide our own place for top_level to jump to. */
794 int code
, function_code
, retval
;
795 #if defined (ARRAY_VARS)
799 trap_saved_exit_value
= last_command_exit_value
;
800 #if defined (ARRAY_VARS)
801 ps
= save_pipestatus_array ();
805 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
806 currently running in the trap handler (call to exit in the list of
807 commands given to trap 0). */
808 if ((sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
) &&
809 (sigmodes
[EXIT_TRAP
] & (SIG_IGNORED
|SIG_INPROGRESS
)) == 0)
811 trap_command
= savestring (trap_list
[EXIT_TRAP
]);
812 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
813 sigmodes
[EXIT_TRAP
] |= SIG_INPROGRESS
;
815 retval
= trap_saved_exit_value
;
818 code
= setjmp_nosigs (top_level
);
820 /* If we're in a function, make sure return longjmps come here, too. */
821 if (return_catch_flag
)
822 function_code
= setjmp_nosigs (return_catch
);
824 if (code
== 0 && function_code
== 0)
827 parse_and_execute (trap_command
, "exit trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
829 else if (code
== ERREXIT
)
830 retval
= last_command_exit_value
;
831 else if (code
== EXITPROG
)
832 retval
= last_command_exit_value
;
833 else if (function_code
!= 0)
834 retval
= return_catch_value
;
836 retval
= trap_saved_exit_value
;
842 #if defined (ARRAY_VARS)
843 restore_pipestatus_array (ps
);
845 return (trap_saved_exit_value
);
849 run_trap_cleanup (sig
)
852 sigmodes
[sig
] &= ~(SIG_INPROGRESS
|SIG_CHANGED
);
855 /* Run a trap command for SIG. SIG is one of the signals the shell treats
856 specially. Returns the exit status of the executed trap command list. */
858 _run_trap_internal (sig
, tag
)
862 char *trap_command
, *old_trap
;
863 int trap_exit_value
, *token_state
;
864 volatile int save_return_catch_flag
, function_code
;
866 procenv_t save_return_catch
;
867 WORD_LIST
*save_subst_varlist
;
868 #if defined (ARRAY_VARS)
872 trap_exit_value
= function_code
= 0;
873 /* Run the trap only if SIG is trapped and not ignored, and we are not
874 currently executing in the trap handler. */
875 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0) &&
876 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
) &&
877 ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0))
879 old_trap
= trap_list
[sig
];
880 sigmodes
[sig
] |= SIG_INPROGRESS
;
881 sigmodes
[sig
] &= ~SIG_CHANGED
; /* just to be sure */
882 trap_command
= savestring (old_trap
);
884 running_trap
= sig
+ 1;
885 trap_saved_exit_value
= last_command_exit_value
;
886 #if defined (ARRAY_VARS)
887 ps
= save_pipestatus_array ();
890 token_state
= save_token_state ();
891 save_subst_varlist
= subst_assign_varlist
;
892 subst_assign_varlist
= 0;
894 /* If we're in a function, make sure return longjmps come here, too. */
895 save_return_catch_flag
= return_catch_flag
;
896 if (return_catch_flag
)
898 COPY_PROCENV (return_catch
, save_return_catch
);
899 function_code
= setjmp_nosigs (return_catch
);
902 flags
= SEVAL_NONINT
|SEVAL_NOHIST
;
903 if (sig
!= DEBUG_TRAP
&& sig
!= RETURN_TRAP
&& sig
!= ERROR_TRAP
)
904 flags
|= SEVAL_RESETLINE
;
905 if (function_code
== 0)
906 parse_and_execute (trap_command
, tag
, flags
);
908 restore_token_state (token_state
);
911 subst_assign_varlist
= save_subst_varlist
;
913 trap_exit_value
= last_command_exit_value
;
914 last_command_exit_value
= trap_saved_exit_value
;
915 #if defined (ARRAY_VARS)
916 restore_pipestatus_array (ps
);
920 sigmodes
[sig
] &= ~SIG_INPROGRESS
;
922 if (sigmodes
[sig
] & SIG_CHANGED
)
925 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
926 the places where they can be changed using unwind-protects. For
927 example, look at execute_cmd.c:execute_function(). */
928 if (SPECIAL_TRAP (sig
) == 0)
931 sigmodes
[sig
] &= ~SIG_CHANGED
;
934 if (save_return_catch_flag
)
936 return_catch_flag
= save_return_catch_flag
;
937 return_catch_value
= trap_exit_value
;
938 COPY_PROCENV (save_return_catch
, return_catch
);
940 longjmp (return_catch
, 1);
944 return trap_exit_value
;
954 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
956 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[DEBUG_TRAP
] & SIG_IGNORED
) == 0) && ((sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
) == 0))
958 #if defined (JOB_CONTROL)
959 save_pgrp
= pipeline_pgrp
;
962 # if defined (PGRP_PIPE)
963 save_pgrp_pipe (save_pipe
, 1);
965 stop_making_children ();
968 trap_exit_value
= _run_trap_internal (DEBUG_TRAP
, "debug trap");
970 #if defined (JOB_CONTROL)
971 pipeline_pgrp
= save_pgrp
;
972 restore_pipeline (1);
973 # if defined (PGRP_PIPE)
975 restore_pgrp_pipe (save_pipe
);
977 if (pipeline_pgrp
> 0)
978 give_terminal_to (pipeline_pgrp
, 1);
979 notify_and_cleanup ();
982 #if defined (DEBUGGER)
983 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
984 a function or sourced script, we force a `return'. */
985 if (debugging_mode
&& trap_exit_value
== 2 && return_catch_flag
)
987 return_catch_value
= trap_exit_value
;
988 longjmp (return_catch
, 1);
992 return trap_exit_value
;
998 if ((sigmodes
[ERROR_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[ERROR_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[ERROR_TRAP
] & SIG_INPROGRESS
) == 0)
999 _run_trap_internal (ERROR_TRAP
, "error trap");
1008 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && (sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
))
1012 if ((sigmodes
[RETURN_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[RETURN_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[RETURN_TRAP
] & SIG_INPROGRESS
) == 0)
1014 old_exit_value
= last_command_exit_value
;
1015 _run_trap_internal (RETURN_TRAP
, "return trap");
1016 last_command_exit_value
= old_exit_value
;
1020 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1021 declared here to localize the trap functions. */
1023 run_interrupt_trap ()
1025 _run_trap_internal (SIGINT
, "interrupt trap");
1028 /* Free all the allocated strings in the list of traps and reset the trap
1029 values to the default. Intended to be called from subshells that want
1030 to complete work done by reset_signal_handlers upon execution of a
1031 subsequent `trap' command that changes a signal's disposition. We need
1032 to make sure that we duplicate the behavior of
1033 reset_or_restore_signal_handlers and not change the disposition of signals
1034 that are set to be ignored. */
1036 free_trap_strings ()
1040 for (i
= 0; i
< BASH_NSIG
; i
++)
1042 if (trap_list
[i
] != (char *)IGNORE_SIG
)
1043 free_trap_string (i
);
1045 trap_list
[DEBUG_TRAP
] = trap_list
[EXIT_TRAP
] = trap_list
[ERROR_TRAP
] = trap_list
[RETURN_TRAP
] = (char *)NULL
;
1048 /* Free a trap command string associated with SIG without changing signal
1049 disposition. Intended to be called from free_trap_strings() */
1051 free_trap_string (sig
)
1054 change_signal (sig
, (char *)DEFAULT_SIG
);
1055 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1058 /* Reset the handler for SIG to the original value but leave the trap string
1064 set_signal_handler (sig
, original_signals
[sig
]);
1065 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1068 /* Set the handler signal SIG to the original and free any trap
1069 command associated with it. */
1071 restore_signal (sig
)
1074 set_signal_handler (sig
, original_signals
[sig
]);
1075 change_signal (sig
, (char *)DEFAULT_SIG
);
1076 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1080 reset_or_restore_signal_handlers (reset
)
1081 sh_resetsig_func_t
*reset
;
1085 /* Take care of the exit trap first */
1086 if (sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
)
1088 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
1089 if (reset
!= reset_signal
)
1091 free_trap_command (EXIT_TRAP
);
1092 trap_list
[EXIT_TRAP
] = (char *)NULL
;
1096 for (i
= 1; i
< NSIG
; i
++)
1098 if (sigmodes
[i
] & SIG_TRAPPED
)
1100 if (trap_list
[i
] == (char *)IGNORE_SIG
)
1101 set_signal_handler (i
, SIG_IGN
);
1105 else if (sigmodes
[i
] & SIG_SPECIAL
)
1109 /* Command substitution and other child processes don't inherit the
1110 debug, error, or return traps. If we're in the debugger, and the
1111 `functrace' or `errtrace' options have been set, then let command
1112 substitutions inherit them. Let command substitution inherit the
1113 RETURN trap if we're in the debugger and tracing functions. */
1114 if (function_trace_mode
== 0)
1116 sigmodes
[DEBUG_TRAP
] &= ~SIG_TRAPPED
;
1117 sigmodes
[RETURN_TRAP
] &= ~SIG_TRAPPED
;
1119 if (error_trace_mode
== 0)
1120 sigmodes
[ERROR_TRAP
] &= ~SIG_TRAPPED
;
1123 /* Reset trapped signals to their original values, but don't free the
1124 trap strings. Called by the command substitution code and other places
1125 that create a "subshell environment". */
1127 reset_signal_handlers ()
1129 reset_or_restore_signal_handlers (reset_signal
);
1132 /* Reset all trapped signals to their original values. Signals set to be
1133 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1134 are. Called by child processes after they are forked. */
1136 restore_original_signals ()
1138 reset_or_restore_signal_handlers (restore_signal
);
1141 /* If a trap handler exists for signal SIG, then call it; otherwise just
1142 return failure. Returns 1 if it called the trap handler. */
1144 maybe_call_trap_handler (sig
)
1147 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
1148 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
1153 run_interrupt_trap ();
1175 signal_is_trapped (sig
)
1178 return (sigmodes
[sig
] & SIG_TRAPPED
);
1182 signal_is_pending (sig
)
1185 return (pending_traps
[sig
]);
1189 signal_is_special (sig
)
1192 return (sigmodes
[sig
] & SIG_SPECIAL
);
1196 signal_is_ignored (sig
)
1199 return (sigmodes
[sig
] & SIG_IGNORED
);
1203 signal_is_hard_ignored (sig
)
1206 return (sigmodes
[sig
] & SIG_HARD_IGNORE
);
1210 set_signal_ignored (sig
)
1213 sigmodes
[sig
] |= SIG_HARD_IGNORE
;
1214 original_signals
[sig
] = SIG_IGN
;
1218 signal_in_progress (sig
)
1221 return (sigmodes
[sig
] & SIG_INPROGRESS
);