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