]> git.ipfire.org Git - thirdparty/bash.git/blob - trap.c
Imported from ../bash-3.1.tar.gz.
[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-2005 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 it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
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 "trap.h"
37
38 #include "shell.h"
39 #include "flags.h"
40 #include "input.h" /* for save_token_state, restore_token_state */
41 #include "signames.h"
42 #include "builtins.h"
43 #include "builtins/common.h"
44 #include "builtins/builtext.h"
45
46 #ifndef errno
47 extern int errno;
48 #endif
49
50 /* Flags which describe the current handling state of a signal. */
51 #define SIG_INHERITED 0x0 /* Value inherited from parent. */
52 #define SIG_TRAPPED 0x1 /* Currently trapped. */
53 #define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
54 #define SIG_SPECIAL 0x4 /* Treat this signal specially. */
55 #define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
56 #define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
57 #define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
58 #define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
59
60 #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
61
62 /* An array of such flags, one for each signal, describing what the
63 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
64 assumes this. */
65 static int sigmodes[BASH_NSIG];
66
67 static void free_trap_command __P((int));
68 static void change_signal __P((int, char *));
69
70 static void get_original_signal __P((int));
71
72 static int _run_trap_internal __P((int, char *));
73
74 static void reset_signal __P((int));
75 static void restore_signal __P((int));
76 static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
77
78 /* Variables used here but defined in other files. */
79 extern int interrupt_immediately;
80 extern int last_command_exit_value;
81 extern int line_number;
82
83 extern char *this_command_name;
84 extern sh_builtin_func_t *this_shell_builtin;
85 extern procenv_t wait_intr_buf;
86 extern int return_catch_flag, return_catch_value;
87 extern int subshell_level;
88
89 /* The list of things to do originally, before we started trapping. */
90 SigHandler *original_signals[NSIG];
91
92 /* For each signal, a slot for a string, which is a command to be
93 executed when that signal is recieved. The slot can also contain
94 DEFAULT_SIG, which means do whatever you were going to do before
95 you were so rudely interrupted, or IGNORE_SIG, which says ignore
96 this signal. */
97 char *trap_list[BASH_NSIG];
98
99 /* A bitmap of signals received for which we have trap handlers. */
100 int pending_traps[NSIG];
101
102 /* Set to the number of the signal we're running the trap for + 1.
103 Used in execute_cmd.c and builtins/common.c to clean up when
104 parse_and_execute does not return normally after executing the
105 trap command (e.g., when `return' is executed in the trap command). */
106 int running_trap;
107
108 /* Set to last_command_exit_value before running a trap. */
109 int trap_saved_exit_value;
110
111 /* The (trapped) signal received while executing in the `wait' builtin */
112 int wait_signal_received;
113
114 /* A value which can never be the target of a trap handler. */
115 #define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
116
117 void
118 initialize_traps ()
119 {
120 register int i;
121
122 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
123 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
124 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
125
126 for (i = 1; i < NSIG; i++)
127 {
128 pending_traps[i] = 0;
129 trap_list[i] = (char *)DEFAULT_SIG;
130 sigmodes[i] = SIG_INHERITED;
131 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
132 }
133
134 /* Show which signals are treated specially by the shell. */
135 #if defined (SIGCHLD)
136 original_signals[SIGCHLD] =
137 (SigHandler *) set_signal_handler (SIGCHLD, SIG_DFL);
138 set_signal_handler (SIGCHLD, original_signals[SIGCHLD]);
139 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
140 #endif /* SIGCHLD */
141
142 original_signals[SIGINT] =
143 (SigHandler *) set_signal_handler (SIGINT, SIG_DFL);
144 set_signal_handler (SIGINT, original_signals[SIGINT]);
145 sigmodes[SIGINT] |= SIG_SPECIAL;
146
147 #if defined (__BEOS__)
148 /* BeOS sets SIGINT to SIG_IGN! */
149 original_signals[SIGINT] = SIG_DFL;
150 #endif
151
152 original_signals[SIGQUIT] =
153 (SigHandler *) set_signal_handler (SIGQUIT, SIG_DFL);
154 set_signal_handler (SIGQUIT, original_signals[SIGQUIT]);
155 sigmodes[SIGQUIT] |= SIG_SPECIAL;
156
157 if (interactive)
158 {
159 original_signals[SIGTERM] =
160 (SigHandler *)set_signal_handler (SIGTERM, SIG_DFL);
161 set_signal_handler (SIGTERM, original_signals[SIGTERM]);
162 sigmodes[SIGTERM] |= SIG_SPECIAL;
163 }
164 }
165
166 #ifdef INCLUDE_UNUSED
167 /* Return a printable representation of the trap handler for SIG. */
168 static char *
169 trap_handler_string (sig)
170 int sig;
171 {
172 if (trap_list[sig] == (char *)DEFAULT_SIG)
173 return "DEFAULT_SIG";
174 else if (trap_list[sig] == (char *)IGNORE_SIG)
175 return "IGNORE_SIG";
176 else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
177 return "IMPOSSIBLE_TRAP_HANDLER";
178 else if (trap_list[sig])
179 return trap_list[sig];
180 else
181 return "NULL";
182 }
183 #endif
184
185 /* Return the print name of this signal. */
186 char *
187 signal_name (sig)
188 int sig;
189 {
190 char *ret;
191
192 /* on cygwin32, signal_names[sig] could be null */
193 ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
194 ? _("invalid signal number")
195 : signal_names[sig];
196
197 return ret;
198 }
199
200 /* Turn a string into a signal number, or a number into
201 a signal number. If STRING is "2", "SIGINT", or "INT",
202 then (int)2 is returned. Return NO_SIG if STRING doesn't
203 contain a valid signal descriptor. */
204 int
205 decode_signal (string, flags)
206 char *string;
207 int flags;
208 {
209 intmax_t sig;
210 char *name;
211
212 if (legal_number (string, &sig))
213 return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
214
215 /* A leading `SIG' may be omitted. */
216 for (sig = 0; sig < BASH_NSIG; sig++)
217 {
218 name = signal_names[sig];
219 if (name == 0 || name[0] == '\0')
220 continue;
221
222 /* Check name without the SIG prefix first case sensitivly or
223 insensitively depending on whether flags includes DSIG_NOCASE */
224 if (STREQN (name, "SIG", 3))
225 {
226 name += 3;
227
228 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
229 return ((int)sig);
230 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
231 return ((int)sig);
232 /* If we can't use the `SIG' prefix to match, punt on this
233 name now. */
234 else if ((flags & DSIG_SIGPREFIX) == 0)
235 continue;
236 }
237
238 /* Check name with SIG prefix case sensitively or insensitively
239 depending on whether flags includes DSIG_NOCASE */
240 name = signal_names[sig];
241 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
242 return ((int)sig);
243 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
244 return ((int)sig);
245 }
246
247 return (NO_SIG);
248 }
249
250 /* Non-zero when we catch a trapped signal. */
251 static int catch_flag;
252
253 void
254 run_pending_traps ()
255 {
256 register int sig;
257 int old_exit_value, *token_state;
258
259 if (catch_flag == 0) /* simple optimization */
260 return;
261
262 catch_flag = 0;
263
264 /* Preserve $? when running trap. */
265 old_exit_value = last_command_exit_value;
266
267 for (sig = 1; sig < NSIG; sig++)
268 {
269 /* XXX this could be made into a counter by using
270 while (pending_traps[sig]--) instead of the if statement. */
271 if (pending_traps[sig])
272 {
273 #if defined (HAVE_POSIX_SIGNALS)
274 sigset_t set, oset;
275
276 sigemptyset (&set);
277 sigemptyset (&oset);
278
279 sigaddset (&set, sig);
280 sigprocmask (SIG_BLOCK, &set, &oset);
281 #else
282 # if defined (HAVE_BSD_SIGNALS)
283 int oldmask = sigblock (sigmask (sig));
284 # endif
285 #endif /* HAVE_POSIX_SIGNALS */
286
287 if (sig == SIGINT)
288 {
289 run_interrupt_trap ();
290 CLRINTERRUPT;
291 }
292 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
293 trap_list[sig] == (char *)IGNORE_SIG ||
294 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
295 {
296 /* This is possible due to a race condition. Say a bash
297 process has SIGTERM trapped. A subshell is spawned
298 using { list; } & and the parent does something and kills
299 the subshell with SIGTERM. It's possible for the subshell
300 to set pending_traps[SIGTERM] to 1 before the code in
301 execute_cmd.c eventually calls restore_original_signals
302 to reset the SIGTERM signal handler in the subshell. The
303 next time run_pending_traps is called, pending_traps[SIGTERM]
304 will be 1, but the trap handler in trap_list[SIGTERM] will
305 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
306 Unless we catch this, the subshell will dump core when
307 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
308 usually 0x0. */
309 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
310 sig, trap_list[sig]);
311 if (trap_list[sig] == (char *)DEFAULT_SIG)
312 {
313 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
314 kill (getpid (), sig);
315 }
316 }
317 else
318 {
319 token_state = save_token_state ();
320 parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST);
321 restore_token_state (token_state);
322 free (token_state);
323 }
324
325 pending_traps[sig] = 0;
326
327 #if defined (HAVE_POSIX_SIGNALS)
328 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
329 #else
330 # if defined (HAVE_BSD_SIGNALS)
331 sigsetmask (oldmask);
332 # endif
333 #endif /* POSIX_VERSION */
334 }
335 }
336
337 last_command_exit_value = old_exit_value;
338 }
339
340 sighandler
341 trap_handler (sig)
342 int sig;
343 {
344 int oerrno;
345
346 if ((sig >= NSIG) ||
347 (trap_list[sig] == (char *)DEFAULT_SIG) ||
348 (trap_list[sig] == (char *)IGNORE_SIG))
349 programming_error (_("trap_handler: bad signal %d"), sig);
350 else
351 {
352 oerrno = errno;
353 #if defined (MUST_REINSTALL_SIGHANDLERS)
354 set_signal_handler (sig, trap_handler);
355 #endif /* MUST_REINSTALL_SIGHANDLERS */
356
357 catch_flag = 1;
358 pending_traps[sig]++;
359
360 if (interrupt_immediately && this_shell_builtin && (this_shell_builtin == wait_builtin))
361 {
362 wait_signal_received = sig;
363 longjmp (wait_intr_buf, 1);
364 }
365
366 if (interrupt_immediately)
367 run_pending_traps ();
368
369 errno = oerrno;
370 }
371
372 SIGRETURN (0);
373 }
374
375 #if defined (JOB_CONTROL) && defined (SIGCHLD)
376
377 #ifdef INCLUDE_UNUSED
378 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
379 void
380 set_sigchld_trap (command_string)
381 char *command_string;
382 {
383 set_signal (SIGCHLD, command_string);
384 }
385 #endif
386
387 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
388 is not already trapped. */
389 void
390 maybe_set_sigchld_trap (command_string)
391 char *command_string;
392 {
393 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
394 set_signal (SIGCHLD, command_string);
395 }
396 #endif /* JOB_CONTROL && SIGCHLD */
397
398 void
399 set_debug_trap (command)
400 char *command;
401 {
402 set_signal (DEBUG_TRAP, command);
403 }
404
405 void
406 set_error_trap (command)
407 char *command;
408 {
409 set_signal (ERROR_TRAP, command);
410 }
411
412 void
413 set_return_trap (command)
414 char *command;
415 {
416 set_signal (RETURN_TRAP, command);
417 }
418
419 #ifdef INCLUDE_UNUSED
420 void
421 set_sigint_trap (command)
422 char *command;
423 {
424 set_signal (SIGINT, command);
425 }
426 #endif
427
428 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
429 things, like waiting for command substitution or executing commands
430 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
431 SigHandler *
432 set_sigint_handler ()
433 {
434 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
435 return ((SigHandler *)SIG_IGN);
436
437 else if (sigmodes[SIGINT] & SIG_IGNORED)
438 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
439
440 else if (sigmodes[SIGINT] & SIG_TRAPPED)
441 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
442
443 /* The signal is not trapped, so set the handler to the shell's special
444 interrupt handler. */
445 else if (interactive) /* XXX - was interactive_shell */
446 return (set_signal_handler (SIGINT, sigint_sighandler));
447 else
448 return (set_signal_handler (SIGINT, termination_unwind_protect));
449 }
450
451 /* Return the correct handler for signal SIG according to the values in
452 sigmodes[SIG]. */
453 SigHandler *
454 trap_to_sighandler (sig)
455 int sig;
456 {
457 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
458 return (SIG_IGN);
459 else if (sigmodes[sig] & SIG_TRAPPED)
460 return (trap_handler);
461 else
462 return (SIG_DFL);
463 }
464
465 /* Set SIG to call STRING as a command. */
466 void
467 set_signal (sig, string)
468 int sig;
469 char *string;
470 {
471 if (SPECIAL_TRAP (sig))
472 {
473 change_signal (sig, savestring (string));
474 if (sig == EXIT_TRAP && interactive == 0)
475 initialize_terminating_signals ();
476 return;
477 }
478
479 /* A signal ignored on entry to the shell cannot be trapped or reset, but
480 no error is reported when attempting to do so. -- Posix.2 */
481 if (sigmodes[sig] & SIG_HARD_IGNORE)
482 return;
483
484 /* Make sure we have original_signals[sig] if the signal has not yet
485 been trapped. */
486 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
487 {
488 /* If we aren't sure of the original value, check it. */
489 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
490 {
491 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
492 set_signal_handler (sig, original_signals[sig]);
493 }
494
495 /* Signals ignored on entry to the shell cannot be trapped or reset. */
496 if (original_signals[sig] == SIG_IGN)
497 {
498 sigmodes[sig] |= SIG_HARD_IGNORE;
499 return;
500 }
501 }
502
503 /* Only change the system signal handler if SIG_NO_TRAP is not set.
504 The trap command string is changed in either case. The shell signal
505 handlers for SIGINT and SIGCHLD run the user specified traps in an
506 environment in which it is safe to do so. */
507 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
508 {
509 set_signal_handler (sig, SIG_IGN);
510 change_signal (sig, savestring (string));
511 set_signal_handler (sig, trap_handler);
512 }
513 else
514 change_signal (sig, savestring (string));
515 }
516
517 static void
518 free_trap_command (sig)
519 int sig;
520 {
521 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
522 (trap_list[sig] != (char *)IGNORE_SIG) &&
523 (trap_list[sig] != (char *)DEFAULT_SIG) &&
524 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
525 free (trap_list[sig]);
526 }
527
528 /* If SIG has a string assigned to it, get rid of it. Then give it
529 VALUE. */
530 static void
531 change_signal (sig, value)
532 int sig;
533 char *value;
534 {
535 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
536 free_trap_command (sig);
537 trap_list[sig] = value;
538
539 sigmodes[sig] |= SIG_TRAPPED;
540 if (value == (char *)IGNORE_SIG)
541 sigmodes[sig] |= SIG_IGNORED;
542 else
543 sigmodes[sig] &= ~SIG_IGNORED;
544 if (sigmodes[sig] & SIG_INPROGRESS)
545 sigmodes[sig] |= SIG_CHANGED;
546 }
547
548 #define GET_ORIGINAL_SIGNAL(sig) \
549 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
550 get_original_signal (sig)
551
552 static void
553 get_original_signal (sig)
554 int sig;
555 {
556 /* If we aren't sure the of the original value, then get it. */
557 if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
558 {
559 original_signals[sig] =
560 (SigHandler *) set_signal_handler (sig, SIG_DFL);
561 set_signal_handler (sig, original_signals[sig]);
562
563 /* Signals ignored on entry to the shell cannot be trapped. */
564 if (original_signals[sig] == SIG_IGN)
565 sigmodes[sig] |= SIG_HARD_IGNORE;
566 }
567 }
568
569 /* Restore the default action for SIG; i.e., the action the shell
570 would have taken before you used the trap command. This is called
571 from trap_builtin (), which takes care to restore the handlers for
572 the signals the shell treats specially. */
573 void
574 restore_default_signal (sig)
575 int sig;
576 {
577 if (SPECIAL_TRAP (sig))
578 {
579 if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
580 (sigmodes[sig] & SIG_INPROGRESS) == 0)
581 free_trap_command (sig);
582 trap_list[sig] = (char *)NULL;
583 sigmodes[sig] &= ~SIG_TRAPPED;
584 if (sigmodes[sig] & SIG_INPROGRESS)
585 sigmodes[sig] |= SIG_CHANGED;
586 return;
587 }
588
589 GET_ORIGINAL_SIGNAL (sig);
590
591 /* A signal ignored on entry to the shell cannot be trapped or reset, but
592 no error is reported when attempting to do so. Thanks Posix.2. */
593 if (sigmodes[sig] & SIG_HARD_IGNORE)
594 return;
595
596 /* If we aren't trapping this signal, don't bother doing anything else. */
597 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
598 return;
599
600 /* Only change the signal handler for SIG if it allows it. */
601 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
602 set_signal_handler (sig, original_signals[sig]);
603
604 /* Change the trap command in either case. */
605 change_signal (sig, (char *)DEFAULT_SIG);
606
607 /* Mark the signal as no longer trapped. */
608 sigmodes[sig] &= ~SIG_TRAPPED;
609 }
610
611 /* Make this signal be ignored. */
612 void
613 ignore_signal (sig)
614 int sig;
615 {
616 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
617 {
618 change_signal (sig, (char *)IGNORE_SIG);
619 return;
620 }
621
622 GET_ORIGINAL_SIGNAL (sig);
623
624 /* A signal ignored on entry to the shell cannot be trapped or reset.
625 No error is reported when the user attempts to do so. */
626 if (sigmodes[sig] & SIG_HARD_IGNORE)
627 return;
628
629 /* If already trapped and ignored, no change necessary. */
630 if (sigmodes[sig] & SIG_IGNORED)
631 return;
632
633 /* Only change the signal handler for SIG if it allows it. */
634 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
635 set_signal_handler (sig, SIG_IGN);
636
637 /* Change the trap command in either case. */
638 change_signal (sig, (char *)IGNORE_SIG);
639 }
640
641 /* Handle the calling of "trap 0". The only sticky situation is when
642 the command to be executed includes an "exit". This is why we have
643 to provide our own place for top_level to jump to. */
644 int
645 run_exit_trap ()
646 {
647 char *trap_command;
648 int code, function_code, retval;
649
650 trap_saved_exit_value = last_command_exit_value;
651 function_code = 0;
652
653 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
654 currently running in the trap handler (call to exit in the list of
655 commands given to trap 0). */
656 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
657 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
658 {
659 trap_command = savestring (trap_list[EXIT_TRAP]);
660 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
661 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
662
663 retval = trap_saved_exit_value;
664 running_trap = 1;
665
666 code = setjmp (top_level);
667
668 /* If we're in a function, make sure return longjmps come here, too. */
669 if (return_catch_flag)
670 function_code = setjmp (return_catch);
671
672 if (code == 0 && function_code == 0)
673 {
674 reset_parser ();
675 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST);
676 }
677 else if (code == ERREXIT)
678 retval = last_command_exit_value;
679 else if (code == EXITPROG)
680 retval = last_command_exit_value;
681 else if (function_code != 0)
682 retval = return_catch_value;
683 else
684 retval = trap_saved_exit_value;
685
686 running_trap = 0;
687 return retval;
688 }
689
690 return (trap_saved_exit_value);
691 }
692
693 void
694 run_trap_cleanup (sig)
695 int sig;
696 {
697 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
698 }
699
700 /* Run a trap command for SIG. SIG is one of the signals the shell treats
701 specially. Returns the exit status of the executed trap command list. */
702 static int
703 _run_trap_internal (sig, tag)
704 int sig;
705 char *tag;
706 {
707 char *trap_command, *old_trap;
708 int trap_exit_value, *token_state;
709 int save_return_catch_flag, function_code;
710 procenv_t save_return_catch;
711
712 trap_exit_value = function_code = 0;
713 /* Run the trap only if SIG is trapped and not ignored, and we are not
714 currently executing in the trap handler. */
715 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
716 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
717 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
718 {
719 old_trap = trap_list[sig];
720 sigmodes[sig] |= SIG_INPROGRESS;
721 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
722 trap_command = savestring (old_trap);
723
724 running_trap = sig + 1;
725 trap_saved_exit_value = last_command_exit_value;
726
727 token_state = save_token_state ();
728
729 /* If we're in a function, make sure return longjmps come here, too. */
730 save_return_catch_flag = return_catch_flag;
731 if (return_catch_flag)
732 {
733 COPY_PROCENV (return_catch, save_return_catch);
734 function_code = setjmp (return_catch);
735 }
736
737 if (function_code == 0)
738 parse_and_execute (trap_command, tag, SEVAL_NONINT|SEVAL_NOHIST);
739
740 restore_token_state (token_state);
741 free (token_state);
742
743 trap_exit_value = last_command_exit_value;
744 last_command_exit_value = trap_saved_exit_value;
745 running_trap = 0;
746
747 sigmodes[sig] &= ~SIG_INPROGRESS;
748
749 if (sigmodes[sig] & SIG_CHANGED)
750 {
751 #if 0
752 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
753 the places where they can be changed using unwind-protects. For
754 example, look at execute_cmd.c:execute_function(). */
755 if (SPECIAL_TRAP (sig) == 0)
756 #endif
757 free (old_trap);
758 sigmodes[sig] &= ~SIG_CHANGED;
759 }
760
761 if (save_return_catch_flag)
762 {
763 return_catch_flag = save_return_catch_flag;
764 return_catch_value = trap_exit_value;
765 COPY_PROCENV (save_return_catch, return_catch);
766 if (function_code)
767 longjmp (return_catch, 1);
768 }
769 }
770
771 return trap_exit_value;
772 }
773
774 int
775 run_debug_trap ()
776 {
777 int trap_exit_value;
778
779 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
780 trap_exit_value = 0;
781 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
782 {
783 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
784
785 #if defined (DEBUGGER)
786 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
787 a function or sourced script, we force a `return'. */
788 if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
789 {
790 return_catch_value = trap_exit_value;
791 longjmp (return_catch, 1);
792 }
793 #endif
794 }
795 return trap_exit_value;
796 }
797
798 void
799 run_error_trap ()
800 {
801 if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
802 _run_trap_internal (ERROR_TRAP, "error trap");
803 }
804
805 void
806 run_return_trap ()
807 {
808 int old_exit_value;
809
810 #if 0
811 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
812 return;
813 #endif
814
815 if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
816 {
817 old_exit_value = last_command_exit_value;
818 _run_trap_internal (RETURN_TRAP, "return trap");
819 last_command_exit_value = old_exit_value;
820 }
821 }
822
823 /* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
824 declared here to localize the trap functions. */
825 void
826 run_interrupt_trap ()
827 {
828 _run_trap_internal (SIGINT, "interrupt trap");
829 }
830
831 #ifdef INCLUDE_UNUSED
832 /* Free all the allocated strings in the list of traps and reset the trap
833 values to the default. */
834 void
835 free_trap_strings ()
836 {
837 register int i;
838
839 for (i = 0; i < BASH_NSIG; i++)
840 {
841 free_trap_command (i);
842 trap_list[i] = (char *)DEFAULT_SIG;
843 sigmodes[i] &= ~SIG_TRAPPED;
844 }
845 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
846 }
847 #endif
848
849 /* Reset the handler for SIG to the original value. */
850 static void
851 reset_signal (sig)
852 int sig;
853 {
854 set_signal_handler (sig, original_signals[sig]);
855 sigmodes[sig] &= ~SIG_TRAPPED;
856 }
857
858 /* Set the handler signal SIG to the original and free any trap
859 command associated with it. */
860 static void
861 restore_signal (sig)
862 int sig;
863 {
864 set_signal_handler (sig, original_signals[sig]);
865 change_signal (sig, (char *)DEFAULT_SIG);
866 sigmodes[sig] &= ~SIG_TRAPPED;
867 }
868
869 static void
870 reset_or_restore_signal_handlers (reset)
871 sh_resetsig_func_t *reset;
872 {
873 register int i;
874
875 /* Take care of the exit trap first */
876 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
877 {
878 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
879 if (reset != reset_signal)
880 {
881 free_trap_command (EXIT_TRAP);
882 trap_list[EXIT_TRAP] = (char *)NULL;
883 }
884 }
885
886 for (i = 1; i < NSIG; i++)
887 {
888 if (sigmodes[i] & SIG_TRAPPED)
889 {
890 if (trap_list[i] == (char *)IGNORE_SIG)
891 set_signal_handler (i, SIG_IGN);
892 else
893 (*reset) (i);
894 }
895 else if (sigmodes[i] & SIG_SPECIAL)
896 (*reset) (i);
897 }
898
899 /* Command substitution and other child processes don't inherit the
900 debug, error, or return traps. If we're in the debugger, and the
901 `functrace' or `errtrace' options have been set, then let command
902 substitutions inherit them. Let command substitution inherit the
903 RETURN trap if we're in the debugger and tracing functions. */
904 #if defined (DEBUGGER)
905 if (debugging_mode == 0 || function_trace_mode == 0)
906 #endif
907 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
908 #if defined (DEBUGGER)
909 if (debugging_mode == 0 || error_trace_mode == 0)
910 #endif
911 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
912 #if defined (DEBUGGER)
913 if (debugging_mode == 0 || function_trace_mode == 0)
914 #endif
915 sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
916 }
917
918 /* Reset trapped signals to their original values, but don't free the
919 trap strings. Called by the command substitution code. */
920 void
921 reset_signal_handlers ()
922 {
923 reset_or_restore_signal_handlers (reset_signal);
924 }
925
926 /* Reset all trapped signals to their original values. Signals set to be
927 ignored with trap '' SIGNAL should be ignored, so we make sure that they
928 are. Called by child processes after they are forked. */
929 void
930 restore_original_signals ()
931 {
932 reset_or_restore_signal_handlers (restore_signal);
933 }
934
935 /* If a trap handler exists for signal SIG, then call it; otherwise just
936 return failure. */
937 int
938 maybe_call_trap_handler (sig)
939 int sig;
940 {
941 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
942 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
943 {
944 switch (sig)
945 {
946 case SIGINT:
947 run_interrupt_trap ();
948 break;
949 case EXIT_TRAP:
950 run_exit_trap ();
951 break;
952 case DEBUG_TRAP:
953 run_debug_trap ();
954 break;
955 case ERROR_TRAP:
956 run_error_trap ();
957 break;
958 default:
959 trap_handler (sig);
960 break;
961 }
962 return (1);
963 }
964 else
965 return (0);
966 }
967
968 int
969 signal_is_trapped (sig)
970 int sig;
971 {
972 return (sigmodes[sig] & SIG_TRAPPED);
973 }
974
975 int
976 signal_is_special (sig)
977 int sig;
978 {
979 return (sigmodes[sig] & SIG_SPECIAL);
980 }
981
982 int
983 signal_is_ignored (sig)
984 int sig;
985 {
986 return (sigmodes[sig] & SIG_IGNORED);
987 }
988
989 void
990 set_signal_ignored (sig)
991 int sig;
992 {
993 sigmodes[sig] |= SIG_HARD_IGNORE;
994 original_signals[sig] = SIG_IGN;
995 }
996
997 int
998 signal_in_progress (sig)
999 int sig;
1000 {
1001 return (sigmodes[sig] & SIG_INPROGRESS);
1002 }