Imported from ../bash-3.2.tar.gz.
[platform/upstream/bash.git] / trap.c
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-2006 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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
21
22 #include "config.h"
23
24 #if defined (HAVE_UNISTD_H)
25 #  include <unistd.h>
26 #endif
27
28 #include "bashtypes.h"
29 #include "bashansi.h"
30
31 #include <stdio.h>
32 #include <errno.h>
33
34 #include "bashintl.h"
35
36 #include "trap.h"
37
38 #include "shell.h"
39 #include "flags.h"
40 #include "input.h"      /* for save_token_state, restore_token_state */
41 #include "signames.h"
42 #include "builtins.h"
43 #include "builtins/common.h"
44 #include "builtins/builtext.h"
45
46 #ifndef errno
47 extern int errno;
48 #endif
49
50 /* 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. */
56 #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. */
59
60 #define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
61
62 /* An array of such flags, one for each signal, describing what the
63    shell will do with a signal.  DEBUG_TRAP == NSIG; some code below
64    assumes this. */
65 static int sigmodes[BASH_NSIG];
66
67 static void free_trap_command __P((int));
68 static void change_signal __P((int, char *));
69
70 static void get_original_signal __P((int));
71
72 static int _run_trap_internal __P((int, char *));
73
74 static void reset_signal __P((int));
75 static void restore_signal __P((int));
76 static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
77
78 /* Variables used here but defined in other files. */
79 extern int last_command_exit_value;
80 extern int line_number;
81
82 extern char *this_command_name;
83 extern sh_builtin_func_t *this_shell_builtin;
84 extern procenv_t wait_intr_buf;
85 extern int return_catch_flag, return_catch_value;
86 extern int subshell_level;
87
88 /* The list of things to do originally, before we started trapping. */
89 SigHandler *original_signals[NSIG];
90
91 /* For each signal, a slot for a string, which is a command to be
92    executed when that signal is recieved.  The slot can also contain
93    DEFAULT_SIG, which means do whatever you were going to do before
94    you were so rudely interrupted, or IGNORE_SIG, which says ignore
95    this signal. */
96 char *trap_list[BASH_NSIG];
97
98 /* A bitmap of signals received for which we have trap handlers. */
99 int pending_traps[NSIG];
100
101 /* Set to the number of the signal we're running the trap for + 1.
102    Used in execute_cmd.c and builtins/common.c to clean up when
103    parse_and_execute does not return normally after executing the
104    trap command (e.g., when `return' is executed in the trap command). */
105 int running_trap;
106
107 /* Set to last_command_exit_value before running a trap. */
108 int trap_saved_exit_value;
109
110 /* The (trapped) signal received while executing in the `wait' builtin */
111 int wait_signal_received;
112
113 /* A value which can never be the target of a trap handler. */
114 #define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
115
116 #define GETORIGSIG(sig) \
117   do { \
118     original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
119     set_signal_handler (sig, original_signals[sig]); \
120     if (original_signals[sig] == SIG_IGN) \
121       sigmodes[sig] |= SIG_HARD_IGNORE; \
122   } while (0)
123
124 #define GET_ORIGINAL_SIGNAL(sig) \
125   if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
126     GETORIGSIG(sig)
127
128 void
129 initialize_traps ()
130 {
131   register int i;
132
133   initialize_signames();
134
135   trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
136   sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
137   original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
138
139   for (i = 1; i < NSIG; i++)
140     {
141       pending_traps[i] = 0;
142       trap_list[i] = (char *)DEFAULT_SIG;
143       sigmodes[i] = SIG_INHERITED;
144       original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
145     }
146
147   /* Show which signals are treated specially by the shell. */
148 #if defined (SIGCHLD)
149   GETORIGSIG (SIGCHLD);
150   sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
151 #endif /* SIGCHLD */
152
153   GETORIGSIG (SIGINT);
154   sigmodes[SIGINT] |= SIG_SPECIAL;
155
156 #if defined (__BEOS__)
157   /* BeOS sets SIGINT to SIG_IGN! */
158   original_signals[SIGINT] = SIG_DFL;
159   sigmodes[SIGINT] &= ~SIG_HARD_IGNORE;
160 #endif
161
162   GETORIGSIG (SIGQUIT);
163   sigmodes[SIGQUIT] |= SIG_SPECIAL;
164
165   if (interactive)
166     {
167       GETORIGSIG (SIGTERM);
168       sigmodes[SIGTERM] |= SIG_SPECIAL;
169     }
170 }
171
172 #ifdef INCLUDE_UNUSED
173 /* Return a printable representation of the trap handler for SIG. */
174 static char *
175 trap_handler_string (sig)
176      int sig;
177 {
178   if (trap_list[sig] == (char *)DEFAULT_SIG)
179     return "DEFAULT_SIG";
180   else if (trap_list[sig] == (char *)IGNORE_SIG)
181     return "IGNORE_SIG";
182   else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
183     return "IMPOSSIBLE_TRAP_HANDLER";
184   else if (trap_list[sig])
185     return trap_list[sig];
186   else
187     return "NULL";
188 }
189 #endif
190
191 /* Return the print name of this signal. */
192 char *
193 signal_name (sig)
194      int sig;
195 {
196   char *ret;
197
198   /* on cygwin32, signal_names[sig] could be null */
199   ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
200         ? _("invalid signal number")
201         : signal_names[sig];
202
203   return ret;
204 }
205
206 /* Turn a string into a signal number, or a number into
207    a signal number.  If STRING is "2", "SIGINT", or "INT",
208    then (int)2 is returned.  Return NO_SIG if STRING doesn't
209    contain a valid signal descriptor. */
210 int
211 decode_signal (string, flags)
212      char *string;
213      int flags;
214 {
215   intmax_t sig;
216   char *name;
217
218   if (legal_number (string, &sig))
219     return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
220
221   /* A leading `SIG' may be omitted. */
222   for (sig = 0; sig < BASH_NSIG; sig++)
223     {
224       name = signal_names[sig];
225       if (name == 0 || name[0] == '\0')
226         continue;
227
228       /* Check name without the SIG prefix first case sensitivly or
229          insensitively depending on whether flags includes DSIG_NOCASE */
230       if (STREQN (name, "SIG", 3))
231         {
232           name += 3;
233
234           if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
235             return ((int)sig);
236           else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
237             return ((int)sig);
238           /* If we can't use the `SIG' prefix to match, punt on this
239              name now. */
240           else if ((flags & DSIG_SIGPREFIX) == 0)
241             continue;
242         }
243
244       /* Check name with SIG prefix case sensitively or insensitively
245          depending on whether flags includes DSIG_NOCASE */
246       name = signal_names[sig];
247       if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
248         return ((int)sig);
249       else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
250         return ((int)sig);
251     }
252
253   return (NO_SIG);
254 }
255
256 /* Non-zero when we catch a trapped signal. */
257 static int catch_flag;
258
259 void
260 run_pending_traps ()
261 {
262   register int sig;
263   int old_exit_value, *token_state;
264
265   if (catch_flag == 0)          /* simple optimization */
266     return;
267
268   catch_flag = 0;
269
270   /* Preserve $? when running trap. */
271   old_exit_value = last_command_exit_value;
272
273   for (sig = 1; sig < NSIG; sig++)
274     {
275       /* XXX this could be made into a counter by using
276          while (pending_traps[sig]--) instead of the if statement. */
277       if (pending_traps[sig])
278         {
279 #if defined (HAVE_POSIX_SIGNALS)
280           sigset_t set, oset;
281
282           sigemptyset (&set);
283           sigemptyset (&oset);
284
285           sigaddset (&set, sig);
286           sigprocmask (SIG_BLOCK, &set, &oset);
287 #else
288 #  if defined (HAVE_BSD_SIGNALS)
289           int oldmask = sigblock (sigmask (sig));
290 #  endif
291 #endif /* HAVE_POSIX_SIGNALS */
292
293           if (sig == SIGINT)
294             {
295               run_interrupt_trap ();
296               CLRINTERRUPT;
297             }
298           else if (trap_list[sig] == (char *)DEFAULT_SIG ||
299                    trap_list[sig] == (char *)IGNORE_SIG ||
300                    trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
301             {
302               /* This is possible due to a race condition.  Say a bash
303                  process has SIGTERM trapped.  A subshell is spawned
304                  using { list; } & and the parent does something and kills
305                  the subshell with SIGTERM.  It's possible for the subshell
306                  to set pending_traps[SIGTERM] to 1 before the code in
307                  execute_cmd.c eventually calls restore_original_signals
308                  to reset the SIGTERM signal handler in the subshell.  The
309                  next time run_pending_traps is called, pending_traps[SIGTERM]
310                  will be 1, but the trap handler in trap_list[SIGTERM] will
311                  be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
312                  Unless we catch this, the subshell will dump core when
313                  trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
314                  usually 0x0. */
315               internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
316                                 sig, trap_list[sig]);
317               if (trap_list[sig] == (char *)DEFAULT_SIG)
318                 {
319                   internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
320                   kill (getpid (), sig);
321                 }
322             }
323           else
324             {
325               token_state = save_token_state ();
326               parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST);
327               restore_token_state (token_state);
328               free (token_state);
329             }
330
331           pending_traps[sig] = 0;
332
333 #if defined (HAVE_POSIX_SIGNALS)
334           sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
335 #else
336 #  if defined (HAVE_BSD_SIGNALS)
337           sigsetmask (oldmask);
338 #  endif
339 #endif /* POSIX_VERSION */
340         }
341     }
342
343   last_command_exit_value = old_exit_value;
344 }
345
346 sighandler
347 trap_handler (sig)
348      int sig;
349 {
350   int oerrno;
351
352   if ((sig >= NSIG) ||
353       (trap_list[sig] == (char *)DEFAULT_SIG) ||
354       (trap_list[sig] == (char *)IGNORE_SIG))
355     programming_error (_("trap_handler: bad signal %d"), sig);
356   else
357     {
358       oerrno = errno;
359 #if defined (MUST_REINSTALL_SIGHANDLERS)
360       set_signal_handler (sig, trap_handler);
361 #endif /* MUST_REINSTALL_SIGHANDLERS */
362
363       catch_flag = 1;
364       pending_traps[sig]++;
365
366       if (interrupt_immediately && this_shell_builtin && (this_shell_builtin == wait_builtin))
367         {
368           wait_signal_received = sig;
369           longjmp (wait_intr_buf, 1);
370         }
371
372       if (interrupt_immediately)
373         run_pending_traps ();
374
375       errno = oerrno;
376     }
377
378   SIGRETURN (0);
379 }
380
381 #if defined (JOB_CONTROL) && defined (SIGCHLD)
382
383 #ifdef INCLUDE_UNUSED
384 /* Make COMMAND_STRING be executed when SIGCHLD is caught. */
385 void
386 set_sigchld_trap (command_string)
387      char *command_string;
388 {
389   set_signal (SIGCHLD, command_string);
390 }
391 #endif
392
393 /* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
394    is not already trapped. */
395 void
396 maybe_set_sigchld_trap (command_string)
397      char *command_string;
398 {
399   if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
400     set_signal (SIGCHLD, command_string);
401 }
402 #endif /* JOB_CONTROL && SIGCHLD */
403
404 void
405 set_debug_trap (command)
406      char *command;
407 {
408   set_signal (DEBUG_TRAP, command);
409 }
410
411 void
412 set_error_trap (command)
413      char *command;
414 {
415   set_signal (ERROR_TRAP, command);
416 }
417
418 void
419 set_return_trap (command)
420      char *command;
421 {
422   set_signal (RETURN_TRAP, command);
423 }
424
425 #ifdef INCLUDE_UNUSED
426 void
427 set_sigint_trap (command)
428      char *command;
429 {
430   set_signal (SIGINT, command);
431 }
432 #endif
433
434 /* Reset the SIGINT handler so that subshells that are doing `shellsy'
435    things, like waiting for command substitution or executing commands
436    in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
437 SigHandler *
438 set_sigint_handler ()
439 {
440   if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
441     return ((SigHandler *)SIG_IGN);
442
443   else if (sigmodes[SIGINT] & SIG_IGNORED)
444     return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
445
446   else if (sigmodes[SIGINT] & SIG_TRAPPED)
447     return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
448
449   /* The signal is not trapped, so set the handler to the shell's special
450      interrupt handler. */
451   else if (interactive) /* XXX - was interactive_shell */
452     return (set_signal_handler (SIGINT, sigint_sighandler));
453   else
454     return (set_signal_handler (SIGINT, termsig_sighandler));
455 }
456
457 /* Return the correct handler for signal SIG according to the values in
458    sigmodes[SIG]. */
459 SigHandler *
460 trap_to_sighandler (sig)
461      int sig;
462 {
463   if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
464     return (SIG_IGN);
465   else if (sigmodes[sig] & SIG_TRAPPED)
466     return (trap_handler);
467   else
468     return (SIG_DFL);
469 }
470
471 /* Set SIG to call STRING as a command. */
472 void
473 set_signal (sig, string)
474      int sig;
475      char *string;
476 {
477   if (SPECIAL_TRAP (sig))
478     {
479       change_signal (sig, savestring (string));
480       if (sig == EXIT_TRAP && interactive == 0)
481         initialize_terminating_signals ();
482       return;
483     }
484
485   /* A signal ignored on entry to the shell cannot be trapped or reset, but
486      no error is reported when attempting to do so.  -- Posix.2 */
487   if (sigmodes[sig] & SIG_HARD_IGNORE)
488     return;
489
490   /* Make sure we have original_signals[sig] if the signal has not yet
491      been trapped. */
492   if ((sigmodes[sig] & SIG_TRAPPED) == 0)
493     {
494       /* If we aren't sure of the original value, check it. */
495       if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
496         GETORIGSIG (sig);
497       if (original_signals[sig] == SIG_IGN)
498         return;
499     }
500
501   /* Only change the system signal handler if SIG_NO_TRAP is not set.
502      The trap command string is changed in either case.  The shell signal
503      handlers for SIGINT and SIGCHLD run the user specified traps in an
504      environment in which it is safe to do so. */
505   if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
506     {
507       set_signal_handler (sig, SIG_IGN);
508       change_signal (sig, savestring (string));
509       set_signal_handler (sig, trap_handler);
510     }
511   else
512     change_signal (sig, savestring (string));
513 }
514
515 static void
516 free_trap_command (sig)
517      int sig;
518 {
519   if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
520       (trap_list[sig] != (char *)IGNORE_SIG) &&
521       (trap_list[sig] != (char *)DEFAULT_SIG) &&
522       (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
523     free (trap_list[sig]);
524 }
525
526 /* If SIG has a string assigned to it, get rid of it.  Then give it
527    VALUE. */
528 static void
529 change_signal (sig, value)
530      int sig;
531      char *value;
532 {
533   if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
534     free_trap_command (sig);
535   trap_list[sig] = value;
536
537   sigmodes[sig] |= SIG_TRAPPED;
538   if (value == (char *)IGNORE_SIG)
539     sigmodes[sig] |= SIG_IGNORED;
540   else
541     sigmodes[sig] &= ~SIG_IGNORED;
542   if (sigmodes[sig] & SIG_INPROGRESS)
543     sigmodes[sig] |= SIG_CHANGED;
544 }
545
546 static void
547 get_original_signal (sig)
548      int sig;
549 {
550   /* If we aren't sure the of the original value, then get it. */
551   if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
552     GETORIGSIG (sig);
553 }
554
555 /* Restore the default action for SIG; i.e., the action the shell
556    would have taken before you used the trap command.  This is called
557    from trap_builtin (), which takes care to restore the handlers for
558    the signals the shell treats specially. */
559 void
560 restore_default_signal (sig)
561      int sig;
562 {
563   if (SPECIAL_TRAP (sig))
564     {
565       if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
566           (sigmodes[sig] & SIG_INPROGRESS) == 0)
567         free_trap_command (sig);
568       trap_list[sig] = (char *)NULL;
569       sigmodes[sig] &= ~SIG_TRAPPED;
570       if (sigmodes[sig] & SIG_INPROGRESS)
571         sigmodes[sig] |= SIG_CHANGED;
572       return;
573     }
574
575   GET_ORIGINAL_SIGNAL (sig);
576
577   /* A signal ignored on entry to the shell cannot be trapped or reset, but
578      no error is reported when attempting to do so.  Thanks Posix.2. */
579   if (sigmodes[sig] & SIG_HARD_IGNORE)
580     return;
581
582   /* If we aren't trapping this signal, don't bother doing anything else. */
583   if ((sigmodes[sig] & SIG_TRAPPED) == 0)
584     return;
585
586   /* Only change the signal handler for SIG if it allows it. */
587   if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
588     set_signal_handler (sig, original_signals[sig]);
589
590   /* Change the trap command in either case. */
591   change_signal (sig, (char *)DEFAULT_SIG);
592
593   /* Mark the signal as no longer trapped. */
594   sigmodes[sig] &= ~SIG_TRAPPED;
595 }
596
597 /* Make this signal be ignored. */
598 void
599 ignore_signal (sig)
600      int sig;
601 {
602   if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
603     {
604       change_signal (sig, (char *)IGNORE_SIG);
605       return;
606     }
607
608   GET_ORIGINAL_SIGNAL (sig);
609
610   /* A signal ignored on entry to the shell cannot be trapped or reset.
611      No error is reported when the user attempts to do so. */
612   if (sigmodes[sig] & SIG_HARD_IGNORE)
613     return;
614
615   /* If already trapped and ignored, no change necessary. */
616   if (sigmodes[sig] & SIG_IGNORED)
617     return;
618
619   /* Only change the signal handler for SIG if it allows it. */
620   if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
621     set_signal_handler (sig, SIG_IGN);
622
623   /* Change the trap command in either case. */
624   change_signal (sig, (char *)IGNORE_SIG);
625 }
626
627 /* Handle the calling of "trap 0".  The only sticky situation is when
628    the command to be executed includes an "exit".  This is why we have
629    to provide our own place for top_level to jump to. */
630 int
631 run_exit_trap ()
632 {
633   char *trap_command;
634   int code, function_code, retval;
635
636   trap_saved_exit_value = last_command_exit_value;
637   function_code = 0;
638
639   /* Run the trap only if signal 0 is trapped and not ignored, and we are not
640      currently running in the trap handler (call to exit in the list of
641      commands given to trap 0). */
642   if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
643       (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
644     {
645       trap_command = savestring (trap_list[EXIT_TRAP]);
646       sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
647       sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
648
649       retval = trap_saved_exit_value;
650       running_trap = 1;
651
652       code = setjmp (top_level);
653
654       /* If we're in a function, make sure return longjmps come here, too. */
655       if (return_catch_flag)
656         function_code = setjmp (return_catch);
657
658       if (code == 0 && function_code == 0)
659         {
660           reset_parser ();
661           parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST);
662         }
663       else if (code == ERREXIT)
664         retval = last_command_exit_value;
665       else if (code == EXITPROG)
666         retval = last_command_exit_value;
667       else if (function_code != 0)
668         retval = return_catch_value;
669       else
670         retval = trap_saved_exit_value;
671
672       running_trap = 0;
673       return retval;
674     }
675
676   return (trap_saved_exit_value);
677 }
678
679 void
680 run_trap_cleanup (sig)
681      int sig;
682 {
683   sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
684 }
685
686 /* Run a trap command for SIG.  SIG is one of the signals the shell treats
687    specially.  Returns the exit status of the executed trap command list. */
688 static int
689 _run_trap_internal (sig, tag)
690      int sig;
691      char *tag;
692 {
693   char *trap_command, *old_trap;
694   int trap_exit_value, *token_state;
695   int save_return_catch_flag, function_code;
696   procenv_t save_return_catch;
697
698   trap_exit_value = function_code = 0;
699   /* Run the trap only if SIG is trapped and not ignored, and we are not
700      currently executing in the trap handler. */
701   if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
702       (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
703       ((sigmodes[sig] & SIG_INPROGRESS) == 0))
704     {
705       old_trap = trap_list[sig];
706       sigmodes[sig] |= SIG_INPROGRESS;
707       sigmodes[sig] &= ~SIG_CHANGED;            /* just to be sure */
708       trap_command =  savestring (old_trap);
709
710       running_trap = sig + 1;
711       trap_saved_exit_value = last_command_exit_value;
712
713       token_state = save_token_state ();
714
715       /* If we're in a function, make sure return longjmps come here, too. */
716       save_return_catch_flag = return_catch_flag;
717       if (return_catch_flag)
718         {
719           COPY_PROCENV (return_catch, save_return_catch);
720           function_code = setjmp (return_catch);
721         }
722
723       if (function_code == 0)
724         parse_and_execute (trap_command, tag, SEVAL_NONINT|SEVAL_NOHIST);
725
726       restore_token_state (token_state);
727       free (token_state);
728
729       trap_exit_value = last_command_exit_value;
730       last_command_exit_value = trap_saved_exit_value;
731       running_trap = 0;
732
733       sigmodes[sig] &= ~SIG_INPROGRESS;
734
735       if (sigmodes[sig] & SIG_CHANGED)
736         {
737 #if 0
738           /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
739              the places where they can be changed using unwind-protects.  For
740              example, look at execute_cmd.c:execute_function(). */
741           if (SPECIAL_TRAP (sig) == 0)
742 #endif
743             free (old_trap);
744           sigmodes[sig] &= ~SIG_CHANGED;
745         }
746
747       if (save_return_catch_flag)
748         {
749           return_catch_flag = save_return_catch_flag;
750           return_catch_value = trap_exit_value;
751           COPY_PROCENV (save_return_catch, return_catch);
752           if (function_code)
753             longjmp (return_catch, 1);
754         }
755     }
756
757   return trap_exit_value;
758 }
759
760 int
761 run_debug_trap ()
762 {
763   int trap_exit_value;
764
765   /* XXX - question:  should the DEBUG trap inherit the RETURN trap? */
766   trap_exit_value = 0;
767   if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
768     {
769       trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
770       
771 #if defined (DEBUGGER)
772       /* If we're in the debugger and the DEBUG trap returns 2 while we're in
773          a function or sourced script, we force a `return'. */
774       if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
775         {
776           return_catch_value = trap_exit_value;
777           longjmp (return_catch, 1);
778         }
779 #endif
780     }
781   return trap_exit_value;
782 }
783
784 void
785 run_error_trap ()
786 {
787   if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
788     _run_trap_internal (ERROR_TRAP, "error trap");
789 }
790
791 void
792 run_return_trap ()
793 {
794   int old_exit_value;
795
796 #if 0
797   if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
798     return;
799 #endif
800
801   if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
802     {
803       old_exit_value = last_command_exit_value;
804       _run_trap_internal (RETURN_TRAP, "return trap");
805       last_command_exit_value = old_exit_value;
806     }
807 }
808
809 /* Run a trap set on SIGINT.  This is called from throw_to_top_level (), and
810    declared here to localize the trap functions. */
811 void
812 run_interrupt_trap ()
813 {
814   _run_trap_internal (SIGINT, "interrupt trap");
815 }
816
817 #ifdef INCLUDE_UNUSED
818 /* Free all the allocated strings in the list of traps and reset the trap
819    values to the default. */
820 void
821 free_trap_strings ()
822 {
823   register int i;
824
825   for (i = 0; i < BASH_NSIG; i++)
826     {
827       free_trap_command (i);
828       trap_list[i] = (char *)DEFAULT_SIG;
829       sigmodes[i] &= ~SIG_TRAPPED;
830     }
831   trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
832 }
833 #endif
834
835 /* Reset the handler for SIG to the original value. */
836 static void
837 reset_signal (sig)
838      int sig;
839 {
840   set_signal_handler (sig, original_signals[sig]);
841   sigmodes[sig] &= ~SIG_TRAPPED;
842 }
843
844 /* Set the handler signal SIG to the original and free any trap
845    command associated with it. */
846 static void
847 restore_signal (sig)
848      int sig;
849 {
850   set_signal_handler (sig, original_signals[sig]);
851   change_signal (sig, (char *)DEFAULT_SIG);
852   sigmodes[sig] &= ~SIG_TRAPPED;
853 }
854
855 static void
856 reset_or_restore_signal_handlers (reset)
857      sh_resetsig_func_t *reset;
858 {
859   register int i;
860
861   /* Take care of the exit trap first */
862   if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
863     {
864       sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
865       if (reset != reset_signal)
866         {
867           free_trap_command (EXIT_TRAP);
868           trap_list[EXIT_TRAP] = (char *)NULL;
869         }
870     }
871
872   for (i = 1; i < NSIG; i++)
873     {
874       if (sigmodes[i] & SIG_TRAPPED)
875         {
876           if (trap_list[i] == (char *)IGNORE_SIG)
877             set_signal_handler (i, SIG_IGN);
878           else
879             (*reset) (i);
880         }
881       else if (sigmodes[i] & SIG_SPECIAL)
882         (*reset) (i);
883     }
884
885   /* Command substitution and other child processes don't inherit the
886      debug, error, or return traps.  If we're in the debugger, and the
887      `functrace' or `errtrace' options have been set, then let command
888      substitutions inherit them.  Let command substitution inherit the
889      RETURN trap if we're in the debugger and tracing functions. */
890   if (function_trace_mode == 0)
891     {
892       sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
893       sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
894     }
895   if (error_trace_mode == 0)
896     sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
897 }
898
899 /* Reset trapped signals to their original values, but don't free the
900    trap strings.  Called by the command substitution code. */
901 void
902 reset_signal_handlers ()
903 {
904   reset_or_restore_signal_handlers (reset_signal);
905 }
906
907 /* Reset all trapped signals to their original values.  Signals set to be
908    ignored with trap '' SIGNAL should be ignored, so we make sure that they
909    are.  Called by child processes after they are forked. */
910 void
911 restore_original_signals ()
912 {
913   reset_or_restore_signal_handlers (restore_signal);
914 }
915
916 /* If a trap handler exists for signal SIG, then call it; otherwise just
917    return failure. */
918 int
919 maybe_call_trap_handler (sig)
920      int sig;
921 {
922   /* Call the trap handler for SIG if the signal is trapped and not ignored. */
923   if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
924     {
925       switch (sig)
926         {
927         case SIGINT:
928           run_interrupt_trap ();
929           break;
930         case EXIT_TRAP:
931           run_exit_trap ();
932           break;
933         case DEBUG_TRAP:
934           run_debug_trap ();
935           break;
936         case ERROR_TRAP:
937           run_error_trap ();
938           break;
939         default:
940           trap_handler (sig);
941           break;
942         }
943       return (1);
944     }
945   else
946     return (0);
947 }
948
949 int
950 signal_is_trapped (sig)
951      int sig;
952 {
953   return (sigmodes[sig] & SIG_TRAPPED);
954 }
955
956 int
957 signal_is_special (sig)
958      int sig;
959 {
960   return (sigmodes[sig] & SIG_SPECIAL);
961 }
962
963 int
964 signal_is_ignored (sig)
965      int sig;
966 {
967   return (sigmodes[sig] & SIG_IGNORED);
968 }
969
970 void
971 set_signal_ignored (sig)
972      int sig;
973 {
974   sigmodes[sig] |= SIG_HARD_IGNORE;
975   original_signals[sig] = SIG_IGN;
976 }
977
978 int
979 signal_in_progress (sig)
980      int sig;
981 {
982   return (sigmodes[sig] & SIG_INPROGRESS);
983 }