]> git.ipfire.org Git - thirdparty/bash.git/blame - trap.c
Bash-5.2 patch 26: fix typo when specifying readline's custom color prefix
[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
74091dd4 4/* Copyright (C) 1987-2021 Free Software Foundation, Inc.
726f6388
JA
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
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
3185942a
JA
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
3185942a
JA
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
b80f6443
JA
34#include "bashintl.h"
35
ac50fbac
CR
36#include <signal.h>
37
cce855bc
JA
38#include "trap.h"
39
726f6388 40#include "shell.h"
d233b485 41#include "execute_cmd.h"
b80f6443 42#include "flags.h"
d233b485 43#include "parser.h"
bb70624e 44#include "input.h" /* for save_token_state, restore_token_state */
3185942a 45#include "jobs.h"
726f6388 46#include "signames.h"
7117c2d2 47#include "builtins.h"
ccc6cda3 48#include "builtins/common.h"
7117c2d2 49#include "builtins/builtext.h"
726f6388 50
ac50fbac
CR
51#if defined (READLINE)
52# include <readline/readline.h>
53# include "bashline.h"
54#endif
55
bb70624e
JA
56#ifndef errno
57extern int errno;
58#endif
59
726f6388
JA
60/* Flags which describe the current handling state of a signal. */
61#define SIG_INHERITED 0x0 /* Value inherited from parent. */
62#define SIG_TRAPPED 0x1 /* Currently trapped. */
63#define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
64#define SIG_SPECIAL 0x4 /* Treat this signal specially. */
65#define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
ccc6cda3
JA
66#define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
67#define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
68#define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
726f6388 69
b80f6443 70#define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
f73dda09 71
726f6388 72/* An array of such flags, one for each signal, describing what the
ccc6cda3
JA
73 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
74 assumes this. */
f73dda09
JA
75static int sigmodes[BASH_NSIG];
76
a0c0a00f
CR
77static void free_trap_command (int);
78static void change_signal (int, char *);
f73dda09 79
a0c0a00f 80static int _run_trap_internal (int, char *);
726f6388 81
a0c0a00f
CR
82static void free_trap_string (int);
83static void reset_signal (int);
84static void restore_signal (int);
85static void reset_or_restore_signal_handlers (sh_resetsig_func_t *);
74091dd4 86static void reinit_trap (int);
a0c0a00f
CR
87
88static void trap_if_untrapped (int, char *);
726f6388
JA
89
90/* Variables used here but defined in other files. */
ac50fbac 91
a0c0a00f 92extern volatile int from_return_trap;
8868edaf 93extern int waiting_for_child;
a0c0a00f 94
0001803f 95extern WORD_LIST *subst_assign_varlist;
7117c2d2 96
726f6388
JA
97/* The list of things to do originally, before we started trapping. */
98SigHandler *original_signals[NSIG];
99
100/* For each signal, a slot for a string, which is a command to be
ac50fbac 101 executed when that signal is received. The slot can also contain
726f6388
JA
102 DEFAULT_SIG, which means do whatever you were going to do before
103 you were so rudely interrupted, or IGNORE_SIG, which says ignore
104 this signal. */
f73dda09 105char *trap_list[BASH_NSIG];
726f6388
JA
106
107/* A bitmap of signals received for which we have trap handlers. */
108int pending_traps[NSIG];
109
ccc6cda3
JA
110/* Set to the number of the signal we're running the trap for + 1.
111 Used in execute_cmd.c and builtins/common.c to clean up when
112 parse_and_execute does not return normally after executing the
113 trap command (e.g., when `return' is executed in the trap command). */
114int running_trap;
115
b80f6443
JA
116/* Set to last_command_exit_value before running a trap. */
117int trap_saved_exit_value;
d166f048 118
7117c2d2
JA
119/* The (trapped) signal received while executing in the `wait' builtin */
120int wait_signal_received;
121
ac50fbac
CR
122int trapped_signal_received;
123
8868edaf
CR
124/* Set to 1 to suppress the effect of `set v' in the DEBUG trap. */
125int suppress_debug_trap_verbose = 0;
126
0628567a
JA
127#define GETORIGSIG(sig) \
128 do { \
129 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
130 set_signal_handler (sig, original_signals[sig]); \
131 if (original_signals[sig] == SIG_IGN) \
132 sigmodes[sig] |= SIG_HARD_IGNORE; \
133 } while (0)
134
495aee44
CR
135#define SETORIGSIG(sig,handler) \
136 do { \
137 original_signals[sig] = handler; \
138 if (original_signals[sig] == SIG_IGN) \
139 sigmodes[sig] |= SIG_HARD_IGNORE; \
140 } while (0)
141
0628567a
JA
142#define GET_ORIGINAL_SIGNAL(sig) \
143 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
144 GETORIGSIG(sig)
145
726f6388
JA
146void
147initialize_traps ()
148{
149 register int i;
150
0628567a
JA
151 initialize_signames();
152
b80f6443
JA
153 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
154 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
ccc6cda3 155 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
726f6388
JA
156
157 for (i = 1; i < NSIG; i++)
158 {
159 pending_traps[i] = 0;
160 trap_list[i] = (char *)DEFAULT_SIG;
495aee44 161 sigmodes[i] = SIG_INHERITED; /* XXX - only set, not used */
726f6388
JA
162 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
163 }
164
165 /* Show which signals are treated specially by the shell. */
166#if defined (SIGCHLD)
0628567a 167 GETORIGSIG (SIGCHLD);
726f6388
JA
168 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
169#endif /* SIGCHLD */
170
0628567a 171 GETORIGSIG (SIGINT);
726f6388
JA
172 sigmodes[SIGINT] |= SIG_SPECIAL;
173
b72432fd
JA
174#if defined (__BEOS__)
175 /* BeOS sets SIGINT to SIG_IGN! */
176 original_signals[SIGINT] = SIG_DFL;
0628567a 177 sigmodes[SIGINT] &= ~SIG_HARD_IGNORE;
b72432fd
JA
178#endif
179
0628567a 180 GETORIGSIG (SIGQUIT);
726f6388
JA
181 sigmodes[SIGQUIT] |= SIG_SPECIAL;
182
183 if (interactive)
184 {
0628567a 185 GETORIGSIG (SIGTERM);
726f6388
JA
186 sigmodes[SIGTERM] |= SIG_SPECIAL;
187 }
a0c0a00f
CR
188
189 get_original_tty_job_signals ();
726f6388
JA
190}
191
ac50fbac 192#ifdef DEBUG
bb70624e
JA
193/* Return a printable representation of the trap handler for SIG. */
194static char *
195trap_handler_string (sig)
196 int sig;
197{
198 if (trap_list[sig] == (char *)DEFAULT_SIG)
199 return "DEFAULT_SIG";
200 else if (trap_list[sig] == (char *)IGNORE_SIG)
201 return "IGNORE_SIG";
202 else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
203 return "IMPOSSIBLE_TRAP_HANDLER";
204 else if (trap_list[sig])
205 return trap_list[sig];
206 else
207 return "NULL";
208}
209#endif
210
726f6388
JA
211/* Return the print name of this signal. */
212char *
213signal_name (sig)
214 int sig;
215{
cce855bc
JA
216 char *ret;
217
218 /* on cygwin32, signal_names[sig] could be null */
b80f6443
JA
219 ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
220 ? _("invalid signal number")
221 : signal_names[sig];
222
cce855bc 223 return ret;
726f6388
JA
224}
225
226/* Turn a string into a signal number, or a number into
227 a signal number. If STRING is "2", "SIGINT", or "INT",
228 then (int)2 is returned. Return NO_SIG if STRING doesn't
229 contain a valid signal descriptor. */
230int
b80f6443 231decode_signal (string, flags)
726f6388 232 char *string;
b80f6443 233 int flags;
726f6388 234{
7117c2d2 235 intmax_t sig;
b80f6443 236 char *name;
726f6388 237
ccc6cda3 238 if (legal_number (string, &sig))
f73dda09 239 return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
726f6388 240
d233b485
CR
241#if defined (SIGRTMIN) && defined (SIGRTMAX)
242 if (STREQN (string, "SIGRTMIN+", 9) || ((flags & DSIG_NOCASE) && strncasecmp (string, "SIGRTMIN+", 9) == 0))
243 {
244 if (legal_number (string+9, &sig) && sig >= 0 && sig <= SIGRTMAX - SIGRTMIN)
245 return (SIGRTMIN + sig);
246 else
247 return NO_SIG;
248 }
249 else if (STREQN (string, "RTMIN+", 6) || ((flags & DSIG_NOCASE) && strncasecmp (string, "RTMIN+", 6) == 0))
250 {
251 if (legal_number (string+6, &sig) && sig >= 0 && sig <= SIGRTMAX - SIGRTMIN)
252 return (SIGRTMIN + sig);
253 else
254 return NO_SIG;
255 }
256#endif /* SIGRTMIN && SIGRTMAX */
257
e8ce775d 258 /* A leading `SIG' may be omitted. */
f73dda09 259 for (sig = 0; sig < BASH_NSIG; sig++)
b72432fd 260 {
b80f6443
JA
261 name = signal_names[sig];
262 if (name == 0 || name[0] == '\0')
b72432fd 263 continue;
b80f6443 264
ac50fbac 265 /* Check name without the SIG prefix first case sensitively or
b80f6443
JA
266 insensitively depending on whether flags includes DSIG_NOCASE */
267 if (STREQN (name, "SIG", 3))
268 {
269 name += 3;
270
271 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
272 return ((int)sig);
273 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
274 return ((int)sig);
275 /* If we can't use the `SIG' prefix to match, punt on this
276 name now. */
277 else if ((flags & DSIG_SIGPREFIX) == 0)
278 continue;
279 }
280
281 /* Check name with SIG prefix case sensitively or insensitively
282 depending on whether flags includes DSIG_NOCASE */
283 name = signal_names[sig];
284 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
285 return ((int)sig);
286 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
b72432fd
JA
287 return ((int)sig);
288 }
726f6388
JA
289
290 return (NO_SIG);
291}
292
293/* Non-zero when we catch a trapped signal. */
ccc6cda3 294static int catch_flag;
726f6388
JA
295
296void
297run_pending_traps ()
298{
299 register int sig;
74091dd4
CR
300 int x;
301 volatile int old_exit_value, old_running;
0001803f 302 WORD_LIST *save_subst_varlist;
a0c0a00f 303 HASH_TABLE *save_tempenv;
ac50fbac 304 sh_parser_state_t pstate;
74091dd4
CR
305 volatile int save_return_catch_flag, function_code;
306 procenv_t save_return_catch;
ec8113b9 307 char *trap_command, *old_trap;
495aee44
CR
308#if defined (ARRAY_VARS)
309 ARRAY *ps;
310#endif
726f6388
JA
311
312 if (catch_flag == 0) /* simple optimization */
313 return;
314
ac50fbac
CR
315 if (running_trap > 0)
316 {
74091dd4 317 internal_debug ("run_pending_traps: recursive invocation while running trap for signal %d", running_trap-1);
a0c0a00f
CR
318#if defined (SIGWINCH)
319 if (running_trap == SIGWINCH+1 && pending_traps[SIGWINCH])
320 return; /* no recursive SIGWINCH trap invocations */
ac50fbac 321#endif
d233b485
CR
322 /* could check for running the trap handler for the same signal here
323 (running_trap == sig+1) */
324 if (evalnest_max > 0 && evalnest > evalnest_max)
325 {
326 internal_error (_("trap handler: maximum trap handler level exceeded (%d)"), evalnest_max);
327 evalnest = 0;
328 jump_to_top_level (DISCARD);
329 }
ac50fbac
CR
330 }
331
332 catch_flag = trapped_signal_received = 0;
726f6388
JA
333
334 /* Preserve $? when running trap. */
a0c0a00f 335 trap_saved_exit_value = old_exit_value = last_command_exit_value;
495aee44
CR
336#if defined (ARRAY_VARS)
337 ps = save_pipestatus_array ();
338#endif
8868edaf 339 old_running = running_trap;
726f6388
JA
340
341 for (sig = 1; sig < NSIG; sig++)
342 {
343 /* XXX this could be made into a counter by using
28ef6c31 344 while (pending_traps[sig]--) instead of the if statement. */
726f6388
JA
345 if (pending_traps[sig])
346 {
74091dd4 347 /* XXX - set last_command_exit_value = trap_saved_exit_value here? */
ac50fbac 348 running_trap = sig + 1;
726f6388
JA
349
350 if (sig == SIGINT)
351 {
ac50fbac 352 pending_traps[sig] = 0; /* XXX */
d233b485
CR
353 /* We don't modify evalnest here, since run_interrupt_trap() calls
354 _run_trap_internal, which does. */
a0c0a00f 355 run_interrupt_trap (0);
d233b485 356 CLRINTERRUPT; /* interrupts don't stack */
726f6388 357 }
3185942a
JA
358#if defined (JOB_CONTROL) && defined (SIGCHLD)
359 else if (sig == SIGCHLD &&
360 trap_list[SIGCHLD] != (char *)IMPOSSIBLE_TRAP_HANDLER &&
361 (sigmodes[SIGCHLD] & SIG_INPROGRESS) == 0)
362 {
ac50fbac 363 sigmodes[SIGCHLD] |= SIG_INPROGRESS;
d233b485
CR
364 /* We modify evalnest here even though run_sigchld_trap can run
365 the trap action more than once */
366 evalnest++;
a0c0a00f
CR
367 x = pending_traps[sig];
368 pending_traps[sig] = 0;
369 run_sigchld_trap (x); /* use as counter */
370 running_trap = 0;
d233b485 371 evalnest--;
ac50fbac 372 sigmodes[SIGCHLD] &= ~SIG_INPROGRESS;
a0c0a00f
CR
373 /* continue here rather than reset pending_traps[SIGCHLD] below in
374 case there are recursive calls to run_pending_traps and children
375 have been reaped while run_sigchld_trap was running. */
376 continue;
ac50fbac
CR
377 }
378 else if (sig == SIGCHLD &&
379 trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER &&
380 (sigmodes[SIGCHLD] & SIG_INPROGRESS) != 0)
381 {
382 /* This can happen when run_pending_traps is called while
383 running a SIGCHLD trap handler. */
384 running_trap = 0;
385 /* want to leave pending_traps[SIGCHLD] alone here */
386 continue; /* XXX */
387 }
388 else if (sig == SIGCHLD && (sigmodes[SIGCHLD] & SIG_INPROGRESS))
389 {
390 /* whoops -- print warning? */
391 running_trap = 0; /* XXX */
392 /* want to leave pending_traps[SIGCHLD] alone here */
393 continue;
3185942a
JA
394 }
395#endif
bb70624e
JA
396 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
397 trap_list[sig] == (char *)IGNORE_SIG ||
398 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
399 {
400 /* This is possible due to a race condition. Say a bash
401 process has SIGTERM trapped. A subshell is spawned
402 using { list; } & and the parent does something and kills
403 the subshell with SIGTERM. It's possible for the subshell
404 to set pending_traps[SIGTERM] to 1 before the code in
405 execute_cmd.c eventually calls restore_original_signals
406 to reset the SIGTERM signal handler in the subshell. The
407 next time run_pending_traps is called, pending_traps[SIGTERM]
408 will be 1, but the trap handler in trap_list[SIGTERM] will
409 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
410 Unless we catch this, the subshell will dump core when
411 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
412 usually 0x0. */
b80f6443 413 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
f73dda09 414 sig, trap_list[sig]);
bb70624e
JA
415 if (trap_list[sig] == (char *)DEFAULT_SIG)
416 {
b80f6443 417 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
bb70624e
JA
418 kill (getpid (), sig);
419 }
420 }
726f6388 421 else
bb70624e 422 {
ec8113b9
CR
423 old_trap = trap_list[sig];
424 trap_command = savestring (old_trap);
425
ac50fbac 426 save_parser_state (&pstate);
0001803f
CR
427 save_subst_varlist = subst_assign_varlist;
428 subst_assign_varlist = 0;
a0c0a00f
CR
429 save_tempenv = temporary_env;
430 temporary_env = 0; /* traps should not run with temporary env */
0001803f 431
ac50fbac
CR
432#if defined (JOB_CONTROL)
433 save_pipeline (1); /* XXX only provides one save level */
434#endif
435 /* XXX - set pending_traps[sig] = 0 here? */
436 pending_traps[sig] = 0;
d233b485 437 evalnest++;
74091dd4
CR
438
439 function_code = 0;
440 save_return_catch_flag = return_catch_flag;
441 if (return_catch_flag)
442 {
443 COPY_PROCENV (return_catch, save_return_catch);
444 function_code = setjmp_nosigs (return_catch);
445 }
446
447 if (function_code == 0)
ec8113b9
CR
448 /* XXX is x always last_command_exit_value? */
449 x = parse_and_execute (trap_command, "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE);
74091dd4
CR
450 else
451 {
452 parse_and_execute_cleanup (sig + 1); /* XXX - could use -1 */
453 x = return_catch_value;
454 }
455
d233b485 456 evalnest--;
ac50fbac
CR
457#if defined (JOB_CONTROL)
458 restore_pipeline (1);
459#endif
0001803f
CR
460
461 subst_assign_varlist = save_subst_varlist;
ac50fbac 462 restore_parser_state (&pstate);
a0c0a00f 463 temporary_env = save_tempenv;
74091dd4
CR
464
465 if (save_return_catch_flag)
466 {
467 return_catch_flag = save_return_catch_flag;
468 return_catch_value = x;
469 COPY_PROCENV (save_return_catch, return_catch);
470 if (function_code)
471 {
472 running_trap = old_running; /* XXX */
473 /* caller will set last_command_exit_value */
474 sh_longjmp (return_catch, 1);
475 }
476 }
bb70624e 477 }
726f6388 478
ac50fbac 479 pending_traps[sig] = 0; /* XXX - move before evalstring? */
8868edaf 480 running_trap = old_running;
726f6388
JA
481 }
482 }
483
495aee44
CR
484#if defined (ARRAY_VARS)
485 restore_pipestatus_array (ps);
486#endif
726f6388
JA
487 last_command_exit_value = old_exit_value;
488}
489
8868edaf
CR
490/* Set the private state variables noting that we received a signal SIG
491 for which we have a trap set. */
492void
493set_trap_state (sig)
494 int sig;
495{
496 catch_flag = 1;
497 pending_traps[sig]++;
498 trapped_signal_received = sig;
499}
500
726f6388
JA
501sighandler
502trap_handler (sig)
503 int sig;
504{
bb70624e
JA
505 int oerrno;
506
3185942a
JA
507 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
508 {
74091dd4 509 internal_debug ("trap_handler: signal %d: signal not trapped", sig);
3185942a
JA
510 SIGRETURN (0);
511 }
512
15409324
CR
513 /* This means we're in a subshell, but have not yet reset the handler for
514 trapped signals. We're not supposed to execute the trap in this situation;
515 we should restore the original signal and resend the signal to ourselves
516 to preserve the Posix "signal traps that are not being ignored shall be
517 set to the default action" semantics. */
518 if ((subshell_environment & SUBSHELL_IGNTRAP) && trap_list[sig] != (char *)IGNORE_SIG)
519 {
520 sigset_t mask;
521
522 /* Paranoia */
523 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
524 original_signals[sig] = SIG_DFL;
525
526 restore_signal (sig);
527
528 /* Make sure we let the signal we just caught through */
529 sigemptyset (&mask);
530 sigprocmask (SIG_SETMASK, (sigset_t *)NULL, &mask);
531 sigdelset (&mask, sig);
532 sigprocmask (SIG_SETMASK, &mask, (sigset_t *)NULL);
533
534 kill (getpid (), sig);
535
536 SIGRETURN (0);
537 }
538
726f6388
JA
539 if ((sig >= NSIG) ||
540 (trap_list[sig] == (char *)DEFAULT_SIG) ||
541 (trap_list[sig] == (char *)IGNORE_SIG))
b80f6443 542 programming_error (_("trap_handler: bad signal %d"), sig);
726f6388
JA
543 else
544 {
28ef6c31 545 oerrno = errno;
ccc6cda3 546#if defined (MUST_REINSTALL_SIGHANDLERS)
3185942a
JA
547# if defined (JOB_CONTROL) && defined (SIGCHLD)
548 if (sig != SIGCHLD)
549# endif /* JOB_CONTROL && SIGCHLD */
726f6388 550 set_signal_handler (sig, trap_handler);
ccc6cda3 551#endif /* MUST_REINSTALL_SIGHANDLERS */
726f6388 552
8868edaf 553 set_trap_state (sig);
ac50fbac
CR
554
555 if (this_shell_builtin && (this_shell_builtin == wait_builtin))
7117c2d2
JA
556 {
557 wait_signal_received = sig;
8868edaf 558 if (waiting_for_child && wait_intr_flag)
a0c0a00f 559 sh_longjmp (wait_intr_buf, 1);
7117c2d2
JA
560 }
561
ac50fbac
CR
562#if defined (READLINE)
563 /* Set the event hook so readline will call it after the signal handlers
564 finish executing, so if this interrupted character input we can get
565 quick response. */
8868edaf 566 if (RL_ISSTATE (RL_STATE_SIGHANDLER))
ac50fbac
CR
567 bashline_set_event_hook ();
568#endif
569
bb70624e 570 errno = oerrno;
726f6388 571 }
d233b485 572
ccc6cda3 573 SIGRETURN (0);
726f6388
JA
574}
575
ac50fbac 576int
8868edaf
CR
577next_pending_trap (start)
578 int start;
ac50fbac
CR
579{
580 register int i;
581
8868edaf 582 for (i = start; i < NSIG; i++)
ac50fbac
CR
583 if (pending_traps[i])
584 return i;
585 return -1;
586}
587
8868edaf
CR
588int
589first_pending_trap ()
590{
591 return (next_pending_trap (1));
592}
593
d233b485
CR
594/* Return > 0 if any of the "real" signals (not fake signals like EXIT) are
595 trapped. */
ac50fbac
CR
596int
597any_signals_trapped ()
598{
599 register int i;
600
601 for (i = 1; i < NSIG; i++)
74091dd4 602 if ((sigmodes[i] & SIG_TRAPPED) && (sigmodes[i] & SIG_IGNORED) == 0)
ac50fbac
CR
603 return i;
604 return -1;
605}
606
8868edaf
CR
607void
608clear_pending_traps ()
609{
610 register int i;
611
612 for (i = 1; i < NSIG; i++)
613 pending_traps[i] = 0;
614}
615
ac50fbac
CR
616void
617check_signals ()
618{
74091dd4
CR
619 /* Add any other shell timeouts here */
620 check_read_timeout (); /* set by the read builtin */
ac50fbac
CR
621 QUIT;
622}
623
624/* Convenience functions the rest of the shell can use */
625void
626check_signals_and_traps ()
627{
628 check_signals ();
629
630 run_pending_traps ();
631}
632
726f6388 633#if defined (JOB_CONTROL) && defined (SIGCHLD)
cce855bc
JA
634
635#ifdef INCLUDE_UNUSED
726f6388
JA
636/* Make COMMAND_STRING be executed when SIGCHLD is caught. */
637void
638set_sigchld_trap (command_string)
639 char *command_string;
640{
726f6388
JA
641 set_signal (SIGCHLD, command_string);
642}
cce855bc 643#endif
726f6388 644
95732b49 645/* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
3185942a
JA
646 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
647 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
648 reset the disposition to the default and not have the original signal
649 accidentally restored, undoing the user's command. */
726f6388
JA
650void
651maybe_set_sigchld_trap (command_string)
652 char *command_string;
653{
3185942a 654 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER)
726f6388
JA
655 set_signal (SIGCHLD, command_string);
656}
3185942a
JA
657
658/* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
659 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
660 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
661void
662set_impossible_sigchld_trap ()
663{
664 restore_default_signal (SIGCHLD);
665 change_signal (SIGCHLD, (char *)IMPOSSIBLE_TRAP_HANDLER);
666 sigmodes[SIGCHLD] &= ~SIG_TRAPPED; /* maybe_set_sigchld_trap checks this */
667}
ac50fbac
CR
668
669/* Act as if we received SIGCHLD NCHILD times and increment
670 pending_traps[SIGCHLD] by that amount. This allows us to still run the
671 SIGCHLD trap once for each exited child. */
672void
673queue_sigchld_trap (nchild)
674 int nchild;
675{
676 if (nchild > 0)
677 {
678 catch_flag = 1;
679 pending_traps[SIGCHLD] += nchild;
680 trapped_signal_received = SIGCHLD;
681 }
682}
726f6388
JA
683#endif /* JOB_CONTROL && SIGCHLD */
684
a0c0a00f
CR
685/* Set a trap for SIG only if SIG is not already trapped. */
686static inline void
687trap_if_untrapped (sig, command)
688 int sig;
689 char *command;
690{
691 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
692 set_signal (sig, command);
693}
694
ccc6cda3
JA
695void
696set_debug_trap (command)
726f6388
JA
697 char *command;
698{
ccc6cda3
JA
699 set_signal (DEBUG_TRAP, command);
700}
726f6388 701
a0c0a00f
CR
702/* Separate function to call when functions and sourced files want to restore
703 the original version of the DEBUG trap before returning. Unless the -T
704 option is set, source and shell function execution save the old debug trap
705 and unset the trap. If the function or sourced file changes the DEBUG trap,
706 SIG_TRAPPED will be set and we don't bother restoring the original trap string.
707 This is used by both functions and the source builtin. */
708void
709maybe_set_debug_trap (command)
710 char *command;
711{
712 trap_if_untrapped (DEBUG_TRAP, command);
713}
714
f73dda09
JA
715void
716set_error_trap (command)
717 char *command;
718{
719 set_signal (ERROR_TRAP, command);
720}
721
a0c0a00f
CR
722void
723maybe_set_error_trap (command)
724 char *command;
725{
726 trap_if_untrapped (ERROR_TRAP, command);
727}
728
b80f6443
JA
729void
730set_return_trap (command)
731 char *command;
732{
733 set_signal (RETURN_TRAP, command);
734}
735
a0c0a00f
CR
736void
737maybe_set_return_trap (command)
738 char *command;
739{
740 trap_if_untrapped (RETURN_TRAP, command);
741}
742
cce855bc 743#ifdef INCLUDE_UNUSED
ccc6cda3
JA
744void
745set_sigint_trap (command)
746 char *command;
747{
726f6388
JA
748 set_signal (SIGINT, command);
749}
cce855bc 750#endif
726f6388
JA
751
752/* Reset the SIGINT handler so that subshells that are doing `shellsy'
753 things, like waiting for command substitution or executing commands
754 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
755SigHandler *
756set_sigint_handler ()
757{
758 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
759 return ((SigHandler *)SIG_IGN);
760
761 else if (sigmodes[SIGINT] & SIG_IGNORED)
ccc6cda3
JA
762 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
763
726f6388
JA
764 else if (sigmodes[SIGINT] & SIG_TRAPPED)
765 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
766
767 /* The signal is not trapped, so set the handler to the shell's special
768 interrupt handler. */
769 else if (interactive) /* XXX - was interactive_shell */
770 return (set_signal_handler (SIGINT, sigint_sighandler));
771 else
0628567a 772 return (set_signal_handler (SIGINT, termsig_sighandler));
726f6388
JA
773}
774
e8ce775d
JA
775/* Return the correct handler for signal SIG according to the values in
776 sigmodes[SIG]. */
777SigHandler *
778trap_to_sighandler (sig)
779 int sig;
780{
781 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
782 return (SIG_IGN);
783 else if (sigmodes[sig] & SIG_TRAPPED)
784 return (trap_handler);
785 else
786 return (SIG_DFL);
787}
788
726f6388
JA
789/* Set SIG to call STRING as a command. */
790void
791set_signal (sig, string)
792 int sig;
793 char *string;
794{
ac50fbac
CR
795 sigset_t set, oset;
796
f73dda09 797 if (SPECIAL_TRAP (sig))
ccc6cda3
JA
798 {
799 change_signal (sig, savestring (string));
d166f048
JA
800 if (sig == EXIT_TRAP && interactive == 0)
801 initialize_terminating_signals ();
ccc6cda3
JA
802 return;
803 }
804
726f6388
JA
805 /* A signal ignored on entry to the shell cannot be trapped or reset, but
806 no error is reported when attempting to do so. -- Posix.2 */
807 if (sigmodes[sig] & SIG_HARD_IGNORE)
808 return;
809
810 /* Make sure we have original_signals[sig] if the signal has not yet
811 been trapped. */
812 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
813 {
814 /* If we aren't sure of the original value, check it. */
815 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
0628567a 816 GETORIGSIG (sig);
726f6388 817 if (original_signals[sig] == SIG_IGN)
0628567a 818 return;
726f6388
JA
819 }
820
821 /* Only change the system signal handler if SIG_NO_TRAP is not set.
822 The trap command string is changed in either case. The shell signal
823 handlers for SIGINT and SIGCHLD run the user specified traps in an
824 environment in which it is safe to do so. */
825 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
826 {
ac50fbac 827 BLOCK_SIGNAL (sig, set, oset);
726f6388
JA
828 change_signal (sig, savestring (string));
829 set_signal_handler (sig, trap_handler);
ac50fbac 830 UNBLOCK_SIGNAL (oset);
726f6388
JA
831 }
832 else
833 change_signal (sig, savestring (string));
834}
835
836static void
837free_trap_command (sig)
838 int sig;
839{
840 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
841 (trap_list[sig] != (char *)IGNORE_SIG) &&
842 (trap_list[sig] != (char *)DEFAULT_SIG) &&
843 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
844 free (trap_list[sig]);
845}
ccc6cda3 846
726f6388
JA
847/* If SIG has a string assigned to it, get rid of it. Then give it
848 VALUE. */
849static void
850change_signal (sig, value)
851 int sig;
852 char *value;
853{
d166f048
JA
854 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
855 free_trap_command (sig);
726f6388
JA
856 trap_list[sig] = value;
857
858 sigmodes[sig] |= SIG_TRAPPED;
859 if (value == (char *)IGNORE_SIG)
860 sigmodes[sig] |= SIG_IGNORED;
861 else
862 sigmodes[sig] &= ~SIG_IGNORED;
863 if (sigmodes[sig] & SIG_INPROGRESS)
864 sigmodes[sig] |= SIG_CHANGED;
865}
866
ac50fbac 867void
726f6388
JA
868get_original_signal (sig)
869 int sig;
870{
871 /* If we aren't sure the of the original value, then get it. */
0001803f 872 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
0628567a 873 GETORIGSIG (sig);
726f6388
JA
874}
875
495aee44
CR
876void
877get_all_original_signals ()
878{
879 register int i;
880
881 for (i = 1; i < NSIG; i++)
882 GET_ORIGINAL_SIGNAL (i);
883}
884
885void
886set_original_signal (sig, handler)
887 int sig;
888 SigHandler *handler;
889{
890 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
891 SETORIGSIG (sig, handler);
892}
893
726f6388
JA
894/* Restore the default action for SIG; i.e., the action the shell
895 would have taken before you used the trap command. This is called
896 from trap_builtin (), which takes care to restore the handlers for
897 the signals the shell treats specially. */
898void
899restore_default_signal (sig)
900 int sig;
901{
f73dda09 902 if (SPECIAL_TRAP (sig))
726f6388 903 {
b80f6443
JA
904 if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
905 (sigmodes[sig] & SIG_INPROGRESS) == 0)
d166f048 906 free_trap_command (sig);
726f6388
JA
907 trap_list[sig] = (char *)NULL;
908 sigmodes[sig] &= ~SIG_TRAPPED;
d166f048
JA
909 if (sigmodes[sig] & SIG_INPROGRESS)
910 sigmodes[sig] |= SIG_CHANGED;
726f6388
JA
911 return;
912 }
913
914 GET_ORIGINAL_SIGNAL (sig);
915
916 /* A signal ignored on entry to the shell cannot be trapped or reset, but
917 no error is reported when attempting to do so. Thanks Posix.2. */
918 if (sigmodes[sig] & SIG_HARD_IGNORE)
919 return;
920
921 /* If we aren't trapping this signal, don't bother doing anything else. */
ac50fbac
CR
922 /* We special-case SIGCHLD and IMPOSSIBLE_TRAP_HANDLER (see above) as a
923 sentinel to determine whether or not disposition is reset to the default
924 while the trap handler is executing. */
925 if (((sigmodes[sig] & SIG_TRAPPED) == 0) &&
926 (sig != SIGCHLD || (sigmodes[sig] & SIG_INPROGRESS) == 0 || trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
726f6388
JA
927 return;
928
929 /* Only change the signal handler for SIG if it allows it. */
ccc6cda3 930 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
726f6388
JA
931 set_signal_handler (sig, original_signals[sig]);
932
933 /* Change the trap command in either case. */
934 change_signal (sig, (char *)DEFAULT_SIG);
935
936 /* Mark the signal as no longer trapped. */
937 sigmodes[sig] &= ~SIG_TRAPPED;
938}
939
940/* Make this signal be ignored. */
941void
942ignore_signal (sig)
943 int sig;
944{
f73dda09 945 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
ccc6cda3
JA
946 {
947 change_signal (sig, (char *)IGNORE_SIG);
948 return;
949 }
950
726f6388
JA
951 GET_ORIGINAL_SIGNAL (sig);
952
953 /* A signal ignored on entry to the shell cannot be trapped or reset.
ccc6cda3 954 No error is reported when the user attempts to do so. */
726f6388
JA
955 if (sigmodes[sig] & SIG_HARD_IGNORE)
956 return;
957
958 /* If already trapped and ignored, no change necessary. */
ccc6cda3 959 if (sigmodes[sig] & SIG_IGNORED)
726f6388
JA
960 return;
961
962 /* Only change the signal handler for SIG if it allows it. */
ccc6cda3 963 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
726f6388
JA
964 set_signal_handler (sig, SIG_IGN);
965
966 /* Change the trap command in either case. */
967 change_signal (sig, (char *)IGNORE_SIG);
968}
969
970/* Handle the calling of "trap 0". The only sticky situation is when
971 the command to be executed includes an "exit". This is why we have
972 to provide our own place for top_level to jump to. */
973int
974run_exit_trap ()
975{
ccc6cda3 976 char *trap_command;
b80f6443 977 int code, function_code, retval;
495aee44
CR
978#if defined (ARRAY_VARS)
979 ARRAY *ps;
980#endif
726f6388 981
b80f6443 982 trap_saved_exit_value = last_command_exit_value;
495aee44
CR
983#if defined (ARRAY_VARS)
984 ps = save_pipestatus_array ();
985#endif
b80f6443 986 function_code = 0;
726f6388 987
ccc6cda3
JA
988 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
989 currently running in the trap handler (call to exit in the list of
990 commands given to trap 0). */
991 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
992 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
726f6388 993 {
ccc6cda3
JA
994 trap_command = savestring (trap_list[EXIT_TRAP]);
995 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
996 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
726f6388 997
b80f6443
JA
998 retval = trap_saved_exit_value;
999 running_trap = 1;
1000
ac50fbac 1001 code = setjmp_nosigs (top_level);
726f6388 1002
b80f6443
JA
1003 /* If we're in a function, make sure return longjmps come here, too. */
1004 if (return_catch_flag)
ac50fbac 1005 function_code = setjmp_nosigs (return_catch);
b80f6443
JA
1006
1007 if (code == 0 && function_code == 0)
cce855bc
JA
1008 {
1009 reset_parser ();
ec8113b9 1010 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE|SEVAL_NOOPTIMIZE);
cce855bc 1011 }
b80f6443
JA
1012 else if (code == ERREXIT)
1013 retval = last_command_exit_value;
74091dd4 1014 else if (code == EXITPROG || code == EXITBLTIN)
b80f6443
JA
1015 retval = last_command_exit_value;
1016 else if (function_code != 0)
1017 retval = return_catch_value;
726f6388 1018 else
b80f6443
JA
1019 retval = trap_saved_exit_value;
1020
1021 running_trap = 0;
a0c0a00f
CR
1022#if defined (ARRAY_VARS)
1023 array_dispose (ps);
1024#endif
1025
b80f6443 1026 return retval;
726f6388
JA
1027 }
1028
495aee44
CR
1029#if defined (ARRAY_VARS)
1030 restore_pipestatus_array (ps);
1031#endif
b80f6443 1032 return (trap_saved_exit_value);
726f6388
JA
1033}
1034
ccc6cda3
JA
1035void
1036run_trap_cleanup (sig)
1037 int sig;
1038{
8868edaf 1039 /* XXX - should we clean up trap_list[sig] == IMPOSSIBLE_TRAP_HANDLER? */
ccc6cda3
JA
1040 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
1041}
1042
ac50fbac
CR
1043#define RECURSIVE_SIG(s) (SPECIAL_TRAP(s) == 0)
1044
ccc6cda3 1045/* Run a trap command for SIG. SIG is one of the signals the shell treats
b80f6443
JA
1046 specially. Returns the exit status of the executed trap command list. */
1047static int
ccc6cda3 1048_run_trap_internal (sig, tag)
726f6388 1049 int sig;
ccc6cda3 1050 char *tag;
726f6388 1051{
ccc6cda3 1052 char *trap_command, *old_trap;
d233b485 1053 int trap_exit_value;
8868edaf
CR
1054 volatile int save_return_catch_flag, function_code;
1055 int old_modes, old_running, old_int;
ac50fbac 1056 int flags;
b80f6443 1057 procenv_t save_return_catch;
0001803f 1058 WORD_LIST *save_subst_varlist;
a0c0a00f 1059 HASH_TABLE *save_tempenv;
ac50fbac 1060 sh_parser_state_t pstate;
495aee44
CR
1061#if defined (ARRAY_VARS)
1062 ARRAY *ps;
1063#endif
ccc6cda3 1064
8868edaf
CR
1065 old_modes = old_running = -1;
1066
b80f6443 1067 trap_exit_value = function_code = 0;
a0c0a00f 1068 trap_saved_exit_value = last_command_exit_value;
ccc6cda3
JA
1069 /* Run the trap only if SIG is trapped and not ignored, and we are not
1070 currently executing in the trap handler. */
1071 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
1072 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
8868edaf 1073#if 1
ac50fbac
CR
1074 /* Uncomment this to allow some special signals to recursively execute
1075 trap handlers. */
1076 (RECURSIVE_SIG (sig) || (sigmodes[sig] & SIG_INPROGRESS) == 0))
1077#else
ccc6cda3 1078 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
ac50fbac 1079#endif
ccc6cda3
JA
1080 {
1081 old_trap = trap_list[sig];
8868edaf
CR
1082 old_modes = sigmodes[sig];
1083 old_running = running_trap;
1084
ccc6cda3
JA
1085 sigmodes[sig] |= SIG_INPROGRESS;
1086 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
1087 trap_command = savestring (old_trap);
1088
1089 running_trap = sig + 1;
ac50fbac 1090
a0c0a00f
CR
1091 old_int = interrupt_state; /* temporarily suppress pending interrupts */
1092 CLRINTERRUPT;
1093
495aee44
CR
1094#if defined (ARRAY_VARS)
1095 ps = save_pipestatus_array ();
1096#endif
bb70624e 1097
ac50fbac 1098 save_parser_state (&pstate);
0001803f
CR
1099 save_subst_varlist = subst_assign_varlist;
1100 subst_assign_varlist = 0;
a0c0a00f
CR
1101 save_tempenv = temporary_env;
1102 temporary_env = 0; /* traps should not run with temporary env */
b80f6443 1103
ac50fbac 1104#if defined (JOB_CONTROL)
7f89f4cd
CR
1105 if (sig != DEBUG_TRAP) /* run_debug_trap does this */
1106 save_pipeline (1); /* XXX only provides one save level */
ac50fbac
CR
1107#endif
1108
b80f6443
JA
1109 /* If we're in a function, make sure return longjmps come here, too. */
1110 save_return_catch_flag = return_catch_flag;
1111 if (return_catch_flag)
1112 {
1113 COPY_PROCENV (return_catch, save_return_catch);
ac50fbac 1114 function_code = setjmp_nosigs (return_catch);
b80f6443
JA
1115 }
1116
ec8113b9 1117 flags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOOPTIMIZE;
89a92869 1118 if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
17345e5a 1119 flags |= SEVAL_RESETLINE;
d233b485 1120 evalnest++;
b80f6443 1121 if (function_code == 0)
a0c0a00f
CR
1122 {
1123 parse_and_execute (trap_command, tag, flags);
1124 trap_exit_value = last_command_exit_value;
1125 }
1126 else
1127 trap_exit_value = return_catch_value;
d233b485 1128 evalnest--;
ac50fbac
CR
1129
1130#if defined (JOB_CONTROL)
7f89f4cd
CR
1131 if (sig != DEBUG_TRAP) /* run_debug_trap does this */
1132 restore_pipeline (1);
ac50fbac 1133#endif
bb70624e 1134
0001803f 1135 subst_assign_varlist = save_subst_varlist;
ac50fbac 1136 restore_parser_state (&pstate);
0001803f 1137
495aee44
CR
1138#if defined (ARRAY_VARS)
1139 restore_pipestatus_array (ps);
1140#endif
a0c0a00f
CR
1141
1142 temporary_env = save_tempenv;
ccc6cda3 1143
8868edaf
CR
1144 if ((old_modes & SIG_INPROGRESS) == 0)
1145 sigmodes[sig] &= ~SIG_INPROGRESS;
1146
1147 running_trap = old_running;
a0c0a00f 1148 interrupt_state = old_int;
ccc6cda3
JA
1149
1150 if (sigmodes[sig] & SIG_CHANGED)
1151 {
b80f6443
JA
1152#if 0
1153 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
1154 the places where they can be changed using unwind-protects. For
1155 example, look at execute_cmd.c:execute_function(). */
1156 if (SPECIAL_TRAP (sig) == 0)
1157#endif
1158 free (old_trap);
ccc6cda3 1159 sigmodes[sig] &= ~SIG_CHANGED;
d233b485
CR
1160
1161 CHECK_TERMSIG; /* some pathological conditions lead here */
ccc6cda3 1162 }
b80f6443
JA
1163
1164 if (save_return_catch_flag)
1165 {
1166 return_catch_flag = save_return_catch_flag;
1167 return_catch_value = trap_exit_value;
1168 COPY_PROCENV (save_return_catch, return_catch);
1169 if (function_code)
a0c0a00f
CR
1170 {
1171#if 0
1172 from_return_trap = sig == RETURN_TRAP;
1173#endif
1174 sh_longjmp (return_catch, 1);
1175 }
b80f6443 1176 }
ccc6cda3 1177 }
b80f6443
JA
1178
1179 return trap_exit_value;
ccc6cda3
JA
1180}
1181
b80f6443 1182int
ccc6cda3
JA
1183run_debug_trap ()
1184{
d233b485 1185 int trap_exit_value, old_verbose;
89a92869 1186 pid_t save_pgrp;
d233b485 1187#if defined (PGRP_PIPE)
89a92869 1188 int save_pipe[2];
d233b485 1189#endif
b80f6443
JA
1190
1191 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
1192 trap_exit_value = 0;
1193 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
1194 {
89a92869
CR
1195#if defined (JOB_CONTROL)
1196 save_pgrp = pipeline_pgrp;
1197 pipeline_pgrp = 0;
1198 save_pipeline (1);
1199# if defined (PGRP_PIPE)
1200 save_pgrp_pipe (save_pipe, 1);
1201# endif
1202 stop_making_children ();
1203#endif
1204
d233b485 1205 old_verbose = echo_input_at_read;
8868edaf 1206 echo_input_at_read = suppress_debug_trap_verbose ? 0 : echo_input_at_read;
d233b485 1207
b80f6443 1208 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
89a92869 1209
d233b485
CR
1210 echo_input_at_read = old_verbose;
1211
89a92869
CR
1212#if defined (JOB_CONTROL)
1213 pipeline_pgrp = save_pgrp;
1214 restore_pipeline (1);
1215# if defined (PGRP_PIPE)
1216 close_pgrp_pipe ();
1217 restore_pgrp_pipe (save_pipe);
1218# endif
d233b485 1219 if (pipeline_pgrp > 0 && ((subshell_environment & (SUBSHELL_ASYNC|SUBSHELL_PIPE)) == 0))
89a92869 1220 give_terminal_to (pipeline_pgrp, 1);
d233b485 1221
89a92869
CR
1222 notify_and_cleanup ();
1223#endif
b80f6443
JA
1224
1225#if defined (DEBUGGER)
1226 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
1227 a function or sourced script, we force a `return'. */
1228 if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
1229 {
1230 return_catch_value = trap_exit_value;
a0c0a00f 1231 sh_longjmp (return_catch, 1);
b80f6443
JA
1232 }
1233#endif
1234 }
1235 return trap_exit_value;
ccc6cda3
JA
1236}
1237
f73dda09
JA
1238void
1239run_error_trap ()
1240{
b80f6443 1241 if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
f73dda09
JA
1242 _run_trap_internal (ERROR_TRAP, "error trap");
1243}
1244
b80f6443
JA
1245void
1246run_return_trap ()
1247{
1248 int old_exit_value;
1249
95732b49
JA
1250#if 0
1251 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
1252 return;
1253#endif
1254
b80f6443
JA
1255 if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
1256 {
1257 old_exit_value = last_command_exit_value;
1258 _run_trap_internal (RETURN_TRAP, "return trap");
1259 last_command_exit_value = old_exit_value;
1260 }
1261}
1262
ccc6cda3
JA
1263/* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1264 declared here to localize the trap functions. */
1265void
a0c0a00f
CR
1266run_interrupt_trap (will_throw)
1267 int will_throw; /* from throw_to_top_level? */
ccc6cda3 1268{
a0c0a00f
CR
1269 if (will_throw && running_trap > 0)
1270 run_trap_cleanup (running_trap - 1);
8868edaf
CR
1271 pending_traps[SIGINT] = 0; /* run_pending_traps does this */
1272 catch_flag = 0;
ccc6cda3 1273 _run_trap_internal (SIGINT, "interrupt trap");
726f6388
JA
1274}
1275
1276/* Free all the allocated strings in the list of traps and reset the trap
0001803f
CR
1277 values to the default. Intended to be called from subshells that want
1278 to complete work done by reset_signal_handlers upon execution of a
ac50fbac
CR
1279 subsequent `trap' command that changes a signal's disposition. We need
1280 to make sure that we duplicate the behavior of
1281 reset_or_restore_signal_handlers and not change the disposition of signals
1282 that are set to be ignored. */
726f6388
JA
1283void
1284free_trap_strings ()
1285{
1286 register int i;
1287
a0c0a00f 1288 for (i = 0; i < NSIG; i++)
ac50fbac
CR
1289 {
1290 if (trap_list[i] != (char *)IGNORE_SIG)
1291 free_trap_string (i);
1292 }
a0c0a00f
CR
1293 for (i = NSIG; i < BASH_NSIG; i++)
1294 {
1295 /* Don't free the trap string if the subshell inherited the trap */
1296 if ((sigmodes[i] & SIG_TRAPPED) == 0)
1297 {
1298 free_trap_string (i);
1299 trap_list[i] = (char *)NULL;
1300 }
1301 }
726f6388 1302}
0001803f
CR
1303
1304/* Free a trap command string associated with SIG without changing signal
1305 disposition. Intended to be called from free_trap_strings() */
1306static void
1307free_trap_string (sig)
1308 int sig;
1309{
1310 change_signal (sig, (char *)DEFAULT_SIG);
d233b485 1311 sigmodes[sig] &= ~SIG_TRAPPED; /* XXX - SIG_INPROGRESS? */
0001803f 1312}
726f6388 1313
495aee44
CR
1314/* Reset the handler for SIG to the original value but leave the trap string
1315 in place. */
726f6388
JA
1316static void
1317reset_signal (sig)
1318 int sig;
1319{
1320 set_signal_handler (sig, original_signals[sig]);
d233b485 1321 sigmodes[sig] &= ~SIG_TRAPPED; /* XXX - SIG_INPROGRESS? */
726f6388
JA
1322}
1323
ccc6cda3
JA
1324/* Set the handler signal SIG to the original and free any trap
1325 command associated with it. */
1326static void
1327restore_signal (sig)
1328 int sig;
726f6388 1329{
ccc6cda3
JA
1330 set_signal_handler (sig, original_signals[sig]);
1331 change_signal (sig, (char *)DEFAULT_SIG);
1332 sigmodes[sig] &= ~SIG_TRAPPED;
726f6388
JA
1333}
1334
ccc6cda3
JA
1335static void
1336reset_or_restore_signal_handlers (reset)
f73dda09 1337 sh_resetsig_func_t *reset;
726f6388
JA
1338{
1339 register int i;
1340
ccc6cda3
JA
1341 /* Take care of the exit trap first */
1342 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
726f6388 1343 {
d233b485 1344 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED; /* XXX - SIG_INPROGRESS? */
95732b49
JA
1345 if (reset != reset_signal)
1346 {
1347 free_trap_command (EXIT_TRAP);
1348 trap_list[EXIT_TRAP] = (char *)NULL;
1349 }
726f6388 1350 }
b80f6443 1351
726f6388
JA
1352 for (i = 1; i < NSIG; i++)
1353 {
ccc6cda3 1354 if (sigmodes[i] & SIG_TRAPPED)
726f6388
JA
1355 {
1356 if (trap_list[i] == (char *)IGNORE_SIG)
1357 set_signal_handler (i, SIG_IGN);
1358 else
ccc6cda3 1359 (*reset) (i);
726f6388 1360 }
ccc6cda3
JA
1361 else if (sigmodes[i] & SIG_SPECIAL)
1362 (*reset) (i);
a0c0a00f 1363 pending_traps[i] = 0; /* XXX */
726f6388 1364 }
f73dda09
JA
1365
1366 /* Command substitution and other child processes don't inherit the
b80f6443
JA
1367 debug, error, or return traps. If we're in the debugger, and the
1368 `functrace' or `errtrace' options have been set, then let command
1369 substitutions inherit them. Let command substitution inherit the
1370 RETURN trap if we're in the debugger and tracing functions. */
0628567a
JA
1371 if (function_trace_mode == 0)
1372 {
1373 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
1374 sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
1375 }
1376 if (error_trace_mode == 0)
b80f6443 1377 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
726f6388
JA
1378}
1379
f73dda09 1380/* Reset trapped signals to their original values, but don't free the
495aee44
CR
1381 trap strings. Called by the command substitution code and other places
1382 that create a "subshell environment". */
726f6388 1383void
ccc6cda3 1384reset_signal_handlers ()
726f6388 1385{
ccc6cda3
JA
1386 reset_or_restore_signal_handlers (reset_signal);
1387}
726f6388 1388
ccc6cda3
JA
1389/* Reset all trapped signals to their original values. Signals set to be
1390 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1391 are. Called by child processes after they are forked. */
1392void
1393restore_original_signals ()
1394{
1395 reset_or_restore_signal_handlers (restore_signal);
726f6388
JA
1396}
1397
74091dd4
CR
1398/* Change the flags associated with signal SIG without changing the trap
1399 string. The string is TRAP_LIST[SIG] if we need it. */
1400static void
1401reinit_trap (sig)
1402 int sig;
1403{
1404 sigmodes[sig] |= SIG_TRAPPED;
1405 if (trap_list[sig] == (char *)IGNORE_SIG)
1406 sigmodes[sig] |= SIG_IGNORED;
1407 else
1408 sigmodes[sig] &= ~SIG_IGNORED;
1409 if (sigmodes[sig] & SIG_INPROGRESS)
1410 sigmodes[sig] |= SIG_CHANGED;
1411}
1412
1413/* Undo the effects of reset_signal_handlers(), which unsets the traps but
1414 leaves the trap strings in place. This understands how reset_signal_handlers
1415 works. */
1416void
1417restore_traps ()
1418{
1419 char *trapstr;
1420 int i;
1421
1422 /* Take care of the exit trap first. If TRAP_LIST[0] is non-null, the trap
1423 has been set. */
1424 trapstr = trap_list[EXIT_TRAP];
1425 if (trapstr)
1426 reinit_trap (EXIT_TRAP);
1427
1428 /* Then DEBUG, RETURN, and ERROR. TRAP_LIST[N] == 0 if these signals are
1429 not trapped. This knows what reset_signal_handlers does for these traps */
1430 trapstr = trap_list[DEBUG_TRAP];
1431 if (trapstr && function_trace_mode == 0)
1432 reinit_trap (DEBUG_TRAP);
1433 trapstr = trap_list[RETURN_TRAP];
1434 if (trapstr && function_trace_mode == 0)
1435 reinit_trap (RETURN_TRAP);
1436 trapstr = trap_list[ERROR_TRAP];
1437 if (trapstr && error_trace_mode == 0)
1438 reinit_trap (ERROR_TRAP);
1439
1440 /* And finally all the `real' signals. reset_signal_handlers just changes the
1441 signal handler for these signals, leaving the trap value in place. We
1442 intuit what to do based on that value. We assume that signals marked as
1443 SIG_SPECIAL are reinitialized by initialize_signals (), so we don't
1444 change the signal handler unless the signal is supposed to be ignored. */
1445 for (i = 1; i < NSIG; i++)
1446 {
1447 trapstr = trap_list[i];
1448 if (sigmodes[i] & SIG_SPECIAL)
1449 {
1450 if (trapstr && trapstr != (char *)DEFAULT_SIG)
1451 reinit_trap (i);
1452 if (trapstr == (char *)IGNORE_SIG && (sigmodes[i] & SIG_NO_TRAP) == 0)
1453 set_signal_handler (i, SIG_IGN);
1454 }
1455 else if (trapstr == (char *)IGNORE_SIG)
1456 {
1457 reinit_trap (i);
1458 if ((sigmodes[i] & SIG_NO_TRAP) == 0)
1459 set_signal_handler (i, SIG_IGN);
1460 }
1461 else if (trapstr != (char *)DEFAULT_SIG)
1462 /* set_signal duplicates the string argument before freeing it. */
1463 set_signal (i, trapstr);
1464
1465 pending_traps[i] = 0; /* XXX */
1466 }
1467}
1468
726f6388 1469/* If a trap handler exists for signal SIG, then call it; otherwise just
ac50fbac 1470 return failure. Returns 1 if it called the trap handler. */
726f6388
JA
1471int
1472maybe_call_trap_handler (sig)
1473 int sig;
1474{
1475 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
ccc6cda3 1476 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
726f6388
JA
1477 {
1478 switch (sig)
1479 {
1480 case SIGINT:
a0c0a00f 1481 run_interrupt_trap (0);
726f6388 1482 break;
ccc6cda3 1483 case EXIT_TRAP:
726f6388
JA
1484 run_exit_trap ();
1485 break;
ccc6cda3
JA
1486 case DEBUG_TRAP:
1487 run_debug_trap ();
1488 break;
f73dda09
JA
1489 case ERROR_TRAP:
1490 run_error_trap ();
1491 break;
726f6388
JA
1492 default:
1493 trap_handler (sig);
1494 break;
1495 }
1496 return (1);
1497 }
1498 else
1499 return (0);
1500}
1501
1502int
1503signal_is_trapped (sig)
1504 int sig;
1505{
1506 return (sigmodes[sig] & SIG_TRAPPED);
1507}
1508
ac50fbac
CR
1509int
1510signal_is_pending (sig)
1511 int sig;
1512{
1513 return (pending_traps[sig]);
1514}
1515
726f6388
JA
1516int
1517signal_is_special (sig)
1518 int sig;
1519{
1520 return (sigmodes[sig] & SIG_SPECIAL);
1521}
1522
1523int
1524signal_is_ignored (sig)
1525 int sig;
1526{
1527 return (sigmodes[sig] & SIG_IGNORED);
1528}
1529
495aee44
CR
1530int
1531signal_is_hard_ignored (sig)
1532 int sig;
1533{
1534 return (sigmodes[sig] & SIG_HARD_IGNORE);
1535}
1536
726f6388 1537void
ac50fbac 1538set_signal_hard_ignored (sig)
726f6388
JA
1539 int sig;
1540{
1541 sigmodes[sig] |= SIG_HARD_IGNORE;
ccc6cda3 1542 original_signals[sig] = SIG_IGN;
726f6388 1543}
95732b49 1544
ac50fbac
CR
1545void
1546set_signal_ignored (sig)
1547 int sig;
1548{
1549 original_signals[sig] = SIG_IGN;
1550}
1551
95732b49
JA
1552int
1553signal_in_progress (sig)
1554 int sig;
1555{
1556 return (sigmodes[sig] & SIG_INPROGRESS);
1557}
8868edaf 1558
74091dd4 1559#if 0 /* unused */
8868edaf
CR
1560int
1561block_trapped_signals (maskp, omaskp)
1562 sigset_t *maskp;
1563 sigset_t *omaskp;
1564{
1565 int i;
1566
1567 sigemptyset (maskp);
1568 for (i = 1; i < NSIG; i++)
1569 if (sigmodes[i] & SIG_TRAPPED)
1570 sigaddset (maskp, i);
1571 return (sigprocmask (SIG_BLOCK, maskp, omaskp));
1572}
1573
1574int
1575unblock_trapped_signals (maskp)
1576 sigset_t *maskp;
1577{
1578 return (sigprocmask (SIG_SETMASK, maskp, 0));
1579}
1580#endif