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