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-2015 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 (int);
76 static void change_signal (int, char *);
78 static int _run_trap_internal (int, char *);
80 static void free_trap_string (int);
81 static void reset_signal (int);
82 static void restore_signal (int);
83 static void reset_or_restore_signal_handlers (sh_resetsig_func_t
*);
85 static void trap_if_untrapped (int, char *);
87 /* Variables used here but defined in other files. */
88 extern int last_command_exit_value
;
89 extern int line_number
;
91 extern int sigalrm_seen
;
92 extern procenv_t alrmbuf
;
94 extern volatile int from_return_trap
;
96 extern char *this_command_name
;
97 extern sh_builtin_func_t
*this_shell_builtin
;
98 extern procenv_t wait_intr_buf
;
99 extern int wait_intr_flag
;
100 extern int return_catch_flag
, return_catch_value
;
101 extern int subshell_level
;
102 extern WORD_LIST
*subst_assign_varlist
;
104 /* The list of things to do originally, before we started trapping. */
105 SigHandler
*original_signals
[NSIG
];
107 /* For each signal, a slot for a string, which is a command to be
108 executed when that signal is received. The slot can also contain
109 DEFAULT_SIG, which means do whatever you were going to do before
110 you were so rudely interrupted, or IGNORE_SIG, which says ignore
112 char *trap_list
[BASH_NSIG
];
114 /* A bitmap of signals received for which we have trap handlers. */
115 int pending_traps
[NSIG
];
117 /* Set to the number of the signal we're running the trap for + 1.
118 Used in execute_cmd.c and builtins/common.c to clean up when
119 parse_and_execute does not return normally after executing the
120 trap command (e.g., when `return' is executed in the trap command). */
123 /* Set to last_command_exit_value before running a trap. */
124 int trap_saved_exit_value
;
126 /* The (trapped) signal received while executing in the `wait' builtin */
127 int wait_signal_received
;
129 int trapped_signal_received
;
131 #define GETORIGSIG(sig) \
133 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
134 set_signal_handler (sig, original_signals[sig]); \
135 if (original_signals[sig] == SIG_IGN) \
136 sigmodes[sig] |= SIG_HARD_IGNORE; \
139 #define SETORIGSIG(sig,handler) \
141 original_signals[sig] = handler; \
142 if (original_signals[sig] == SIG_IGN) \
143 sigmodes[sig] |= SIG_HARD_IGNORE; \
146 #define GET_ORIGINAL_SIGNAL(sig) \
147 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
155 initialize_signames();
157 trap_list
[EXIT_TRAP
] = trap_list
[DEBUG_TRAP
] = trap_list
[ERROR_TRAP
] = trap_list
[RETURN_TRAP
] = (char *)NULL
;
158 sigmodes
[EXIT_TRAP
] = sigmodes
[DEBUG_TRAP
] = sigmodes
[ERROR_TRAP
] = sigmodes
[RETURN_TRAP
] = SIG_INHERITED
;
159 original_signals
[EXIT_TRAP
] = IMPOSSIBLE_TRAP_HANDLER
;
161 for (i
= 1; i
< NSIG
; i
++)
163 pending_traps
[i
] = 0;
164 trap_list
[i
] = (char *)DEFAULT_SIG
;
165 sigmodes
[i
] = SIG_INHERITED
; /* XXX - only set, not used */
166 original_signals
[i
] = IMPOSSIBLE_TRAP_HANDLER
;
169 /* Show which signals are treated specially by the shell. */
170 #if defined (SIGCHLD)
171 GETORIGSIG (SIGCHLD
);
172 sigmodes
[SIGCHLD
] |= (SIG_SPECIAL
| SIG_NO_TRAP
);
176 sigmodes
[SIGINT
] |= SIG_SPECIAL
;
178 #if defined (__BEOS__)
179 /* BeOS sets SIGINT to SIG_IGN! */
180 original_signals
[SIGINT
] = SIG_DFL
;
181 sigmodes
[SIGINT
] &= ~SIG_HARD_IGNORE
;
184 GETORIGSIG (SIGQUIT
);
185 sigmodes
[SIGQUIT
] |= SIG_SPECIAL
;
189 GETORIGSIG (SIGTERM
);
190 sigmodes
[SIGTERM
] |= SIG_SPECIAL
;
193 get_original_tty_job_signals ();
197 /* Return a printable representation of the trap handler for SIG. */
199 trap_handler_string (sig
)
202 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
203 return "DEFAULT_SIG";
204 else if (trap_list
[sig
] == (char *)IGNORE_SIG
)
206 else if (trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
207 return "IMPOSSIBLE_TRAP_HANDLER";
208 else if (trap_list
[sig
])
209 return trap_list
[sig
];
215 /* Return the print name of this signal. */
222 /* on cygwin32, signal_names[sig] could be null */
223 ret
= (sig
>= BASH_NSIG
|| sig
< 0 || signal_names
[sig
] == NULL
)
224 ? _("invalid signal number")
230 /* Turn a string into a signal number, or a number into
231 a signal number. If STRING is "2", "SIGINT", or "INT",
232 then (int)2 is returned. Return NO_SIG if STRING doesn't
233 contain a valid signal descriptor. */
235 decode_signal (string
, flags
)
242 if (legal_number (string
, &sig
))
243 return ((sig
>= 0 && sig
< NSIG
) ? (int)sig
: NO_SIG
);
245 /* A leading `SIG' may be omitted. */
246 for (sig
= 0; sig
< BASH_NSIG
; sig
++)
248 name
= signal_names
[sig
];
249 if (name
== 0 || name
[0] == '\0')
252 /* Check name without the SIG prefix first case sensitively or
253 insensitively depending on whether flags includes DSIG_NOCASE */
254 if (STREQN (name
, "SIG", 3))
258 if ((flags
& DSIG_NOCASE
) && strcasecmp (string
, name
) == 0)
260 else if ((flags
& DSIG_NOCASE
) == 0 && strcmp (string
, name
) == 0)
262 /* If we can't use the `SIG' prefix to match, punt on this
264 else if ((flags
& DSIG_SIGPREFIX
) == 0)
268 /* Check name with SIG prefix case sensitively or insensitively
269 depending on whether flags includes DSIG_NOCASE */
270 name
= signal_names
[sig
];
271 if ((flags
& DSIG_NOCASE
) && strcasecmp (string
, name
) == 0)
273 else if ((flags
& DSIG_NOCASE
) == 0 && strcmp (string
, name
) == 0)
280 /* Non-zero when we catch a trapped signal. */
281 static int catch_flag
;
287 int old_exit_value
, x
;
288 WORD_LIST
*save_subst_varlist
;
289 HASH_TABLE
*save_tempenv
;
290 sh_parser_state_t pstate
;
291 #if defined (ARRAY_VARS)
295 if (catch_flag
== 0) /* simple optimization */
298 if (running_trap
> 0)
301 internal_warning ("run_pending_traps: recursive invocation while running trap for signal %d", running_trap
-1);
303 #if defined (SIGWINCH)
304 if (running_trap
== SIGWINCH
+1 && pending_traps
[SIGWINCH
])
305 return; /* no recursive SIGWINCH trap invocations */
311 catch_flag
= trapped_signal_received
= 0;
313 /* Preserve $? when running trap. */
314 trap_saved_exit_value
= old_exit_value
= last_command_exit_value
;
315 #if defined (ARRAY_VARS)
316 ps
= save_pipestatus_array ();
319 for (sig
= 1; sig
< NSIG
; sig
++)
321 /* XXX this could be made into a counter by using
322 while (pending_traps[sig]--) instead of the if statement. */
323 if (pending_traps
[sig
])
325 if (running_trap
== sig
+1)
328 running_trap
= sig
+ 1;
332 pending_traps
[sig
] = 0; /* XXX */
333 run_interrupt_trap (0);
336 #if defined (JOB_CONTROL) && defined (SIGCHLD)
337 else if (sig
== SIGCHLD
&&
338 trap_list
[SIGCHLD
] != (char *)IMPOSSIBLE_TRAP_HANDLER
&&
339 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) == 0)
341 sigmodes
[SIGCHLD
] |= SIG_INPROGRESS
;
342 x
= pending_traps
[sig
];
343 pending_traps
[sig
] = 0;
344 run_sigchld_trap (x
); /* use as counter */
346 sigmodes
[SIGCHLD
] &= ~SIG_INPROGRESS
;
347 /* continue here rather than reset pending_traps[SIGCHLD] below in
348 case there are recursive calls to run_pending_traps and children
349 have been reaped while run_sigchld_trap was running. */
352 else if (sig
== SIGCHLD
&&
353 trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
&&
354 (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
) != 0)
356 /* This can happen when run_pending_traps is called while
357 running a SIGCHLD trap handler. */
359 /* want to leave pending_traps[SIGCHLD] alone here */
362 else if (sig
== SIGCHLD
&& (sigmodes
[SIGCHLD
] & SIG_INPROGRESS
))
364 /* whoops -- print warning? */
365 running_trap
= 0; /* XXX */
366 /* want to leave pending_traps[SIGCHLD] alone here */
370 else if (trap_list
[sig
] == (char *)DEFAULT_SIG
||
371 trap_list
[sig
] == (char *)IGNORE_SIG
||
372 trap_list
[sig
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
374 /* This is possible due to a race condition. Say a bash
375 process has SIGTERM trapped. A subshell is spawned
376 using { list; } & and the parent does something and kills
377 the subshell with SIGTERM. It's possible for the subshell
378 to set pending_traps[SIGTERM] to 1 before the code in
379 execute_cmd.c eventually calls restore_original_signals
380 to reset the SIGTERM signal handler in the subshell. The
381 next time run_pending_traps is called, pending_traps[SIGTERM]
382 will be 1, but the trap handler in trap_list[SIGTERM] will
383 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
384 Unless we catch this, the subshell will dump core when
385 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
387 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
388 sig
, trap_list
[sig
]);
389 if (trap_list
[sig
] == (char *)DEFAULT_SIG
)
391 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig
, signal_name (sig
));
392 kill (getpid (), sig
);
397 /* XXX - should we use save_parser_state/restore_parser_state? */
398 save_parser_state (&pstate
);
399 save_subst_varlist
= subst_assign_varlist
;
400 subst_assign_varlist
= 0;
401 save_tempenv
= temporary_env
;
402 temporary_env
= 0; /* traps should not run with temporary env */
404 #if defined (JOB_CONTROL)
405 save_pipeline (1); /* XXX only provides one save level */
407 /* XXX - set pending_traps[sig] = 0 here? */
408 pending_traps
[sig
] = 0;
409 evalstring (savestring (trap_list
[sig
]), "trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
410 #if defined (JOB_CONTROL)
411 restore_pipeline (1);
414 subst_assign_varlist
= save_subst_varlist
;
415 restore_parser_state (&pstate
);
416 temporary_env
= save_tempenv
;
419 pending_traps
[sig
] = 0; /* XXX - move before evalstring? */
424 #if defined (ARRAY_VARS)
425 restore_pipestatus_array (ps
);
427 last_command_exit_value
= old_exit_value
;
436 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
439 internal_warning ("trap_handler: signal %d: signal not trapped", sig
);
445 (trap_list
[sig
] == (char *)DEFAULT_SIG
) ||
446 (trap_list
[sig
] == (char *)IGNORE_SIG
))
447 programming_error (_("trap_handler: bad signal %d"), sig
);
451 #if defined (MUST_REINSTALL_SIGHANDLERS)
452 # if defined (JOB_CONTROL) && defined (SIGCHLD)
454 # endif /* JOB_CONTROL && SIGCHLD */
455 set_signal_handler (sig
, trap_handler
);
456 #endif /* MUST_REINSTALL_SIGHANDLERS */
459 pending_traps
[sig
]++;
460 trapped_signal_received
= sig
;
462 if (this_shell_builtin
&& (this_shell_builtin
== wait_builtin
))
464 wait_signal_received
= sig
;
465 if (interrupt_immediately
&& wait_intr_flag
)
466 sh_longjmp (wait_intr_buf
, 1);
469 #if defined (READLINE)
470 /* Set the event hook so readline will call it after the signal handlers
471 finish executing, so if this interrupted character input we can get
473 if (RL_ISSTATE (RL_STATE_SIGHANDLER
) && interrupt_immediately
== 0)
474 bashline_set_event_hook ();
477 if (interrupt_immediately
)
478 run_pending_traps ();
487 first_pending_trap ()
491 for (i
= 1; i
< NSIG
; i
++)
492 if (pending_traps
[i
])
498 any_signals_trapped ()
502 for (i
= 1; i
< NSIG
; i
++)
503 if (sigmodes
[i
] & SIG_TRAPPED
)
511 CHECK_ALRM
; /* set by the read builtin */
515 /* Convenience functions the rest of the shell can use */
517 check_signals_and_traps ()
521 run_pending_traps ();
524 #if defined (JOB_CONTROL) && defined (SIGCHLD)
526 #ifdef INCLUDE_UNUSED
527 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
529 set_sigchld_trap (command_string
)
530 char *command_string
;
532 set_signal (SIGCHLD
, command_string
);
536 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
537 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
538 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
539 reset the disposition to the default and not have the original signal
540 accidentally restored, undoing the user's command. */
542 maybe_set_sigchld_trap (command_string
)
543 char *command_string
;
545 if ((sigmodes
[SIGCHLD
] & SIG_TRAPPED
) == 0 && trap_list
[SIGCHLD
] == (char *)IMPOSSIBLE_TRAP_HANDLER
)
546 set_signal (SIGCHLD
, command_string
);
549 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
550 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
551 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
553 set_impossible_sigchld_trap ()
555 restore_default_signal (SIGCHLD
);
556 change_signal (SIGCHLD
, (char *)IMPOSSIBLE_TRAP_HANDLER
);
557 sigmodes
[SIGCHLD
] &= ~SIG_TRAPPED
; /* maybe_set_sigchld_trap checks this */
560 /* Act as if we received SIGCHLD NCHILD times and increment
561 pending_traps[SIGCHLD] by that amount. This allows us to still run the
562 SIGCHLD trap once for each exited child. */
564 queue_sigchld_trap (nchild
)
570 pending_traps
[SIGCHLD
] += nchild
;
571 trapped_signal_received
= SIGCHLD
;
574 #endif /* JOB_CONTROL && SIGCHLD */
576 /* Set a trap for SIG only if SIG is not already trapped. */
578 trap_if_untrapped (sig
, command
)
582 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
583 set_signal (sig
, command
);
587 set_debug_trap (command
)
590 set_signal (DEBUG_TRAP
, command
);
593 /* Separate function to call when functions and sourced files want to restore
594 the original version of the DEBUG trap before returning. Unless the -T
595 option is set, source and shell function execution save the old debug trap
596 and unset the trap. If the function or sourced file changes the DEBUG trap,
597 SIG_TRAPPED will be set and we don't bother restoring the original trap string.
598 This is used by both functions and the source builtin. */
600 maybe_set_debug_trap (command
)
603 trap_if_untrapped (DEBUG_TRAP
, command
);
607 set_error_trap (command
)
610 set_signal (ERROR_TRAP
, command
);
614 maybe_set_error_trap (command
)
617 trap_if_untrapped (ERROR_TRAP
, command
);
621 set_return_trap (command
)
624 set_signal (RETURN_TRAP
, command
);
628 maybe_set_return_trap (command
)
631 trap_if_untrapped (RETURN_TRAP
, command
);
634 #ifdef INCLUDE_UNUSED
636 set_sigint_trap (command
)
639 set_signal (SIGINT
, command
);
643 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
644 things, like waiting for command substitution or executing commands
645 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
647 set_sigint_handler ()
649 if (sigmodes
[SIGINT
] & SIG_HARD_IGNORE
)
650 return ((SigHandler
*)SIG_IGN
);
652 else if (sigmodes
[SIGINT
] & SIG_IGNORED
)
653 return ((SigHandler
*)set_signal_handler (SIGINT
, SIG_IGN
)); /* XXX */
655 else if (sigmodes
[SIGINT
] & SIG_TRAPPED
)
656 return ((SigHandler
*)set_signal_handler (SIGINT
, trap_handler
));
658 /* The signal is not trapped, so set the handler to the shell's special
659 interrupt handler. */
660 else if (interactive
) /* XXX - was interactive_shell */
661 return (set_signal_handler (SIGINT
, sigint_sighandler
));
663 return (set_signal_handler (SIGINT
, termsig_sighandler
));
666 /* Return the correct handler for signal SIG according to the values in
669 trap_to_sighandler (sig
)
672 if (sigmodes
[sig
] & (SIG_IGNORED
|SIG_HARD_IGNORE
))
674 else if (sigmodes
[sig
] & SIG_TRAPPED
)
675 return (trap_handler
);
680 /* Set SIG to call STRING as a command. */
682 set_signal (sig
, string
)
688 if (SPECIAL_TRAP (sig
))
690 change_signal (sig
, savestring (string
));
691 if (sig
== EXIT_TRAP
&& interactive
== 0)
692 initialize_terminating_signals ();
696 /* A signal ignored on entry to the shell cannot be trapped or reset, but
697 no error is reported when attempting to do so. -- Posix.2 */
698 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
701 /* Make sure we have original_signals[sig] if the signal has not yet
703 if ((sigmodes
[sig
] & SIG_TRAPPED
) == 0)
705 /* If we aren't sure of the original value, check it. */
706 if (original_signals
[sig
] == IMPOSSIBLE_TRAP_HANDLER
)
708 if (original_signals
[sig
] == SIG_IGN
)
712 /* Only change the system signal handler if SIG_NO_TRAP is not set.
713 The trap command string is changed in either case. The shell signal
714 handlers for SIGINT and SIGCHLD run the user specified traps in an
715 environment in which it is safe to do so. */
716 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
718 BLOCK_SIGNAL (sig
, set
, oset
);
719 change_signal (sig
, savestring (string
));
720 set_signal_handler (sig
, trap_handler
);
721 UNBLOCK_SIGNAL (oset
);
724 change_signal (sig
, savestring (string
));
728 free_trap_command (sig
)
731 if ((sigmodes
[sig
] & SIG_TRAPPED
) && trap_list
[sig
] &&
732 (trap_list
[sig
] != (char *)IGNORE_SIG
) &&
733 (trap_list
[sig
] != (char *)DEFAULT_SIG
) &&
734 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
))
735 free (trap_list
[sig
]);
738 /* If SIG has a string assigned to it, get rid of it. Then give it
741 change_signal (sig
, value
)
745 if ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
746 free_trap_command (sig
);
747 trap_list
[sig
] = value
;
749 sigmodes
[sig
] |= SIG_TRAPPED
;
750 if (value
== (char *)IGNORE_SIG
)
751 sigmodes
[sig
] |= SIG_IGNORED
;
753 sigmodes
[sig
] &= ~SIG_IGNORED
;
754 if (sigmodes
[sig
] & SIG_INPROGRESS
)
755 sigmodes
[sig
] |= SIG_CHANGED
;
759 get_original_signal (sig
)
762 /* If we aren't sure the of the original value, then get it. */
763 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
768 get_all_original_signals ()
772 for (i
= 1; i
< NSIG
; i
++)
773 GET_ORIGINAL_SIGNAL (i
);
777 set_original_signal (sig
, handler
)
781 if (sig
> 0 && sig
< NSIG
&& original_signals
[sig
] == (SigHandler
*)IMPOSSIBLE_TRAP_HANDLER
)
782 SETORIGSIG (sig
, handler
);
785 /* Restore the default action for SIG; i.e., the action the shell
786 would have taken before you used the trap command. This is called
787 from trap_builtin (), which takes care to restore the handlers for
788 the signals the shell treats specially. */
790 restore_default_signal (sig
)
793 if (SPECIAL_TRAP (sig
))
795 if ((sig
!= DEBUG_TRAP
&& sig
!= ERROR_TRAP
&& sig
!= RETURN_TRAP
) ||
796 (sigmodes
[sig
] & SIG_INPROGRESS
) == 0)
797 free_trap_command (sig
);
798 trap_list
[sig
] = (char *)NULL
;
799 sigmodes
[sig
] &= ~SIG_TRAPPED
;
800 if (sigmodes
[sig
] & SIG_INPROGRESS
)
801 sigmodes
[sig
] |= SIG_CHANGED
;
805 GET_ORIGINAL_SIGNAL (sig
);
807 /* A signal ignored on entry to the shell cannot be trapped or reset, but
808 no error is reported when attempting to do so. Thanks Posix.2. */
809 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
812 /* If we aren't trapping this signal, don't bother doing anything else. */
813 /* We special-case SIGCHLD and IMPOSSIBLE_TRAP_HANDLER (see above) as a
814 sentinel to determine whether or not disposition is reset to the default
815 while the trap handler is executing. */
816 if (((sigmodes
[sig
] & SIG_TRAPPED
) == 0) &&
817 (sig
!= SIGCHLD
|| (sigmodes
[sig
] & SIG_INPROGRESS
) == 0 || trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
))
820 /* Only change the signal handler for SIG if it allows it. */
821 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
822 set_signal_handler (sig
, original_signals
[sig
]);
824 /* Change the trap command in either case. */
825 change_signal (sig
, (char *)DEFAULT_SIG
);
827 /* Mark the signal as no longer trapped. */
828 sigmodes
[sig
] &= ~SIG_TRAPPED
;
831 /* Make this signal be ignored. */
836 if (SPECIAL_TRAP (sig
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
838 change_signal (sig
, (char *)IGNORE_SIG
);
842 GET_ORIGINAL_SIGNAL (sig
);
844 /* A signal ignored on entry to the shell cannot be trapped or reset.
845 No error is reported when the user attempts to do so. */
846 if (sigmodes
[sig
] & SIG_HARD_IGNORE
)
849 /* If already trapped and ignored, no change necessary. */
850 if (sigmodes
[sig
] & SIG_IGNORED
)
853 /* Only change the signal handler for SIG if it allows it. */
854 if ((sigmodes
[sig
] & SIG_NO_TRAP
) == 0)
855 set_signal_handler (sig
, SIG_IGN
);
857 /* Change the trap command in either case. */
858 change_signal (sig
, (char *)IGNORE_SIG
);
861 /* Handle the calling of "trap 0". The only sticky situation is when
862 the command to be executed includes an "exit". This is why we have
863 to provide our own place for top_level to jump to. */
868 int code
, function_code
, retval
;
869 #if defined (ARRAY_VARS)
873 trap_saved_exit_value
= last_command_exit_value
;
874 #if defined (ARRAY_VARS)
875 ps
= save_pipestatus_array ();
879 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
880 currently running in the trap handler (call to exit in the list of
881 commands given to trap 0). */
882 if ((sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
) &&
883 (sigmodes
[EXIT_TRAP
] & (SIG_IGNORED
|SIG_INPROGRESS
)) == 0)
885 trap_command
= savestring (trap_list
[EXIT_TRAP
]);
886 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
887 sigmodes
[EXIT_TRAP
] |= SIG_INPROGRESS
;
889 retval
= trap_saved_exit_value
;
892 code
= setjmp_nosigs (top_level
);
894 /* If we're in a function, make sure return longjmps come here, too. */
895 if (return_catch_flag
)
896 function_code
= setjmp_nosigs (return_catch
);
898 if (code
== 0 && function_code
== 0)
901 parse_and_execute (trap_command
, "exit trap", SEVAL_NONINT
|SEVAL_NOHIST
|SEVAL_RESETLINE
);
903 else if (code
== ERREXIT
)
904 retval
= last_command_exit_value
;
905 else if (code
== EXITPROG
)
906 retval
= last_command_exit_value
;
907 else if (function_code
!= 0)
908 retval
= return_catch_value
;
910 retval
= trap_saved_exit_value
;
913 #if defined (ARRAY_VARS)
920 #if defined (ARRAY_VARS)
921 restore_pipestatus_array (ps
);
923 return (trap_saved_exit_value
);
927 run_trap_cleanup (sig
)
930 sigmodes
[sig
] &= ~(SIG_INPROGRESS
|SIG_CHANGED
);
933 #define RECURSIVE_SIG(s) (SPECIAL_TRAP(s) == 0)
935 /* Run a trap command for SIG. SIG is one of the signals the shell treats
936 specially. Returns the exit status of the executed trap command list. */
938 _run_trap_internal (sig
, tag
)
942 char *trap_command
, *old_trap
;
943 int trap_exit_value
, *token_state
;
944 volatile int save_return_catch_flag
, function_code
, top_level_code
, old_int
;
946 procenv_t save_return_catch
;
947 WORD_LIST
*save_subst_varlist
;
948 HASH_TABLE
*save_tempenv
;
949 sh_parser_state_t pstate
;
950 #if defined (ARRAY_VARS)
954 trap_exit_value
= function_code
= 0;
955 trap_saved_exit_value
= last_command_exit_value
;
956 /* Run the trap only if SIG is trapped and not ignored, and we are not
957 currently executing in the trap handler. */
958 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0) &&
959 (trap_list
[sig
] != (char *)IMPOSSIBLE_TRAP_HANDLER
) &&
961 /* Uncomment this to allow some special signals to recursively execute
963 (RECURSIVE_SIG (sig
) || (sigmodes
[sig
] & SIG_INPROGRESS
) == 0))
965 ((sigmodes
[sig
] & SIG_INPROGRESS
) == 0))
968 old_trap
= trap_list
[sig
];
969 sigmodes
[sig
] |= SIG_INPROGRESS
;
970 sigmodes
[sig
] &= ~SIG_CHANGED
; /* just to be sure */
971 trap_command
= savestring (old_trap
);
973 running_trap
= sig
+ 1;
975 old_int
= interrupt_state
; /* temporarily suppress pending interrupts */
978 #if defined (ARRAY_VARS)
979 ps
= save_pipestatus_array ();
982 save_parser_state (&pstate
);
983 save_subst_varlist
= subst_assign_varlist
;
984 subst_assign_varlist
= 0;
985 save_tempenv
= temporary_env
;
986 temporary_env
= 0; /* traps should not run with temporary env */
988 #if defined (JOB_CONTROL)
989 if (sig
!= DEBUG_TRAP
) /* run_debug_trap does this */
990 save_pipeline (1); /* XXX only provides one save level */
993 /* If we're in a function, make sure return longjmps come here, too. */
994 save_return_catch_flag
= return_catch_flag
;
995 if (return_catch_flag
)
997 COPY_PROCENV (return_catch
, save_return_catch
);
998 function_code
= setjmp_nosigs (return_catch
);
1001 flags
= SEVAL_NONINT
|SEVAL_NOHIST
;
1002 if (sig
!= DEBUG_TRAP
&& sig
!= RETURN_TRAP
&& sig
!= ERROR_TRAP
)
1003 flags
|= SEVAL_RESETLINE
;
1004 if (function_code
== 0)
1006 parse_and_execute (trap_command
, tag
, flags
);
1007 trap_exit_value
= last_command_exit_value
;
1010 trap_exit_value
= return_catch_value
;
1012 #if defined (JOB_CONTROL)
1013 if (sig
!= DEBUG_TRAP
) /* run_debug_trap does this */
1014 restore_pipeline (1);
1017 subst_assign_varlist
= save_subst_varlist
;
1018 restore_parser_state (&pstate
);
1020 #if defined (ARRAY_VARS)
1021 restore_pipestatus_array (ps
);
1024 temporary_env
= save_tempenv
;
1026 sigmodes
[sig
] &= ~SIG_INPROGRESS
;
1028 interrupt_state
= old_int
;
1030 if (sigmodes
[sig
] & SIG_CHANGED
)
1033 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
1034 the places where they can be changed using unwind-protects. For
1035 example, look at execute_cmd.c:execute_function(). */
1036 if (SPECIAL_TRAP (sig
) == 0)
1039 sigmodes
[sig
] &= ~SIG_CHANGED
;
1042 if (save_return_catch_flag
)
1044 return_catch_flag
= save_return_catch_flag
;
1045 return_catch_value
= trap_exit_value
;
1046 COPY_PROCENV (save_return_catch
, return_catch
);
1050 from_return_trap
= sig
== RETURN_TRAP
;
1052 sh_longjmp (return_catch
, 1);
1057 return trap_exit_value
;
1063 int trap_exit_value
;
1067 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
1068 trap_exit_value
= 0;
1069 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[DEBUG_TRAP
] & SIG_IGNORED
) == 0) && ((sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
) == 0))
1071 #if defined (JOB_CONTROL)
1072 save_pgrp
= pipeline_pgrp
;
1075 # if defined (PGRP_PIPE)
1076 save_pgrp_pipe (save_pipe
, 1);
1078 stop_making_children ();
1081 trap_exit_value
= _run_trap_internal (DEBUG_TRAP
, "debug trap");
1083 #if defined (JOB_CONTROL)
1084 pipeline_pgrp
= save_pgrp
;
1085 restore_pipeline (1);
1086 # if defined (PGRP_PIPE)
1088 restore_pgrp_pipe (save_pipe
);
1090 if (pipeline_pgrp
> 0)
1091 give_terminal_to (pipeline_pgrp
, 1);
1092 notify_and_cleanup ();
1095 #if defined (DEBUGGER)
1096 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
1097 a function or sourced script, we force a `return'. */
1098 if (debugging_mode
&& trap_exit_value
== 2 && return_catch_flag
)
1100 return_catch_value
= trap_exit_value
;
1101 sh_longjmp (return_catch
, 1);
1105 return trap_exit_value
;
1111 if ((sigmodes
[ERROR_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[ERROR_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[ERROR_TRAP
] & SIG_INPROGRESS
) == 0)
1112 _run_trap_internal (ERROR_TRAP
, "error trap");
1121 if ((sigmodes
[DEBUG_TRAP
] & SIG_TRAPPED
) && (sigmodes
[DEBUG_TRAP
] & SIG_INPROGRESS
))
1125 if ((sigmodes
[RETURN_TRAP
] & SIG_TRAPPED
) && ((sigmodes
[RETURN_TRAP
] & SIG_IGNORED
) == 0) && (sigmodes
[RETURN_TRAP
] & SIG_INPROGRESS
) == 0)
1127 old_exit_value
= last_command_exit_value
;
1128 _run_trap_internal (RETURN_TRAP
, "return trap");
1129 last_command_exit_value
= old_exit_value
;
1133 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1134 declared here to localize the trap functions. */
1136 run_interrupt_trap (will_throw
)
1137 int will_throw
; /* from throw_to_top_level? */
1139 if (will_throw
&& running_trap
> 0)
1140 run_trap_cleanup (running_trap
- 1);
1141 _run_trap_internal (SIGINT
, "interrupt trap");
1144 /* Free all the allocated strings in the list of traps and reset the trap
1145 values to the default. Intended to be called from subshells that want
1146 to complete work done by reset_signal_handlers upon execution of a
1147 subsequent `trap' command that changes a signal's disposition. We need
1148 to make sure that we duplicate the behavior of
1149 reset_or_restore_signal_handlers and not change the disposition of signals
1150 that are set to be ignored. */
1152 free_trap_strings ()
1156 for (i
= 0; i
< NSIG
; i
++)
1158 if (trap_list
[i
] != (char *)IGNORE_SIG
)
1159 free_trap_string (i
);
1161 for (i
= NSIG
; i
< BASH_NSIG
; i
++)
1163 /* Don't free the trap string if the subshell inherited the trap */
1164 if ((sigmodes
[i
] & SIG_TRAPPED
) == 0)
1166 free_trap_string (i
);
1167 trap_list
[i
] = (char *)NULL
;
1172 /* Free a trap command string associated with SIG without changing signal
1173 disposition. Intended to be called from free_trap_strings() */
1175 free_trap_string (sig
)
1178 change_signal (sig
, (char *)DEFAULT_SIG
);
1179 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1182 /* Reset the handler for SIG to the original value but leave the trap string
1188 set_signal_handler (sig
, original_signals
[sig
]);
1189 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1192 /* Set the handler signal SIG to the original and free any trap
1193 command associated with it. */
1195 restore_signal (sig
)
1198 set_signal_handler (sig
, original_signals
[sig
]);
1199 change_signal (sig
, (char *)DEFAULT_SIG
);
1200 sigmodes
[sig
] &= ~SIG_TRAPPED
;
1204 reset_or_restore_signal_handlers (reset
)
1205 sh_resetsig_func_t
*reset
;
1209 /* Take care of the exit trap first */
1210 if (sigmodes
[EXIT_TRAP
] & SIG_TRAPPED
)
1212 sigmodes
[EXIT_TRAP
] &= ~SIG_TRAPPED
;
1213 if (reset
!= reset_signal
)
1215 free_trap_command (EXIT_TRAP
);
1216 trap_list
[EXIT_TRAP
] = (char *)NULL
;
1220 for (i
= 1; i
< NSIG
; i
++)
1222 if (sigmodes
[i
] & SIG_TRAPPED
)
1224 if (trap_list
[i
] == (char *)IGNORE_SIG
)
1225 set_signal_handler (i
, SIG_IGN
);
1229 else if (sigmodes
[i
] & SIG_SPECIAL
)
1231 pending_traps
[i
] = 0; /* XXX */
1234 /* Command substitution and other child processes don't inherit the
1235 debug, error, or return traps. If we're in the debugger, and the
1236 `functrace' or `errtrace' options have been set, then let command
1237 substitutions inherit them. Let command substitution inherit the
1238 RETURN trap if we're in the debugger and tracing functions. */
1239 if (function_trace_mode
== 0)
1241 sigmodes
[DEBUG_TRAP
] &= ~SIG_TRAPPED
;
1242 sigmodes
[RETURN_TRAP
] &= ~SIG_TRAPPED
;
1244 if (error_trace_mode
== 0)
1245 sigmodes
[ERROR_TRAP
] &= ~SIG_TRAPPED
;
1248 /* Reset trapped signals to their original values, but don't free the
1249 trap strings. Called by the command substitution code and other places
1250 that create a "subshell environment". */
1252 reset_signal_handlers ()
1254 reset_or_restore_signal_handlers (reset_signal
);
1257 /* Reset all trapped signals to their original values. Signals set to be
1258 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1259 are. Called by child processes after they are forked. */
1261 restore_original_signals ()
1263 reset_or_restore_signal_handlers (restore_signal
);
1266 /* If a trap handler exists for signal SIG, then call it; otherwise just
1267 return failure. Returns 1 if it called the trap handler. */
1269 maybe_call_trap_handler (sig
)
1272 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
1273 if ((sigmodes
[sig
] & SIG_TRAPPED
) && ((sigmodes
[sig
] & SIG_IGNORED
) == 0))
1278 run_interrupt_trap (0);
1300 signal_is_trapped (sig
)
1303 return (sigmodes
[sig
] & SIG_TRAPPED
);
1307 signal_is_pending (sig
)
1310 return (pending_traps
[sig
]);
1314 signal_is_special (sig
)
1317 return (sigmodes
[sig
] & SIG_SPECIAL
);
1321 signal_is_ignored (sig
)
1324 return (sigmodes
[sig
] & SIG_IGNORED
);
1328 signal_is_hard_ignored (sig
)
1331 return (sigmodes
[sig
] & SIG_HARD_IGNORE
);
1335 set_signal_hard_ignored (sig
)
1338 sigmodes
[sig
] |= SIG_HARD_IGNORE
;
1339 original_signals
[sig
] = SIG_IGN
;
1343 set_signal_ignored (sig
)
1346 original_signals
[sig
] = SIG_IGN
;
1350 signal_in_progress (sig
)
1353 return (sigmodes
[sig
] & SIG_INPROGRESS
);