blob: 3641caf38b1aef1b54e3caa416ac5ffba42d04a0 [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001/* trap.c -- Not the trap command, but useful functions for manipulating
2 those objects. The trap command is in builtins/trap.def. */
3
Jari Aaltob80f6442004-07-27 13:29:18 +00004/* Copyright (C) 1987-2003 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
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
Jari Aaltobb706242000-03-17 21:46:59 +000010 Software Foundation; either version 2, or (at your option) any later
Jari Aalto726f6381996-08-26 18:22:31 +000011 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
Jari Aaltobb706242000-03-17 21:46:59 +000020 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
Jari Aalto726f6381996-08-26 18:22:31 +000021
Jari Aaltoccc6cda1996-12-23 17:02:34 +000022#include "config.h"
23
Jari Aaltoe8ce7751997-09-22 20:22:27 +000024#if defined (HAVE_UNISTD_H)
25# include <unistd.h>
26#endif
27
Jari Aalto726f6381996-08-26 18:22:31 +000028#include "bashtypes.h"
Jari Aaltod166f041997-06-05 14:59:13 +000029#include "bashansi.h"
Jari Aalto726f6381996-08-26 18:22:31 +000030
Jari Aaltocce855b1998-04-17 19:52:44 +000031#include <stdio.h>
Jari Aaltobb706242000-03-17 21:46:59 +000032#include <errno.h>
Jari Aaltocce855b1998-04-17 19:52:44 +000033
Jari Aaltob80f6442004-07-27 13:29:18 +000034#include "bashintl.h"
35
Jari Aaltocce855b1998-04-17 19:52:44 +000036#include "trap.h"
37
Jari Aalto726f6381996-08-26 18:22:31 +000038#include "shell.h"
Jari Aaltob80f6442004-07-27 13:29:18 +000039#include "flags.h"
Jari Aaltobb706242000-03-17 21:46:59 +000040#include "input.h" /* for save_token_state, restore_token_state */
Jari Aalto726f6381996-08-26 18:22:31 +000041#include "signames.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000042#include "builtins.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000043#include "builtins/common.h"
Jari Aalto7117c2d2002-07-17 14:10:11 +000044#include "builtins/builtext.h"
Jari Aalto726f6381996-08-26 18:22:31 +000045
Jari Aaltobb706242000-03-17 21:46:59 +000046#ifndef errno
47extern int errno;
48#endif
49
Jari Aalto726f6381996-08-26 18:22:31 +000050/* Flags which describe the current handling state of a signal. */
51#define SIG_INHERITED 0x0 /* Value inherited from parent. */
52#define SIG_TRAPPED 0x1 /* Currently trapped. */
53#define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
54#define SIG_SPECIAL 0x4 /* Treat this signal specially. */
55#define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +000056#define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
57#define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
58#define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
Jari Aalto726f6381996-08-26 18:22:31 +000059
Jari Aaltob80f6442004-07-27 13:29:18 +000060#define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
Jari Aaltof73dda02001-11-13 17:56:06 +000061
Jari Aalto726f6381996-08-26 18:22:31 +000062/* An array of such flags, one for each signal, describing what the
Jari Aaltoccc6cda1996-12-23 17:02:34 +000063 shell will do with a signal. DEBUG_TRAP == NSIG; some code below
64 assumes this. */
Jari Aaltof73dda02001-11-13 17:56:06 +000065static int sigmodes[BASH_NSIG];
Jari Aalto726f6381996-08-26 18:22:31 +000066
Jari Aaltof73dda02001-11-13 17:56:06 +000067static void free_trap_command __P((int));
68static void change_signal __P((int, char *));
69
70static void get_original_signal __P((int));
71
Jari Aaltob80f6442004-07-27 13:29:18 +000072static int _run_trap_internal __P((int, char *));
Jari Aaltof73dda02001-11-13 17:56:06 +000073
74static void reset_signal __P((int));
75static void restore_signal __P((int));
76static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
Jari Aalto726f6381996-08-26 18:22:31 +000077
78/* Variables used here but defined in other files. */
Jari Aalto726f6381996-08-26 18:22:31 +000079extern int interrupt_immediately;
80extern int last_command_exit_value;
Jari Aaltod166f041997-06-05 14:59:13 +000081extern int line_number;
Jari Aalto726f6381996-08-26 18:22:31 +000082
Jari Aaltob80f6442004-07-27 13:29:18 +000083extern char *this_command_name;
Jari Aalto7117c2d2002-07-17 14:10:11 +000084extern sh_builtin_func_t *this_shell_builtin;
85extern procenv_t wait_intr_buf;
Jari Aaltob80f6442004-07-27 13:29:18 +000086extern int return_catch_flag, return_catch_value;
87extern int subshell_level;
Jari Aalto7117c2d2002-07-17 14:10:11 +000088
Jari Aalto726f6381996-08-26 18:22:31 +000089/* The list of things to do originally, before we started trapping. */
90SigHandler *original_signals[NSIG];
91
92/* For each signal, a slot for a string, which is a command to be
93 executed when that signal is recieved. The slot can also contain
94 DEFAULT_SIG, which means do whatever you were going to do before
95 you were so rudely interrupted, or IGNORE_SIG, which says ignore
96 this signal. */
Jari Aaltof73dda02001-11-13 17:56:06 +000097char *trap_list[BASH_NSIG];
Jari Aalto726f6381996-08-26 18:22:31 +000098
99/* A bitmap of signals received for which we have trap handlers. */
100int pending_traps[NSIG];
101
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000102/* Set to the number of the signal we're running the trap for + 1.
103 Used in execute_cmd.c and builtins/common.c to clean up when
104 parse_and_execute does not return normally after executing the
105 trap command (e.g., when `return' is executed in the trap command). */
106int running_trap;
107
Jari Aaltob80f6442004-07-27 13:29:18 +0000108/* Set to last_command_exit_value before running a trap. */
109int trap_saved_exit_value;
Jari Aaltod166f041997-06-05 14:59:13 +0000110
Jari Aalto7117c2d2002-07-17 14:10:11 +0000111/* The (trapped) signal received while executing in the `wait' builtin */
112int wait_signal_received;
113
Jari Aalto726f6381996-08-26 18:22:31 +0000114/* A value which can never be the target of a trap handler. */
115#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
116
117void
118initialize_traps ()
119{
120 register int i;
121
Jari Aaltob80f6442004-07-27 13:29:18 +0000122 trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
123 sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000124 original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
Jari Aalto726f6381996-08-26 18:22:31 +0000125
126 for (i = 1; i < NSIG; i++)
127 {
128 pending_traps[i] = 0;
129 trap_list[i] = (char *)DEFAULT_SIG;
130 sigmodes[i] = SIG_INHERITED;
131 original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
132 }
133
134 /* Show which signals are treated specially by the shell. */
135#if defined (SIGCHLD)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000136 original_signals[SIGCHLD] =
137 (SigHandler *) set_signal_handler (SIGCHLD, SIG_DFL);
Jari Aalto726f6381996-08-26 18:22:31 +0000138 set_signal_handler (SIGCHLD, original_signals[SIGCHLD]);
139 sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
140#endif /* SIGCHLD */
141
142 original_signals[SIGINT] =
143 (SigHandler *) set_signal_handler (SIGINT, SIG_DFL);
144 set_signal_handler (SIGINT, original_signals[SIGINT]);
145 sigmodes[SIGINT] |= SIG_SPECIAL;
146
Jari Aaltob72432f1999-02-19 17:11:39 +0000147#if defined (__BEOS__)
148 /* BeOS sets SIGINT to SIG_IGN! */
149 original_signals[SIGINT] = SIG_DFL;
150#endif
151
Jari Aalto726f6381996-08-26 18:22:31 +0000152 original_signals[SIGQUIT] =
153 (SigHandler *) set_signal_handler (SIGQUIT, SIG_DFL);
154 set_signal_handler (SIGQUIT, original_signals[SIGQUIT]);
155 sigmodes[SIGQUIT] |= SIG_SPECIAL;
156
157 if (interactive)
158 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000159 original_signals[SIGTERM] =
160 (SigHandler *)set_signal_handler (SIGTERM, SIG_DFL);
Jari Aalto726f6381996-08-26 18:22:31 +0000161 set_signal_handler (SIGTERM, original_signals[SIGTERM]);
162 sigmodes[SIGTERM] |= SIG_SPECIAL;
163 }
164}
165
Jari Aaltobb706242000-03-17 21:46:59 +0000166#ifdef INCLUDE_UNUSED
167/* Return a printable representation of the trap handler for SIG. */
168static char *
169trap_handler_string (sig)
170 int sig;
171{
172 if (trap_list[sig] == (char *)DEFAULT_SIG)
173 return "DEFAULT_SIG";
174 else if (trap_list[sig] == (char *)IGNORE_SIG)
175 return "IGNORE_SIG";
176 else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
177 return "IMPOSSIBLE_TRAP_HANDLER";
178 else if (trap_list[sig])
179 return trap_list[sig];
180 else
181 return "NULL";
182}
183#endif
184
Jari Aalto726f6381996-08-26 18:22:31 +0000185/* Return the print name of this signal. */
186char *
187signal_name (sig)
188 int sig;
189{
Jari Aaltocce855b1998-04-17 19:52:44 +0000190 char *ret;
191
192 /* on cygwin32, signal_names[sig] could be null */
Jari Aaltob80f6442004-07-27 13:29:18 +0000193 ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
194 ? _("invalid signal number")
195 : signal_names[sig];
196
Jari Aaltocce855b1998-04-17 19:52:44 +0000197 return ret;
Jari Aalto726f6381996-08-26 18:22:31 +0000198}
199
200/* Turn a string into a signal number, or a number into
201 a signal number. If STRING is "2", "SIGINT", or "INT",
202 then (int)2 is returned. Return NO_SIG if STRING doesn't
203 contain a valid signal descriptor. */
204int
Jari Aaltob80f6442004-07-27 13:29:18 +0000205decode_signal (string, flags)
Jari Aalto726f6381996-08-26 18:22:31 +0000206 char *string;
Jari Aaltob80f6442004-07-27 13:29:18 +0000207 int flags;
Jari Aalto726f6381996-08-26 18:22:31 +0000208{
Jari Aalto7117c2d2002-07-17 14:10:11 +0000209 intmax_t sig;
Jari Aaltob80f6442004-07-27 13:29:18 +0000210 char *name;
Jari Aalto726f6381996-08-26 18:22:31 +0000211
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000212 if (legal_number (string, &sig))
Jari Aaltof73dda02001-11-13 17:56:06 +0000213 return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
Jari Aalto726f6381996-08-26 18:22:31 +0000214
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000215 /* A leading `SIG' may be omitted. */
Jari Aaltof73dda02001-11-13 17:56:06 +0000216 for (sig = 0; sig < BASH_NSIG; sig++)
Jari Aaltob72432f1999-02-19 17:11:39 +0000217 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000218 name = signal_names[sig];
219 if (name == 0 || name[0] == '\0')
Jari Aaltob72432f1999-02-19 17:11:39 +0000220 continue;
Jari Aaltob80f6442004-07-27 13:29:18 +0000221
222 /* Check name without the SIG prefix first case sensitivly or
223 insensitively depending on whether flags includes DSIG_NOCASE */
224 if (STREQN (name, "SIG", 3))
225 {
226 name += 3;
227
228 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
229 return ((int)sig);
230 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
231 return ((int)sig);
232 /* If we can't use the `SIG' prefix to match, punt on this
233 name now. */
234 else if ((flags & DSIG_SIGPREFIX) == 0)
235 continue;
236 }
237
238 /* Check name with SIG prefix case sensitively or insensitively
239 depending on whether flags includes DSIG_NOCASE */
240 name = signal_names[sig];
241 if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
242 return ((int)sig);
243 else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
Jari Aaltob72432f1999-02-19 17:11:39 +0000244 return ((int)sig);
245 }
Jari Aalto726f6381996-08-26 18:22:31 +0000246
247 return (NO_SIG);
248}
249
250/* Non-zero when we catch a trapped signal. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000251static int catch_flag;
Jari Aalto726f6381996-08-26 18:22:31 +0000252
253void
254run_pending_traps ()
255{
256 register int sig;
Jari Aaltobb706242000-03-17 21:46:59 +0000257 int old_exit_value, *token_state;
Jari Aalto726f6381996-08-26 18:22:31 +0000258
259 if (catch_flag == 0) /* simple optimization */
260 return;
261
262 catch_flag = 0;
263
264 /* Preserve $? when running trap. */
265 old_exit_value = last_command_exit_value;
266
267 for (sig = 1; sig < NSIG; sig++)
268 {
269 /* XXX this could be made into a counter by using
Jari Aalto28ef6c32001-04-06 19:14:31 +0000270 while (pending_traps[sig]--) instead of the if statement. */
Jari Aalto726f6381996-08-26 18:22:31 +0000271 if (pending_traps[sig])
272 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000273#if defined (HAVE_POSIX_SIGNALS)
Jari Aalto726f6381996-08-26 18:22:31 +0000274 sigset_t set, oset;
275
276 sigemptyset (&set);
277 sigemptyset (&oset);
278
279 sigaddset (&set, sig);
280 sigprocmask (SIG_BLOCK, &set, &oset);
281#else
282# if defined (HAVE_BSD_SIGNALS)
283 int oldmask = sigblock (sigmask (sig));
284# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000285#endif /* HAVE_POSIX_SIGNALS */
Jari Aalto726f6381996-08-26 18:22:31 +0000286
287 if (sig == SIGINT)
288 {
289 run_interrupt_trap ();
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000290 CLRINTERRUPT;
Jari Aalto726f6381996-08-26 18:22:31 +0000291 }
Jari Aaltobb706242000-03-17 21:46:59 +0000292 else if (trap_list[sig] == (char *)DEFAULT_SIG ||
293 trap_list[sig] == (char *)IGNORE_SIG ||
294 trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
295 {
296 /* This is possible due to a race condition. Say a bash
297 process has SIGTERM trapped. A subshell is spawned
298 using { list; } & and the parent does something and kills
299 the subshell with SIGTERM. It's possible for the subshell
300 to set pending_traps[SIGTERM] to 1 before the code in
301 execute_cmd.c eventually calls restore_original_signals
302 to reset the SIGTERM signal handler in the subshell. The
303 next time run_pending_traps is called, pending_traps[SIGTERM]
304 will be 1, but the trap handler in trap_list[SIGTERM] will
305 be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
306 Unless we catch this, the subshell will dump core when
307 trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
308 usually 0x0. */
Jari Aaltob80f6442004-07-27 13:29:18 +0000309 internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
Jari Aaltof73dda02001-11-13 17:56:06 +0000310 sig, trap_list[sig]);
Jari Aaltobb706242000-03-17 21:46:59 +0000311 if (trap_list[sig] == (char *)DEFAULT_SIG)
312 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000313 internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
Jari Aaltobb706242000-03-17 21:46:59 +0000314 kill (getpid (), sig);
315 }
316 }
Jari Aalto726f6381996-08-26 18:22:31 +0000317 else
Jari Aaltobb706242000-03-17 21:46:59 +0000318 {
319 token_state = save_token_state ();
320 parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST);
321 restore_token_state (token_state);
322 free (token_state);
323 }
Jari Aalto726f6381996-08-26 18:22:31 +0000324
325 pending_traps[sig] = 0;
326
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000327#if defined (HAVE_POSIX_SIGNALS)
Jari Aalto726f6381996-08-26 18:22:31 +0000328 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
329#else
330# if defined (HAVE_BSD_SIGNALS)
331 sigsetmask (oldmask);
332# endif
333#endif /* POSIX_VERSION */
334 }
335 }
336
337 last_command_exit_value = old_exit_value;
338}
339
340sighandler
341trap_handler (sig)
342 int sig;
343{
Jari Aaltobb706242000-03-17 21:46:59 +0000344 int oerrno;
345
Jari Aalto726f6381996-08-26 18:22:31 +0000346 if ((sig >= NSIG) ||
347 (trap_list[sig] == (char *)DEFAULT_SIG) ||
348 (trap_list[sig] == (char *)IGNORE_SIG))
Jari Aaltob80f6442004-07-27 13:29:18 +0000349 programming_error (_("trap_handler: bad signal %d"), sig);
Jari Aalto726f6381996-08-26 18:22:31 +0000350 else
351 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000352 oerrno = errno;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000353#if defined (MUST_REINSTALL_SIGHANDLERS)
Jari Aalto726f6381996-08-26 18:22:31 +0000354 set_signal_handler (sig, trap_handler);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000355#endif /* MUST_REINSTALL_SIGHANDLERS */
Jari Aalto726f6381996-08-26 18:22:31 +0000356
357 catch_flag = 1;
358 pending_traps[sig]++;
359
Jari Aalto7117c2d2002-07-17 14:10:11 +0000360 if (interrupt_immediately && this_shell_builtin && (this_shell_builtin == wait_builtin))
361 {
362 wait_signal_received = sig;
363 longjmp (wait_intr_buf, 1);
364 }
365
Jari Aalto726f6381996-08-26 18:22:31 +0000366 if (interrupt_immediately)
367 run_pending_traps ();
Jari Aaltobb706242000-03-17 21:46:59 +0000368
369 errno = oerrno;
Jari Aalto726f6381996-08-26 18:22:31 +0000370 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000371
372 SIGRETURN (0);
Jari Aalto726f6381996-08-26 18:22:31 +0000373}
374
375#if defined (JOB_CONTROL) && defined (SIGCHLD)
Jari Aaltocce855b1998-04-17 19:52:44 +0000376
377#ifdef INCLUDE_UNUSED
Jari Aalto726f6381996-08-26 18:22:31 +0000378/* Make COMMAND_STRING be executed when SIGCHLD is caught. */
379void
380set_sigchld_trap (command_string)
381 char *command_string;
382{
Jari Aalto726f6381996-08-26 18:22:31 +0000383 set_signal (SIGCHLD, command_string);
384}
Jari Aaltocce855b1998-04-17 19:52:44 +0000385#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000386
387/* Make COMMAND_STRING be executed when SIGCHLD is caught iff the current
388 SIGCHLD trap handler is DEFAULT_SIG. */
389void
390maybe_set_sigchld_trap (command_string)
391 char *command_string;
392{
Jari Aalto726f6381996-08-26 18:22:31 +0000393 if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
394 set_signal (SIGCHLD, command_string);
395}
396#endif /* JOB_CONTROL && SIGCHLD */
397
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000398void
399set_debug_trap (command)
400 char *command;
401{
402 set_signal (DEBUG_TRAP, command);
403}
404
Jari Aaltof73dda02001-11-13 17:56:06 +0000405void
406set_error_trap (command)
407 char *command;
408{
409 set_signal (ERROR_TRAP, command);
410}
411
Jari Aaltob80f6442004-07-27 13:29:18 +0000412void
413set_return_trap (command)
414 char *command;
415{
416 set_signal (RETURN_TRAP, command);
417}
418
Jari Aaltocce855b1998-04-17 19:52:44 +0000419#ifdef INCLUDE_UNUSED
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000420void
Jari Aalto726f6381996-08-26 18:22:31 +0000421set_sigint_trap (command)
422 char *command;
423{
Jari Aalto726f6381996-08-26 18:22:31 +0000424 set_signal (SIGINT, command);
425}
Jari Aaltocce855b1998-04-17 19:52:44 +0000426#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000427
428/* Reset the SIGINT handler so that subshells that are doing `shellsy'
429 things, like waiting for command substitution or executing commands
430 in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
431SigHandler *
432set_sigint_handler ()
433{
434 if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
435 return ((SigHandler *)SIG_IGN);
436
437 else if (sigmodes[SIGINT] & SIG_IGNORED)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000438 return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
439
Jari Aalto726f6381996-08-26 18:22:31 +0000440 else if (sigmodes[SIGINT] & SIG_TRAPPED)
441 return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
442
443 /* The signal is not trapped, so set the handler to the shell's special
444 interrupt handler. */
445 else if (interactive) /* XXX - was interactive_shell */
446 return (set_signal_handler (SIGINT, sigint_sighandler));
447 else
448 return (set_signal_handler (SIGINT, termination_unwind_protect));
449}
450
Jari Aaltoe8ce7751997-09-22 20:22:27 +0000451/* Return the correct handler for signal SIG according to the values in
452 sigmodes[SIG]. */
453SigHandler *
454trap_to_sighandler (sig)
455 int sig;
456{
457 if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
458 return (SIG_IGN);
459 else if (sigmodes[sig] & SIG_TRAPPED)
460 return (trap_handler);
461 else
462 return (SIG_DFL);
463}
464
Jari Aalto726f6381996-08-26 18:22:31 +0000465/* Set SIG to call STRING as a command. */
466void
467set_signal (sig, string)
468 int sig;
469 char *string;
470{
Jari Aaltof73dda02001-11-13 17:56:06 +0000471 if (SPECIAL_TRAP (sig))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000472 {
473 change_signal (sig, savestring (string));
Jari Aaltod166f041997-06-05 14:59:13 +0000474 if (sig == EXIT_TRAP && interactive == 0)
475 initialize_terminating_signals ();
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000476 return;
477 }
478
Jari Aalto726f6381996-08-26 18:22:31 +0000479 /* A signal ignored on entry to the shell cannot be trapped or reset, but
480 no error is reported when attempting to do so. -- Posix.2 */
481 if (sigmodes[sig] & SIG_HARD_IGNORE)
482 return;
483
484 /* Make sure we have original_signals[sig] if the signal has not yet
485 been trapped. */
486 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
487 {
488 /* If we aren't sure of the original value, check it. */
489 if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
490 {
491 original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
492 set_signal_handler (sig, original_signals[sig]);
493 }
494
495 /* Signals ignored on entry to the shell cannot be trapped or reset. */
496 if (original_signals[sig] == SIG_IGN)
497 {
498 sigmodes[sig] |= SIG_HARD_IGNORE;
499 return;
500 }
501 }
502
503 /* Only change the system signal handler if SIG_NO_TRAP is not set.
504 The trap command string is changed in either case. The shell signal
505 handlers for SIGINT and SIGCHLD run the user specified traps in an
506 environment in which it is safe to do so. */
507 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
508 {
509 set_signal_handler (sig, SIG_IGN);
510 change_signal (sig, savestring (string));
511 set_signal_handler (sig, trap_handler);
512 }
513 else
514 change_signal (sig, savestring (string));
515}
516
517static void
518free_trap_command (sig)
519 int sig;
520{
521 if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
522 (trap_list[sig] != (char *)IGNORE_SIG) &&
523 (trap_list[sig] != (char *)DEFAULT_SIG) &&
524 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
525 free (trap_list[sig]);
526}
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000527
Jari Aalto726f6381996-08-26 18:22:31 +0000528/* If SIG has a string assigned to it, get rid of it. Then give it
529 VALUE. */
530static void
531change_signal (sig, value)
532 int sig;
533 char *value;
534{
Jari Aaltod166f041997-06-05 14:59:13 +0000535 if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
536 free_trap_command (sig);
Jari Aalto726f6381996-08-26 18:22:31 +0000537 trap_list[sig] = value;
538
539 sigmodes[sig] |= SIG_TRAPPED;
540 if (value == (char *)IGNORE_SIG)
541 sigmodes[sig] |= SIG_IGNORED;
542 else
543 sigmodes[sig] &= ~SIG_IGNORED;
544 if (sigmodes[sig] & SIG_INPROGRESS)
545 sigmodes[sig] |= SIG_CHANGED;
546}
547
548#define GET_ORIGINAL_SIGNAL(sig) \
549 if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
550 get_original_signal (sig)
551
552static void
553get_original_signal (sig)
554 int sig;
555{
556 /* If we aren't sure the of the original value, then get it. */
557 if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
558 {
559 original_signals[sig] =
560 (SigHandler *) set_signal_handler (sig, SIG_DFL);
561 set_signal_handler (sig, original_signals[sig]);
562
563 /* Signals ignored on entry to the shell cannot be trapped. */
564 if (original_signals[sig] == SIG_IGN)
565 sigmodes[sig] |= SIG_HARD_IGNORE;
566 }
567}
568
569/* Restore the default action for SIG; i.e., the action the shell
570 would have taken before you used the trap command. This is called
571 from trap_builtin (), which takes care to restore the handlers for
572 the signals the shell treats specially. */
573void
574restore_default_signal (sig)
575 int sig;
576{
Jari Aaltof73dda02001-11-13 17:56:06 +0000577 if (SPECIAL_TRAP (sig))
Jari Aalto726f6381996-08-26 18:22:31 +0000578 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000579 if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
580 (sigmodes[sig] & SIG_INPROGRESS) == 0)
Jari Aaltod166f041997-06-05 14:59:13 +0000581 free_trap_command (sig);
Jari Aalto726f6381996-08-26 18:22:31 +0000582 trap_list[sig] = (char *)NULL;
583 sigmodes[sig] &= ~SIG_TRAPPED;
Jari Aaltod166f041997-06-05 14:59:13 +0000584 if (sigmodes[sig] & SIG_INPROGRESS)
585 sigmodes[sig] |= SIG_CHANGED;
Jari Aalto726f6381996-08-26 18:22:31 +0000586 return;
587 }
588
589 GET_ORIGINAL_SIGNAL (sig);
590
591 /* A signal ignored on entry to the shell cannot be trapped or reset, but
592 no error is reported when attempting to do so. Thanks Posix.2. */
593 if (sigmodes[sig] & SIG_HARD_IGNORE)
594 return;
595
596 /* If we aren't trapping this signal, don't bother doing anything else. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000597 if ((sigmodes[sig] & SIG_TRAPPED) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000598 return;
599
600 /* Only change the signal handler for SIG if it allows it. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000601 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000602 set_signal_handler (sig, original_signals[sig]);
603
604 /* Change the trap command in either case. */
605 change_signal (sig, (char *)DEFAULT_SIG);
606
607 /* Mark the signal as no longer trapped. */
608 sigmodes[sig] &= ~SIG_TRAPPED;
609}
610
611/* Make this signal be ignored. */
612void
613ignore_signal (sig)
614 int sig;
615{
Jari Aaltof73dda02001-11-13 17:56:06 +0000616 if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000617 {
618 change_signal (sig, (char *)IGNORE_SIG);
619 return;
620 }
621
Jari Aalto726f6381996-08-26 18:22:31 +0000622 GET_ORIGINAL_SIGNAL (sig);
623
624 /* A signal ignored on entry to the shell cannot be trapped or reset.
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000625 No error is reported when the user attempts to do so. */
Jari Aalto726f6381996-08-26 18:22:31 +0000626 if (sigmodes[sig] & SIG_HARD_IGNORE)
627 return;
628
629 /* If already trapped and ignored, no change necessary. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000630 if (sigmodes[sig] & SIG_IGNORED)
Jari Aalto726f6381996-08-26 18:22:31 +0000631 return;
632
633 /* Only change the signal handler for SIG if it allows it. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000634 if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000635 set_signal_handler (sig, SIG_IGN);
636
637 /* Change the trap command in either case. */
638 change_signal (sig, (char *)IGNORE_SIG);
639}
640
641/* Handle the calling of "trap 0". The only sticky situation is when
642 the command to be executed includes an "exit". This is why we have
643 to provide our own place for top_level to jump to. */
644int
645run_exit_trap ()
646{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000647 char *trap_command;
Jari Aaltob80f6442004-07-27 13:29:18 +0000648 int code, function_code, retval;
Jari Aalto726f6381996-08-26 18:22:31 +0000649
Jari Aaltob80f6442004-07-27 13:29:18 +0000650 trap_saved_exit_value = last_command_exit_value;
651 function_code = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000652
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000653 /* Run the trap only if signal 0 is trapped and not ignored, and we are not
654 currently running in the trap handler (call to exit in the list of
655 commands given to trap 0). */
656 if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
657 (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000658 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000659 trap_command = savestring (trap_list[EXIT_TRAP]);
660 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
661 sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
Jari Aalto726f6381996-08-26 18:22:31 +0000662
Jari Aaltob80f6442004-07-27 13:29:18 +0000663 retval = trap_saved_exit_value;
664 running_trap = 1;
665
Jari Aalto726f6381996-08-26 18:22:31 +0000666 code = setjmp (top_level);
667
Jari Aaltob80f6442004-07-27 13:29:18 +0000668 /* If we're in a function, make sure return longjmps come here, too. */
669 if (return_catch_flag)
670 function_code = setjmp (return_catch);
671
672 if (code == 0 && function_code == 0)
Jari Aaltocce855b1998-04-17 19:52:44 +0000673 {
674 reset_parser ();
675 parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST);
676 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000677 else if (code == ERREXIT)
678 retval = last_command_exit_value;
Jari Aalto726f6381996-08-26 18:22:31 +0000679 else if (code == EXITPROG)
Jari Aaltob80f6442004-07-27 13:29:18 +0000680 retval = last_command_exit_value;
681 else if (function_code != 0)
682 retval = return_catch_value;
Jari Aalto726f6381996-08-26 18:22:31 +0000683 else
Jari Aaltob80f6442004-07-27 13:29:18 +0000684 retval = trap_saved_exit_value;
685
686 running_trap = 0;
687 return retval;
Jari Aalto726f6381996-08-26 18:22:31 +0000688 }
689
Jari Aaltob80f6442004-07-27 13:29:18 +0000690 return (trap_saved_exit_value);
Jari Aalto726f6381996-08-26 18:22:31 +0000691}
692
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000693void
694run_trap_cleanup (sig)
Jari Aalto726f6381996-08-26 18:22:31 +0000695 int sig;
696{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000697 sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
698}
699
700/* Run a trap command for SIG. SIG is one of the signals the shell treats
Jari Aaltob80f6442004-07-27 13:29:18 +0000701 specially. Returns the exit status of the executed trap command list. */
702static int
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000703_run_trap_internal (sig, tag)
704 int sig;
705 char *tag;
706{
707 char *trap_command, *old_trap;
Jari Aaltob80f6442004-07-27 13:29:18 +0000708 int trap_exit_value, *token_state;
709 int save_return_catch_flag, function_code;
710 procenv_t save_return_catch;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000711
Jari Aaltob80f6442004-07-27 13:29:18 +0000712 trap_exit_value = function_code = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000713 /* Run the trap only if SIG is trapped and not ignored, and we are not
714 currently executing in the trap handler. */
715 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
716 (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
717 ((sigmodes[sig] & SIG_INPROGRESS) == 0))
718 {
719 old_trap = trap_list[sig];
720 sigmodes[sig] |= SIG_INPROGRESS;
721 sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
722 trap_command = savestring (old_trap);
723
724 running_trap = sig + 1;
Jari Aaltob80f6442004-07-27 13:29:18 +0000725 trap_saved_exit_value = last_command_exit_value;
Jari Aaltobb706242000-03-17 21:46:59 +0000726
727 token_state = save_token_state ();
Jari Aaltob80f6442004-07-27 13:29:18 +0000728
729 /* If we're in a function, make sure return longjmps come here, too. */
730 save_return_catch_flag = return_catch_flag;
731 if (return_catch_flag)
732 {
733 COPY_PROCENV (return_catch, save_return_catch);
734 function_code = setjmp (return_catch);
735 }
736
737 if (function_code == 0)
738 parse_and_execute (trap_command, tag, SEVAL_NONINT|SEVAL_NOHIST);
739
Jari Aaltobb706242000-03-17 21:46:59 +0000740 restore_token_state (token_state);
741 free (token_state);
742
Jari Aaltob80f6442004-07-27 13:29:18 +0000743 trap_exit_value = last_command_exit_value;
744 last_command_exit_value = trap_saved_exit_value;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000745 running_trap = 0;
746
747 sigmodes[sig] &= ~SIG_INPROGRESS;
748
749 if (sigmodes[sig] & SIG_CHANGED)
750 {
Jari Aaltob80f6442004-07-27 13:29:18 +0000751#if 0
752 /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
753 the places where they can be changed using unwind-protects. For
754 example, look at execute_cmd.c:execute_function(). */
755 if (SPECIAL_TRAP (sig) == 0)
756#endif
757 free (old_trap);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000758 sigmodes[sig] &= ~SIG_CHANGED;
759 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000760
761 if (save_return_catch_flag)
762 {
763 return_catch_flag = save_return_catch_flag;
764 return_catch_value = trap_exit_value;
765 COPY_PROCENV (save_return_catch, return_catch);
766 if (function_code)
767 longjmp (return_catch, 1);
768 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000769 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000770
771 return trap_exit_value;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000772}
773
Jari Aaltob80f6442004-07-27 13:29:18 +0000774int
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000775run_debug_trap ()
776{
Jari Aaltob80f6442004-07-27 13:29:18 +0000777 int trap_exit_value;
778
779 /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
780 trap_exit_value = 0;
781 if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
782 {
783 trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
784
785#if defined (DEBUGGER)
786 /* If we're in the debugger and the DEBUG trap returns 2 while we're in
787 a function or sourced script, we force a `return'. */
788 if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
789 {
790 return_catch_value = trap_exit_value;
791 longjmp (return_catch, 1);
792 }
793#endif
794 }
795 return trap_exit_value;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000796}
797
Jari Aaltof73dda02001-11-13 17:56:06 +0000798void
799run_error_trap ()
800{
Jari Aaltob80f6442004-07-27 13:29:18 +0000801 if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
Jari Aaltof73dda02001-11-13 17:56:06 +0000802 _run_trap_internal (ERROR_TRAP, "error trap");
803}
804
Jari Aaltob80f6442004-07-27 13:29:18 +0000805void
806run_return_trap ()
807{
808 int old_exit_value;
809
810 if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
811 {
812 old_exit_value = last_command_exit_value;
813 _run_trap_internal (RETURN_TRAP, "return trap");
814 last_command_exit_value = old_exit_value;
815 }
816}
817
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000818/* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
819 declared here to localize the trap functions. */
820void
821run_interrupt_trap ()
822{
823 _run_trap_internal (SIGINT, "interrupt trap");
Jari Aalto726f6381996-08-26 18:22:31 +0000824}
825
Jari Aaltocce855b1998-04-17 19:52:44 +0000826#ifdef INCLUDE_UNUSED
Jari Aalto726f6381996-08-26 18:22:31 +0000827/* Free all the allocated strings in the list of traps and reset the trap
828 values to the default. */
829void
830free_trap_strings ()
831{
832 register int i;
833
Jari Aaltof73dda02001-11-13 17:56:06 +0000834 for (i = 0; i < BASH_NSIG; i++)
Jari Aalto726f6381996-08-26 18:22:31 +0000835 {
836 free_trap_command (i);
837 trap_list[i] = (char *)DEFAULT_SIG;
838 sigmodes[i] &= ~SIG_TRAPPED;
839 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000840 trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +0000841}
Jari Aaltocce855b1998-04-17 19:52:44 +0000842#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000843
844/* Reset the handler for SIG to the original value. */
845static void
846reset_signal (sig)
847 int sig;
848{
849 set_signal_handler (sig, original_signals[sig]);
Jari Aalto7117c2d2002-07-17 14:10:11 +0000850 sigmodes[sig] &= ~SIG_TRAPPED;
Jari Aalto726f6381996-08-26 18:22:31 +0000851}
852
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000853/* Set the handler signal SIG to the original and free any trap
854 command associated with it. */
855static void
856restore_signal (sig)
857 int sig;
858{
859 set_signal_handler (sig, original_signals[sig]);
860 change_signal (sig, (char *)DEFAULT_SIG);
861 sigmodes[sig] &= ~SIG_TRAPPED;
862}
863
864static void
865reset_or_restore_signal_handlers (reset)
Jari Aaltof73dda02001-11-13 17:56:06 +0000866 sh_resetsig_func_t *reset;
Jari Aalto726f6381996-08-26 18:22:31 +0000867{
868 register int i;
869
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000870 /* Take care of the exit trap first */
871 if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
Jari Aalto726f6381996-08-26 18:22:31 +0000872 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000873 free_trap_command (EXIT_TRAP);
874 trap_list[EXIT_TRAP] = (char *)NULL;
875 sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
Jari Aalto726f6381996-08-26 18:22:31 +0000876 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000877
Jari Aalto726f6381996-08-26 18:22:31 +0000878 for (i = 1; i < NSIG; i++)
879 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000880 if (sigmodes[i] & SIG_TRAPPED)
Jari Aalto726f6381996-08-26 18:22:31 +0000881 {
882 if (trap_list[i] == (char *)IGNORE_SIG)
883 set_signal_handler (i, SIG_IGN);
884 else
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000885 (*reset) (i);
Jari Aalto726f6381996-08-26 18:22:31 +0000886 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000887 else if (sigmodes[i] & SIG_SPECIAL)
888 (*reset) (i);
Jari Aalto726f6381996-08-26 18:22:31 +0000889 }
Jari Aaltof73dda02001-11-13 17:56:06 +0000890
891 /* Command substitution and other child processes don't inherit the
Jari Aaltob80f6442004-07-27 13:29:18 +0000892 debug, error, or return traps. If we're in the debugger, and the
893 `functrace' or `errtrace' options have been set, then let command
894 substitutions inherit them. Let command substitution inherit the
895 RETURN trap if we're in the debugger and tracing functions. */
896#if defined (DEBUGGER)
897 if (debugging_mode == 0 || function_trace_mode == 0)
898#endif
899 sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
900#if defined (DEBUGGER)
901 if (debugging_mode == 0 || error_trace_mode == 0)
902#endif
903 sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
904#if defined (DEBUGGER)
905 if (debugging_mode == 0 || function_trace_mode == 0)
906 sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
907#endif
Jari Aalto726f6381996-08-26 18:22:31 +0000908}
909
Jari Aaltof73dda02001-11-13 17:56:06 +0000910/* Reset trapped signals to their original values, but don't free the
911 trap strings. Called by the command substitution code. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000912void
913reset_signal_handlers ()
914{
915 reset_or_restore_signal_handlers (reset_signal);
916}
917
Jari Aalto726f6381996-08-26 18:22:31 +0000918/* Reset all trapped signals to their original values. Signals set to be
919 ignored with trap '' SIGNAL should be ignored, so we make sure that they
920 are. Called by child processes after they are forked. */
921void
922restore_original_signals ()
923{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000924 reset_or_restore_signal_handlers (restore_signal);
Jari Aalto726f6381996-08-26 18:22:31 +0000925}
926
927/* If a trap handler exists for signal SIG, then call it; otherwise just
928 return failure. */
929int
930maybe_call_trap_handler (sig)
931 int sig;
932{
933 /* Call the trap handler for SIG if the signal is trapped and not ignored. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000934 if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
Jari Aalto726f6381996-08-26 18:22:31 +0000935 {
936 switch (sig)
937 {
938 case SIGINT:
939 run_interrupt_trap ();
940 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000941 case EXIT_TRAP:
Jari Aalto726f6381996-08-26 18:22:31 +0000942 run_exit_trap ();
943 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000944 case DEBUG_TRAP:
945 run_debug_trap ();
946 break;
Jari Aaltof73dda02001-11-13 17:56:06 +0000947 case ERROR_TRAP:
948 run_error_trap ();
949 break;
Jari Aalto726f6381996-08-26 18:22:31 +0000950 default:
951 trap_handler (sig);
952 break;
953 }
954 return (1);
955 }
956 else
957 return (0);
958}
959
960int
961signal_is_trapped (sig)
962 int sig;
963{
964 return (sigmodes[sig] & SIG_TRAPPED);
965}
966
967int
968signal_is_special (sig)
969 int sig;
970{
971 return (sigmodes[sig] & SIG_SPECIAL);
972}
973
974int
975signal_is_ignored (sig)
976 int sig;
977{
978 return (sigmodes[sig] & SIG_IGNORED);
979}
980
981void
982set_signal_ignored (sig)
983 int sig;
984{
985 sigmodes[sig] |= SIG_HARD_IGNORE;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000986 original_signals[sig] = SIG_IGN;
Jari Aalto726f6381996-08-26 18:22:31 +0000987}