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