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-2010 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 #define GETORIGSIG(sig) \
118 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
119 set_signal_handler (sig, original_signals[sig]); \
120 if (original_signals[sig] == SIG_IGN) \
121 sigmodes[sig] |= SIG_HARD_IGNORE; \
124 #define SETORIGSIG(sig,handler) \
126 original_signals[sig] = handler; \
127 if (original_signals[sig] == SIG_IGN) \
128 sigmodes[sig] |= SIG_HARD_IGNORE; \
131 #define GET_ORIGINAL_SIGNAL(sig) \
132 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
140 initialize_signames();
142 trap_list
[EXIT_TRAP
] = trap_list
[DEBUG_TRAP
] = trap_list
[ERROR_TRAP
] = trap_list
[RETURN_TRAP
] = (char *)NULL
;
143 sigmodes
[EXIT_TRAP
] = sigmodes
[DEBUG_TRAP
] = sigmodes
[ERROR_TRAP
] = sigmodes
[RETURN_TRAP
] = SIG_INHERITED
;
144 original_signals
[EXIT_TRAP
] = IMPOSSIBLE_TRAP_HANDLER
;
146 for (i
= 1; i
< NSIG
; i
++)
148 pending_traps
[i
] = 0;
149 trap_list
[i
] = (char *)DEFAULT_SIG
;
150 sigmodes
[i
] = SIG_INHERITED
; /* XXX - only set, not used */
151 original_signals
[i
] = IMPOSSIBLE_TRAP_HANDLER
;
154 /* Show which signals are treated specially by the shell. */
155 #if defined (SIGCHLD)
156 GETORIGSIG (SIGCHLD
);
157 sigmodes
[SIGCHLD
] |= (SIG_SPECIAL
| SIG_NO_TRAP
);
161 sigmodes
[SIGINT
] |= SIG_SPECIAL
;
163 #if defined (__BEOS__)
164 /* BeOS sets SIGINT to SIG_IGN! */
165 original_signals
[SIGINT
] = SIG_DFL
;
166 sigmodes
[SIGINT
] &= ~SIG_HARD_IGNORE
;
169 GETORIGSIG (SIGQUIT
);
170 sigmodes
[SIGQUIT
] |= SIG_SPECIAL
;
174 GETORIGSIG (SIGTERM
);
175 sigmodes
[SIGTERM
] |= SIG_SPECIAL
;
179 #ifdef INCLUDE_UNUSED
180 /* Return a printable representation of the trap handler for SIG. */
182 trap_handler_string (sig
)
185 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
186 return "DEFAULT_SIG";
187 else if (trap_list
[sig
] == (char *)IGNORE_SIG
)
189 else if (trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
190 return "IMPOSSIBLE_TRAP_HANDLER";
191 else if (trap_list
[sig
])
192 return trap_list
[sig
];
198 /* Return the print name of this signal. */
205 /* on cygwin32, signal_names[sig] could be null */
206 ret
= (sig
>= BASH_NSIG
|| sig
< 0 || signal_names
[sig
] == NULL
)
207 ? _("invalid signal number")
213 /* Turn a string into a signal number, or a number into
214 a signal number. If STRING is "2", "SIGINT", or "INT",
215 then (int)2 is returned. Return NO_SIG if STRING doesn't
216 contain a valid signal descriptor. */
218 decode_signal (string
, flags
)
225 if (legal_number (string
, &sig
))
226 return ((sig
>= 0 && sig
< NSIG
) ? (int)sig
: NO_SIG
);
228 /* A leading `SIG' may be omitted. */
229 for (sig
= 0; sig
< BASH_NSIG
; sig
++)
231 name
= signal_names
[sig
];
232 if (name
== 0 || name
[0] == '\0')
235 /* Check name without the SIG prefix first case sensitivly or
236 insensitively depending on whether flags includes DSIG_NOCASE */
237 if (STREQN (name
, "SIG", 3))
241 if ((flags
& DSIG_NOCASE
) && strcasecmp (string
, name
) == 0)
243 else if ((flags
& DSIG_NOCASE
) == 0 && strcmp (string
, name
) == 0)
245 /* If we can't use the `SIG' prefix to match, punt on this
247 else if ((flags
& DSIG_SIGPREFIX
) == 0)
251 /* Check name with SIG prefix case sensitively or insensitively
252 depending on whether flags includes DSIG_NOCASE */
253 name
= signal_names
[sig
];
254 if ((flags
& DSIG_NOCASE
) && strcasecmp (string
, name
) == 0)
256 else if ((flags
& DSIG_NOCASE
) == 0 && strcmp (string
, name
) == 0)
263 /* Non-zero when we catch a trapped signal. */
264 static int catch_flag
;
270 int old_exit_value
, *token_state
;
271 WORD_LIST
*save_subst_varlist
;
272 #if defined (ARRAY_VARS)
276 if (catch_flag
== 0) /* simple optimization */
281 /* Preserve $? when running trap. */
282 old_exit_value
= last_command_exit_value
;
283 #if defined (ARRAY_VARS)
284 ps
= save_pipestatus_array ();
287 for (sig
= 1; sig
< NSIG
; sig
++)
289 /* XXX this could be made into a counter by using
290 while (pending_traps[sig]--) instead of the if statement. */
291 if (pending_traps
[sig
])
293 #if defined (HAVE_POSIX_SIGNALS)
299 sigaddset (&set
, sig
);
300 sigprocmask (SIG_BLOCK
, &set
, &oset
);
302 # if defined (HAVE_BSD_SIGNALS)
303 int oldmask
= sigblock (sigmask (sig
));
305 #endif /* HAVE_POSIX_SIGNALS */
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 run_sigchld_trap (pending_traps
[sig
]); /* use as counter */
320 else if (trap_list
[sig
] == (char *)DEFAULT_SIG
||
321 trap_list
[sig
] == (char *)IGNORE_SIG
||
322 trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
324 /* This is possible due to a race condition. Say a bash
325 process has SIGTERM trapped. A subshell is spawned
326 using { list; } & and the parent does something and kills
327 the subshell with SIGTERM. It's possible for the subshell
328 to set pending_traps[SIGTERM] to 1 before the code in
329 execute_cmd.c eventually calls restore_original_signals
330 to reset the SIGTERM signal handler in the subshell. The
331 next time run_pending_traps is called, pending_traps[SIGTERM]
332 will be 1, but the trap handler in trap_list[SIGTERM] will
333 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
334 Unless we catch this, the subshell will dump core when
335 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
337 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
338 sig
, trap_list
[sig
]);
339 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
341 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig
, signal_name (sig
));
342 kill (getpid (), sig
);
347 token_state
= save_token_state ();
348 save_subst_varlist
= subst_assign_varlist
;
349 subst_assign_varlist
= 0;
351 parse_and_execute (savestring (trap_list
[sig
]), "trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
352 restore_token_state (token_state
);
355 subst_assign_varlist
= save_subst_varlist
;
358 pending_traps
[sig
] = 0;
360 #if defined (HAVE_POSIX_SIGNALS)
361 sigprocmask (SIG_SETMASK
, &oset
, (sigset_t
*)NULL
);
363 # if defined (HAVE_BSD_SIGNALS)
364 sigsetmask (oldmask
);
366 #endif /* POSIX_VERSION */
370 #if defined (ARRAY_VARS)
371 restore_pipestatus_array (ps
);
373 last_command_exit_value
= old_exit_value
;
382 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
385 internal_warning ("trap_handler: signal %d: signal not trapped", sig
);
391 (trap_list
[sig
] == (char *)DEFAULT_SIG
) ||
392 (trap_list
[sig
] == (char *)IGNORE_SIG
))
393 programming_error (_("trap_handler: bad signal %d"), sig
);
397 #if defined (MUST_REINSTALL_SIGHANDLERS)
398 # if defined (JOB_CONTROL) && defined (SIGCHLD)
400 # endif /* JOB_CONTROL && SIGCHLD */
401 set_signal_handler (sig
, trap_handler
);
402 #endif /* MUST_REINSTALL_SIGHANDLERS */
405 pending_traps
[sig
]++;
407 if (interrupt_immediately
&& this_shell_builtin
&& (this_shell_builtin
== wait_builtin
))
409 wait_signal_received
= sig
;
410 longjmp (wait_intr_buf
, 1);
413 if (interrupt_immediately
)
414 run_pending_traps ();
422 #if defined (JOB_CONTROL) && defined (SIGCHLD)
424 #ifdef INCLUDE_UNUSED
425 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
427 set_sigchld_trap (command_string
)
428 char *command_string
;
430 set_signal (SIGCHLD
, command_string
);
434 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
435 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
436 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
437 reset the disposition to the default and not have the original signal
438 accidentally restored, undoing the user's command. */
440 maybe_set_sigchld_trap (command_string
)
441 char *command_string
;
443 if ((sigmodes
[SIGCHLD
] & SIG_TRAPPED
) == 0 && trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
444 set_signal (SIGCHLD
, command_string
);
447 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
448 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
449 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
451 set_impossible_sigchld_trap ()
453 restore_default_signal (SIGCHLD
);
454 change_signal (SIGCHLD
, (char *)IMPOSSIBLE_TRAP_HANDLER
);
455 sigmodes
[SIGCHLD
] &= ~SIG_TRAPPED
; /* maybe_set_sigchld_trap checks this */
457 #endif /* JOB_CONTROL && SIGCHLD */
460 set_debug_trap (command
)
463 set_signal (DEBUG_TRAP
, command
);
467 set_error_trap (command
)
470 set_signal (ERROR_TRAP
, command
);
474 set_return_trap (command
)
477 set_signal (RETURN_TRAP
, command
);
480 #ifdef INCLUDE_UNUSED
482 set_sigint_trap (command
)
485 set_signal (SIGINT
, command
);
489 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
490 things, like waiting for command substitution or executing commands
491 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
493 set_sigint_handler ()
495 if (sigmodes
[SIGINT
] & SIG_HARD_IGNORE
)
496 return ((SigHandler
*)SIG_IGN
);
498 else if (sigmodes
[SIGINT
] & SIG_IGNORED
)
499 return ((SigHandler
*)set_signal_handler (SIGINT
, SIG_IGN
)); /* XXX */
501 else if (sigmodes
[SIGINT
] & SIG_TRAPPED
)
502 return ((SigHandler
*)set_signal_handler (SIGINT
, trap_handler
));
504 /* The signal is not trapped, so set the handler to the shell's special
505 interrupt handler. */
506 else if (interactive
) /* XXX - was interactive_shell */
507 return (set_signal_handler (SIGINT
, sigint_sighandler
));
509 return (set_signal_handler (SIGINT
, termsig_sighandler
));
512 /* Return the correct handler for signal SIG according to the values in
515 trap_to_sighandler (sig
)
518 if (sigmodes
[sig
] & (SIG_IGNORED
|SIG_HARD_IGNORE
))
520 else if (sigmodes
[sig
] & SIG_TRAPPED
)
521 return (trap_handler
);
526 /* Set SIG to call STRING as a command. */
528 set_signal (sig
, string
)
532 if (SPECIAL_TRAP (sig
))
534 change_signal (sig
, savestring (string
));
535 if (sig
== EXIT_TRAP
&& interactive
== 0)
536 initialize_terminating_signals ();
540 /* A signal ignored on entry to the shell cannot be trapped or reset, but
541 no error is reported when attempting to do so. -- Posix.2 */
542 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
545 /* Make sure we have original_signals[sig] if the signal has not yet
547 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
549 /* If we aren't sure of the original value, check it. */
550 if (original_signals
[sig
] == IMPOSSIBLE_TRAP_HANDLER
)
552 if (original_signals
[sig
] == SIG_IGN
)
556 /* Only change the system signal handler if SIG_NO_TRAP is not set.
557 The trap command string is changed in either case. The shell signal
558 handlers for SIGINT and SIGCHLD run the user specified traps in an
559 environment in which it is safe to do so. */
560 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
562 set_signal_handler (sig
, SIG_IGN
);
563 change_signal (sig
, savestring (string
));
564 set_signal_handler (sig
, trap_handler
);
567 change_signal (sig
, savestring (string
));
571 free_trap_command (sig
)
574 if ((sigmodes
[sig
] & SIG_TRAPPED
) && trap_list
[sig
] &&
575 (trap_list
[sig
] != (char *)IGNORE_SIG
) &&
576 (trap_list
[sig
] != (char *)DEFAULT_SIG
) &&
577 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
))
578 free (trap_list
[sig
]);
581 /* If SIG has a string assigned to it, get rid of it. Then give it
584 change_signal (sig
, value
)
588 if ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
589 free_trap_command (sig
);
590 trap_list
[sig
] = value
;
592 sigmodes
[sig
] |= SIG_TRAPPED
;
593 if (value
== (char *)IGNORE_SIG
)
594 sigmodes
[sig
] |= SIG_IGNORED
;
596 sigmodes
[sig
] &= ~SIG_IGNORED
;
597 if (sigmodes
[sig
] & SIG_INPROGRESS
)
598 sigmodes
[sig
] |= SIG_CHANGED
;
602 get_original_signal (sig
)
605 /* If we aren't sure the of the original value, then get it. */
606 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
611 get_all_original_signals ()
615 for (i
= 1; i
< NSIG
; i
++)
616 GET_ORIGINAL_SIGNAL (i
);
620 set_original_signal (sig
, handler
)
624 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
625 SETORIGSIG (sig
, handler
);
628 /* Restore the default action for SIG; i.e., the action the shell
629 would have taken before you used the trap command. This is called
630 from trap_builtin (), which takes care to restore the handlers for
631 the signals the shell treats specially. */
633 restore_default_signal (sig
)
636 if (SPECIAL_TRAP (sig
))
638 if ((sig
!= DEBUG_TRAP
&& sig
!= ERROR_TRAP
&& sig
!= RETURN_TRAP
) ||
639 (sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
640 free_trap_command (sig
);
641 trap_list
[sig
] = (char *)NULL
;
642 sigmodes
[sig
] &= ~SIG_TRAPPED
;
643 if (sigmodes
[sig
] & SIG_INPROGRESS
)
644 sigmodes
[sig
] |= SIG_CHANGED
;
648 GET_ORIGINAL_SIGNAL (sig
);
650 /* A signal ignored on entry to the shell cannot be trapped or reset, but
651 no error is reported when attempting to do so. Thanks Posix.2. */
652 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
655 /* If we aren't trapping this signal, don't bother doing anything else. */
656 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
659 /* Only change the signal handler for SIG if it allows it. */
660 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
661 set_signal_handler (sig
, original_signals
[sig
]);
663 /* Change the trap command in either case. */
664 change_signal (sig
, (char *)DEFAULT_SIG
);
666 /* Mark the signal as no longer trapped. */
667 sigmodes
[sig
] &= ~SIG_TRAPPED
;
670 /* Make this signal be ignored. */
675 if (SPECIAL_TRAP (sig
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
677 change_signal (sig
, (char *)IGNORE_SIG
);
681 GET_ORIGINAL_SIGNAL (sig
);
683 /* A signal ignored on entry to the shell cannot be trapped or reset.
684 No error is reported when the user attempts to do so. */
685 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
688 /* If already trapped and ignored, no change necessary. */
689 if (sigmodes
[sig
] & SIG_IGNORED
)
692 /* Only change the signal handler for SIG if it allows it. */
693 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
694 set_signal_handler (sig
, SIG_IGN
);
696 /* Change the trap command in either case. */
697 change_signal (sig
, (char *)IGNORE_SIG
);
700 /* Handle the calling of "trap 0". The only sticky situation is when
701 the command to be executed includes an "exit". This is why we have
702 to provide our own place for top_level to jump to. */
707 int code
, function_code
, retval
;
708 #if defined (ARRAY_VARS)
712 trap_saved_exit_value
= last_command_exit_value
;
713 #if defined (ARRAY_VARS)
714 ps
= save_pipestatus_array ();
718 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
719 currently running in the trap handler (call to exit in the list of
720 commands given to trap 0). */
721 if ((sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
) &&
722 (sigmodes
[EXIT_TRAP
] & (SIG_IGNORED
|SIG_INPROGRESS
)) == 0)
724 trap_command
= savestring (trap_list
[EXIT_TRAP
]);
725 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
726 sigmodes
[EXIT_TRAP
] |= SIG_INPROGRESS
;
728 retval
= trap_saved_exit_value
;
731 code
= setjmp (top_level
);
733 /* If we're in a function, make sure return longjmps come here, too. */
734 if (return_catch_flag
)
735 function_code
= setjmp (return_catch
);
737 if (code
== 0 && function_code
== 0)
740 parse_and_execute (trap_command
, "exit trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
742 else if (code
== ERREXIT
)
743 retval
= last_command_exit_value
;
744 else if (code
== EXITPROG
)
745 retval
= last_command_exit_value
;
746 else if (function_code
!= 0)
747 retval
= return_catch_value
;
749 retval
= trap_saved_exit_value
;
755 #if defined (ARRAY_VARS)
756 restore_pipestatus_array (ps
);
758 return (trap_saved_exit_value
);
762 run_trap_cleanup (sig
)
765 sigmodes
[sig
] &= ~(SIG_INPROGRESS
|SIG_CHANGED
);
768 /* Run a trap command for SIG. SIG is one of the signals the shell treats
769 specially. Returns the exit status of the executed trap command list. */
771 _run_trap_internal (sig
, tag
)
775 char *trap_command
, *old_trap
;
776 int trap_exit_value
, *token_state
;
777 int save_return_catch_flag
, function_code
, flags
;
778 procenv_t save_return_catch
;
779 WORD_LIST
*save_subst_varlist
;
780 #if defined (ARRAY_VARS)
784 trap_exit_value
= function_code
= 0;
785 /* Run the trap only if SIG is trapped and not ignored, and we are not
786 currently executing in the trap handler. */
787 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0) &&
788 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
) &&
789 ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0))
791 old_trap
= trap_list
[sig
];
792 sigmodes
[sig
] |= SIG_INPROGRESS
;
793 sigmodes
[sig
] &= ~SIG_CHANGED
; /* just to be sure */
794 trap_command
= savestring (old_trap
);
796 running_trap
= sig
+ 1;
797 trap_saved_exit_value
= last_command_exit_value
;
798 #if defined (ARRAY_VARS)
799 ps
= save_pipestatus_array ();
802 token_state
= save_token_state ();
803 save_subst_varlist
= subst_assign_varlist
;
804 subst_assign_varlist
= 0;
806 /* If we're in a function, make sure return longjmps come here, too. */
807 save_return_catch_flag
= return_catch_flag
;
808 if (return_catch_flag
)
810 COPY_PROCENV (return_catch
, save_return_catch
);
811 function_code
= setjmp (return_catch
);
814 flags
= SEVAL_NONINT
|SEVAL_NOHIST
;
815 if (sig
!= DEBUG_TRAP
&& sig
!= RETURN_TRAP
&& sig
!= ERROR_TRAP
)
816 flags
|= SEVAL_RESETLINE
;
817 if (function_code
== 0)
818 parse_and_execute (trap_command
, tag
, flags
);
820 restore_token_state (token_state
);
823 subst_assign_varlist
= save_subst_varlist
;
825 trap_exit_value
= last_command_exit_value
;
826 last_command_exit_value
= trap_saved_exit_value
;
827 #if defined (ARRAY_VARS)
828 restore_pipestatus_array (ps
);
832 sigmodes
[sig
] &= ~SIG_INPROGRESS
;
834 if (sigmodes
[sig
] & SIG_CHANGED
)
837 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
838 the places where they can be changed using unwind-protects. For
839 example, look at execute_cmd.c:execute_function(). */
840 if (SPECIAL_TRAP (sig
) == 0)
843 sigmodes
[sig
] &= ~SIG_CHANGED
;
846 if (save_return_catch_flag
)
848 return_catch_flag
= save_return_catch_flag
;
849 return_catch_value
= trap_exit_value
;
850 COPY_PROCENV (save_return_catch
, return_catch
);
852 longjmp (return_catch
, 1);
856 return trap_exit_value
;
866 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
868 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[DEBUG_TRAP
] & SIG_IGNORED
) == 0) && ((sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
) == 0))
870 #if defined (JOB_CONTROL)
871 save_pgrp
= pipeline_pgrp
;
874 # if defined (PGRP_PIPE)
875 save_pgrp_pipe (save_pipe
, 1);
877 stop_making_children ();
880 trap_exit_value
= _run_trap_internal (DEBUG_TRAP
, "debug trap");
882 #if defined (JOB_CONTROL)
883 pipeline_pgrp
= save_pgrp
;
884 restore_pipeline (1);
885 # if defined (PGRP_PIPE)
887 restore_pgrp_pipe (save_pipe
);
889 if (pipeline_pgrp
> 0)
890 give_terminal_to (pipeline_pgrp
, 1);
891 notify_and_cleanup ();
894 #if defined (DEBUGGER)
895 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
896 a function or sourced script, we force a `return'. */
897 if (debugging_mode
&& trap_exit_value
== 2 && return_catch_flag
)
899 return_catch_value
= trap_exit_value
;
900 longjmp (return_catch
, 1);
904 return trap_exit_value
;
910 if ((sigmodes
[ERROR_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[ERROR_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[ERROR_TRAP
] & SIG_INPROGRESS
) == 0)
911 _run_trap_internal (ERROR_TRAP
, "error trap");
920 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && (sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
))
924 if ((sigmodes
[RETURN_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[RETURN_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[RETURN_TRAP
] & SIG_INPROGRESS
) == 0)
926 old_exit_value
= last_command_exit_value
;
927 _run_trap_internal (RETURN_TRAP
, "return trap");
928 last_command_exit_value
= old_exit_value
;
932 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
933 declared here to localize the trap functions. */
935 run_interrupt_trap ()
937 _run_trap_internal (SIGINT
, "interrupt trap");
940 /* Free all the allocated strings in the list of traps and reset the trap
941 values to the default. Intended to be called from subshells that want
942 to complete work done by reset_signal_handlers upon execution of a
943 subsequent `trap' command that changes a signal's disposition. */
949 for (i
= 0; i
< BASH_NSIG
; i
++)
950 free_trap_string (i
);
951 trap_list
[DEBUG_TRAP
] = trap_list
[EXIT_TRAP
] = trap_list
[ERROR_TRAP
] = trap_list
[RETURN_TRAP
] = (char *)NULL
;
954 /* Free a trap command string associated with SIG without changing signal
955 disposition. Intended to be called from free_trap_strings() */
957 free_trap_string (sig
)
960 change_signal (sig
, (char *)DEFAULT_SIG
);
961 sigmodes
[sig
] &= ~SIG_TRAPPED
;
964 /* Reset the handler for SIG to the original value but leave the trap string
970 set_signal_handler (sig
, original_signals
[sig
]);
971 sigmodes
[sig
] &= ~SIG_TRAPPED
;
974 /* Set the handler signal SIG to the original and free any trap
975 command associated with it. */
980 set_signal_handler (sig
, original_signals
[sig
]);
981 change_signal (sig
, (char *)DEFAULT_SIG
);
982 sigmodes
[sig
] &= ~SIG_TRAPPED
;
986 reset_or_restore_signal_handlers (reset
)
987 sh_resetsig_func_t
*reset
;
991 /* Take care of the exit trap first */
992 if (sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
)
994 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
995 if (reset
!= reset_signal
)
997 free_trap_command (EXIT_TRAP
);
998 trap_list
[EXIT_TRAP
] = (char *)NULL
;
1002 for (i
= 1; i
< NSIG
; i
++)
1004 if (sigmodes
[i
] & SIG_TRAPPED
)
1006 if (trap_list
[i
] == (char *)IGNORE_SIG
)
1007 set_signal_handler (i
, SIG_IGN
);
1011 else if (sigmodes
[i
] & SIG_SPECIAL
)
1015 /* Command substitution and other child processes don't inherit the
1016 debug, error, or return traps. If we're in the debugger, and the
1017 `functrace' or `errtrace' options have been set, then let command
1018 substitutions inherit them. Let command substitution inherit the
1019 RETURN trap if we're in the debugger and tracing functions. */
1020 if (function_trace_mode
== 0)
1022 sigmodes
[DEBUG_TRAP
] &= ~SIG_TRAPPED
;
1023 sigmodes
[RETURN_TRAP
] &= ~SIG_TRAPPED
;
1025 if (error_trace_mode
== 0)
1026 sigmodes
[ERROR_TRAP
] &= ~SIG_TRAPPED
;
1029 /* Reset trapped signals to their original values, but don't free the
1030 trap strings. Called by the command substitution code and other places
1031 that create a "subshell environment". */
1033 reset_signal_handlers ()
1035 reset_or_restore_signal_handlers (reset_signal
);
1038 /* Reset all trapped signals to their original values. Signals set to be
1039 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1040 are. Called by child processes after they are forked. */
1042 restore_original_signals ()
1044 reset_or_restore_signal_handlers (restore_signal
);
1047 /* If a trap handler exists for signal SIG, then call it; otherwise just
1050 maybe_call_trap_handler (sig
)
1053 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
1054 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
1059 run_interrupt_trap ();
1081 signal_is_trapped (sig
)
1084 return (sigmodes
[sig
] & SIG_TRAPPED
);
1088 signal_is_special (sig
)
1091 return (sigmodes
[sig
] & SIG_SPECIAL
);
1095 signal_is_ignored (sig
)
1098 return (sigmodes
[sig
] & SIG_IGNORED
);
1102 signal_is_hard_ignored (sig
)
1105 return (sigmodes
[sig
] & SIG_HARD_IGNORE
);
1109 set_signal_ignored (sig
)
1112 sigmodes
[sig
] |= SIG_HARD_IGNORE
;
1113 original_signals
[sig
] = SIG_IGN
;
1117 signal_in_progress (sig
)
1120 return (sigmodes
[sig
] & SIG_INPROGRESS
);