]> git.ipfire.org Git - thirdparty/bash.git/blob - trap.c
Bash-4.4 patch 6
[thirdparty/bash.git] / trap.c
1 /* trap.c -- Not the trap command, but useful functions for manipulating
2 those objects. The trap command is in builtins/trap.def. */
3
4 /* Copyright (C) 1987-2015 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
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.
12
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.
17
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/>.
20 */
21
22 #include "config.h"
23
24 #if defined (HAVE_UNISTD_H)
25 # include <unistd.h>
26 #endif
27
28 #include "bashtypes.h"
29 #include "bashansi.h"
30
31 #include <stdio.h>
32 #include <errno.h>
33
34 #include "bashintl.h"
35
36 #include <signal.h>
37
38 #include "trap.h"
39
40 #include "shell.h"
41 #include "flags.h"
42 #include "input.h" /* for save_token_state, restore_token_state */
43 #include "jobs.h"
44 #include "signames.h"
45 #include "builtins.h"
46 #include "builtins/common.h"
47 #include "builtins/builtext.h"
48
49 #if defined (READLINE)
50 # include <readline/readline.h>
51 # include "bashline.h"
52 #endif
53
54 #ifndef errno
55 extern int errno;
56 #endif
57
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. */
67
68 #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
69
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
72 assumes this. */
73 static int sigmodes[BASH_NSIG];
74
75 static void free_trap_command (int);
76 static void change_signal (int, char *);
77
78 static int _run_trap_internal (int, char *);
79
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 *);
84
85 static void trap_if_untrapped (int, char *);
86
87 /* Variables used here but defined in other files. */
88 extern int last_command_exit_value;
89 extern int line_number;
90
91 extern int sigalrm_seen;
92 extern procenv_t alrmbuf;
93
94 extern volatile int from_return_trap;
95
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;
103
104 /* The list of things to do originally, before we started trapping. */
105 SigHandler *original_signals[NSIG];
106
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
111 this signal. */
112 char *trap_list[BASH_NSIG];
113
114 /* A bitmap of signals received for which we have trap handlers. */
115 int pending_traps[NSIG];
116
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). */
121 int running_trap;
122
123 /* Set to last_command_exit_value before running a trap. */
124 int trap_saved_exit_value;
125
126 /* The (trapped) signal received while executing in the `wait' builtin */
127 int wait_signal_received;
128
129 int trapped_signal_received;
130
131 #define GETORIGSIG(sig) \
132 do { \
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; \
137 } while (0)
138
139 #define SETORIGSIG(sig,handler) \
140 do { \
141 original_signals[sig] = handler; \
142 if (original_signals[sig] == SIG_IGN) \
143 sigmodes[sig] |= SIG_HARD_IGNORE; \
144 } while (0)
145
146 #define GET_ORIGINAL_SIGNAL(sig) \
147 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
148 GETORIGSIG(sig)
149
150 void
151 initialize_traps ()
152 {
153 register int i;
154
155 initialize_signames();
156
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;
160
161 for (i = 1; i < NSIG; i++)
162 {
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;
167 }
168
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);
173 #endif /* SIGCHLD */
174
175 GETORIGSIG (SIGINT);
176 sigmodes[SIGINT] |= SIG_SPECIAL;
177
178 #if defined (__BEOS__)
179 /* BeOS sets SIGINT to SIG_IGN! */
180 original_signals[SIGINT] = SIG_DFL;
181 sigmodes[SIGINT] &= ~SIG_HARD_IGNORE;
182 #endif
183
184 GETORIGSIG (SIGQUIT);
185 sigmodes[SIGQUIT] |= SIG_SPECIAL;
186
187 if (interactive)
188 {
189 GETORIGSIG (SIGTERM);
190 sigmodes[SIGTERM] |= SIG_SPECIAL;
191 }
192
193 get_original_tty_job_signals ();
194 }
195
196 #ifdef DEBUG
197 /* Return a printable representation of the trap handler for SIG. */
198 static char *
199 trap_handler_string (sig)
200 int sig;
201 {
202 if (trap_list[sig] == (char *)DEFAULT_SIG)
203 return "DEFAULT_SIG";
204 else if (trap_list[sig] == (char *)IGNORE_SIG)
205 return "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];
210 else
211 return "NULL";
212 }
213 #endif
214
215 /* Return the print name of this signal. */
216 char *
217 signal_name (sig)
218 int sig;
219 {
220 char *ret;
221
222 /* on cygwin32, signal_names[sig] could be null */
223 ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
224 ? _("invalid signal number")
225 : signal_names[sig];
226
227 return ret;
228 }
229
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. */
234 int
235 decode_signal (string, flags)
236 char *string;
237 int flags;
238 {
239 intmax_t sig;
240 char *name;
241
242 if (legal_number (string, &sig))
243 return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
244
245 /* A leading `SIG' may be omitted. */
246 for (sig = 0; sig < BASH_NSIG; sig++)
247 {
248 name = signal_names[sig];
249 if (name == 0 || name[0] == '\0')
250 continue;
251
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))
255 {
256 name += 3;
257
258 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
259 return ((int)sig);
260 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
261 return ((int)sig);
262 /* If we can't use the `SIG' prefix to match, punt on this
263 name now. */
264 else if ((flags & DSIG_SIGPREFIX) == 0)
265 continue;
266 }
267
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)
272 return ((int)sig);
273 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
274 return ((int)sig);
275 }
276
277 return (NO_SIG);
278 }
279
280 /* Non-zero when we catch a trapped signal. */
281 static int catch_flag;
282
283 void
284 run_pending_traps ()
285 {
286 register int sig;
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)
292 ARRAY *ps;
293 #endif
294
295 if (catch_flag == 0) /* simple optimization */
296 return;
297
298 if (running_trap > 0)
299 {
300 #if defined (DEBUG)
301 internal_warning ("run_pending_traps: recursive invocation while running trap for signal %d", running_trap-1);
302 #endif
303 #if defined (SIGWINCH)
304 if (running_trap == SIGWINCH+1 && pending_traps[SIGWINCH])
305 return; /* no recursive SIGWINCH trap invocations */
306 #else
307 ;
308 #endif
309 }
310
311 catch_flag = trapped_signal_received = 0;
312
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 ();
317 #endif
318
319 for (sig = 1; sig < NSIG; sig++)
320 {
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])
324 {
325 if (running_trap == sig+1)
326 /*continue*/;
327
328 running_trap = sig + 1;
329
330 if (sig == SIGINT)
331 {
332 pending_traps[sig] = 0; /* XXX */
333 run_interrupt_trap (0);
334 CLRINTERRUPT;
335 }
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)
340 {
341 sigmodes[SIGCHLD] |= SIG_INPROGRESS;
342 x = pending_traps[sig];
343 pending_traps[sig] = 0;
344 run_sigchld_trap (x); /* use as counter */
345 running_trap = 0;
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. */
350 continue;
351 }
352 else if (sig == SIGCHLD &&
353 trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER &&
354 (sigmodes[SIGCHLD] & SIG_INPROGRESS) != 0)
355 {
356 /* This can happen when run_pending_traps is called while
357 running a SIGCHLD trap handler. */
358 running_trap = 0;
359 /* want to leave pending_traps[SIGCHLD] alone here */
360 continue; /* XXX */
361 }
362 else if (sig == SIGCHLD && (sigmodes[SIGCHLD] & SIG_INPROGRESS))
363 {
364 /* whoops -- print warning? */
365 running_trap = 0; /* XXX */
366 /* want to leave pending_traps[SIGCHLD] alone here */
367 continue;
368 }
369 #endif
370 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
371 trap_list[sig] == (char *)IGNORE_SIG ||
372 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
373 {
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
386 usually 0x0. */
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)
390 {
391 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
392 kill (getpid (), sig);
393 }
394 }
395 else
396 {
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 */
403
404 #if defined (JOB_CONTROL)
405 save_pipeline (1); /* XXX only provides one save level */
406 #endif
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);
412 #endif
413
414 subst_assign_varlist = save_subst_varlist;
415 restore_parser_state (&pstate);
416 temporary_env = save_tempenv;
417 }
418
419 pending_traps[sig] = 0; /* XXX - move before evalstring? */
420 running_trap = 0;
421 }
422 }
423
424 #if defined (ARRAY_VARS)
425 restore_pipestatus_array (ps);
426 #endif
427 last_command_exit_value = old_exit_value;
428 }
429
430 sighandler
431 trap_handler (sig)
432 int sig;
433 {
434 int oerrno;
435
436 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
437 {
438 #if defined (DEBUG)
439 internal_warning ("trap_handler: signal %d: signal not trapped", sig);
440 #endif
441 SIGRETURN (0);
442 }
443
444 if ((sig >= NSIG) ||
445 (trap_list[sig] == (char *)DEFAULT_SIG) ||
446 (trap_list[sig] == (char *)IGNORE_SIG))
447 programming_error (_("trap_handler: bad signal %d"), sig);
448 else
449 {
450 oerrno = errno;
451 #if defined (MUST_REINSTALL_SIGHANDLERS)
452 # if defined (JOB_CONTROL) && defined (SIGCHLD)
453 if (sig != SIGCHLD)
454 # endif /* JOB_CONTROL && SIGCHLD */
455 set_signal_handler (sig, trap_handler);
456 #endif /* MUST_REINSTALL_SIGHANDLERS */
457
458 catch_flag = 1;
459 pending_traps[sig]++;
460 trapped_signal_received = sig;
461
462 if (this_shell_builtin && (this_shell_builtin == wait_builtin))
463 {
464 wait_signal_received = sig;
465 if (interrupt_immediately && wait_intr_flag)
466 sh_longjmp (wait_intr_buf, 1);
467 }
468
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
472 quick response. */
473 if (RL_ISSTATE (RL_STATE_SIGHANDLER) && interrupt_immediately == 0)
474 bashline_set_event_hook ();
475 #endif
476
477 if (interrupt_immediately)
478 run_pending_traps ();
479
480 errno = oerrno;
481 }
482
483 SIGRETURN (0);
484 }
485
486 int
487 first_pending_trap ()
488 {
489 register int i;
490
491 for (i = 1; i < NSIG; i++)
492 if (pending_traps[i])
493 return i;
494 return -1;
495 }
496
497 int
498 any_signals_trapped ()
499 {
500 register int i;
501
502 for (i = 1; i < NSIG; i++)
503 if (sigmodes[i] & SIG_TRAPPED)
504 return i;
505 return -1;
506 }
507
508 void
509 check_signals ()
510 {
511 CHECK_ALRM; /* set by the read builtin */
512 QUIT;
513 }
514
515 /* Convenience functions the rest of the shell can use */
516 void
517 check_signals_and_traps ()
518 {
519 check_signals ();
520
521 run_pending_traps ();
522 }
523
524 #if defined (JOB_CONTROL) && defined (SIGCHLD)
525
526 #ifdef INCLUDE_UNUSED
527 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
528 void
529 set_sigchld_trap (command_string)
530 char *command_string;
531 {
532 set_signal (SIGCHLD, command_string);
533 }
534 #endif
535
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. */
541 void
542 maybe_set_sigchld_trap (command_string)
543 char *command_string;
544 {
545 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER)
546 set_signal (SIGCHLD, command_string);
547 }
548
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. */
552 void
553 set_impossible_sigchld_trap ()
554 {
555 restore_default_signal (SIGCHLD);
556 change_signal (SIGCHLD, (char *)IMPOSSIBLE_TRAP_HANDLER);
557 sigmodes[SIGCHLD] &= ~SIG_TRAPPED; /* maybe_set_sigchld_trap checks this */
558 }
559
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. */
563 void
564 queue_sigchld_trap (nchild)
565 int nchild;
566 {
567 if (nchild > 0)
568 {
569 catch_flag = 1;
570 pending_traps[SIGCHLD] += nchild;
571 trapped_signal_received = SIGCHLD;
572 }
573 }
574 #endif /* JOB_CONTROL && SIGCHLD */
575
576 /* Set a trap for SIG only if SIG is not already trapped. */
577 static inline void
578 trap_if_untrapped (sig, command)
579 int sig;
580 char *command;
581 {
582 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
583 set_signal (sig, command);
584 }
585
586 void
587 set_debug_trap (command)
588 char *command;
589 {
590 set_signal (DEBUG_TRAP, command);
591 }
592
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. */
599 void
600 maybe_set_debug_trap (command)
601 char *command;
602 {
603 trap_if_untrapped (DEBUG_TRAP, command);
604 }
605
606 void
607 set_error_trap (command)
608 char *command;
609 {
610 set_signal (ERROR_TRAP, command);
611 }
612
613 void
614 maybe_set_error_trap (command)
615 char *command;
616 {
617 trap_if_untrapped (ERROR_TRAP, command);
618 }
619
620 void
621 set_return_trap (command)
622 char *command;
623 {
624 set_signal (RETURN_TRAP, command);
625 }
626
627 void
628 maybe_set_return_trap (command)
629 char *command;
630 {
631 trap_if_untrapped (RETURN_TRAP, command);
632 }
633
634 #ifdef INCLUDE_UNUSED
635 void
636 set_sigint_trap (command)
637 char *command;
638 {
639 set_signal (SIGINT, command);
640 }
641 #endif
642
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. */
646 SigHandler *
647 set_sigint_handler ()
648 {
649 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
650 return ((SigHandler *)SIG_IGN);
651
652 else if (sigmodes[SIGINT] & SIG_IGNORED)
653 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
654
655 else if (sigmodes[SIGINT] & SIG_TRAPPED)
656 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
657
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));
662 else
663 return (set_signal_handler (SIGINT, termsig_sighandler));
664 }
665
666 /* Return the correct handler for signal SIG according to the values in
667 sigmodes[SIG]. */
668 SigHandler *
669 trap_to_sighandler (sig)
670 int sig;
671 {
672 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
673 return (SIG_IGN);
674 else if (sigmodes[sig] & SIG_TRAPPED)
675 return (trap_handler);
676 else
677 return (SIG_DFL);
678 }
679
680 /* Set SIG to call STRING as a command. */
681 void
682 set_signal (sig, string)
683 int sig;
684 char *string;
685 {
686 sigset_t set, oset;
687
688 if (SPECIAL_TRAP (sig))
689 {
690 change_signal (sig, savestring (string));
691 if (sig == EXIT_TRAP && interactive == 0)
692 initialize_terminating_signals ();
693 return;
694 }
695
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)
699 return;
700
701 /* Make sure we have original_signals[sig] if the signal has not yet
702 been trapped. */
703 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
704 {
705 /* If we aren't sure of the original value, check it. */
706 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
707 GETORIGSIG (sig);
708 if (original_signals[sig] == SIG_IGN)
709 return;
710 }
711
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)
717 {
718 BLOCK_SIGNAL (sig, set, oset);
719 change_signal (sig, savestring (string));
720 set_signal_handler (sig, trap_handler);
721 UNBLOCK_SIGNAL (oset);
722 }
723 else
724 change_signal (sig, savestring (string));
725 }
726
727 static void
728 free_trap_command (sig)
729 int sig;
730 {
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]);
736 }
737
738 /* If SIG has a string assigned to it, get rid of it. Then give it
739 VALUE. */
740 static void
741 change_signal (sig, value)
742 int sig;
743 char *value;
744 {
745 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
746 free_trap_command (sig);
747 trap_list[sig] = value;
748
749 sigmodes[sig] |= SIG_TRAPPED;
750 if (value == (char *)IGNORE_SIG)
751 sigmodes[sig] |= SIG_IGNORED;
752 else
753 sigmodes[sig] &= ~SIG_IGNORED;
754 if (sigmodes[sig] & SIG_INPROGRESS)
755 sigmodes[sig] |= SIG_CHANGED;
756 }
757
758 void
759 get_original_signal (sig)
760 int sig;
761 {
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)
764 GETORIGSIG (sig);
765 }
766
767 void
768 get_all_original_signals ()
769 {
770 register int i;
771
772 for (i = 1; i < NSIG; i++)
773 GET_ORIGINAL_SIGNAL (i);
774 }
775
776 void
777 set_original_signal (sig, handler)
778 int sig;
779 SigHandler *handler;
780 {
781 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
782 SETORIGSIG (sig, handler);
783 }
784
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. */
789 void
790 restore_default_signal (sig)
791 int sig;
792 {
793 if (SPECIAL_TRAP (sig))
794 {
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;
802 return;
803 }
804
805 GET_ORIGINAL_SIGNAL (sig);
806
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)
810 return;
811
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))
818 return;
819
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]);
823
824 /* Change the trap command in either case. */
825 change_signal (sig, (char *)DEFAULT_SIG);
826
827 /* Mark the signal as no longer trapped. */
828 sigmodes[sig] &= ~SIG_TRAPPED;
829 }
830
831 /* Make this signal be ignored. */
832 void
833 ignore_signal (sig)
834 int sig;
835 {
836 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
837 {
838 change_signal (sig, (char *)IGNORE_SIG);
839 return;
840 }
841
842 GET_ORIGINAL_SIGNAL (sig);
843
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)
847 return;
848
849 /* If already trapped and ignored, no change necessary. */
850 if (sigmodes[sig] & SIG_IGNORED)
851 return;
852
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);
856
857 /* Change the trap command in either case. */
858 change_signal (sig, (char *)IGNORE_SIG);
859 }
860
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. */
864 int
865 run_exit_trap ()
866 {
867 char *trap_command;
868 int code, function_code, retval;
869 #if defined (ARRAY_VARS)
870 ARRAY *ps;
871 #endif
872
873 trap_saved_exit_value = last_command_exit_value;
874 #if defined (ARRAY_VARS)
875 ps = save_pipestatus_array ();
876 #endif
877 function_code = 0;
878
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)
884 {
885 trap_command = savestring (trap_list[EXIT_TRAP]);
886 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
887 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
888
889 retval = trap_saved_exit_value;
890 running_trap = 1;
891
892 code = setjmp_nosigs (top_level);
893
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);
897
898 if (code == 0 && function_code == 0)
899 {
900 reset_parser ();
901 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
902 }
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;
909 else
910 retval = trap_saved_exit_value;
911
912 running_trap = 0;
913 #if defined (ARRAY_VARS)
914 array_dispose (ps);
915 #endif
916
917 return retval;
918 }
919
920 #if defined (ARRAY_VARS)
921 restore_pipestatus_array (ps);
922 #endif
923 return (trap_saved_exit_value);
924 }
925
926 void
927 run_trap_cleanup (sig)
928 int sig;
929 {
930 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
931 }
932
933 #define RECURSIVE_SIG(s) (SPECIAL_TRAP(s) == 0)
934
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. */
937 static int
938 _run_trap_internal (sig, tag)
939 int sig;
940 char *tag;
941 {
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;
945 int flags;
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)
951 ARRAY *ps;
952 #endif
953
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) &&
960 #if 0
961 /* Uncomment this to allow some special signals to recursively execute
962 trap handlers. */
963 (RECURSIVE_SIG (sig) || (sigmodes[sig] & SIG_INPROGRESS) == 0))
964 #else
965 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
966 #endif
967 {
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);
972
973 running_trap = sig + 1;
974
975 old_int = interrupt_state; /* temporarily suppress pending interrupts */
976 CLRINTERRUPT;
977
978 #if defined (ARRAY_VARS)
979 ps = save_pipestatus_array ();
980 #endif
981
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 */
987
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 */
991 #endif
992
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)
996 {
997 COPY_PROCENV (return_catch, save_return_catch);
998 function_code = setjmp_nosigs (return_catch);
999 }
1000
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)
1005 {
1006 parse_and_execute (trap_command, tag, flags);
1007 trap_exit_value = last_command_exit_value;
1008 }
1009 else
1010 trap_exit_value = return_catch_value;
1011
1012 #if defined (JOB_CONTROL)
1013 if (sig != DEBUG_TRAP) /* run_debug_trap does this */
1014 restore_pipeline (1);
1015 #endif
1016
1017 subst_assign_varlist = save_subst_varlist;
1018 restore_parser_state (&pstate);
1019
1020 #if defined (ARRAY_VARS)
1021 restore_pipestatus_array (ps);
1022 #endif
1023
1024 temporary_env = save_tempenv;
1025
1026 sigmodes[sig] &= ~SIG_INPROGRESS;
1027 running_trap = 0;
1028 interrupt_state = old_int;
1029
1030 if (sigmodes[sig] & SIG_CHANGED)
1031 {
1032 #if 0
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)
1037 #endif
1038 free (old_trap);
1039 sigmodes[sig] &= ~SIG_CHANGED;
1040 }
1041
1042 if (save_return_catch_flag)
1043 {
1044 return_catch_flag = save_return_catch_flag;
1045 return_catch_value = trap_exit_value;
1046 COPY_PROCENV (save_return_catch, return_catch);
1047 if (function_code)
1048 {
1049 #if 0
1050 from_return_trap = sig == RETURN_TRAP;
1051 #endif
1052 sh_longjmp (return_catch, 1);
1053 }
1054 }
1055 }
1056
1057 return trap_exit_value;
1058 }
1059
1060 int
1061 run_debug_trap ()
1062 {
1063 int trap_exit_value;
1064 pid_t save_pgrp;
1065 int save_pipe[2];
1066
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))
1070 {
1071 #if defined (JOB_CONTROL)
1072 save_pgrp = pipeline_pgrp;
1073 pipeline_pgrp = 0;
1074 save_pipeline (1);
1075 # if defined (PGRP_PIPE)
1076 save_pgrp_pipe (save_pipe, 1);
1077 # endif
1078 stop_making_children ();
1079 #endif
1080
1081 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
1082
1083 #if defined (JOB_CONTROL)
1084 pipeline_pgrp = save_pgrp;
1085 restore_pipeline (1);
1086 # if defined (PGRP_PIPE)
1087 close_pgrp_pipe ();
1088 restore_pgrp_pipe (save_pipe);
1089 # endif
1090 if (pipeline_pgrp > 0)
1091 give_terminal_to (pipeline_pgrp, 1);
1092 notify_and_cleanup ();
1093 #endif
1094
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)
1099 {
1100 return_catch_value = trap_exit_value;
1101 sh_longjmp (return_catch, 1);
1102 }
1103 #endif
1104 }
1105 return trap_exit_value;
1106 }
1107
1108 void
1109 run_error_trap ()
1110 {
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");
1113 }
1114
1115 void
1116 run_return_trap ()
1117 {
1118 int old_exit_value;
1119
1120 #if 0
1121 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
1122 return;
1123 #endif
1124
1125 if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
1126 {
1127 old_exit_value = last_command_exit_value;
1128 _run_trap_internal (RETURN_TRAP, "return trap");
1129 last_command_exit_value = old_exit_value;
1130 }
1131 }
1132
1133 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1134 declared here to localize the trap functions. */
1135 void
1136 run_interrupt_trap (will_throw)
1137 int will_throw; /* from throw_to_top_level? */
1138 {
1139 if (will_throw && running_trap > 0)
1140 run_trap_cleanup (running_trap - 1);
1141 _run_trap_internal (SIGINT, "interrupt trap");
1142 }
1143
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. */
1151 void
1152 free_trap_strings ()
1153 {
1154 register int i;
1155
1156 for (i = 0; i < NSIG; i++)
1157 {
1158 if (trap_list[i] != (char *)IGNORE_SIG)
1159 free_trap_string (i);
1160 }
1161 for (i = NSIG; i < BASH_NSIG; i++)
1162 {
1163 /* Don't free the trap string if the subshell inherited the trap */
1164 if ((sigmodes[i] & SIG_TRAPPED) == 0)
1165 {
1166 free_trap_string (i);
1167 trap_list[i] = (char *)NULL;
1168 }
1169 }
1170 }
1171
1172 /* Free a trap command string associated with SIG without changing signal
1173 disposition. Intended to be called from free_trap_strings() */
1174 static void
1175 free_trap_string (sig)
1176 int sig;
1177 {
1178 change_signal (sig, (char *)DEFAULT_SIG);
1179 sigmodes[sig] &= ~SIG_TRAPPED;
1180 }
1181
1182 /* Reset the handler for SIG to the original value but leave the trap string
1183 in place. */
1184 static void
1185 reset_signal (sig)
1186 int sig;
1187 {
1188 set_signal_handler (sig, original_signals[sig]);
1189 sigmodes[sig] &= ~SIG_TRAPPED;
1190 }
1191
1192 /* Set the handler signal SIG to the original and free any trap
1193 command associated with it. */
1194 static void
1195 restore_signal (sig)
1196 int sig;
1197 {
1198 set_signal_handler (sig, original_signals[sig]);
1199 change_signal (sig, (char *)DEFAULT_SIG);
1200 sigmodes[sig] &= ~SIG_TRAPPED;
1201 }
1202
1203 static void
1204 reset_or_restore_signal_handlers (reset)
1205 sh_resetsig_func_t *reset;
1206 {
1207 register int i;
1208
1209 /* Take care of the exit trap first */
1210 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
1211 {
1212 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
1213 if (reset != reset_signal)
1214 {
1215 free_trap_command (EXIT_TRAP);
1216 trap_list[EXIT_TRAP] = (char *)NULL;
1217 }
1218 }
1219
1220 for (i = 1; i < NSIG; i++)
1221 {
1222 if (sigmodes[i] & SIG_TRAPPED)
1223 {
1224 if (trap_list[i] == (char *)IGNORE_SIG)
1225 set_signal_handler (i, SIG_IGN);
1226 else
1227 (*reset) (i);
1228 }
1229 else if (sigmodes[i] & SIG_SPECIAL)
1230 (*reset) (i);
1231 pending_traps[i] = 0; /* XXX */
1232 }
1233
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)
1240 {
1241 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
1242 sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
1243 }
1244 if (error_trace_mode == 0)
1245 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
1246 }
1247
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". */
1251 void
1252 reset_signal_handlers ()
1253 {
1254 reset_or_restore_signal_handlers (reset_signal);
1255 }
1256
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. */
1260 void
1261 restore_original_signals ()
1262 {
1263 reset_or_restore_signal_handlers (restore_signal);
1264 }
1265
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. */
1268 int
1269 maybe_call_trap_handler (sig)
1270 int sig;
1271 {
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))
1274 {
1275 switch (sig)
1276 {
1277 case SIGINT:
1278 run_interrupt_trap (0);
1279 break;
1280 case EXIT_TRAP:
1281 run_exit_trap ();
1282 break;
1283 case DEBUG_TRAP:
1284 run_debug_trap ();
1285 break;
1286 case ERROR_TRAP:
1287 run_error_trap ();
1288 break;
1289 default:
1290 trap_handler (sig);
1291 break;
1292 }
1293 return (1);
1294 }
1295 else
1296 return (0);
1297 }
1298
1299 int
1300 signal_is_trapped (sig)
1301 int sig;
1302 {
1303 return (sigmodes[sig] & SIG_TRAPPED);
1304 }
1305
1306 int
1307 signal_is_pending (sig)
1308 int sig;
1309 {
1310 return (pending_traps[sig]);
1311 }
1312
1313 int
1314 signal_is_special (sig)
1315 int sig;
1316 {
1317 return (sigmodes[sig] & SIG_SPECIAL);
1318 }
1319
1320 int
1321 signal_is_ignored (sig)
1322 int sig;
1323 {
1324 return (sigmodes[sig] & SIG_IGNORED);
1325 }
1326
1327 int
1328 signal_is_hard_ignored (sig)
1329 int sig;
1330 {
1331 return (sigmodes[sig] & SIG_HARD_IGNORE);
1332 }
1333
1334 void
1335 set_signal_hard_ignored (sig)
1336 int sig;
1337 {
1338 sigmodes[sig] |= SIG_HARD_IGNORE;
1339 original_signals[sig] = SIG_IGN;
1340 }
1341
1342 void
1343 set_signal_ignored (sig)
1344 int sig;
1345 {
1346 original_signals[sig] = SIG_IGN;
1347 }
1348
1349 int
1350 signal_in_progress (sig)
1351 int sig;
1352 {
1353 return (sigmodes[sig] & SIG_INPROGRESS);
1354 }