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