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