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-2018 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"
41 #include "execute_cmd.h"
44 #include "input.h" /* for save_token_state, restore_token_state */
48 #include "builtins/common.h"
49 #include "builtins/builtext.h"
51 #if defined (READLINE)
52 # include <readline/readline.h>
53 # include "bashline.h"
60 /* Flags which describe the current handling state of a signal. */
61 #define SIG_INHERITED 0x0 /* Value inherited from parent. */
62 #define SIG_TRAPPED 0x1 /* Currently trapped. */
63 #define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
64 #define SIG_SPECIAL 0x4 /* Treat this signal specially. */
65 #define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
66 #define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
67 #define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
68 #define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
70 #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
72 /* An array of such flags, one for each signal, describing what the
73 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
75 static int sigmodes
[BASH_NSIG
];
77 static void free_trap_command (int);
78 static void change_signal (int, char *);
80 static int _run_trap_internal (int, char *);
82 static void free_trap_string (int);
83 static void reset_signal (int);
84 static void restore_signal (int);
85 static void reset_or_restore_signal_handlers (sh_resetsig_func_t
*);
87 static void trap_if_untrapped (int, char *);
89 /* Variables used here but defined in other files. */
90 extern procenv_t alrmbuf
;
92 extern volatile int from_return_trap
;
94 extern WORD_LIST
*subst_assign_varlist
;
96 /* The list of things to do originally, before we started trapping. */
97 SigHandler
*original_signals
[NSIG
];
99 /* For each signal, a slot for a string, which is a command to be
100 executed when that signal is received. The slot can also contain
101 DEFAULT_SIG, which means do whatever you were going to do before
102 you were so rudely interrupted, or IGNORE_SIG, which says ignore
104 char *trap_list
[BASH_NSIG
];
106 /* A bitmap of signals received for which we have trap handlers. */
107 int pending_traps
[NSIG
];
109 /* Set to the number of the signal we're running the trap for + 1.
110 Used in execute_cmd.c and builtins/common.c to clean up when
111 parse_and_execute does not return normally after executing the
112 trap command (e.g., when `return' is executed in the trap command). */
115 /* Set to last_command_exit_value before running a trap. */
116 int trap_saved_exit_value
;
118 /* The (trapped) signal received while executing in the `wait' builtin */
119 int wait_signal_received
;
121 int trapped_signal_received
;
123 #define GETORIGSIG(sig) \
125 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
126 set_signal_handler (sig, original_signals[sig]); \
127 if (original_signals[sig] == SIG_IGN) \
128 sigmodes[sig] |= SIG_HARD_IGNORE; \
131 #define SETORIGSIG(sig,handler) \
133 original_signals[sig] = handler; \
134 if (original_signals[sig] == SIG_IGN) \
135 sigmodes[sig] |= SIG_HARD_IGNORE; \
138 #define GET_ORIGINAL_SIGNAL(sig) \
139 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
147 initialize_signames();
149 trap_list
[EXIT_TRAP
] = trap_list
[DEBUG_TRAP
] = trap_list
[ERROR_TRAP
] = trap_list
[RETURN_TRAP
] = (char *)NULL
;
150 sigmodes
[EXIT_TRAP
] = sigmodes
[DEBUG_TRAP
] = sigmodes
[ERROR_TRAP
] = sigmodes
[RETURN_TRAP
] = SIG_INHERITED
;
151 original_signals
[EXIT_TRAP
] = IMPOSSIBLE_TRAP_HANDLER
;
153 for (i
= 1; i
< NSIG
; i
++)
155 pending_traps
[i
] = 0;
156 trap_list
[i
] = (char *)DEFAULT_SIG
;
157 sigmodes
[i
] = SIG_INHERITED
; /* XXX - only set, not used */
158 original_signals
[i
] = IMPOSSIBLE_TRAP_HANDLER
;
161 /* Show which signals are treated specially by the shell. */
162 #if defined (SIGCHLD)
163 GETORIGSIG (SIGCHLD
);
164 sigmodes
[SIGCHLD
] |= (SIG_SPECIAL
| SIG_NO_TRAP
);
168 sigmodes
[SIGINT
] |= SIG_SPECIAL
;
170 #if defined (__BEOS__)
171 /* BeOS sets SIGINT to SIG_IGN! */
172 original_signals
[SIGINT
] = SIG_DFL
;
173 sigmodes
[SIGINT
] &= ~SIG_HARD_IGNORE
;
176 GETORIGSIG (SIGQUIT
);
177 sigmodes
[SIGQUIT
] |= SIG_SPECIAL
;
181 GETORIGSIG (SIGTERM
);
182 sigmodes
[SIGTERM
] |= SIG_SPECIAL
;
185 get_original_tty_job_signals ();
189 /* Return a printable representation of the trap handler for SIG. */
191 trap_handler_string (sig
)
194 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
195 return "DEFAULT_SIG";
196 else if (trap_list
[sig
] == (char *)IGNORE_SIG
)
198 else if (trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
199 return "IMPOSSIBLE_TRAP_HANDLER";
200 else if (trap_list
[sig
])
201 return trap_list
[sig
];
207 /* Return the print name of this signal. */
214 /* on cygwin32, signal_names[sig] could be null */
215 ret
= (sig
>= BASH_NSIG
|| sig
< 0 || signal_names
[sig
] == NULL
)
216 ? _("invalid signal number")
222 /* Turn a string into a signal number, or a number into
223 a signal number. If STRING is "2", "SIGINT", or "INT",
224 then (int)2 is returned. Return NO_SIG if STRING doesn't
225 contain a valid signal descriptor. */
227 decode_signal (string
, flags
)
234 if (legal_number (string
, &sig
))
235 return ((sig
>= 0 && sig
< NSIG
) ? (int)sig
: NO_SIG
);
237 #if defined (SIGRTMIN) && defined (SIGRTMAX)
238 if (STREQN (string
, "SIGRTMIN+", 9) || ((flags
& DSIG_NOCASE
) && strncasecmp (string
, "SIGRTMIN+", 9) == 0))
240 if (legal_number (string
+9, &sig
) && sig
>= 0 && sig
<= SIGRTMAX
- SIGRTMIN
)
241 return (SIGRTMIN
+ sig
);
245 else if (STREQN (string
, "RTMIN+", 6) || ((flags
& DSIG_NOCASE
) && strncasecmp (string
, "RTMIN+", 6) == 0))
247 if (legal_number (string
+6, &sig
) && sig
>= 0 && sig
<= SIGRTMAX
- SIGRTMIN
)
248 return (SIGRTMIN
+ sig
);
252 #endif /* SIGRTMIN && SIGRTMAX */
254 /* A leading `SIG' may be omitted. */
255 for (sig
= 0; sig
< BASH_NSIG
; sig
++)
257 name
= signal_names
[sig
];
258 if (name
== 0 || name
[0] == '\0')
261 /* Check name without the SIG prefix first case sensitively or
262 insensitively depending on whether flags includes DSIG_NOCASE */
263 if (STREQN (name
, "SIG", 3))
267 if ((flags
& DSIG_NOCASE
) && strcasecmp (string
, name
) == 0)
269 else if ((flags
& DSIG_NOCASE
) == 0 && strcmp (string
, name
) == 0)
271 /* If we can't use the `SIG' prefix to match, punt on this
273 else if ((flags
& DSIG_SIGPREFIX
) == 0)
277 /* Check name with SIG prefix case sensitively or insensitively
278 depending on whether flags includes DSIG_NOCASE */
279 name
= signal_names
[sig
];
280 if ((flags
& DSIG_NOCASE
) && strcasecmp (string
, name
) == 0)
282 else if ((flags
& DSIG_NOCASE
) == 0 && strcmp (string
, name
) == 0)
289 /* Non-zero when we catch a trapped signal. */
290 static int catch_flag
;
296 int old_exit_value
, x
;
297 WORD_LIST
*save_subst_varlist
;
298 HASH_TABLE
*save_tempenv
;
299 sh_parser_state_t pstate
;
300 #if defined (ARRAY_VARS)
304 if (catch_flag
== 0) /* simple optimization */
307 if (running_trap
> 0)
310 internal_warning ("run_pending_traps: recursive invocation while running trap for signal %d", running_trap
-1);
312 #if defined (SIGWINCH)
313 if (running_trap
== SIGWINCH
+1 && pending_traps
[SIGWINCH
])
314 return; /* no recursive SIGWINCH trap invocations */
316 /* could check for running the trap handler for the same signal here
317 (running_trap == sig+1) */
318 if (evalnest_max
> 0 && evalnest
> evalnest_max
)
320 internal_error (_("trap handler: maximum trap handler level exceeded (%d)"), evalnest_max
);
322 jump_to_top_level (DISCARD
);
326 catch_flag
= trapped_signal_received
= 0;
328 /* Preserve $? when running trap. */
329 trap_saved_exit_value
= old_exit_value
= last_command_exit_value
;
330 #if defined (ARRAY_VARS)
331 ps
= save_pipestatus_array ();
334 for (sig
= 1; sig
< NSIG
; sig
++)
336 /* XXX this could be made into a counter by using
337 while (pending_traps[sig]--) instead of the if statement. */
338 if (pending_traps
[sig
])
340 if (running_trap
== sig
+1)
343 running_trap
= sig
+ 1;
347 pending_traps
[sig
] = 0; /* XXX */
348 /* We don't modify evalnest here, since run_interrupt_trap() calls
349 _run_trap_internal, which does. */
350 run_interrupt_trap (0);
351 CLRINTERRUPT
; /* interrupts don't stack */
353 #if defined (JOB_CONTROL) && defined (SIGCHLD)
354 else if (sig
== SIGCHLD
&&
355 trap_list
[SIGCHLD
] != (char *)IMPOSSIBLE_TRAP_HANDLER
&&
356 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) == 0)
358 sigmodes
[SIGCHLD
] |= SIG_INPROGRESS
;
359 /* We modify evalnest here even though run_sigchld_trap can run
360 the trap action more than once */
362 x
= pending_traps
[sig
];
363 pending_traps
[sig
] = 0;
364 run_sigchld_trap (x
); /* use as counter */
367 sigmodes
[SIGCHLD
] &= ~SIG_INPROGRESS
;
368 /* continue here rather than reset pending_traps[SIGCHLD] below in
369 case there are recursive calls to run_pending_traps and children
370 have been reaped while run_sigchld_trap was running. */
373 else if (sig
== SIGCHLD
&&
374 trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
&&
375 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) != 0)
377 /* This can happen when run_pending_traps is called while
378 running a SIGCHLD trap handler. */
380 /* want to leave pending_traps[SIGCHLD] alone here */
383 else if (sig
== SIGCHLD
&& (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
))
385 /* whoops -- print warning? */
386 running_trap
= 0; /* XXX */
387 /* want to leave pending_traps[SIGCHLD] alone here */
391 else if (trap_list
[sig
] == (char *)DEFAULT_SIG
||
392 trap_list
[sig
] == (char *)IGNORE_SIG
||
393 trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
395 /* This is possible due to a race condition. Say a bash
396 process has SIGTERM trapped. A subshell is spawned
397 using { list; } & and the parent does something and kills
398 the subshell with SIGTERM. It's possible for the subshell
399 to set pending_traps[SIGTERM] to 1 before the code in
400 execute_cmd.c eventually calls restore_original_signals
401 to reset the SIGTERM signal handler in the subshell. The
402 next time run_pending_traps is called, pending_traps[SIGTERM]
403 will be 1, but the trap handler in trap_list[SIGTERM] will
404 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
405 Unless we catch this, the subshell will dump core when
406 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
408 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
409 sig
, trap_list
[sig
]);
410 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
412 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig
, signal_name (sig
));
413 kill (getpid (), sig
);
418 /* XXX - should we use save_parser_state/restore_parser_state? */
419 save_parser_state (&pstate
);
420 save_subst_varlist
= subst_assign_varlist
;
421 subst_assign_varlist
= 0;
422 save_tempenv
= temporary_env
;
423 temporary_env
= 0; /* traps should not run with temporary env */
425 #if defined (JOB_CONTROL)
426 save_pipeline (1); /* XXX only provides one save level */
428 /* XXX - set pending_traps[sig] = 0 here? */
429 pending_traps
[sig
] = 0;
431 evalstring (savestring (trap_list
[sig
]), "trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
433 #if defined (JOB_CONTROL)
434 restore_pipeline (1);
437 subst_assign_varlist
= save_subst_varlist
;
438 restore_parser_state (&pstate
);
439 temporary_env
= save_tempenv
;
442 pending_traps
[sig
] = 0; /* XXX - move before evalstring? */
447 #if defined (ARRAY_VARS)
448 restore_pipestatus_array (ps
);
450 last_command_exit_value
= old_exit_value
;
459 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
462 internal_warning ("trap_handler: signal %d: signal not trapped", sig
);
468 (trap_list
[sig
] == (char *)DEFAULT_SIG
) ||
469 (trap_list
[sig
] == (char *)IGNORE_SIG
))
470 programming_error (_("trap_handler: bad signal %d"), sig
);
474 #if defined (MUST_REINSTALL_SIGHANDLERS)
475 # if defined (JOB_CONTROL) && defined (SIGCHLD)
477 # endif /* JOB_CONTROL && SIGCHLD */
478 set_signal_handler (sig
, trap_handler
);
479 #endif /* MUST_REINSTALL_SIGHANDLERS */
482 pending_traps
[sig
]++;
483 trapped_signal_received
= sig
;
485 if (this_shell_builtin
&& (this_shell_builtin
== wait_builtin
))
487 wait_signal_received
= sig
;
488 if (interrupt_immediately
&& wait_intr_flag
)
489 sh_longjmp (wait_intr_buf
, 1);
492 #if defined (READLINE)
493 /* Set the event hook so readline will call it after the signal handlers
494 finish executing, so if this interrupted character input we can get
496 if (RL_ISSTATE (RL_STATE_SIGHANDLER
) && interrupt_immediately
== 0)
497 bashline_set_event_hook ();
500 if (interrupt_immediately
)
501 run_pending_traps ();
510 first_pending_trap ()
514 for (i
= 1; i
< NSIG
; i
++)
515 if (pending_traps
[i
])
520 /* Return > 0 if any of the "real" signals (not fake signals like EXIT) are
523 any_signals_trapped ()
527 for (i
= 1; i
< NSIG
; i
++)
528 if (sigmodes
[i
] & SIG_TRAPPED
)
536 CHECK_ALRM
; /* set by the read builtin */
540 /* Convenience functions the rest of the shell can use */
542 check_signals_and_traps ()
546 run_pending_traps ();
549 #if defined (JOB_CONTROL) && defined (SIGCHLD)
551 #ifdef INCLUDE_UNUSED
552 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
554 set_sigchld_trap (command_string
)
555 char *command_string
;
557 set_signal (SIGCHLD
, command_string
);
561 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
562 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
563 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
564 reset the disposition to the default and not have the original signal
565 accidentally restored, undoing the user's command. */
567 maybe_set_sigchld_trap (command_string
)
568 char *command_string
;
570 if ((sigmodes
[SIGCHLD
] & SIG_TRAPPED
) == 0 && trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
571 set_signal (SIGCHLD
, command_string
);
574 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
575 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
576 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
578 set_impossible_sigchld_trap ()
580 restore_default_signal (SIGCHLD
);
581 change_signal (SIGCHLD
, (char *)IMPOSSIBLE_TRAP_HANDLER
);
582 sigmodes
[SIGCHLD
] &= ~SIG_TRAPPED
; /* maybe_set_sigchld_trap checks this */
585 /* Act as if we received SIGCHLD NCHILD times and increment
586 pending_traps[SIGCHLD] by that amount. This allows us to still run the
587 SIGCHLD trap once for each exited child. */
589 queue_sigchld_trap (nchild
)
595 pending_traps
[SIGCHLD
] += nchild
;
596 trapped_signal_received
= SIGCHLD
;
599 #endif /* JOB_CONTROL && SIGCHLD */
601 /* Set a trap for SIG only if SIG is not already trapped. */
603 trap_if_untrapped (sig
, command
)
607 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
608 set_signal (sig
, command
);
612 set_debug_trap (command
)
615 set_signal (DEBUG_TRAP
, command
);
618 /* Separate function to call when functions and sourced files want to restore
619 the original version of the DEBUG trap before returning. Unless the -T
620 option is set, source and shell function execution save the old debug trap
621 and unset the trap. If the function or sourced file changes the DEBUG trap,
622 SIG_TRAPPED will be set and we don't bother restoring the original trap string.
623 This is used by both functions and the source builtin. */
625 maybe_set_debug_trap (command
)
628 trap_if_untrapped (DEBUG_TRAP
, command
);
632 set_error_trap (command
)
635 set_signal (ERROR_TRAP
, command
);
639 maybe_set_error_trap (command
)
642 trap_if_untrapped (ERROR_TRAP
, command
);
646 set_return_trap (command
)
649 set_signal (RETURN_TRAP
, command
);
653 maybe_set_return_trap (command
)
656 trap_if_untrapped (RETURN_TRAP
, command
);
659 #ifdef INCLUDE_UNUSED
661 set_sigint_trap (command
)
664 set_signal (SIGINT
, command
);
668 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
669 things, like waiting for command substitution or executing commands
670 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
672 set_sigint_handler ()
674 if (sigmodes
[SIGINT
] & SIG_HARD_IGNORE
)
675 return ((SigHandler
*)SIG_IGN
);
677 else if (sigmodes
[SIGINT
] & SIG_IGNORED
)
678 return ((SigHandler
*)set_signal_handler (SIGINT
, SIG_IGN
)); /* XXX */
680 else if (sigmodes
[SIGINT
] & SIG_TRAPPED
)
681 return ((SigHandler
*)set_signal_handler (SIGINT
, trap_handler
));
683 /* The signal is not trapped, so set the handler to the shell's special
684 interrupt handler. */
685 else if (interactive
) /* XXX - was interactive_shell */
686 return (set_signal_handler (SIGINT
, sigint_sighandler
));
688 return (set_signal_handler (SIGINT
, termsig_sighandler
));
691 /* Return the correct handler for signal SIG according to the values in
694 trap_to_sighandler (sig
)
697 if (sigmodes
[sig
] & (SIG_IGNORED
|SIG_HARD_IGNORE
))
699 else if (sigmodes
[sig
] & SIG_TRAPPED
)
700 return (trap_handler
);
705 /* Set SIG to call STRING as a command. */
707 set_signal (sig
, string
)
713 if (SPECIAL_TRAP (sig
))
715 change_signal (sig
, savestring (string
));
716 if (sig
== EXIT_TRAP
&& interactive
== 0)
717 initialize_terminating_signals ();
721 /* A signal ignored on entry to the shell cannot be trapped or reset, but
722 no error is reported when attempting to do so. -- Posix.2 */
723 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
726 /* Make sure we have original_signals[sig] if the signal has not yet
728 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
730 /* If we aren't sure of the original value, check it. */
731 if (original_signals
[sig
] == IMPOSSIBLE_TRAP_HANDLER
)
733 if (original_signals
[sig
] == SIG_IGN
)
737 /* Only change the system signal handler if SIG_NO_TRAP is not set.
738 The trap command string is changed in either case. The shell signal
739 handlers for SIGINT and SIGCHLD run the user specified traps in an
740 environment in which it is safe to do so. */
741 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
743 BLOCK_SIGNAL (sig
, set
, oset
);
744 change_signal (sig
, savestring (string
));
745 set_signal_handler (sig
, trap_handler
);
746 UNBLOCK_SIGNAL (oset
);
749 change_signal (sig
, savestring (string
));
753 free_trap_command (sig
)
756 if ((sigmodes
[sig
] & SIG_TRAPPED
) && trap_list
[sig
] &&
757 (trap_list
[sig
] != (char *)IGNORE_SIG
) &&
758 (trap_list
[sig
] != (char *)DEFAULT_SIG
) &&
759 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
))
760 free (trap_list
[sig
]);
763 /* If SIG has a string assigned to it, get rid of it. Then give it
766 change_signal (sig
, value
)
770 if ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
771 free_trap_command (sig
);
772 trap_list
[sig
] = value
;
774 sigmodes
[sig
] |= SIG_TRAPPED
;
775 if (value
== (char *)IGNORE_SIG
)
776 sigmodes
[sig
] |= SIG_IGNORED
;
778 sigmodes
[sig
] &= ~SIG_IGNORED
;
779 if (sigmodes
[sig
] & SIG_INPROGRESS
)
780 sigmodes
[sig
] |= SIG_CHANGED
;
784 get_original_signal (sig
)
787 /* If we aren't sure the of the original value, then get it. */
788 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
793 get_all_original_signals ()
797 for (i
= 1; i
< NSIG
; i
++)
798 GET_ORIGINAL_SIGNAL (i
);
802 set_original_signal (sig
, handler
)
806 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
807 SETORIGSIG (sig
, handler
);
810 /* Restore the default action for SIG; i.e., the action the shell
811 would have taken before you used the trap command. This is called
812 from trap_builtin (), which takes care to restore the handlers for
813 the signals the shell treats specially. */
815 restore_default_signal (sig
)
818 if (SPECIAL_TRAP (sig
))
820 if ((sig
!= DEBUG_TRAP
&& sig
!= ERROR_TRAP
&& sig
!= RETURN_TRAP
) ||
821 (sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
822 free_trap_command (sig
);
823 trap_list
[sig
] = (char *)NULL
;
824 sigmodes
[sig
] &= ~SIG_TRAPPED
;
825 if (sigmodes
[sig
] & SIG_INPROGRESS
)
826 sigmodes
[sig
] |= SIG_CHANGED
;
830 GET_ORIGINAL_SIGNAL (sig
);
832 /* A signal ignored on entry to the shell cannot be trapped or reset, but
833 no error is reported when attempting to do so. Thanks Posix.2. */
834 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
837 /* If we aren't trapping this signal, don't bother doing anything else. */
838 /* We special-case SIGCHLD and IMPOSSIBLE_TRAP_HANDLER (see above) as a
839 sentinel to determine whether or not disposition is reset to the default
840 while the trap handler is executing. */
841 if (((sigmodes
[sig
] & SIG_TRAPPED
) == 0) &&
842 (sig
!= SIGCHLD
|| (sigmodes
[sig
] & SIG_INPROGRESS
) == 0 || trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
))
845 /* Only change the signal handler for SIG if it allows it. */
846 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
847 set_signal_handler (sig
, original_signals
[sig
]);
849 /* Change the trap command in either case. */
850 change_signal (sig
, (char *)DEFAULT_SIG
);
852 /* Mark the signal as no longer trapped. */
853 sigmodes
[sig
] &= ~SIG_TRAPPED
;
856 /* Make this signal be ignored. */
861 if (SPECIAL_TRAP (sig
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
863 change_signal (sig
, (char *)IGNORE_SIG
);
867 GET_ORIGINAL_SIGNAL (sig
);
869 /* A signal ignored on entry to the shell cannot be trapped or reset.
870 No error is reported when the user attempts to do so. */
871 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
874 /* If already trapped and ignored, no change necessary. */
875 if (sigmodes
[sig
] & SIG_IGNORED
)
878 /* Only change the signal handler for SIG if it allows it. */
879 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
880 set_signal_handler (sig
, SIG_IGN
);
882 /* Change the trap command in either case. */
883 change_signal (sig
, (char *)IGNORE_SIG
);
886 /* Handle the calling of "trap 0". The only sticky situation is when
887 the command to be executed includes an "exit". This is why we have
888 to provide our own place for top_level to jump to. */
893 int code
, function_code
, retval
;
894 #if defined (ARRAY_VARS)
898 trap_saved_exit_value
= last_command_exit_value
;
899 #if defined (ARRAY_VARS)
900 ps
= save_pipestatus_array ();
904 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
905 currently running in the trap handler (call to exit in the list of
906 commands given to trap 0). */
907 if ((sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
) &&
908 (sigmodes
[EXIT_TRAP
] & (SIG_IGNORED
|SIG_INPROGRESS
)) == 0)
910 trap_command
= savestring (trap_list
[EXIT_TRAP
]);
911 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
912 sigmodes
[EXIT_TRAP
] |= SIG_INPROGRESS
;
914 retval
= trap_saved_exit_value
;
917 code
= setjmp_nosigs (top_level
);
919 /* If we're in a function, make sure return longjmps come here, too. */
920 if (return_catch_flag
)
921 function_code
= setjmp_nosigs (return_catch
);
923 if (code
== 0 && function_code
== 0)
926 parse_and_execute (trap_command
, "exit trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
928 else if (code
== ERREXIT
)
929 retval
= last_command_exit_value
;
930 else if (code
== EXITPROG
)
931 retval
= last_command_exit_value
;
932 else if (function_code
!= 0)
933 retval
= return_catch_value
;
935 retval
= trap_saved_exit_value
;
938 #if defined (ARRAY_VARS)
945 #if defined (ARRAY_VARS)
946 restore_pipestatus_array (ps
);
948 return (trap_saved_exit_value
);
952 run_trap_cleanup (sig
)
955 sigmodes
[sig
] &= ~(SIG_INPROGRESS
|SIG_CHANGED
);
958 #define RECURSIVE_SIG(s) (SPECIAL_TRAP(s) == 0)
960 /* Run a trap command for SIG. SIG is one of the signals the shell treats
961 specially. Returns the exit status of the executed trap command list. */
963 _run_trap_internal (sig
, tag
)
967 char *trap_command
, *old_trap
;
969 volatile int save_return_catch_flag
, function_code
, old_int
;
971 procenv_t save_return_catch
;
972 WORD_LIST
*save_subst_varlist
;
973 HASH_TABLE
*save_tempenv
;
974 sh_parser_state_t pstate
;
975 #if defined (ARRAY_VARS)
979 trap_exit_value
= function_code
= 0;
980 trap_saved_exit_value
= last_command_exit_value
;
981 /* Run the trap only if SIG is trapped and not ignored, and we are not
982 currently executing in the trap handler. */
983 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0) &&
984 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
) &&
986 /* Uncomment this to allow some special signals to recursively execute
988 (RECURSIVE_SIG (sig
) || (sigmodes
[sig
] & SIG_INPROGRESS
) == 0))
990 ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0))
993 old_trap
= trap_list
[sig
];
994 sigmodes
[sig
] |= SIG_INPROGRESS
;
995 sigmodes
[sig
] &= ~SIG_CHANGED
; /* just to be sure */
996 trap_command
= savestring (old_trap
);
998 running_trap
= sig
+ 1;
1000 old_int
= interrupt_state
; /* temporarily suppress pending interrupts */
1003 #if defined (ARRAY_VARS)
1004 ps
= save_pipestatus_array ();
1007 save_parser_state (&pstate
);
1008 save_subst_varlist
= subst_assign_varlist
;
1009 subst_assign_varlist
= 0;
1010 save_tempenv
= temporary_env
;
1011 temporary_env
= 0; /* traps should not run with temporary env */
1013 #if defined (JOB_CONTROL)
1014 if (sig
!= DEBUG_TRAP
) /* run_debug_trap does this */
1015 save_pipeline (1); /* XXX only provides one save level */
1018 /* If we're in a function, make sure return longjmps come here, too. */
1019 save_return_catch_flag
= return_catch_flag
;
1020 if (return_catch_flag
)
1022 COPY_PROCENV (return_catch
, save_return_catch
);
1023 function_code
= setjmp_nosigs (return_catch
);
1026 flags
= SEVAL_NONINT
|SEVAL_NOHIST
;
1027 if (sig
!= DEBUG_TRAP
&& sig
!= RETURN_TRAP
&& sig
!= ERROR_TRAP
)
1028 flags
|= SEVAL_RESETLINE
;
1030 if (function_code
== 0)
1032 parse_and_execute (trap_command
, tag
, flags
);
1033 trap_exit_value
= last_command_exit_value
;
1036 trap_exit_value
= return_catch_value
;
1039 #if defined (JOB_CONTROL)
1040 if (sig
!= DEBUG_TRAP
) /* run_debug_trap does this */
1041 restore_pipeline (1);
1044 subst_assign_varlist
= save_subst_varlist
;
1045 restore_parser_state (&pstate
);
1047 #if defined (ARRAY_VARS)
1048 restore_pipestatus_array (ps
);
1051 temporary_env
= save_tempenv
;
1053 sigmodes
[sig
] &= ~SIG_INPROGRESS
;
1055 interrupt_state
= old_int
;
1057 if (sigmodes
[sig
] & SIG_CHANGED
)
1060 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
1061 the places where they can be changed using unwind-protects. For
1062 example, look at execute_cmd.c:execute_function(). */
1063 if (SPECIAL_TRAP (sig
) == 0)
1066 sigmodes
[sig
] &= ~SIG_CHANGED
;
1068 CHECK_TERMSIG
; /* some pathological conditions lead here */
1071 if (save_return_catch_flag
)
1073 return_catch_flag
= save_return_catch_flag
;
1074 return_catch_value
= trap_exit_value
;
1075 COPY_PROCENV (save_return_catch
, return_catch
);
1079 from_return_trap
= sig
== RETURN_TRAP
;
1081 sh_longjmp (return_catch
, 1);
1086 return trap_exit_value
;
1092 int trap_exit_value
, old_verbose
;
1094 #if defined (PGRP_PIPE)
1098 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
1099 trap_exit_value
= 0;
1100 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[DEBUG_TRAP
] & SIG_IGNORED
) == 0) && ((sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
) == 0))
1102 #if defined (JOB_CONTROL)
1103 save_pgrp
= pipeline_pgrp
;
1106 # if defined (PGRP_PIPE)
1107 save_pgrp_pipe (save_pipe
, 1);
1109 stop_making_children ();
1112 old_verbose
= echo_input_at_read
;
1114 echo_input_at_read
= 0;
1117 trap_exit_value
= _run_trap_internal (DEBUG_TRAP
, "debug trap");
1119 echo_input_at_read
= old_verbose
;
1121 #if defined (JOB_CONTROL)
1122 pipeline_pgrp
= save_pgrp
;
1123 restore_pipeline (1);
1124 # if defined (PGRP_PIPE)
1126 restore_pgrp_pipe (save_pipe
);
1128 if (pipeline_pgrp
> 0 && ((subshell_environment
& (SUBSHELL_ASYNC
|SUBSHELL_PIPE
)) == 0))
1129 give_terminal_to (pipeline_pgrp
, 1);
1131 notify_and_cleanup ();
1134 #if defined (DEBUGGER)
1135 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
1136 a function or sourced script, we force a `return'. */
1137 if (debugging_mode
&& trap_exit_value
== 2 && return_catch_flag
)
1139 return_catch_value
= trap_exit_value
;
1140 sh_longjmp (return_catch
, 1);
1144 return trap_exit_value
;
1150 if ((sigmodes
[ERROR_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[ERROR_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[ERROR_TRAP
] & SIG_INPROGRESS
) == 0)
1151 _run_trap_internal (ERROR_TRAP
, "error trap");
1160 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && (sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
))
1164 if ((sigmodes
[RETURN_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[RETURN_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[RETURN_TRAP
] & SIG_INPROGRESS
) == 0)
1166 old_exit_value
= last_command_exit_value
;
1167 _run_trap_internal (RETURN_TRAP
, "return trap");
1168 last_command_exit_value
= old_exit_value
;
1172 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1173 declared here to localize the trap functions. */
1175 run_interrupt_trap (will_throw
)
1176 int will_throw
; /* from throw_to_top_level? */
1178 if (will_throw
&& running_trap
> 0)
1179 run_trap_cleanup (running_trap
- 1);
1180 _run_trap_internal (SIGINT
, "interrupt trap");
1183 /* Free all the allocated strings in the list of traps and reset the trap
1184 values to the default. Intended to be called from subshells that want
1185 to complete work done by reset_signal_handlers upon execution of a
1186 subsequent `trap' command that changes a signal's disposition. We need
1187 to make sure that we duplicate the behavior of
1188 reset_or_restore_signal_handlers and not change the disposition of signals
1189 that are set to be ignored. */
1191 free_trap_strings ()
1195 for (i
= 0; i
< NSIG
; i
++)
1197 if (trap_list
[i
] != (char *)IGNORE_SIG
)
1198 free_trap_string (i
);
1200 for (i
= NSIG
; i
< BASH_NSIG
; i
++)
1202 /* Don't free the trap string if the subshell inherited the trap */
1203 if ((sigmodes
[i
] & SIG_TRAPPED
) == 0)
1205 free_trap_string (i
);
1206 trap_list
[i
] = (char *)NULL
;
1211 /* Free a trap command string associated with SIG without changing signal
1212 disposition. Intended to be called from free_trap_strings() */
1214 free_trap_string (sig
)
1217 change_signal (sig
, (char *)DEFAULT_SIG
);
1218 sigmodes
[sig
] &= ~SIG_TRAPPED
; /* XXX - SIG_INPROGRESS? */
1221 /* Reset the handler for SIG to the original value but leave the trap string
1227 set_signal_handler (sig
, original_signals
[sig
]);
1228 sigmodes
[sig
] &= ~SIG_TRAPPED
; /* XXX - SIG_INPROGRESS? */
1231 /* Set the handler signal SIG to the original and free any trap
1232 command associated with it. */
1234 restore_signal (sig
)
1237 set_signal_handler (sig
, original_signals
[sig
]);
1238 change_signal (sig
, (char *)DEFAULT_SIG
);
1239 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1243 reset_or_restore_signal_handlers (reset
)
1244 sh_resetsig_func_t
*reset
;
1248 /* Take care of the exit trap first */
1249 if (sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
)
1251 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
; /* XXX - SIG_INPROGRESS? */
1252 if (reset
!= reset_signal
)
1254 free_trap_command (EXIT_TRAP
);
1255 trap_list
[EXIT_TRAP
] = (char *)NULL
;
1259 for (i
= 1; i
< NSIG
; i
++)
1261 if (sigmodes
[i
] & SIG_TRAPPED
)
1263 if (trap_list
[i
] == (char *)IGNORE_SIG
)
1264 set_signal_handler (i
, SIG_IGN
);
1268 else if (sigmodes
[i
] & SIG_SPECIAL
)
1270 pending_traps
[i
] = 0; /* XXX */
1273 /* Command substitution and other child processes don't inherit the
1274 debug, error, or return traps. If we're in the debugger, and the
1275 `functrace' or `errtrace' options have been set, then let command
1276 substitutions inherit them. Let command substitution inherit the
1277 RETURN trap if we're in the debugger and tracing functions. */
1278 if (function_trace_mode
== 0)
1280 sigmodes
[DEBUG_TRAP
] &= ~SIG_TRAPPED
;
1281 sigmodes
[RETURN_TRAP
] &= ~SIG_TRAPPED
;
1283 if (error_trace_mode
== 0)
1284 sigmodes
[ERROR_TRAP
] &= ~SIG_TRAPPED
;
1287 /* Reset trapped signals to their original values, but don't free the
1288 trap strings. Called by the command substitution code and other places
1289 that create a "subshell environment". */
1291 reset_signal_handlers ()
1293 reset_or_restore_signal_handlers (reset_signal
);
1296 /* Reset all trapped signals to their original values. Signals set to be
1297 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1298 are. Called by child processes after they are forked. */
1300 restore_original_signals ()
1302 reset_or_restore_signal_handlers (restore_signal
);
1305 /* If a trap handler exists for signal SIG, then call it; otherwise just
1306 return failure. Returns 1 if it called the trap handler. */
1308 maybe_call_trap_handler (sig
)
1311 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
1312 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
1317 run_interrupt_trap (0);
1339 signal_is_trapped (sig
)
1342 return (sigmodes
[sig
] & SIG_TRAPPED
);
1346 signal_is_pending (sig
)
1349 return (pending_traps
[sig
]);
1353 signal_is_special (sig
)
1356 return (sigmodes
[sig
] & SIG_SPECIAL
);
1360 signal_is_ignored (sig
)
1363 return (sigmodes
[sig
] & SIG_IGNORED
);
1367 signal_is_hard_ignored (sig
)
1370 return (sigmodes
[sig
] & SIG_HARD_IGNORE
);
1374 set_signal_hard_ignored (sig
)
1377 sigmodes
[sig
] |= SIG_HARD_IGNORE
;
1378 original_signals
[sig
] = SIG_IGN
;
1382 set_signal_ignored (sig
)
1385 original_signals
[sig
] = SIG_IGN
;
1389 signal_in_progress (sig
)
1392 return (sigmodes
[sig
] & SIG_INPROGRESS
);