]> git.ipfire.org Git - thirdparty/bash.git/blame - trap.c
Imported from ../bash-2.02.1.tar.gz.
[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
4/* Copyright (C) 1987, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 1, or (at your option) any later
11 version.
12
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
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
JA
31#include <stdio.h>
32
33#include "trap.h"
34
726f6388
JA
35#include "shell.h"
36#include "signames.h"
ccc6cda3 37#include "builtins/common.h"
726f6388
JA
38
39/* Flags which describe the current handling state of a signal. */
40#define SIG_INHERITED 0x0 /* Value inherited from parent. */
41#define SIG_TRAPPED 0x1 /* Currently trapped. */
42#define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
43#define SIG_SPECIAL 0x4 /* Treat this signal specially. */
44#define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
ccc6cda3
JA
45#define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
46#define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
47#define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
726f6388
JA
48
49/* An array of such flags, one for each signal, describing what the
ccc6cda3
JA
50 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
51 assumes this. */
52static int sigmodes[NSIG+1];
726f6388
JA
53
54static void change_signal (), restore_signal ();
55
56/* Variables used here but defined in other files. */
57extern int interactive_shell, interactive;
58extern int interrupt_immediately;
59extern int last_command_exit_value;
d166f048 60extern int line_number;
726f6388
JA
61
62/* The list of things to do originally, before we started trapping. */
63SigHandler *original_signals[NSIG];
64
65/* For each signal, a slot for a string, which is a command to be
66 executed when that signal is recieved. The slot can also contain
67 DEFAULT_SIG, which means do whatever you were going to do before
68 you were so rudely interrupted, or IGNORE_SIG, which says ignore
69 this signal. */
ccc6cda3 70char *trap_list[NSIG+1];
726f6388
JA
71
72/* A bitmap of signals received for which we have trap handlers. */
73int pending_traps[NSIG];
74
ccc6cda3
JA
75/* Set to the number of the signal we're running the trap for + 1.
76 Used in execute_cmd.c and builtins/common.c to clean up when
77 parse_and_execute does not return normally after executing the
78 trap command (e.g., when `return' is executed in the trap command). */
79int running_trap;
80
d166f048
JA
81/* The value of line_number when the trap started executing, since
82 parse_and_execute resets it to 1 and the trap command might want
83 it. */
84int trap_line_number;
85
726f6388
JA
86/* A value which can never be the target of a trap handler. */
87#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
88
89void
90initialize_traps ()
91{
92 register int i;
93
ccc6cda3
JA
94 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = (char *)NULL;
95 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = SIG_INHERITED;
96 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
726f6388
JA
97
98 for (i = 1; i < NSIG; i++)
99 {
100 pending_traps[i] = 0;
101 trap_list[i] = (char *)DEFAULT_SIG;
102 sigmodes[i] = SIG_INHERITED;
103 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
104 }
105
106 /* Show which signals are treated specially by the shell. */
107#if defined (SIGCHLD)
ccc6cda3
JA
108 original_signals[SIGCHLD] =
109 (SigHandler *) set_signal_handler (SIGCHLD, SIG_DFL);
726f6388
JA
110 set_signal_handler (SIGCHLD, original_signals[SIGCHLD]);
111 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
112#endif /* SIGCHLD */
113
114 original_signals[SIGINT] =
115 (SigHandler *) set_signal_handler (SIGINT, SIG_DFL);
116 set_signal_handler (SIGINT, original_signals[SIGINT]);
117 sigmodes[SIGINT] |= SIG_SPECIAL;
118
119 original_signals[SIGQUIT] =
120 (SigHandler *) set_signal_handler (SIGQUIT, SIG_DFL);
121 set_signal_handler (SIGQUIT, original_signals[SIGQUIT]);
122 sigmodes[SIGQUIT] |= SIG_SPECIAL;
123
124 if (interactive)
125 {
ccc6cda3
JA
126 original_signals[SIGTERM] =
127 (SigHandler *)set_signal_handler (SIGTERM, SIG_DFL);
726f6388
JA
128 set_signal_handler (SIGTERM, original_signals[SIGTERM]);
129 sigmodes[SIGTERM] |= SIG_SPECIAL;
130 }
131}
132
133/* Return the print name of this signal. */
134char *
135signal_name (sig)
136 int sig;
137{
cce855bc
JA
138 char *ret;
139
140 /* on cygwin32, signal_names[sig] could be null */
141 ret = (sig > NSIG || sig < 0) ? "bad signal number" : signal_names[sig];
142 if (ret == NULL)
143 ret = "unrecognized signal number";
144 return ret;
726f6388
JA
145}
146
147/* Turn a string into a signal number, or a number into
148 a signal number. If STRING is "2", "SIGINT", or "INT",
149 then (int)2 is returned. Return NO_SIG if STRING doesn't
150 contain a valid signal descriptor. */
151int
152decode_signal (string)
153 char *string;
154{
ccc6cda3 155 long sig;
726f6388 156
ccc6cda3
JA
157 if (legal_number (string, &sig))
158 return ((sig >= 0 && sig <= NSIG) ? (int)sig : NO_SIG);
726f6388 159
e8ce775d 160 /* A leading `SIG' may be omitted. */
ccc6cda3
JA
161 for (sig = 0; sig <= NSIG; sig++)
162 if (strcasecmp (string, signal_names[sig]) == 0 ||
e8ce775d
JA
163 (STREQN (signal_names[sig], "SIG", 3) &&
164 strcasecmp (string, &(signal_names[sig])[3]) == 0))
ccc6cda3 165 return ((int)sig);
726f6388
JA
166
167 return (NO_SIG);
168}
169
170/* Non-zero when we catch a trapped signal. */
ccc6cda3 171static int catch_flag;
726f6388
JA
172
173void
174run_pending_traps ()
175{
176 register int sig;
177 int old_exit_value;
178
179 if (catch_flag == 0) /* simple optimization */
180 return;
181
182 catch_flag = 0;
183
184 /* Preserve $? when running trap. */
185 old_exit_value = last_command_exit_value;
186
187 for (sig = 1; sig < NSIG; sig++)
188 {
189 /* XXX this could be made into a counter by using
190 while (pending_traps[sig]--) instead of the if statement. */
191 if (pending_traps[sig])
192 {
ccc6cda3 193#if defined (HAVE_POSIX_SIGNALS)
726f6388
JA
194 sigset_t set, oset;
195
196 sigemptyset (&set);
197 sigemptyset (&oset);
198
199 sigaddset (&set, sig);
200 sigprocmask (SIG_BLOCK, &set, &oset);
201#else
202# if defined (HAVE_BSD_SIGNALS)
203 int oldmask = sigblock (sigmask (sig));
204# endif
ccc6cda3 205#endif /* HAVE_POSIX_SIGNALS */
726f6388
JA
206
207 if (sig == SIGINT)
208 {
209 run_interrupt_trap ();
ccc6cda3 210 CLRINTERRUPT;
726f6388
JA
211 }
212 else
d166f048 213 parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST);
726f6388
JA
214
215 pending_traps[sig] = 0;
216
ccc6cda3 217#if defined (HAVE_POSIX_SIGNALS)
726f6388
JA
218 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
219#else
220# if defined (HAVE_BSD_SIGNALS)
221 sigsetmask (oldmask);
222# endif
223#endif /* POSIX_VERSION */
224 }
225 }
226
227 last_command_exit_value = old_exit_value;
228}
229
230sighandler
231trap_handler (sig)
232 int sig;
233{
234 if ((sig >= NSIG) ||
235 (trap_list[sig] == (char *)DEFAULT_SIG) ||
236 (trap_list[sig] == (char *)IGNORE_SIG))
ccc6cda3 237 programming_error ("trap_handler: bad signal %d", sig);
726f6388
JA
238 else
239 {
ccc6cda3 240#if defined (MUST_REINSTALL_SIGHANDLERS)
726f6388 241 set_signal_handler (sig, trap_handler);
ccc6cda3 242#endif /* MUST_REINSTALL_SIGHANDLERS */
726f6388
JA
243
244 catch_flag = 1;
245 pending_traps[sig]++;
246
247 if (interrupt_immediately)
248 run_pending_traps ();
249 }
ccc6cda3
JA
250
251 SIGRETURN (0);
726f6388
JA
252}
253
254#if defined (JOB_CONTROL) && defined (SIGCHLD)
cce855bc
JA
255
256#ifdef INCLUDE_UNUSED
726f6388
JA
257/* Make COMMAND_STRING be executed when SIGCHLD is caught. */
258void
259set_sigchld_trap (command_string)
260 char *command_string;
261{
726f6388
JA
262 set_signal (SIGCHLD, command_string);
263}
cce855bc 264#endif
726f6388
JA
265
266/* Make COMMAND_STRING be executed when SIGCHLD is caught iff the current
267 SIGCHLD trap handler is DEFAULT_SIG. */
268void
269maybe_set_sigchld_trap (command_string)
270 char *command_string;
271{
726f6388
JA
272 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
273 set_signal (SIGCHLD, command_string);
274}
275#endif /* JOB_CONTROL && SIGCHLD */
276
ccc6cda3
JA
277void
278set_debug_trap (command)
726f6388
JA
279 char *command;
280{
ccc6cda3
JA
281 set_signal (DEBUG_TRAP, command);
282}
726f6388 283
cce855bc 284#ifdef INCLUDE_UNUSED
ccc6cda3
JA
285void
286set_sigint_trap (command)
287 char *command;
288{
726f6388
JA
289 set_signal (SIGINT, command);
290}
cce855bc 291#endif
726f6388
JA
292
293/* Reset the SIGINT handler so that subshells that are doing `shellsy'
294 things, like waiting for command substitution or executing commands
295 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
296SigHandler *
297set_sigint_handler ()
298{
299 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
300 return ((SigHandler *)SIG_IGN);
301
302 else if (sigmodes[SIGINT] & SIG_IGNORED)
ccc6cda3
JA
303 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
304
726f6388
JA
305 else if (sigmodes[SIGINT] & SIG_TRAPPED)
306 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
307
308 /* The signal is not trapped, so set the handler to the shell's special
309 interrupt handler. */
310 else if (interactive) /* XXX - was interactive_shell */
311 return (set_signal_handler (SIGINT, sigint_sighandler));
312 else
313 return (set_signal_handler (SIGINT, termination_unwind_protect));
314}
315
e8ce775d
JA
316/* Return the correct handler for signal SIG according to the values in
317 sigmodes[SIG]. */
318SigHandler *
319trap_to_sighandler (sig)
320 int sig;
321{
322 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
323 return (SIG_IGN);
324 else if (sigmodes[sig] & SIG_TRAPPED)
325 return (trap_handler);
326 else
327 return (SIG_DFL);
328}
329
726f6388
JA
330/* Set SIG to call STRING as a command. */
331void
332set_signal (sig, string)
333 int sig;
334 char *string;
335{
ccc6cda3
JA
336 if (sig == DEBUG_TRAP || sig == EXIT_TRAP)
337 {
338 change_signal (sig, savestring (string));
d166f048
JA
339 if (sig == EXIT_TRAP && interactive == 0)
340 initialize_terminating_signals ();
ccc6cda3
JA
341 return;
342 }
343
726f6388
JA
344 /* A signal ignored on entry to the shell cannot be trapped or reset, but
345 no error is reported when attempting to do so. -- Posix.2 */
346 if (sigmodes[sig] & SIG_HARD_IGNORE)
347 return;
348
349 /* Make sure we have original_signals[sig] if the signal has not yet
350 been trapped. */
351 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
352 {
353 /* If we aren't sure of the original value, check it. */
354 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
355 {
356 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
357 set_signal_handler (sig, original_signals[sig]);
358 }
359
360 /* Signals ignored on entry to the shell cannot be trapped or reset. */
361 if (original_signals[sig] == SIG_IGN)
362 {
363 sigmodes[sig] |= SIG_HARD_IGNORE;
364 return;
365 }
366 }
367
368 /* Only change the system signal handler if SIG_NO_TRAP is not set.
369 The trap command string is changed in either case. The shell signal
370 handlers for SIGINT and SIGCHLD run the user specified traps in an
371 environment in which it is safe to do so. */
372 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
373 {
374 set_signal_handler (sig, SIG_IGN);
375 change_signal (sig, savestring (string));
376 set_signal_handler (sig, trap_handler);
377 }
378 else
379 change_signal (sig, savestring (string));
380}
381
382static void
383free_trap_command (sig)
384 int sig;
385{
386 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
387 (trap_list[sig] != (char *)IGNORE_SIG) &&
388 (trap_list[sig] != (char *)DEFAULT_SIG) &&
389 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
390 free (trap_list[sig]);
391}
ccc6cda3 392
726f6388
JA
393/* If SIG has a string assigned to it, get rid of it. Then give it
394 VALUE. */
395static void
396change_signal (sig, value)
397 int sig;
398 char *value;
399{
d166f048
JA
400 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
401 free_trap_command (sig);
726f6388
JA
402 trap_list[sig] = value;
403
404 sigmodes[sig] |= SIG_TRAPPED;
405 if (value == (char *)IGNORE_SIG)
406 sigmodes[sig] |= SIG_IGNORED;
407 else
408 sigmodes[sig] &= ~SIG_IGNORED;
409 if (sigmodes[sig] & SIG_INPROGRESS)
410 sigmodes[sig] |= SIG_CHANGED;
411}
412
413#define GET_ORIGINAL_SIGNAL(sig) \
414 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
415 get_original_signal (sig)
416
417static void
418get_original_signal (sig)
419 int sig;
420{
421 /* If we aren't sure the of the original value, then get it. */
422 if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
423 {
424 original_signals[sig] =
425 (SigHandler *) set_signal_handler (sig, SIG_DFL);
426 set_signal_handler (sig, original_signals[sig]);
427
428 /* Signals ignored on entry to the shell cannot be trapped. */
429 if (original_signals[sig] == SIG_IGN)
430 sigmodes[sig] |= SIG_HARD_IGNORE;
431 }
432}
433
434/* Restore the default action for SIG; i.e., the action the shell
435 would have taken before you used the trap command. This is called
436 from trap_builtin (), which takes care to restore the handlers for
437 the signals the shell treats specially. */
438void
439restore_default_signal (sig)
440 int sig;
441{
ccc6cda3 442 if (sig == DEBUG_TRAP || sig == EXIT_TRAP)
726f6388 443 {
d166f048
JA
444 if ((sig != DEBUG_TRAP) || (sigmodes[sig] & SIG_INPROGRESS) == 0)
445 free_trap_command (sig);
726f6388
JA
446 trap_list[sig] = (char *)NULL;
447 sigmodes[sig] &= ~SIG_TRAPPED;
d166f048
JA
448 if (sigmodes[sig] & SIG_INPROGRESS)
449 sigmodes[sig] |= SIG_CHANGED;
726f6388
JA
450 return;
451 }
452
453 GET_ORIGINAL_SIGNAL (sig);
454
455 /* A signal ignored on entry to the shell cannot be trapped or reset, but
456 no error is reported when attempting to do so. Thanks Posix.2. */
457 if (sigmodes[sig] & SIG_HARD_IGNORE)
458 return;
459
460 /* If we aren't trapping this signal, don't bother doing anything else. */
ccc6cda3 461 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
726f6388
JA
462 return;
463
464 /* Only change the signal handler for SIG if it allows it. */
ccc6cda3 465 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
726f6388
JA
466 set_signal_handler (sig, original_signals[sig]);
467
468 /* Change the trap command in either case. */
469 change_signal (sig, (char *)DEFAULT_SIG);
470
471 /* Mark the signal as no longer trapped. */
472 sigmodes[sig] &= ~SIG_TRAPPED;
473}
474
475/* Make this signal be ignored. */
476void
477ignore_signal (sig)
478 int sig;
479{
ccc6cda3
JA
480 if ((sig == EXIT_TRAP || sig == DEBUG_TRAP) && ((sigmodes[sig] & SIG_IGNORED) == 0))
481 {
482 change_signal (sig, (char *)IGNORE_SIG);
483 return;
484 }
485
726f6388
JA
486 GET_ORIGINAL_SIGNAL (sig);
487
488 /* A signal ignored on entry to the shell cannot be trapped or reset.
ccc6cda3 489 No error is reported when the user attempts to do so. */
726f6388
JA
490 if (sigmodes[sig] & SIG_HARD_IGNORE)
491 return;
492
493 /* If already trapped and ignored, no change necessary. */
ccc6cda3 494 if (sigmodes[sig] & SIG_IGNORED)
726f6388
JA
495 return;
496
497 /* Only change the signal handler for SIG if it allows it. */
ccc6cda3 498 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
726f6388
JA
499 set_signal_handler (sig, SIG_IGN);
500
501 /* Change the trap command in either case. */
502 change_signal (sig, (char *)IGNORE_SIG);
503}
504
505/* Handle the calling of "trap 0". The only sticky situation is when
506 the command to be executed includes an "exit". This is why we have
507 to provide our own place for top_level to jump to. */
508int
509run_exit_trap ()
510{
ccc6cda3
JA
511 char *trap_command;
512 int code, old_exit_value;
726f6388
JA
513
514 old_exit_value = last_command_exit_value;
515
ccc6cda3
JA
516 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
517 currently running in the trap handler (call to exit in the list of
518 commands given to trap 0). */
519 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
520 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
726f6388 521 {
ccc6cda3
JA
522 trap_command = savestring (trap_list[EXIT_TRAP]);
523 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
524 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
726f6388
JA
525
526 code = setjmp (top_level);
527
528 if (code == 0)
cce855bc
JA
529 {
530 reset_parser ();
531 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST);
532 }
726f6388 533 else if (code == EXITPROG)
ccc6cda3 534 return (last_command_exit_value);
726f6388
JA
535 else
536 return (old_exit_value);
537 }
538
539 return (old_exit_value);
540}
541
ccc6cda3
JA
542void
543run_trap_cleanup (sig)
544 int sig;
545{
546 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
547}
548
549/* Run a trap command for SIG. SIG is one of the signals the shell treats
550 specially. */
726f6388 551static void
ccc6cda3 552_run_trap_internal (sig, tag)
726f6388 553 int sig;
ccc6cda3 554 char *tag;
726f6388 555{
ccc6cda3 556 char *trap_command, *old_trap;
d166f048 557 int old_exit_value, old_line_number;
ccc6cda3
JA
558
559 /* Run the trap only if SIG is trapped and not ignored, and we are not
560 currently executing in the trap handler. */
561 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
562 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
563 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
564 {
565 old_trap = trap_list[sig];
566 sigmodes[sig] |= SIG_INPROGRESS;
567 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
568 trap_command = savestring (old_trap);
569
570 running_trap = sig + 1;
571 old_exit_value = last_command_exit_value;
d166f048
JA
572 /* Need to copy the value of line_number because parse_and_execute
573 resets it to 1, and the trap command might want it. */
574 trap_line_number = line_number;
575 parse_and_execute (trap_command, tag, SEVAL_NONINT|SEVAL_NOHIST);
ccc6cda3
JA
576 last_command_exit_value = old_exit_value;
577 running_trap = 0;
578
579 sigmodes[sig] &= ~SIG_INPROGRESS;
580
581 if (sigmodes[sig] & SIG_CHANGED)
582 {
583 free (old_trap);
584 sigmodes[sig] &= ~SIG_CHANGED;
585 }
586 }
587}
588
589void
590run_debug_trap ()
591{
592 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0)
593 _run_trap_internal (DEBUG_TRAP, "debug trap");
594}
595
596/* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
597 declared here to localize the trap functions. */
598void
599run_interrupt_trap ()
600{
601 _run_trap_internal (SIGINT, "interrupt trap");
726f6388
JA
602}
603
cce855bc 604#ifdef INCLUDE_UNUSED
726f6388
JA
605/* Free all the allocated strings in the list of traps and reset the trap
606 values to the default. */
607void
608free_trap_strings ()
609{
610 register int i;
611
ccc6cda3 612 for (i = 0; i < NSIG+1; i++)
726f6388
JA
613 {
614 free_trap_command (i);
615 trap_list[i] = (char *)DEFAULT_SIG;
616 sigmodes[i] &= ~SIG_TRAPPED;
617 }
ccc6cda3 618 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = (char *)NULL;
726f6388 619}
cce855bc 620#endif
726f6388
JA
621
622/* Reset the handler for SIG to the original value. */
623static void
624reset_signal (sig)
625 int sig;
626{
627 set_signal_handler (sig, original_signals[sig]);
628}
629
ccc6cda3
JA
630/* Set the handler signal SIG to the original and free any trap
631 command associated with it. */
632static void
633restore_signal (sig)
634 int sig;
726f6388 635{
ccc6cda3
JA
636 set_signal_handler (sig, original_signals[sig]);
637 change_signal (sig, (char *)DEFAULT_SIG);
638 sigmodes[sig] &= ~SIG_TRAPPED;
726f6388
JA
639}
640
ccc6cda3
JA
641static void
642reset_or_restore_signal_handlers (reset)
643 VFunction *reset;
726f6388
JA
644{
645 register int i;
646
ccc6cda3
JA
647 /* Take care of the exit trap first */
648 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
726f6388 649 {
ccc6cda3
JA
650 free_trap_command (EXIT_TRAP);
651 trap_list[EXIT_TRAP] = (char *)NULL;
652 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
726f6388 653 }
726f6388
JA
654 for (i = 1; i < NSIG; i++)
655 {
ccc6cda3 656 if (sigmodes[i] & SIG_TRAPPED)
726f6388
JA
657 {
658 if (trap_list[i] == (char *)IGNORE_SIG)
659 set_signal_handler (i, SIG_IGN);
660 else
ccc6cda3 661 (*reset) (i);
726f6388 662 }
ccc6cda3
JA
663 else if (sigmodes[i] & SIG_SPECIAL)
664 (*reset) (i);
726f6388
JA
665 }
666}
667
726f6388 668void
ccc6cda3 669reset_signal_handlers ()
726f6388 670{
ccc6cda3
JA
671 reset_or_restore_signal_handlers (reset_signal);
672}
726f6388 673
ccc6cda3
JA
674/* Reset all trapped signals to their original values. Signals set to be
675 ignored with trap '' SIGNAL should be ignored, so we make sure that they
676 are. Called by child processes after they are forked. */
677void
678restore_original_signals ()
679{
680 reset_or_restore_signal_handlers (restore_signal);
726f6388
JA
681}
682
683/* If a trap handler exists for signal SIG, then call it; otherwise just
684 return failure. */
685int
686maybe_call_trap_handler (sig)
687 int sig;
688{
689 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
ccc6cda3 690 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
726f6388
JA
691 {
692 switch (sig)
693 {
694 case SIGINT:
695 run_interrupt_trap ();
696 break;
ccc6cda3 697 case EXIT_TRAP:
726f6388
JA
698 run_exit_trap ();
699 break;
ccc6cda3
JA
700 case DEBUG_TRAP:
701 run_debug_trap ();
702 break;
726f6388
JA
703 default:
704 trap_handler (sig);
705 break;
706 }
707 return (1);
708 }
709 else
710 return (0);
711}
712
713int
714signal_is_trapped (sig)
715 int sig;
716{
717 return (sigmodes[sig] & SIG_TRAPPED);
718}
719
720int
721signal_is_special (sig)
722 int sig;
723{
724 return (sigmodes[sig] & SIG_SPECIAL);
725}
726
727int
728signal_is_ignored (sig)
729 int sig;
730{
731 return (sigmodes[sig] & SIG_IGNORED);
732}
733
734void
735set_signal_ignored (sig)
736 int sig;
737{
738 sigmodes[sig] |= SIG_HARD_IGNORE;
ccc6cda3 739 original_signals[sig] = SIG_IGN;
726f6388 740}