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, 1991 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 it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
24 #if defined (HAVE_UNISTD_H)
28 #include "bashtypes.h"
37 #include "input.h" /* for save_token_state, restore_token_state */
39 #include "builtins/common.h"
45 /* Flags which describe the current handling state of a signal. */
46 #define SIG_INHERITED 0x0 /* Value inherited from parent. */
47 #define SIG_TRAPPED 0x1 /* Currently trapped. */
48 #define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
49 #define SIG_SPECIAL 0x4 /* Treat this signal specially. */
50 #define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
51 #define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
52 #define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
53 #define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
55 #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP)
57 /* An array of such flags, one for each signal, describing what the
58 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
60 static int sigmodes[BASH_NSIG];
62 static void free_trap_command __P((int));
63 static void change_signal __P((int, char *));
65 static void get_original_signal __P((int));
67 static void _run_trap_internal __P((int, char *));
69 static void reset_signal __P((int));
70 static void restore_signal __P((int));
71 static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
73 /* Variables used here but defined in other files. */
74 extern int interrupt_immediately;
75 extern int last_command_exit_value;
76 extern int line_number;
78 /* The list of things to do originally, before we started trapping. */
79 SigHandler *original_signals[NSIG];
81 /* For each signal, a slot for a string, which is a command to be
82 executed when that signal is recieved. The slot can also contain
83 DEFAULT_SIG, which means do whatever you were going to do before
84 you were so rudely interrupted, or IGNORE_SIG, which says ignore
86 char *trap_list[BASH_NSIG];
88 /* A bitmap of signals received for which we have trap handlers. */
89 int pending_traps[NSIG];
91 /* Set to the number of the signal we're running the trap for + 1.
92 Used in execute_cmd.c and builtins/common.c to clean up when
93 parse_and_execute does not return normally after executing the
94 trap command (e.g., when `return' is executed in the trap command). */
97 /* The value of line_number when the trap started executing, since
98 parse_and_execute resets it to 1 and the trap command might want
100 int trap_line_number;
102 /* A value which can never be the target of a trap handler. */
103 #define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
110 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = (char *)NULL;
111 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = SIG_INHERITED;
112 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
114 for (i = 1; i < NSIG; i++)
116 pending_traps[i] = 0;
117 trap_list[i] = (char *)DEFAULT_SIG;
118 sigmodes[i] = SIG_INHERITED;
119 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
122 /* Show which signals are treated specially by the shell. */
123 #if defined (SIGCHLD)
124 original_signals[SIGCHLD] =
125 (SigHandler *) set_signal_handler (SIGCHLD, SIG_DFL);
126 set_signal_handler (SIGCHLD, original_signals[SIGCHLD]);
127 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
130 original_signals[SIGINT] =
131 (SigHandler *) set_signal_handler (SIGINT, SIG_DFL);
132 set_signal_handler (SIGINT, original_signals[SIGINT]);
133 sigmodes[SIGINT] |= SIG_SPECIAL;
135 #if defined (__BEOS__)
136 /* BeOS sets SIGINT to SIG_IGN! */
137 original_signals[SIGINT] = SIG_DFL;
140 original_signals[SIGQUIT] =
141 (SigHandler *) set_signal_handler (SIGQUIT, SIG_DFL);
142 set_signal_handler (SIGQUIT, original_signals[SIGQUIT]);
143 sigmodes[SIGQUIT] |= SIG_SPECIAL;
147 original_signals[SIGTERM] =
148 (SigHandler *)set_signal_handler (SIGTERM, SIG_DFL);
149 set_signal_handler (SIGTERM, original_signals[SIGTERM]);
150 sigmodes[SIGTERM] |= SIG_SPECIAL;
154 #ifdef INCLUDE_UNUSED
155 /* Return a printable representation of the trap handler for SIG. */
157 trap_handler_string (sig)
160 if (trap_list[sig] == (char *)DEFAULT_SIG)
161 return "DEFAULT_SIG";
162 else if (trap_list[sig] == (char *)IGNORE_SIG)
164 else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
165 return "IMPOSSIBLE_TRAP_HANDLER";
166 else if (trap_list[sig])
167 return trap_list[sig];
173 /* Return the print name of this signal. */
180 /* on cygwin32, signal_names[sig] could be null */
181 ret = (sig > NSIG || sig < 0) ? "bad signal number" : signal_names[sig];
183 ret = "unrecognized signal number";
187 /* Turn a string into a signal number, or a number into
188 a signal number. If STRING is "2", "SIGINT", or "INT",
189 then (int)2 is returned. Return NO_SIG if STRING doesn't
190 contain a valid signal descriptor. */
192 decode_signal (string)
197 if (legal_number (string, &sig))
198 return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
200 /* A leading `SIG' may be omitted. */
201 for (sig = 0; sig < BASH_NSIG; sig++)
203 if (signal_names[sig] == 0 || signal_names[sig][0] == '\0')
205 if (strcasecmp (string, signal_names[sig]) == 0 ||
206 (STREQN (signal_names[sig], "SIG", 3) &&
207 strcasecmp (string, &(signal_names[sig])[3]) == 0))
214 /* Non-zero when we catch a trapped signal. */
215 static int catch_flag;
221 int old_exit_value, *token_state;
223 if (catch_flag == 0) /* simple optimization */
228 /* Preserve $? when running trap. */
229 old_exit_value = last_command_exit_value;
231 for (sig = 1; sig < NSIG; sig++)
233 /* XXX this could be made into a counter by using
234 while (pending_traps[sig]--) instead of the if statement. */
235 if (pending_traps[sig])
237 #if defined (HAVE_POSIX_SIGNALS)
243 sigaddset (&set, sig);
244 sigprocmask (SIG_BLOCK, &set, &oset);
246 # if defined (HAVE_BSD_SIGNALS)
247 int oldmask = sigblock (sigmask (sig));
249 #endif /* HAVE_POSIX_SIGNALS */
253 run_interrupt_trap ();
256 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
257 trap_list[sig] == (char *)IGNORE_SIG ||
258 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
260 /* This is possible due to a race condition. Say a bash
261 process has SIGTERM trapped. A subshell is spawned
262 using { list; } & and the parent does something and kills
263 the subshell with SIGTERM. It's possible for the subshell
264 to set pending_traps[SIGTERM] to 1 before the code in
265 execute_cmd.c eventually calls restore_original_signals
266 to reset the SIGTERM signal handler in the subshell. The
267 next time run_pending_traps is called, pending_traps[SIGTERM]
268 will be 1, but the trap handler in trap_list[SIGTERM] will
269 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
270 Unless we catch this, the subshell will dump core when
271 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
273 internal_warning ("run_pending_traps: bad value in trap_list[%d]: %p",
274 sig, trap_list[sig]);
275 if (trap_list[sig] == (char *)DEFAULT_SIG)
277 internal_warning ("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself", sig, signal_name (sig));
278 kill (getpid (), sig);
283 token_state = save_token_state ();
284 parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST);
285 restore_token_state (token_state);
289 pending_traps[sig] = 0;
291 #if defined (HAVE_POSIX_SIGNALS)
292 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
294 # if defined (HAVE_BSD_SIGNALS)
295 sigsetmask (oldmask);
297 #endif /* POSIX_VERSION */
301 last_command_exit_value = old_exit_value;
311 (trap_list[sig] == (char *)DEFAULT_SIG) ||
312 (trap_list[sig] == (char *)IGNORE_SIG))
313 programming_error ("trap_handler: bad signal %d", sig);
317 #if defined (MUST_REINSTALL_SIGHANDLERS)
318 set_signal_handler (sig, trap_handler);
319 #endif /* MUST_REINSTALL_SIGHANDLERS */
322 pending_traps[sig]++;
324 if (interrupt_immediately)
325 run_pending_traps ();
333 #if defined (JOB_CONTROL) && defined (SIGCHLD)
335 #ifdef INCLUDE_UNUSED
336 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
338 set_sigchld_trap (command_string)
339 char *command_string;
341 set_signal (SIGCHLD, command_string);
345 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff the current
346 SIGCHLD trap handler is DEFAULT_SIG. */
348 maybe_set_sigchld_trap (command_string)
349 char *command_string;
351 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
352 set_signal (SIGCHLD, command_string);
354 #endif /* JOB_CONTROL && SIGCHLD */
357 set_debug_trap (command)
360 set_signal (DEBUG_TRAP, command);
364 set_error_trap (command)
367 set_signal (ERROR_TRAP, command);
370 #ifdef INCLUDE_UNUSED
372 set_sigint_trap (command)
375 set_signal (SIGINT, command);
379 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
380 things, like waiting for command substitution or executing commands
381 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
383 set_sigint_handler ()
385 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
386 return ((SigHandler *)SIG_IGN);
388 else if (sigmodes[SIGINT] & SIG_IGNORED)
389 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
391 else if (sigmodes[SIGINT] & SIG_TRAPPED)
392 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
394 /* The signal is not trapped, so set the handler to the shell's special
395 interrupt handler. */
396 else if (interactive) /* XXX - was interactive_shell */
397 return (set_signal_handler (SIGINT, sigint_sighandler));
399 return (set_signal_handler (SIGINT, termination_unwind_protect));
402 /* Return the correct handler for signal SIG according to the values in
405 trap_to_sighandler (sig)
408 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
410 else if (sigmodes[sig] & SIG_TRAPPED)
411 return (trap_handler);
416 /* Set SIG to call STRING as a command. */
418 set_signal (sig, string)
422 if (SPECIAL_TRAP (sig))
424 change_signal (sig, savestring (string));
425 if (sig == EXIT_TRAP && interactive == 0)
426 initialize_terminating_signals ();
430 /* A signal ignored on entry to the shell cannot be trapped or reset, but
431 no error is reported when attempting to do so. -- Posix.2 */
432 if (sigmodes[sig] & SIG_HARD_IGNORE)
435 /* Make sure we have original_signals[sig] if the signal has not yet
437 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
439 /* If we aren't sure of the original value, check it. */
440 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
442 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
443 set_signal_handler (sig, original_signals[sig]);
446 /* Signals ignored on entry to the shell cannot be trapped or reset. */
447 if (original_signals[sig] == SIG_IGN)
449 sigmodes[sig] |= SIG_HARD_IGNORE;
454 /* Only change the system signal handler if SIG_NO_TRAP is not set.
455 The trap command string is changed in either case. The shell signal
456 handlers for SIGINT and SIGCHLD run the user specified traps in an
457 environment in which it is safe to do so. */
458 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
460 set_signal_handler (sig, SIG_IGN);
461 change_signal (sig, savestring (string));
462 set_signal_handler (sig, trap_handler);
465 change_signal (sig, savestring (string));
469 free_trap_command (sig)
472 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
473 (trap_list[sig] != (char *)IGNORE_SIG) &&
474 (trap_list[sig] != (char *)DEFAULT_SIG) &&
475 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
476 free (trap_list[sig]);
479 /* If SIG has a string assigned to it, get rid of it. Then give it
482 change_signal (sig, value)
486 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
487 free_trap_command (sig);
488 trap_list[sig] = value;
490 sigmodes[sig] |= SIG_TRAPPED;
491 if (value == (char *)IGNORE_SIG)
492 sigmodes[sig] |= SIG_IGNORED;
494 sigmodes[sig] &= ~SIG_IGNORED;
495 if (sigmodes[sig] & SIG_INPROGRESS)
496 sigmodes[sig] |= SIG_CHANGED;
499 #define GET_ORIGINAL_SIGNAL(sig) \
500 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
501 get_original_signal (sig)
504 get_original_signal (sig)
507 /* If we aren't sure the of the original value, then get it. */
508 if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
510 original_signals[sig] =
511 (SigHandler *) set_signal_handler (sig, SIG_DFL);
512 set_signal_handler (sig, original_signals[sig]);
514 /* Signals ignored on entry to the shell cannot be trapped. */
515 if (original_signals[sig] == SIG_IGN)
516 sigmodes[sig] |= SIG_HARD_IGNORE;
520 /* Restore the default action for SIG; i.e., the action the shell
521 would have taken before you used the trap command. This is called
522 from trap_builtin (), which takes care to restore the handlers for
523 the signals the shell treats specially. */
525 restore_default_signal (sig)
528 if (SPECIAL_TRAP (sig))
530 if ((sig != DEBUG_TRAP && sig != ERROR_TRAP) || (sigmodes[sig] & SIG_INPROGRESS) == 0)
531 free_trap_command (sig);
532 trap_list[sig] = (char *)NULL;
533 sigmodes[sig] &= ~SIG_TRAPPED;
534 if (sigmodes[sig] & SIG_INPROGRESS)
535 sigmodes[sig] |= SIG_CHANGED;
539 GET_ORIGINAL_SIGNAL (sig);
541 /* A signal ignored on entry to the shell cannot be trapped or reset, but
542 no error is reported when attempting to do so. Thanks Posix.2. */
543 if (sigmodes[sig] & SIG_HARD_IGNORE)
546 /* If we aren't trapping this signal, don't bother doing anything else. */
547 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
550 /* Only change the signal handler for SIG if it allows it. */
551 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
552 set_signal_handler (sig, original_signals[sig]);
554 /* Change the trap command in either case. */
555 change_signal (sig, (char *)DEFAULT_SIG);
557 /* Mark the signal as no longer trapped. */
558 sigmodes[sig] &= ~SIG_TRAPPED;
561 /* Make this signal be ignored. */
566 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
568 change_signal (sig, (char *)IGNORE_SIG);
572 GET_ORIGINAL_SIGNAL (sig);
574 /* A signal ignored on entry to the shell cannot be trapped or reset.
575 No error is reported when the user attempts to do so. */
576 if (sigmodes[sig] & SIG_HARD_IGNORE)
579 /* If already trapped and ignored, no change necessary. */
580 if (sigmodes[sig] & SIG_IGNORED)
583 /* Only change the signal handler for SIG if it allows it. */
584 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
585 set_signal_handler (sig, SIG_IGN);
587 /* Change the trap command in either case. */
588 change_signal (sig, (char *)IGNORE_SIG);
591 /* Handle the calling of "trap 0". The only sticky situation is when
592 the command to be executed includes an "exit". This is why we have
593 to provide our own place for top_level to jump to. */
598 int code, old_exit_value;
600 old_exit_value = last_command_exit_value;
602 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
603 currently running in the trap handler (call to exit in the list of
604 commands given to trap 0). */
605 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
606 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
608 trap_command = savestring (trap_list[EXIT_TRAP]);
609 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
610 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
612 code = setjmp (top_level);
617 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST);
619 else if (code == EXITPROG)
620 return (last_command_exit_value);
622 return (old_exit_value);
625 return (old_exit_value);
629 run_trap_cleanup (sig)
632 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
635 /* Run a trap command for SIG. SIG is one of the signals the shell treats
638 _run_trap_internal (sig, tag)
642 char *trap_command, *old_trap;
643 int old_exit_value, *token_state;
645 /* Run the trap only if SIG is trapped and not ignored, and we are not
646 currently executing in the trap handler. */
647 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
648 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
649 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
651 old_trap = trap_list[sig];
652 sigmodes[sig] |= SIG_INPROGRESS;
653 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
654 trap_command = savestring (old_trap);
656 running_trap = sig + 1;
657 old_exit_value = last_command_exit_value;
658 /* Need to copy the value of line_number because parse_and_execute
659 resets it to 1, and the trap command might want it. */
660 trap_line_number = line_number;
662 token_state = save_token_state ();
663 parse_and_execute (trap_command, tag, SEVAL_NONINT|SEVAL_NOHIST);
664 restore_token_state (token_state);
667 last_command_exit_value = old_exit_value;
670 sigmodes[sig] &= ~SIG_INPROGRESS;
672 if (sigmodes[sig] & SIG_CHANGED)
675 sigmodes[sig] &= ~SIG_CHANGED;
683 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0)
684 _run_trap_internal (DEBUG_TRAP, "debug trap");
690 if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
691 _run_trap_internal (ERROR_TRAP, "error trap");
694 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
695 declared here to localize the trap functions. */
697 run_interrupt_trap ()
699 _run_trap_internal (SIGINT, "interrupt trap");
702 #ifdef INCLUDE_UNUSED
703 /* Free all the allocated strings in the list of traps and reset the trap
704 values to the default. */
710 for (i = 0; i < BASH_NSIG; i++)
712 free_trap_command (i);
713 trap_list[i] = (char *)DEFAULT_SIG;
714 sigmodes[i] &= ~SIG_TRAPPED;
716 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = (char *)NULL;
720 /* Reset the handler for SIG to the original value. */
725 set_signal_handler (sig, original_signals[sig]);
728 /* Set the handler signal SIG to the original and free any trap
729 command associated with it. */
734 set_signal_handler (sig, original_signals[sig]);
735 change_signal (sig, (char *)DEFAULT_SIG);
736 sigmodes[sig] &= ~SIG_TRAPPED;
740 reset_or_restore_signal_handlers (reset)
741 sh_resetsig_func_t *reset;
745 /* Take care of the exit trap first */
746 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
748 free_trap_command (EXIT_TRAP);
749 trap_list[EXIT_TRAP] = (char *)NULL;
750 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
752 for (i = 1; i < NSIG; i++)
754 if (sigmodes[i] & SIG_TRAPPED)
756 if (trap_list[i] == (char *)IGNORE_SIG)
757 set_signal_handler (i, SIG_IGN);
761 else if (sigmodes[i] & SIG_SPECIAL)
765 /* Command substitution and other child processes don't inherit the
766 debug or error traps. */
767 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
768 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
771 /* Reset trapped signals to their original values, but don't free the
772 trap strings. Called by the command substitution code. */
774 reset_signal_handlers ()
776 reset_or_restore_signal_handlers (reset_signal);
779 /* Reset all trapped signals to their original values. Signals set to be
780 ignored with trap '' SIGNAL should be ignored, so we make sure that they
781 are. Called by child processes after they are forked. */
783 restore_original_signals ()
785 reset_or_restore_signal_handlers (restore_signal);
788 /* If a trap handler exists for signal SIG, then call it; otherwise just
791 maybe_call_trap_handler (sig)
794 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
795 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
800 run_interrupt_trap ();
822 signal_is_trapped (sig)
825 return (sigmodes[sig] & SIG_TRAPPED);
829 signal_is_special (sig)
832 return (sigmodes[sig] & SIG_SPECIAL);
836 signal_is_ignored (sig)
839 return (sigmodes[sig] & SIG_IGNORED);
843 set_signal_ignored (sig)
846 sigmodes[sig] |= SIG_HARD_IGNORE;
847 original_signals[sig] = SIG_IGN;