]> git.ipfire.org Git - thirdparty/bash.git/blame - trap.c
bash-4.3-beta overlay
[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
103 executed when that signal is recieved. The slot can also contain
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
CR
244
245 /* Check name without the SIG prefix first case sensitivly or
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;
bb70624e 280 int old_exit_value, *token_state;
0527c903 281 WORD_LIST *save_subst_varlist;
64419627
CR
282#if defined (ARRAY_VARS)
283 ARRAY *ps;
284#endif
726f6388
JA
285
286 if (catch_flag == 0) /* simple optimization */
287 return;
288
1442f67c
CR
289 if (running_trap > 0)
290 return; /* no recursive trap invocations */
291
5a318736 292 catch_flag = trapped_signal_received = 0;
726f6388
JA
293
294 /* Preserve $? when running trap. */
295 old_exit_value = last_command_exit_value;
64419627
CR
296#if defined (ARRAY_VARS)
297 ps = save_pipestatus_array ();
298#endif
726f6388
JA
299
300 for (sig = 1; sig < NSIG; sig++)
301 {
302 /* XXX this could be made into a counter by using
28ef6c31 303 while (pending_traps[sig]--) instead of the if statement. */
726f6388
JA
304 if (pending_traps[sig])
305 {
726f6388
JA
306 sigset_t set, oset;
307
c31d56a7 308 BLOCK_SIGNAL (sig, set, oset);
726f6388 309
1442f67c
CR
310 running_trap = sig + 1;
311
726f6388
JA
312 if (sig == SIGINT)
313 {
314 run_interrupt_trap ();
ccc6cda3 315 CLRINTERRUPT;
726f6388 316 }
ed35cb4a
CR
317#if defined (JOB_CONTROL) && defined (SIGCHLD)
318 else if (sig == SIGCHLD &&
319 trap_list[SIGCHLD] != (char *)IMPOSSIBLE_TRAP_HANDLER &&
320 (sigmodes[SIGCHLD] & SIG_INPROGRESS) == 0)
321 {
0500de0b 322 sigmodes[SIGCHLD] |= SIG_INPROGRESS;
ed35cb4a 323 run_sigchld_trap (pending_traps[sig]); /* use as counter */
0500de0b
CR
324 sigmodes[SIGCHLD] &= ~SIG_INPROGRESS;
325 }
326 else if (sig == SIGCHLD &&
327 trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER &&
328 (sigmodes[SIGCHLD] & SIG_INPROGRESS) != 0)
329 {
330 /* This can happen when run_pending_traps is called while
331 running a SIGCHLD trap handler. */
1442f67c 332 running_trap = 0;
0500de0b
CR
333 UNBLOCK_SIGNAL (oset);
334 continue; /* XXX */
ed35cb4a
CR
335 }
336#endif
bb70624e
JA
337 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
338 trap_list[sig] == (char *)IGNORE_SIG ||
339 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
340 {
341 /* This is possible due to a race condition. Say a bash
342 process has SIGTERM trapped. A subshell is spawned
343 using { list; } & and the parent does something and kills
344 the subshell with SIGTERM. It's possible for the subshell
345 to set pending_traps[SIGTERM] to 1 before the code in
346 execute_cmd.c eventually calls restore_original_signals
347 to reset the SIGTERM signal handler in the subshell. The
348 next time run_pending_traps is called, pending_traps[SIGTERM]
349 will be 1, but the trap handler in trap_list[SIGTERM] will
350 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
351 Unless we catch this, the subshell will dump core when
352 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
353 usually 0x0. */
5e13499c 354 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
f73dda09 355 sig, trap_list[sig]);
bb70624e
JA
356 if (trap_list[sig] == (char *)DEFAULT_SIG)
357 {
5e13499c 358 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
bb70624e
JA
359 kill (getpid (), sig);
360 }
361 }
726f6388 362 else
bb70624e 363 {
1442f67c 364 /* XXX - should we use save_parser_state/restore_parser_state? */
bb70624e 365 token_state = save_token_state ();
0527c903
CR
366 save_subst_varlist = subst_assign_varlist;
367 subst_assign_varlist = 0;
368
1442f67c
CR
369#if defined (JOB_CONTROL)
370 save_pipeline (1); /* XXX only provides one save level */
371#endif
200aed9a 372 evalstring (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
1442f67c
CR
373#if defined (JOB_CONTROL)
374 restore_pipeline (1);
375#endif
376
bb70624e
JA
377 restore_token_state (token_state);
378 free (token_state);
0527c903
CR
379
380 subst_assign_varlist = save_subst_varlist;
bb70624e 381 }
726f6388
JA
382
383 pending_traps[sig] = 0;
1442f67c 384 running_trap = 0;
726f6388 385
c31d56a7 386 UNBLOCK_SIGNAL (oset);
726f6388
JA
387 }
388 }
389
64419627
CR
390#if defined (ARRAY_VARS)
391 restore_pipestatus_array (ps);
392#endif
726f6388
JA
393 last_command_exit_value = old_exit_value;
394}
395
396sighandler
397trap_handler (sig)
398 int sig;
399{
bb70624e
JA
400 int oerrno;
401
7a131ef2
CR
402 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
403 {
404#if defined (DEBUG)
405 internal_warning ("trap_handler: signal %d: signal not trapped", sig);
406#endif
407 SIGRETURN (0);
408 }
409
726f6388
JA
410 if ((sig >= NSIG) ||
411 (trap_list[sig] == (char *)DEFAULT_SIG) ||
412 (trap_list[sig] == (char *)IGNORE_SIG))
5e13499c 413 programming_error (_("trap_handler: bad signal %d"), sig);
726f6388
JA
414 else
415 {
28ef6c31 416 oerrno = errno;
ccc6cda3 417#if defined (MUST_REINSTALL_SIGHANDLERS)
ed35cb4a
CR
418# if defined (JOB_CONTROL) && defined (SIGCHLD)
419 if (sig != SIGCHLD)
420# endif /* JOB_CONTROL && SIGCHLD */
726f6388 421 set_signal_handler (sig, trap_handler);
ccc6cda3 422#endif /* MUST_REINSTALL_SIGHANDLERS */
726f6388
JA
423
424 catch_flag = 1;
425 pending_traps[sig]++;
426
5a318736
CR
427 trapped_signal_received = sig;
428
dfc91666 429 if (this_shell_builtin && (this_shell_builtin == wait_builtin))
7117c2d2
JA
430 {
431 wait_signal_received = sig;
dfc91666 432 if (interrupt_immediately)
dfc91666 433 longjmp (wait_intr_buf, 1);
7117c2d2
JA
434 }
435
55a5a4ac 436#if defined (READLINE)
1b1fe467
CR
437 /* Set the event hook so readline will call it after the signal handlers
438 finish executing, so if this interrupted character input we can get
439 quick response. */
55a5a4ac
CR
440 if (RL_ISSTATE (RL_STATE_SIGHANDLER) && interrupt_immediately == 0)
441 bashline_set_event_hook ();
442#endif
443
726f6388
JA
444 if (interrupt_immediately)
445 run_pending_traps ();
bb70624e
JA
446
447 errno = oerrno;
726f6388 448 }
ccc6cda3
JA
449
450 SIGRETURN (0);
726f6388
JA
451}
452
5a318736
CR
453int
454first_pending_trap ()
455{
456 register int i;
457
458 for (i = 1; i < NSIG; i++)
459 if (pending_traps[i])
460 return i;
461 return -1;
462}
463
55a5a4ac
CR
464int
465any_signals_trapped ()
466{
467 register int i;
468
469 for (i = 1; i < NSIG; i++)
470 if (sigmodes[i] & SIG_TRAPPED)
471 return i;
472 return -1;
473}
474
475void
10e78433 476check_signals ()
55a5a4ac 477{
10e78433 478 CHECK_ALRM; /* set by the read builtin */
55a5a4ac 479 QUIT;
55a5a4ac
CR
480}
481
10e78433 482/* Convenience functions the rest of the shell can use */
1a81420a 483void
10e78433 484check_signals_and_traps ()
1a81420a 485{
10e78433
CR
486 check_signals ();
487
488 run_pending_traps ();
1a81420a
CR
489}
490
726f6388 491#if defined (JOB_CONTROL) && defined (SIGCHLD)
cce855bc
JA
492
493#ifdef INCLUDE_UNUSED
726f6388
JA
494/* Make COMMAND_STRING be executed when SIGCHLD is caught. */
495void
496set_sigchld_trap (command_string)
497 char *command_string;
498{
726f6388
JA
499 set_signal (SIGCHLD, command_string);
500}
cce855bc 501#endif
726f6388 502
f75912ae 503/* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
ed35cb4a
CR
504 is not already trapped. IMPOSSIBLE_TRAP_HANDLER is used as a sentinel
505 to make sure that a SIGCHLD trap handler run via run_sigchld_trap can
506 reset the disposition to the default and not have the original signal
507 accidentally restored, undoing the user's command. */
726f6388
JA
508void
509maybe_set_sigchld_trap (command_string)
510 char *command_string;
511{
ed35cb4a 512 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char *)IMPOSSIBLE_TRAP_HANDLER)
726f6388
JA
513 set_signal (SIGCHLD, command_string);
514}
ed35cb4a
CR
515
516/* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER. Used
517 as a sentinel in run_sigchld_trap and maybe_set_sigchld_trap to see whether
518 or not a SIGCHLD trap handler reset SIGCHLD disposition to the default. */
519void
520set_impossible_sigchld_trap ()
521{
522 restore_default_signal (SIGCHLD);
523 change_signal (SIGCHLD, (char *)IMPOSSIBLE_TRAP_HANDLER);
524 sigmodes[SIGCHLD] &= ~SIG_TRAPPED; /* maybe_set_sigchld_trap checks this */
525}
278286c9
CR
526
527/* Act as if we received SIGCHLD NCHILD times and increment
528 pending_traps[SIGCHLD] by that amount. This allows us to still run the
529 SIGCHLD trap once for each exited child. */
530void
531queue_sigchld_trap (nchild)
532 int nchild;
533{
534 if (nchild > 0)
0500de0b
CR
535 {
536 catch_flag = 1;
537 pending_traps[SIGCHLD] += nchild;
538 trapped_signal_received = SIGCHLD;
539 }
278286c9 540}
726f6388
JA
541#endif /* JOB_CONTROL && SIGCHLD */
542
ccc6cda3
JA
543void
544set_debug_trap (command)
726f6388
JA
545 char *command;
546{
ccc6cda3
JA
547 set_signal (DEBUG_TRAP, command);
548}
726f6388 549
f73dda09
JA
550void
551set_error_trap (command)
552 char *command;
553{
554 set_signal (ERROR_TRAP, command);
555}
556
d3a24ed2
CR
557void
558set_return_trap (command)
559 char *command;
560{
561 set_signal (RETURN_TRAP, command);
562}
563
cce855bc 564#ifdef INCLUDE_UNUSED
ccc6cda3
JA
565void
566set_sigint_trap (command)
567 char *command;
568{
726f6388
JA
569 set_signal (SIGINT, command);
570}
cce855bc 571#endif
726f6388
JA
572
573/* Reset the SIGINT handler so that subshells that are doing `shellsy'
574 things, like waiting for command substitution or executing commands
575 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
576SigHandler *
577set_sigint_handler ()
578{
579 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
580 return ((SigHandler *)SIG_IGN);
581
582 else if (sigmodes[SIGINT] & SIG_IGNORED)
ccc6cda3
JA
583 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
584
726f6388
JA
585 else if (sigmodes[SIGINT] & SIG_TRAPPED)
586 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
587
588 /* The signal is not trapped, so set the handler to the shell's special
589 interrupt handler. */
590 else if (interactive) /* XXX - was interactive_shell */
591 return (set_signal_handler (SIGINT, sigint_sighandler));
592 else
ac18b312 593 return (set_signal_handler (SIGINT, termsig_sighandler));
726f6388
JA
594}
595
e8ce775d
JA
596/* Return the correct handler for signal SIG according to the values in
597 sigmodes[SIG]. */
598SigHandler *
599trap_to_sighandler (sig)
600 int sig;
601{
602 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
603 return (SIG_IGN);
604 else if (sigmodes[sig] & SIG_TRAPPED)
605 return (trap_handler);
606 else
607 return (SIG_DFL);
608}
609
726f6388
JA
610/* Set SIG to call STRING as a command. */
611void
612set_signal (sig, string)
613 int sig;
614 char *string;
615{
f6da9f85
CR
616 sigset_t set, oset;
617
f73dda09 618 if (SPECIAL_TRAP (sig))
ccc6cda3
JA
619 {
620 change_signal (sig, savestring (string));
d166f048
JA
621 if (sig == EXIT_TRAP && interactive == 0)
622 initialize_terminating_signals ();
ccc6cda3
JA
623 return;
624 }
625
726f6388
JA
626 /* A signal ignored on entry to the shell cannot be trapped or reset, but
627 no error is reported when attempting to do so. -- Posix.2 */
628 if (sigmodes[sig] & SIG_HARD_IGNORE)
629 return;
630
631 /* Make sure we have original_signals[sig] if the signal has not yet
632 been trapped. */
633 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
634 {
635 /* If we aren't sure of the original value, check it. */
636 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
11a6f9a9 637 GETORIGSIG (sig);
726f6388 638 if (original_signals[sig] == SIG_IGN)
11a6f9a9 639 return;
726f6388
JA
640 }
641
642 /* Only change the system signal handler if SIG_NO_TRAP is not set.
643 The trap command string is changed in either case. The shell signal
644 handlers for SIGINT and SIGCHLD run the user specified traps in an
645 environment in which it is safe to do so. */
646 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
647 {
f6da9f85 648 BLOCK_SIGNAL (sig, set, oset);
726f6388
JA
649 change_signal (sig, savestring (string));
650 set_signal_handler (sig, trap_handler);
f6da9f85 651 UNBLOCK_SIGNAL (oset);
726f6388
JA
652 }
653 else
654 change_signal (sig, savestring (string));
655}
656
657static void
658free_trap_command (sig)
659 int sig;
660{
661 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
662 (trap_list[sig] != (char *)IGNORE_SIG) &&
663 (trap_list[sig] != (char *)DEFAULT_SIG) &&
664 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
665 free (trap_list[sig]);
666}
ccc6cda3 667
726f6388
JA
668/* If SIG has a string assigned to it, get rid of it. Then give it
669 VALUE. */
670static void
671change_signal (sig, value)
672 int sig;
673 char *value;
674{
d166f048
JA
675 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
676 free_trap_command (sig);
726f6388
JA
677 trap_list[sig] = value;
678
679 sigmodes[sig] |= SIG_TRAPPED;
680 if (value == (char *)IGNORE_SIG)
681 sigmodes[sig] |= SIG_IGNORED;
682 else
683 sigmodes[sig] &= ~SIG_IGNORED;
684 if (sigmodes[sig] & SIG_INPROGRESS)
685 sigmodes[sig] |= SIG_CHANGED;
686}
687
73a146be 688void
726f6388
JA
689get_original_signal (sig)
690 int sig;
691{
692 /* If we aren't sure the of the original value, then get it. */
2c471a92 693 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
11a6f9a9 694 GETORIGSIG (sig);
726f6388
JA
695}
696
e502b4e0
CR
697void
698get_all_original_signals ()
699{
700 register int i;
701
702 for (i = 1; i < NSIG; i++)
703 GET_ORIGINAL_SIGNAL (i);
704}
705
9e51a74d
CR
706void
707set_original_signal (sig, handler)
708 int sig;
709 SigHandler *handler;
710{
711 if (sig > 0 && sig < NSIG && original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
712 SETORIGSIG (sig, handler);
713}
714
726f6388
JA
715/* Restore the default action for SIG; i.e., the action the shell
716 would have taken before you used the trap command. This is called
717 from trap_builtin (), which takes care to restore the handlers for
718 the signals the shell treats specially. */
719void
720restore_default_signal (sig)
721 int sig;
722{
f73dda09 723 if (SPECIAL_TRAP (sig))
726f6388 724 {
d3a24ed2
CR
725 if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
726 (sigmodes[sig] & SIG_INPROGRESS) == 0)
d166f048 727 free_trap_command (sig);
726f6388
JA
728 trap_list[sig] = (char *)NULL;
729 sigmodes[sig] &= ~SIG_TRAPPED;
d166f048
JA
730 if (sigmodes[sig] & SIG_INPROGRESS)
731 sigmodes[sig] |= SIG_CHANGED;
726f6388
JA
732 return;
733 }
734
735 GET_ORIGINAL_SIGNAL (sig);
736
737 /* A signal ignored on entry to the shell cannot be trapped or reset, but
738 no error is reported when attempting to do so. Thanks Posix.2. */
739 if (sigmodes[sig] & SIG_HARD_IGNORE)
740 return;
741
742 /* If we aren't trapping this signal, don't bother doing anything else. */
ccc6cda3 743 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
726f6388
JA
744 return;
745
746 /* Only change the signal handler for SIG if it allows it. */
ccc6cda3 747 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
726f6388
JA
748 set_signal_handler (sig, original_signals[sig]);
749
750 /* Change the trap command in either case. */
751 change_signal (sig, (char *)DEFAULT_SIG);
752
753 /* Mark the signal as no longer trapped. */
754 sigmodes[sig] &= ~SIG_TRAPPED;
755}
756
757/* Make this signal be ignored. */
758void
759ignore_signal (sig)
760 int sig;
761{
f73dda09 762 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
ccc6cda3
JA
763 {
764 change_signal (sig, (char *)IGNORE_SIG);
765 return;
766 }
767
726f6388
JA
768 GET_ORIGINAL_SIGNAL (sig);
769
770 /* A signal ignored on entry to the shell cannot be trapped or reset.
ccc6cda3 771 No error is reported when the user attempts to do so. */
726f6388
JA
772 if (sigmodes[sig] & SIG_HARD_IGNORE)
773 return;
774
775 /* If already trapped and ignored, no change necessary. */
ccc6cda3 776 if (sigmodes[sig] & SIG_IGNORED)
726f6388
JA
777 return;
778
779 /* Only change the signal handler for SIG if it allows it. */
ccc6cda3 780 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
726f6388
JA
781 set_signal_handler (sig, SIG_IGN);
782
783 /* Change the trap command in either case. */
784 change_signal (sig, (char *)IGNORE_SIG);
785}
786
787/* Handle the calling of "trap 0". The only sticky situation is when
788 the command to be executed includes an "exit". This is why we have
789 to provide our own place for top_level to jump to. */
790int
791run_exit_trap ()
792{
ccc6cda3 793 char *trap_command;
5e13499c 794 int code, function_code, retval;
64419627
CR
795#if defined (ARRAY_VARS)
796 ARRAY *ps;
797#endif
726f6388 798
5e13499c 799 trap_saved_exit_value = last_command_exit_value;
64419627
CR
800#if defined (ARRAY_VARS)
801 ps = save_pipestatus_array ();
802#endif
d3a24ed2 803 function_code = 0;
726f6388 804
ccc6cda3
JA
805 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
806 currently running in the trap handler (call to exit in the list of
807 commands given to trap 0). */
808 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
809 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
726f6388 810 {
ccc6cda3
JA
811 trap_command = savestring (trap_list[EXIT_TRAP]);
812 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
813 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
726f6388 814
5e13499c
CR
815 retval = trap_saved_exit_value;
816 running_trap = 1;
817
36eb585c 818 code = setjmp_nosigs (top_level);
726f6388 819
d3a24ed2
CR
820 /* If we're in a function, make sure return longjmps come here, too. */
821 if (return_catch_flag)
36eb585c 822 function_code = setjmp_nosigs (return_catch);
d3a24ed2
CR
823
824 if (code == 0 && function_code == 0)
cce855bc
JA
825 {
826 reset_parser ();
e141c35a 827 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
cce855bc 828 }
d3a24ed2 829 else if (code == ERREXIT)
5e13499c 830 retval = last_command_exit_value;
726f6388 831 else if (code == EXITPROG)
5e13499c 832 retval = last_command_exit_value;
d3a24ed2 833 else if (function_code != 0)
5e13499c 834 retval = return_catch_value;
726f6388 835 else
5e13499c
CR
836 retval = trap_saved_exit_value;
837
838 running_trap = 0;
839 return retval;
726f6388
JA
840 }
841
64419627
CR
842#if defined (ARRAY_VARS)
843 restore_pipestatus_array (ps);
844#endif
5e13499c 845 return (trap_saved_exit_value);
726f6388
JA
846}
847
ccc6cda3
JA
848void
849run_trap_cleanup (sig)
850 int sig;
851{
852 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
853}
854
855/* Run a trap command for SIG. SIG is one of the signals the shell treats
d3a24ed2
CR
856 specially. Returns the exit status of the executed trap command list. */
857static int
ccc6cda3 858_run_trap_internal (sig, tag)
726f6388 859 int sig;
ccc6cda3 860 char *tag;
726f6388 861{
ccc6cda3 862 char *trap_command, *old_trap;
5e13499c 863 int trap_exit_value, *token_state;
63817e33
CR
864 volatile int save_return_catch_flag, function_code;
865 int flags;
5e13499c 866 procenv_t save_return_catch;
0527c903 867 WORD_LIST *save_subst_varlist;
64419627
CR
868#if defined (ARRAY_VARS)
869 ARRAY *ps;
870#endif
ccc6cda3 871
5e13499c 872 trap_exit_value = function_code = 0;
ccc6cda3
JA
873 /* Run the trap only if SIG is trapped and not ignored, and we are not
874 currently executing in the trap handler. */
875 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
876 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
877 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
878 {
879 old_trap = trap_list[sig];
880 sigmodes[sig] |= SIG_INPROGRESS;
881 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
882 trap_command = savestring (old_trap);
883
884 running_trap = sig + 1;
5e13499c 885 trap_saved_exit_value = last_command_exit_value;
64419627
CR
886#if defined (ARRAY_VARS)
887 ps = save_pipestatus_array ();
888#endif
bb70624e
JA
889
890 token_state = save_token_state ();
0527c903
CR
891 save_subst_varlist = subst_assign_varlist;
892 subst_assign_varlist = 0;
5e13499c
CR
893
894 /* If we're in a function, make sure return longjmps come here, too. */
895 save_return_catch_flag = return_catch_flag;
896 if (return_catch_flag)
897 {
898 COPY_PROCENV (return_catch, save_return_catch);
36eb585c 899 function_code = setjmp_nosigs (return_catch);
5e13499c
CR
900 }
901
e141c35a 902 flags = SEVAL_NONINT|SEVAL_NOHIST;
c302751c 903 if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
e141c35a 904 flags |= SEVAL_RESETLINE;
5e13499c 905 if (function_code == 0)
e141c35a 906 parse_and_execute (trap_command, tag, flags);
5e13499c 907
bb70624e
JA
908 restore_token_state (token_state);
909 free (token_state);
910
0527c903
CR
911 subst_assign_varlist = save_subst_varlist;
912
d3a24ed2 913 trap_exit_value = last_command_exit_value;
5e13499c 914 last_command_exit_value = trap_saved_exit_value;
64419627
CR
915#if defined (ARRAY_VARS)
916 restore_pipestatus_array (ps);
917#endif
ccc6cda3
JA
918 running_trap = 0;
919
920 sigmodes[sig] &= ~SIG_INPROGRESS;
921
922 if (sigmodes[sig] & SIG_CHANGED)
923 {
d3a24ed2
CR
924#if 0
925 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
926 the places where they can be changed using unwind-protects. For
927 example, look at execute_cmd.c:execute_function(). */
928 if (SPECIAL_TRAP (sig) == 0)
929#endif
930 free (old_trap);
ccc6cda3
JA
931 sigmodes[sig] &= ~SIG_CHANGED;
932 }
5e13499c
CR
933
934 if (save_return_catch_flag)
935 {
936 return_catch_flag = save_return_catch_flag;
937 return_catch_value = trap_exit_value;
938 COPY_PROCENV (save_return_catch, return_catch);
939 if (function_code)
940 longjmp (return_catch, 1);
941 }
ccc6cda3 942 }
5e13499c 943
d3a24ed2 944 return trap_exit_value;
ccc6cda3
JA
945}
946
d3a24ed2 947int
ccc6cda3
JA
948run_debug_trap ()
949{
d3a24ed2 950 int trap_exit_value;
0d8616ff 951 pid_t save_pgrp;
2d0c84ef 952 int save_pipe[2];
d3a24ed2
CR
953
954 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
955 trap_exit_value = 0;
956 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
957 {
0d8616ff
CR
958#if defined (JOB_CONTROL)
959 save_pgrp = pipeline_pgrp;
2d0c84ef 960 pipeline_pgrp = 0;
0d8616ff 961 save_pipeline (1);
2d0c84ef
CR
962# if defined (PGRP_PIPE)
963 save_pgrp_pipe (save_pipe, 1);
964# endif
0d8616ff
CR
965 stop_making_children ();
966#endif
2d0c84ef 967
d3a24ed2 968 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
2d0c84ef 969
0d8616ff
CR
970#if defined (JOB_CONTROL)
971 pipeline_pgrp = save_pgrp;
972 restore_pipeline (1);
2d0c84ef
CR
973# if defined (PGRP_PIPE)
974 close_pgrp_pipe ();
975 restore_pgrp_pipe (save_pipe);
976# endif
977 if (pipeline_pgrp > 0)
978 give_terminal_to (pipeline_pgrp, 1);
0d8616ff
CR
979 notify_and_cleanup ();
980#endif
d3a24ed2
CR
981
982#if defined (DEBUGGER)
983 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
984 a function or sourced script, we force a `return'. */
985 if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
986 {
987 return_catch_value = trap_exit_value;
988 longjmp (return_catch, 1);
989 }
990#endif
991 }
992 return trap_exit_value;
ccc6cda3
JA
993}
994
f73dda09
JA
995void
996run_error_trap ()
997{
d3a24ed2 998 if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
f73dda09
JA
999 _run_trap_internal (ERROR_TRAP, "error trap");
1000}
1001
d3a24ed2
CR
1002void
1003run_return_trap ()
1004{
1005 int old_exit_value;
1006
76a8d78d
CR
1007#if 0
1008 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
1009 return;
1010#endif
1011
d3a24ed2
CR
1012 if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
1013 {
1014 old_exit_value = last_command_exit_value;
1015 _run_trap_internal (RETURN_TRAP, "return trap");
1016 last_command_exit_value = old_exit_value;
1017 }
1018}
1019
ccc6cda3
JA
1020/* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
1021 declared here to localize the trap functions. */
1022void
1023run_interrupt_trap ()
1024{
1025 _run_trap_internal (SIGINT, "interrupt trap");
726f6388
JA
1026}
1027
1028/* Free all the allocated strings in the list of traps and reset the trap
08e72d7a
CR
1029 values to the default. Intended to be called from subshells that want
1030 to complete work done by reset_signal_handlers upon execution of a
c1854f2d
CR
1031 subsequent `trap' command that changes a signal's disposition. We need
1032 to make sure that we duplicate the behavior of
1033 reset_or_restore_signal_handlers and not change the disposition of signals
1034 that are set to be ignored. */
726f6388
JA
1035void
1036free_trap_strings ()
1037{
1038 register int i;
1039
f73dda09 1040 for (i = 0; i < BASH_NSIG; i++)
c1854f2d
CR
1041 {
1042 if (trap_list[i] != (char *)IGNORE_SIG)
1043 free_trap_string (i);
1044 }
d3a24ed2 1045 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
726f6388 1046}
08e72d7a
CR
1047
1048/* Free a trap command string associated with SIG without changing signal
1049 disposition. Intended to be called from free_trap_strings() */
1050static void
1051free_trap_string (sig)
1052 int sig;
1053{
1054 change_signal (sig, (char *)DEFAULT_SIG);
1055 sigmodes[sig] &= ~SIG_TRAPPED;
1056}
726f6388 1057
d1fab3dc
CR
1058/* Reset the handler for SIG to the original value but leave the trap string
1059 in place. */
726f6388
JA
1060static void
1061reset_signal (sig)
1062 int sig;
1063{
1064 set_signal_handler (sig, original_signals[sig]);
7117c2d2 1065 sigmodes[sig] &= ~SIG_TRAPPED;
726f6388
JA
1066}
1067
ccc6cda3
JA
1068/* Set the handler signal SIG to the original and free any trap
1069 command associated with it. */
1070static void
1071restore_signal (sig)
1072 int sig;
726f6388 1073{
ccc6cda3
JA
1074 set_signal_handler (sig, original_signals[sig]);
1075 change_signal (sig, (char *)DEFAULT_SIG);
1076 sigmodes[sig] &= ~SIG_TRAPPED;
726f6388
JA
1077}
1078
ccc6cda3
JA
1079static void
1080reset_or_restore_signal_handlers (reset)
f73dda09 1081 sh_resetsig_func_t *reset;
726f6388
JA
1082{
1083 register int i;
1084
ccc6cda3
JA
1085 /* Take care of the exit trap first */
1086 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
726f6388 1087 {
ccc6cda3 1088 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
10590446
CR
1089 if (reset != reset_signal)
1090 {
1091 free_trap_command (EXIT_TRAP);
1092 trap_list[EXIT_TRAP] = (char *)NULL;
1093 }
726f6388 1094 }
d3a24ed2 1095
726f6388
JA
1096 for (i = 1; i < NSIG; i++)
1097 {
ccc6cda3 1098 if (sigmodes[i] & SIG_TRAPPED)
726f6388
JA
1099 {
1100 if (trap_list[i] == (char *)IGNORE_SIG)
1101 set_signal_handler (i, SIG_IGN);
1102 else
ccc6cda3 1103 (*reset) (i);
726f6388 1104 }
ccc6cda3
JA
1105 else if (sigmodes[i] & SIG_SPECIAL)
1106 (*reset) (i);
726f6388 1107 }
f73dda09
JA
1108
1109 /* Command substitution and other child processes don't inherit the
d3a24ed2
CR
1110 debug, error, or return traps. If we're in the debugger, and the
1111 `functrace' or `errtrace' options have been set, then let command
1112 substitutions inherit them. Let command substitution inherit the
1113 RETURN trap if we're in the debugger and tracing functions. */
462a7a25
CR
1114 if (function_trace_mode == 0)
1115 {
1116 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
1117 sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
1118 }
1119 if (error_trace_mode == 0)
d3a24ed2 1120 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
726f6388
JA
1121}
1122
f73dda09 1123/* Reset trapped signals to their original values, but don't free the
d1fab3dc
CR
1124 trap strings. Called by the command substitution code and other places
1125 that create a "subshell environment". */
726f6388 1126void
ccc6cda3 1127reset_signal_handlers ()
726f6388 1128{
ccc6cda3
JA
1129 reset_or_restore_signal_handlers (reset_signal);
1130}
726f6388 1131
ccc6cda3
JA
1132/* Reset all trapped signals to their original values. Signals set to be
1133 ignored with trap '' SIGNAL should be ignored, so we make sure that they
1134 are. Called by child processes after they are forked. */
1135void
1136restore_original_signals ()
1137{
1138 reset_or_restore_signal_handlers (restore_signal);
726f6388
JA
1139}
1140
1141/* If a trap handler exists for signal SIG, then call it; otherwise just
631b20c6 1142 return failure. Returns 1 if it called the trap handler. */
726f6388
JA
1143int
1144maybe_call_trap_handler (sig)
1145 int sig;
1146{
1147 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
ccc6cda3 1148 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
726f6388
JA
1149 {
1150 switch (sig)
1151 {
1152 case SIGINT:
1153 run_interrupt_trap ();
1154 break;
ccc6cda3 1155 case EXIT_TRAP:
726f6388
JA
1156 run_exit_trap ();
1157 break;
ccc6cda3
JA
1158 case DEBUG_TRAP:
1159 run_debug_trap ();
1160 break;
f73dda09
JA
1161 case ERROR_TRAP:
1162 run_error_trap ();
1163 break;
726f6388
JA
1164 default:
1165 trap_handler (sig);
1166 break;
1167 }
1168 return (1);
1169 }
1170 else
1171 return (0);
1172}
1173
1174int
1175signal_is_trapped (sig)
1176 int sig;
1177{
1178 return (sigmodes[sig] & SIG_TRAPPED);
1179}
1180
d42cb8c1
CR
1181int
1182signal_is_pending (sig)
1183 int sig;
1184{
1185 return (pending_traps[sig]);
1186}
1187
726f6388
JA
1188int
1189signal_is_special (sig)
1190 int sig;
1191{
1192 return (sigmodes[sig] & SIG_SPECIAL);
1193}
1194
1195int
1196signal_is_ignored (sig)
1197 int sig;
1198{
1199 return (sigmodes[sig] & SIG_IGNORED);
1200}
1201
9e51a74d
CR
1202int
1203signal_is_hard_ignored (sig)
e3af9370 1204 int sig;
9e51a74d
CR
1205{
1206 return (sigmodes[sig] & SIG_HARD_IGNORE);
1207}
1208
726f6388
JA
1209void
1210set_signal_ignored (sig)
1211 int sig;
1212{
1213 sigmodes[sig] |= SIG_HARD_IGNORE;
ccc6cda3 1214 original_signals[sig] = SIG_IGN;
726f6388 1215}
f75912ae
CR
1216
1217int
1218signal_in_progress (sig)
1219 int sig;
1220{
1221 return (sigmodes[sig] & SIG_INPROGRESS);
1222}