]> git.ipfire.org Git - thirdparty/bash.git/blob - trap.c
bash-4.3-beta overlay
[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-2013 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 __P((int));
76 static void change_signal __P((int, char *));
77
78 static int _run_trap_internal __P((int, char *));
79
80 static void free_trap_string __P((int));
81 static void reset_signal __P((int));
82 static void restore_signal __P((int));
83 static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
84
85 /* Variables used here but defined in other files. */
86 extern int last_command_exit_value;
87 extern int line_number;
88
89 extern int sigalrm_seen;
90 extern procenv_t alrmbuf;
91
92 extern char *this_command_name;
93 extern sh_builtin_func_t *this_shell_builtin;
94 extern procenv_t wait_intr_buf;
95 extern int return_catch_flag, return_catch_value;
96 extern int subshell_level;
97 extern WORD_LIST *subst_assign_varlist;
98
99 /* The list of things to do originally, before we started trapping. */
100 SigHandler *original_signals[NSIG];
101
102 /* For each signal, a slot for a string, which is a command to be
103 executed when that signal is recieved. The slot can also contain
104 DEFAULT_SIG, which means do whatever you were going to do before
105 you were so rudely interrupted, or IGNORE_SIG, which says ignore
106 this signal. */
107 char *trap_list[BASH_NSIG];
108
109 /* A bitmap of signals received for which we have trap handlers. */
110 int pending_traps[NSIG];
111
112 /* Set to the number of the signal we're running the trap for + 1.
113 Used in execute_cmd.c and builtins/common.c to clean up when
114 parse_and_execute does not return normally after executing the
115 trap command (e.g., when `return' is executed in the trap command). */
116 int running_trap;
117
118 /* Set to last_command_exit_value before running a trap. */
119 int trap_saved_exit_value;
120
121 /* The (trapped) signal received while executing in the `wait' builtin */
122 int wait_signal_received;
123
124 int trapped_signal_received;
125
126 #define GETORIGSIG(sig) \
127 do { \
128 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
129 set_signal_handler (sig, original_signals[sig]); \
130 if (original_signals[sig] == SIG_IGN) \
131 sigmodes[sig] |= SIG_HARD_IGNORE; \
132 } while (0)
133
134 #define SETORIGSIG(sig,handler) \
135 do { \
136 original_signals[sig] = handler; \
137 if (original_signals[sig] == SIG_IGN) \
138 sigmodes[sig] |= SIG_HARD_IGNORE; \
139 } while (0)
140
141 #define GET_ORIGINAL_SIGNAL(sig) \
142 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
143 GETORIGSIG(sig)
144
145 void
146 initialize_traps ()
147 {
148 register int i;
149
150 initialize_signames();
151
152 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
153 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
154 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
155
156 for (i = 1; i < NSIG; i++)
157 {
158 pending_traps[i] = 0;
159 trap_list[i] = (char *)DEFAULT_SIG;
160 sigmodes[i] = SIG_INHERITED; /* XXX - only set, not used */
161 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
162 }
163
164 /* Show which signals are treated specially by the shell. */
165 #if defined (SIGCHLD)
166 GETORIGSIG (SIGCHLD);
167 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
168 #endif /* SIGCHLD */
169
170 GETORIGSIG (SIGINT);
171 sigmodes[SIGINT] |= SIG_SPECIAL;
172
173 #if defined (__BEOS__)
174 /* BeOS sets SIGINT to SIG_IGN! */
175 original_signals[SIGINT] = SIG_DFL;
176 sigmodes[SIGINT] &= ~SIG_HARD_IGNORE;
177 #endif
178
179 GETORIGSIG (SIGQUIT);
180 sigmodes[SIGQUIT] |= SIG_SPECIAL;
181
182 if (interactive)
183 {
184 GETORIGSIG (SIGTERM);
185 sigmodes[SIGTERM] |= SIG_SPECIAL;
186 }
187 }
188
189 #ifdef DEBUG
190 /* Return a printable representation of the trap handler for SIG. */
191 static char *
192 trap_handler_string (sig)
193 int sig;
194 {
195 if (trap_list[sig] == (char *)DEFAULT_SIG)
196 return "DEFAULT_SIG";
197 else if (trap_list[sig] == (char *)IGNORE_SIG)
198 return "IGNORE_SIG";
199 else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
200 return "IMPOSSIBLE_TRAP_HANDLER";
201 else if (trap_list[sig])
202 return trap_list[sig];
203 else
204 return "NULL";
205 }
206 #endif
207
208 /* Return the print name of this signal. */
209 char *
210 signal_name (sig)
211 int sig;
212 {
213 char *ret;
214
215 /* on cygwin32, signal_names[sig] could be null */
216 ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
217 ? _("invalid signal number")
218 : signal_names[sig];
219
220 return ret;
221 }
222
223 /* Turn a string into a signal number, or a number into
224 a signal number. If STRING is "2", "SIGINT", or "INT",
225 then (int)2 is returned. Return NO_SIG if STRING doesn't
226 contain a valid signal descriptor. */
227 int
228 decode_signal (string, flags)
229 char *string;
230 int flags;
231 {
232 intmax_t sig;
233 char *name;
234
235 if (legal_number (string, &sig))
236 return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
237
238 /* A leading `SIG' may be omitted. */
239 for (sig = 0; sig < BASH_NSIG; sig++)
240 {
241 name = signal_names[sig];
242 if (name == 0 || name[0] == '\0')
243 continue;
244
245 /* Check name without the SIG prefix first case sensitivly or
246 insensitively depending on whether flags includes DSIG_NOCASE */
247 if (STREQN (name, "SIG", 3))
248 {
249 name += 3;
250
251 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
252 return ((int)sig);
253 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
254 return ((int)sig);
255 /* If we can't use the `SIG' prefix to match, punt on this
256 name now. */
257 else if ((flags & DSIG_SIGPREFIX) == 0)
258 continue;
259 }
260
261 /* Check name with SIG prefix case sensitively or insensitively
262 depending on whether flags includes DSIG_NOCASE */
263 name = signal_names[sig];
264 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
265 return ((int)sig);
266 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
267 return ((int)sig);
268 }
269
270 return (NO_SIG);
271 }
272
273 /* Non-zero when we catch a trapped signal. */
274 static int catch_flag;
275
276 void
277 run_pending_traps ()
278 {
279 register int sig;
280 int old_exit_value, *token_state;
281 WORD_LIST *save_subst_varlist;
282 #if defined (ARRAY_VARS)
283 ARRAY *ps;
284 #endif
285
286 if (catch_flag == 0) /* simple optimization */
287 return;
288
289 if (running_trap > 0)
290 return; /* no recursive trap invocations */
291
292 catch_flag = trapped_signal_received = 0;
293
294 /* Preserve $? when running trap. */
295 old_exit_value = last_command_exit_value;
296 #if defined (ARRAY_VARS)
297 ps = save_pipestatus_array ();
298 #endif
299
300 for (sig = 1; sig < NSIG; sig++)
301 {
302 /* XXX this could be made into a counter by using
303 while (pending_traps[sig]--) instead of the if statement. */
304 if (pending_traps[sig])
305 {
306 sigset_t set, oset;
307
308 BLOCK_SIGNAL (sig, set, oset);
309
310 running_trap = sig + 1;
311
312 if (sig == SIGINT)
313 {
314 run_interrupt_trap ();
315 CLRINTERRUPT;
316 }
317 #if defined (JOB_CONTROL) && defined (SIGCHLD)
318 else if (sig == SIGCHLD &&
319 trap_list[SIGCHLD] != (char *)IMPOSSIBLE_TRAP_HANDLER &&
320 (sigmodes[SIGCHLD] & SIG_INPROGRESS) == 0)
321 {
322 sigmodes[SIGCHLD] |= SIG_INPROGRESS;
323 run_sigchld_trap (pending_traps[sig]); /* use as counter */
324 sigmodes[SIGCHLD] &= ~SIG_INPROGRESS;
325 }
326 else if (sig == SIGCHLD &&
327 trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER &&
328 (sigmodes[SIGCHLD] & SIG_INPROGRESS) != 0)
329 {
330 /* This can happen when run_pending_traps is called while
331 running a SIGCHLD trap handler. */
332 running_trap = 0;
333 UNBLOCK_SIGNAL (oset);
334 continue; /* XXX */
335 }
336 #endif
337 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
338 trap_list[sig] == (char *)IGNORE_SIG ||
339 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
340 {
341 /* This is possible due to a race condition. Say a bash
342 process has SIGTERM trapped. A subshell is spawned
343 using { list; } & and the parent does something and kills
344 the subshell with SIGTERM. It's possible for the subshell
345 to set pending_traps[SIGTERM] to 1 before the code in
346 execute_cmd.c eventually calls restore_original_signals
347 to reset the SIGTERM signal handler in the subshell. The
348 next time run_pending_traps is called, pending_traps[SIGTERM]
349 will be 1, but the trap handler in trap_list[SIGTERM] will
350 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
351 Unless we catch this, the subshell will dump core when
352 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
353 usually 0x0. */
354 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
355 sig, trap_list[sig]);
356 if (trap_list[sig] == (char *)DEFAULT_SIG)
357 {
358 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
359 kill (getpid (), sig);
360 }
361 }
362 else
363 {
364 /* XXX - should we use save_parser_state/restore_parser_state? */
365 token_state = save_token_state ();
366 save_subst_varlist = subst_assign_varlist;
367 subst_assign_varlist = 0;
368
369 #if defined (JOB_CONTROL)
370 save_pipeline (1); /* XXX only provides one save level */
371 #endif
372 evalstring (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
373 #if defined (JOB_CONTROL)
374 restore_pipeline (1);
375 #endif
376
377 restore_token_state (token_state);
378 free (token_state);
379
380 subst_assign_varlist = save_subst_varlist;
381 }
382
383 pending_traps[sig] = 0;
384 running_trap = 0;
385
386 UNBLOCK_SIGNAL (oset);
387 }
388 }
389
390 #if defined (ARRAY_VARS)
391 restore_pipestatus_array (ps);
392 #endif
393 last_command_exit_value = old_exit_value;
394 }
395
396 sighandler
397 trap_handler (sig)
398 int sig;
399 {
400 int oerrno;
401
402 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
403 {
404 #if defined (DEBUG)
405 internal_warning ("trap_handler: signal %d: signal not trapped", sig);
406 #endif
407 SIGRETURN (0);
408 }
409
410 if ((sig >= NSIG) ||
411 (trap_list[sig] == (char *)DEFAULT_SIG) ||
412 (trap_list[sig] == (char *)IGNORE_SIG))
413 programming_error (_("trap_handler: bad signal %d"), sig);
414 else
415 {
416 oerrno = errno;
417 #if defined (MUST_REINSTALL_SIGHANDLERS)
418 # if defined (JOB_CONTROL) && defined (SIGCHLD)
419 if (sig != SIGCHLD)
420 # endif /* JOB_CONTROL && SIGCHLD */
421 set_signal_handler (sig, trap_handler);
422 #endif /* MUST_REINSTALL_SIGHANDLERS */
423
424 catch_flag = 1;
425 pending_traps[sig]++;
426
427 trapped_signal_received = sig;
428
429 if (this_shell_builtin && (this_shell_builtin == wait_builtin))
430 {
431 wait_signal_received = sig;
432 if (interrupt_immediately)
433 longjmp (wait_intr_buf, 1);
434 }
435
436 #if defined (READLINE)
437 /* Set the event hook so readline will call it after the signal handlers
438 finish executing, so if this interrupted character input we can get
439 quick response. */
440 if (RL_ISSTATE (RL_STATE_SIGHANDLER) && interrupt_immediately == 0)
441 bashline_set_event_hook ();
442 #endif
443
444 if (interrupt_immediately)
445 run_pending_traps ();
446
447 errno = oerrno;
448 }
449
450 SIGRETURN (0);
451 }
452
453 int
454 first_pending_trap ()
455 {
456 register int i;
457
458 for (i = 1; i < NSIG; i++)
459 if (pending_traps[i])
460 return i;
461 return -1;
462 }
463
464 int
465 any_signals_trapped ()
466 {
467 register int i;
468
469 for (i = 1; i < NSIG; i++)
470 if (sigmodes[i] & SIG_TRAPPED)
471 return i;
472 return -1;
473 }
474
475 void
476 check_signals ()
477 {
478 CHECK_ALRM; /* set by the read builtin */
479 QUIT;
480 }
481
482 /* Convenience functions the rest of the shell can use */
483 void
484 check_signals_and_traps ()
485 {
486 check_signals ();
487
488 run_pending_traps ();
489 }
490
491 #if defined (JOB_CONTROL) && defined (SIGCHLD)
492
493 #ifdef INCLUDE_UNUSED
494 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
495 void
496 set_sigchld_trap (command_string)
497 char *command_string;
498 {
499 set_signal (SIGCHLD, command_string);
500 }
501 #endif
502
503 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
504 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
505 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
506 reset the disposition to the default and not have the original signal
507 accidentally restored, undoing the user's command. */
508 void
509 maybe_set_sigchld_trap (command_string)
510 char *command_string;
511 {
512 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER)
513 set_signal (SIGCHLD, command_string);
514 }
515
516 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
517 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
518 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
519 void
520 set_impossible_sigchld_trap ()
521 {
522 restore_default_signal (SIGCHLD);
523 change_signal (SIGCHLD, (char *)IMPOSSIBLE_TRAP_HANDLER);
524 sigmodes[SIGCHLD] &= ~SIG_TRAPPED; /* maybe_set_sigchld_trap checks this */
525 }
526
527 /* Act as if we received SIGCHLD NCHILD times and increment
528 pending_traps[SIGCHLD] by that amount. This allows us to still run the
529 SIGCHLD trap once for each exited child. */
530 void
531 queue_sigchld_trap (nchild)
532 int nchild;
533 {
534 if (nchild > 0)
535 {
536 catch_flag = 1;
537 pending_traps[SIGCHLD] += nchild;
538 trapped_signal_received = SIGCHLD;
539 }
540 }
541 #endif /* JOB_CONTROL && SIGCHLD */
542
543 void
544 set_debug_trap (command)
545 char *command;
546 {
547 set_signal (DEBUG_TRAP, command);
548 }
549
550 void
551 set_error_trap (command)
552 char *command;
553 {
554 set_signal (ERROR_TRAP, command);
555 }
556
557 void
558 set_return_trap (command)
559 char *command;
560 {
561 set_signal (RETURN_TRAP, command);
562 }
563
564 #ifdef INCLUDE_UNUSED
565 void
566 set_sigint_trap (command)
567 char *command;
568 {
569 set_signal (SIGINT, command);
570 }
571 #endif
572
573 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
574 things, like waiting for command substitution or executing commands
575 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
576 SigHandler *
577 set_sigint_handler ()
578 {
579 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
580 return ((SigHandler *)SIG_IGN);
581
582 else if (sigmodes[SIGINT] & SIG_IGNORED)
583 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
584
585 else if (sigmodes[SIGINT] & SIG_TRAPPED)
586 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
587
588 /* The signal is not trapped, so set the handler to the shell's special
589 interrupt handler. */
590 else if (interactive) /* XXX - was interactive_shell */
591 return (set_signal_handler (SIGINT, sigint_sighandler));
592 else
593 return (set_signal_handler (SIGINT, termsig_sighandler));
594 }
595
596 /* Return the correct handler for signal SIG according to the values in
597 sigmodes[SIG]. */
598 SigHandler *
599 trap_to_sighandler (sig)
600 int sig;
601 {
602 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
603 return (SIG_IGN);
604 else if (sigmodes[sig] & SIG_TRAPPED)
605 return (trap_handler);
606 else
607 return (SIG_DFL);
608 }
609
610 /* Set SIG to call STRING as a command. */
611 void
612 set_signal (sig, string)
613 int sig;
614 char *string;
615 {
616 sigset_t set, oset;
617
618 if (SPECIAL_TRAP (sig))
619 {
620 change_signal (sig, savestring (string));
621 if (sig == EXIT_TRAP && interactive == 0)
622 initialize_terminating_signals ();
623 return;
624 }
625
626 /* A signal ignored on entry to the shell cannot be trapped or reset, but
627 no error is reported when attempting to do so. -- Posix.2 */
628 if (sigmodes[sig] & SIG_HARD_IGNORE)
629 return;
630
631 /* Make sure we have original_signals[sig] if the signal has not yet
632 been trapped. */
633 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
634 {
635 /* If we aren't sure of the original value, check it. */
636 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
637 GETORIGSIG (sig);
638 if (original_signals[sig] == SIG_IGN)
639 return;
640 }
641
642 /* Only change the system signal handler if SIG_NO_TRAP is not set.
643 The trap command string is changed in either case. The shell signal
644 handlers for SIGINT and SIGCHLD run the user specified traps in an
645 environment in which it is safe to do so. */
646 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
647 {
648 BLOCK_SIGNAL (sig, set, oset);
649 change_signal (sig, savestring (string));
650 set_signal_handler (sig, trap_handler);
651 UNBLOCK_SIGNAL (oset);
652 }
653 else
654 change_signal (sig, savestring (string));
655 }
656
657 static void
658 free_trap_command (sig)
659 int sig;
660 {
661 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
662 (trap_list[sig] != (char *)IGNORE_SIG) &&
663 (trap_list[sig] != (char *)DEFAULT_SIG) &&
664 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
665 free (trap_list[sig]);
666 }
667
668 /* If SIG has a string assigned to it, get rid of it. Then give it
669 VALUE. */
670 static void
671 change_signal (sig, value)
672 int sig;
673 char *value;
674 {
675 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
676 free_trap_command (sig);
677 trap_list[sig] = value;
678
679 sigmodes[sig] |= SIG_TRAPPED;
680 if (value == (char *)IGNORE_SIG)
681 sigmodes[sig] |= SIG_IGNORED;
682 else
683 sigmodes[sig] &= ~SIG_IGNORED;
684 if (sigmodes[sig] & SIG_INPROGRESS)
685 sigmodes[sig] |= SIG_CHANGED;
686 }
687
688 void
689 get_original_signal (sig)
690 int sig;
691 {
692 /* If we aren't sure the of the original value, then get it. */
693 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
694 GETORIGSIG (sig);
695 }
696
697 void
698 get_all_original_signals ()
699 {
700 register int i;
701
702 for (i = 1; i < NSIG; i++)
703 GET_ORIGINAL_SIGNAL (i);
704 }
705
706 void
707 set_original_signal (sig, handler)
708 int sig;
709 SigHandler *handler;
710 {
711 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
712 SETORIGSIG (sig, handler);
713 }
714
715 /* Restore the default action for SIG; i.e., the action the shell
716 would have taken before you used the trap command. This is called
717 from trap_builtin (), which takes care to restore the handlers for
718 the signals the shell treats specially. */
719 void
720 restore_default_signal (sig)
721 int sig;
722 {
723 if (SPECIAL_TRAP (sig))
724 {
725 if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
726 (sigmodes[sig] & SIG_INPROGRESS) == 0)
727 free_trap_command (sig);
728 trap_list[sig] = (char *)NULL;
729 sigmodes[sig] &= ~SIG_TRAPPED;
730 if (sigmodes[sig] & SIG_INPROGRESS)
731 sigmodes[sig] |= SIG_CHANGED;
732 return;
733 }
734
735 GET_ORIGINAL_SIGNAL (sig);
736
737 /* A signal ignored on entry to the shell cannot be trapped or reset, but
738 no error is reported when attempting to do so. Thanks Posix.2. */
739 if (sigmodes[sig] & SIG_HARD_IGNORE)
740 return;
741
742 /* If we aren't trapping this signal, don't bother doing anything else. */
743 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
744 return;
745
746 /* Only change the signal handler for SIG if it allows it. */
747 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
748 set_signal_handler (sig, original_signals[sig]);
749
750 /* Change the trap command in either case. */
751 change_signal (sig, (char *)DEFAULT_SIG);
752
753 /* Mark the signal as no longer trapped. */
754 sigmodes[sig] &= ~SIG_TRAPPED;
755 }
756
757 /* Make this signal be ignored. */
758 void
759 ignore_signal (sig)
760 int sig;
761 {
762 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
763 {
764 change_signal (sig, (char *)IGNORE_SIG);
765 return;
766 }
767
768 GET_ORIGINAL_SIGNAL (sig);
769
770 /* A signal ignored on entry to the shell cannot be trapped or reset.
771 No error is reported when the user attempts to do so. */
772 if (sigmodes[sig] & SIG_HARD_IGNORE)
773 return;
774
775 /* If already trapped and ignored, no change necessary. */
776 if (sigmodes[sig] & SIG_IGNORED)
777 return;
778
779 /* Only change the signal handler for SIG if it allows it. */
780 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
781 set_signal_handler (sig, SIG_IGN);
782
783 /* Change the trap command in either case. */
784 change_signal (sig, (char *)IGNORE_SIG);
785 }
786
787 /* Handle the calling of "trap 0". The only sticky situation is when
788 the command to be executed includes an "exit". This is why we have
789 to provide our own place for top_level to jump to. */
790 int
791 run_exit_trap ()
792 {
793 char *trap_command;
794 int code, function_code, retval;
795 #if defined (ARRAY_VARS)
796 ARRAY *ps;
797 #endif
798
799 trap_saved_exit_value = last_command_exit_value;
800 #if defined (ARRAY_VARS)
801 ps = save_pipestatus_array ();
802 #endif
803 function_code = 0;
804
805 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
806 currently running in the trap handler (call to exit in the list of
807 commands given to trap 0). */
808 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
809 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
810 {
811 trap_command = savestring (trap_list[EXIT_TRAP]);
812 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
813 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
814
815 retval = trap_saved_exit_value;
816 running_trap = 1;
817
818 code = setjmp_nosigs (top_level);
819
820 /* If we're in a function, make sure return longjmps come here, too. */
821 if (return_catch_flag)
822 function_code = setjmp_nosigs (return_catch);
823
824 if (code == 0 && function_code == 0)
825 {
826 reset_parser ();
827 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
828 }
829 else if (code == ERREXIT)
830 retval = last_command_exit_value;
831 else if (code == EXITPROG)
832 retval = last_command_exit_value;
833 else if (function_code != 0)
834 retval = return_catch_value;
835 else
836 retval = trap_saved_exit_value;
837
838 running_trap = 0;
839 return retval;
840 }
841
842 #if defined (ARRAY_VARS)
843 restore_pipestatus_array (ps);
844 #endif
845 return (trap_saved_exit_value);
846 }
847
848 void
849 run_trap_cleanup (sig)
850 int sig;
851 {
852 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
853 }
854
855 /* Run a trap command for SIG. SIG is one of the signals the shell treats
856 specially. Returns the exit status of the executed trap command list. */
857 static int
858 _run_trap_internal (sig, tag)
859 int sig;
860 char *tag;
861 {
862 char *trap_command, *old_trap;
863 int trap_exit_value, *token_state;
864 volatile int save_return_catch_flag, function_code;
865 int flags;
866 procenv_t save_return_catch;
867 WORD_LIST *save_subst_varlist;
868 #if defined (ARRAY_VARS)
869 ARRAY *ps;
870 #endif
871
872 trap_exit_value = function_code = 0;
873 /* Run the trap only if SIG is trapped and not ignored, and we are not
874 currently executing in the trap handler. */
875 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
876 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
877 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
878 {
879 old_trap = trap_list[sig];
880 sigmodes[sig] |= SIG_INPROGRESS;
881 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
882 trap_command = savestring (old_trap);
883
884 running_trap = sig + 1;
885 trap_saved_exit_value = last_command_exit_value;
886 #if defined (ARRAY_VARS)
887 ps = save_pipestatus_array ();
888 #endif
889
890 token_state = save_token_state ();
891 save_subst_varlist = subst_assign_varlist;
892 subst_assign_varlist = 0;
893
894 /* If we're in a function, make sure return longjmps come here, too. */
895 save_return_catch_flag = return_catch_flag;
896 if (return_catch_flag)
897 {
898 COPY_PROCENV (return_catch, save_return_catch);
899 function_code = setjmp_nosigs (return_catch);
900 }
901
902 flags = SEVAL_NONINT|SEVAL_NOHIST;
903 if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
904 flags |= SEVAL_RESETLINE;
905 if (function_code == 0)
906 parse_and_execute (trap_command, tag, flags);
907
908 restore_token_state (token_state);
909 free (token_state);
910
911 subst_assign_varlist = save_subst_varlist;
912
913 trap_exit_value = last_command_exit_value;
914 last_command_exit_value = trap_saved_exit_value;
915 #if defined (ARRAY_VARS)
916 restore_pipestatus_array (ps);
917 #endif
918 running_trap = 0;
919
920 sigmodes[sig] &= ~SIG_INPROGRESS;
921
922 if (sigmodes[sig] & SIG_CHANGED)
923 {
924 #if 0
925 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
926 the places where they can be changed using unwind-protects. For
927 example, look at execute_cmd.c:execute_function(). */
928 if (SPECIAL_TRAP (sig) == 0)
929 #endif
930 free (old_trap);
931 sigmodes[sig] &= ~SIG_CHANGED;
932 }
933
934 if (save_return_catch_flag)
935 {
936 return_catch_flag = save_return_catch_flag;
937 return_catch_value = trap_exit_value;
938 COPY_PROCENV (save_return_catch, return_catch);
939 if (function_code)
940 longjmp (return_catch, 1);
941 }
942 }
943
944 return trap_exit_value;
945 }
946
947 int
948 run_debug_trap ()
949 {
950 int trap_exit_value;
951 pid_t save_pgrp;
952 int save_pipe[2];
953
954 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
955 trap_exit_value = 0;
956 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
957 {
958 #if defined (JOB_CONTROL)
959 save_pgrp = pipeline_pgrp;
960 pipeline_pgrp = 0;
961 save_pipeline (1);
962 # if defined (PGRP_PIPE)
963 save_pgrp_pipe (save_pipe, 1);
964 # endif
965 stop_making_children ();
966 #endif
967
968 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
969
970 #if defined (JOB_CONTROL)
971 pipeline_pgrp = save_pgrp;
972 restore_pipeline (1);
973 # if defined (PGRP_PIPE)
974 close_pgrp_pipe ();
975 restore_pgrp_pipe (save_pipe);
976 # endif
977 if (pipeline_pgrp > 0)
978 give_terminal_to (pipeline_pgrp, 1);
979 notify_and_cleanup ();
980 #endif
981
982 #if defined (DEBUGGER)
983 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
984 a function or sourced script, we force a `return'. */
985 if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
986 {
987 return_catch_value = trap_exit_value;
988 longjmp (return_catch, 1);
989 }
990 #endif
991 }
992 return trap_exit_value;
993 }
994
995 void
996 run_error_trap ()
997 {
998 if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
999 _run_trap_internal (ERROR_TRAP, "error trap");
1000 }
1001
1002 void
1003 run_return_trap ()
1004 {
1005 int old_exit_value;
1006
1007 #if 0
1008 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
1009 return;
1010 #endif
1011
1012 if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
1013 {
1014 old_exit_value = last_command_exit_value;
1015 _run_trap_internal (RETURN_TRAP, "return trap");
1016 last_command_exit_value = old_exit_value;
1017 }
1018 }
1019
1020 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1021 declared here to localize the trap functions. */
1022 void
1023 run_interrupt_trap ()
1024 {
1025 _run_trap_internal (SIGINT, "interrupt trap");
1026 }
1027
1028 /* Free all the allocated strings in the list of traps and reset the trap
1029 values to the default. Intended to be called from subshells that want
1030 to complete work done by reset_signal_handlers upon execution of a
1031 subsequent `trap' command that changes a signal's disposition. We need
1032 to make sure that we duplicate the behavior of
1033 reset_or_restore_signal_handlers and not change the disposition of signals
1034 that are set to be ignored. */
1035 void
1036 free_trap_strings ()
1037 {
1038 register int i;
1039
1040 for (i = 0; i < BASH_NSIG; i++)
1041 {
1042 if (trap_list[i] != (char *)IGNORE_SIG)
1043 free_trap_string (i);
1044 }
1045 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
1046 }
1047
1048 /* Free a trap command string associated with SIG without changing signal
1049 disposition. Intended to be called from free_trap_strings() */
1050 static void
1051 free_trap_string (sig)
1052 int sig;
1053 {
1054 change_signal (sig, (char *)DEFAULT_SIG);
1055 sigmodes[sig] &= ~SIG_TRAPPED;
1056 }
1057
1058 /* Reset the handler for SIG to the original value but leave the trap string
1059 in place. */
1060 static void
1061 reset_signal (sig)
1062 int sig;
1063 {
1064 set_signal_handler (sig, original_signals[sig]);
1065 sigmodes[sig] &= ~SIG_TRAPPED;
1066 }
1067
1068 /* Set the handler signal SIG to the original and free any trap
1069 command associated with it. */
1070 static void
1071 restore_signal (sig)
1072 int sig;
1073 {
1074 set_signal_handler (sig, original_signals[sig]);
1075 change_signal (sig, (char *)DEFAULT_SIG);
1076 sigmodes[sig] &= ~SIG_TRAPPED;
1077 }
1078
1079 static void
1080 reset_or_restore_signal_handlers (reset)
1081 sh_resetsig_func_t *reset;
1082 {
1083 register int i;
1084
1085 /* Take care of the exit trap first */
1086 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
1087 {
1088 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
1089 if (reset != reset_signal)
1090 {
1091 free_trap_command (EXIT_TRAP);
1092 trap_list[EXIT_TRAP] = (char *)NULL;
1093 }
1094 }
1095
1096 for (i = 1; i < NSIG; i++)
1097 {
1098 if (sigmodes[i] & SIG_TRAPPED)
1099 {
1100 if (trap_list[i] == (char *)IGNORE_SIG)
1101 set_signal_handler (i, SIG_IGN);
1102 else
1103 (*reset) (i);
1104 }
1105 else if (sigmodes[i] & SIG_SPECIAL)
1106 (*reset) (i);
1107 }
1108
1109 /* Command substitution and other child processes don't inherit the
1110 debug, error, or return traps. If we're in the debugger, and the
1111 `functrace' or `errtrace' options have been set, then let command
1112 substitutions inherit them. Let command substitution inherit the
1113 RETURN trap if we're in the debugger and tracing functions. */
1114 if (function_trace_mode == 0)
1115 {
1116 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
1117 sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
1118 }
1119 if (error_trace_mode == 0)
1120 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
1121 }
1122
1123 /* Reset trapped signals to their original values, but don't free the
1124 trap strings. Called by the command substitution code and other places
1125 that create a "subshell environment". */
1126 void
1127 reset_signal_handlers ()
1128 {
1129 reset_or_restore_signal_handlers (reset_signal);
1130 }
1131
1132 /* Reset all trapped signals to their original values. Signals set to be
1133 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1134 are. Called by child processes after they are forked. */
1135 void
1136 restore_original_signals ()
1137 {
1138 reset_or_restore_signal_handlers (restore_signal);
1139 }
1140
1141 /* If a trap handler exists for signal SIG, then call it; otherwise just
1142 return failure. Returns 1 if it called the trap handler. */
1143 int
1144 maybe_call_trap_handler (sig)
1145 int sig;
1146 {
1147 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
1148 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
1149 {
1150 switch (sig)
1151 {
1152 case SIGINT:
1153 run_interrupt_trap ();
1154 break;
1155 case EXIT_TRAP:
1156 run_exit_trap ();
1157 break;
1158 case DEBUG_TRAP:
1159 run_debug_trap ();
1160 break;
1161 case ERROR_TRAP:
1162 run_error_trap ();
1163 break;
1164 default:
1165 trap_handler (sig);
1166 break;
1167 }
1168 return (1);
1169 }
1170 else
1171 return (0);
1172 }
1173
1174 int
1175 signal_is_trapped (sig)
1176 int sig;
1177 {
1178 return (sigmodes[sig] & SIG_TRAPPED);
1179 }
1180
1181 int
1182 signal_is_pending (sig)
1183 int sig;
1184 {
1185 return (pending_traps[sig]);
1186 }
1187
1188 int
1189 signal_is_special (sig)
1190 int sig;
1191 {
1192 return (sigmodes[sig] & SIG_SPECIAL);
1193 }
1194
1195 int
1196 signal_is_ignored (sig)
1197 int sig;
1198 {
1199 return (sigmodes[sig] & SIG_IGNORED);
1200 }
1201
1202 int
1203 signal_is_hard_ignored (sig)
1204 int sig;
1205 {
1206 return (sigmodes[sig] & SIG_HARD_IGNORE);
1207 }
1208
1209 void
1210 set_signal_ignored (sig)
1211 int sig;
1212 {
1213 sigmodes[sig] |= SIG_HARD_IGNORE;
1214 original_signals[sig] = SIG_IGN;
1215 }
1216
1217 int
1218 signal_in_progress (sig)
1219 int sig;
1220 {
1221 return (sigmodes[sig] & SIG_INPROGRESS);
1222 }