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