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