940dcfdbccd5d9832c0778051b6391a52b540a7b
[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 && sig != ERROR_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   pid_t save_pgrp;
802   int save_pipe[2];
803
804   /* XXX - question:  should the DEBUG trap inherit the RETURN trap? */
805   trap_exit_value = 0;
806   if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
807     {
808 #if defined (JOB_CONTROL)
809       save_pgrp = pipeline_pgrp;
810       pipeline_pgrp = 0;
811       save_pipeline (1);
812 #  if defined (PGRP_PIPE)
813       save_pgrp_pipe (save_pipe, 1);
814 #  endif
815       stop_making_children ();
816 #endif
817
818       trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
819
820 #if defined (JOB_CONTROL)
821       pipeline_pgrp = save_pgrp;
822       restore_pipeline (1);
823 #  if defined (PGRP_PIPE)
824       close_pgrp_pipe ();
825       restore_pgrp_pipe (save_pipe);
826 #  endif
827       if (pipeline_pgrp > 0)
828         give_terminal_to (pipeline_pgrp, 1);
829       notify_and_cleanup ();
830 #endif
831       
832 #if defined (DEBUGGER)
833       /* If we're in the debugger and the DEBUG trap returns 2 while we're in
834          a function or sourced script, we force a `return'. */
835       if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
836         {
837           return_catch_value = trap_exit_value;
838           longjmp (return_catch, 1);
839         }
840 #endif
841     }
842   return trap_exit_value;
843 }
844
845 void
846 run_error_trap ()
847 {
848   if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
849     _run_trap_internal (ERROR_TRAP, "error trap");
850 }
851
852 void
853 run_return_trap ()
854 {
855   int old_exit_value;
856
857 #if 0
858   if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
859     return;
860 #endif
861
862   if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
863     {
864       old_exit_value = last_command_exit_value;
865       _run_trap_internal (RETURN_TRAP, "return trap");
866       last_command_exit_value = old_exit_value;
867     }
868 }
869
870 /* Run a trap set on SIGINT.  This is called from throw_to_top_level (), and
871    declared here to localize the trap functions. */
872 void
873 run_interrupt_trap ()
874 {
875   _run_trap_internal (SIGINT, "interrupt trap");
876 }
877
878 #ifdef INCLUDE_UNUSED
879 /* Free all the allocated strings in the list of traps and reset the trap
880    values to the default. */
881 void
882 free_trap_strings ()
883 {
884   register int i;
885
886   for (i = 0; i < BASH_NSIG; i++)
887     {
888       free_trap_command (i);
889       trap_list[i] = (char *)DEFAULT_SIG;
890       sigmodes[i] &= ~SIG_TRAPPED;
891     }
892   trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
893 }
894 #endif
895
896 /* Reset the handler for SIG to the original value. */
897 static void
898 reset_signal (sig)
899      int sig;
900 {
901   set_signal_handler (sig, original_signals[sig]);
902   sigmodes[sig] &= ~SIG_TRAPPED;
903 }
904
905 /* Set the handler signal SIG to the original and free any trap
906    command associated with it. */
907 static void
908 restore_signal (sig)
909      int sig;
910 {
911   set_signal_handler (sig, original_signals[sig]);
912   change_signal (sig, (char *)DEFAULT_SIG);
913   sigmodes[sig] &= ~SIG_TRAPPED;
914 }
915
916 static void
917 reset_or_restore_signal_handlers (reset)
918      sh_resetsig_func_t *reset;
919 {
920   register int i;
921
922   /* Take care of the exit trap first */
923   if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
924     {
925       sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
926       if (reset != reset_signal)
927         {
928           free_trap_command (EXIT_TRAP);
929           trap_list[EXIT_TRAP] = (char *)NULL;
930         }
931     }
932
933   for (i = 1; i < NSIG; i++)
934     {
935       if (sigmodes[i] & SIG_TRAPPED)
936         {
937           if (trap_list[i] == (char *)IGNORE_SIG)
938             set_signal_handler (i, SIG_IGN);
939           else
940             (*reset) (i);
941         }
942       else if (sigmodes[i] & SIG_SPECIAL)
943         (*reset) (i);
944     }
945
946   /* Command substitution and other child processes don't inherit the
947      debug, error, or return traps.  If we're in the debugger, and the
948      `functrace' or `errtrace' options have been set, then let command
949      substitutions inherit them.  Let command substitution inherit the
950      RETURN trap if we're in the debugger and tracing functions. */
951   if (function_trace_mode == 0)
952     {
953       sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
954       sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
955     }
956   if (error_trace_mode == 0)
957     sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
958 }
959
960 /* Reset trapped signals to their original values, but don't free the
961    trap strings.  Called by the command substitution code. */
962 void
963 reset_signal_handlers ()
964 {
965   reset_or_restore_signal_handlers (reset_signal);
966 }
967
968 /* Reset all trapped signals to their original values.  Signals set to be
969    ignored with trap '' SIGNAL should be ignored, so we make sure that they
970    are.  Called by child processes after they are forked. */
971 void
972 restore_original_signals ()
973 {
974   reset_or_restore_signal_handlers (restore_signal);
975 }
976
977 /* If a trap handler exists for signal SIG, then call it; otherwise just
978    return failure. */
979 int
980 maybe_call_trap_handler (sig)
981      int sig;
982 {
983   /* Call the trap handler for SIG if the signal is trapped and not ignored. */
984   if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
985     {
986       switch (sig)
987         {
988         case SIGINT:
989           run_interrupt_trap ();
990           break;
991         case EXIT_TRAP:
992           run_exit_trap ();
993           break;
994         case DEBUG_TRAP:
995           run_debug_trap ();
996           break;
997         case ERROR_TRAP:
998           run_error_trap ();
999           break;
1000         default:
1001           trap_handler (sig);
1002           break;
1003         }
1004       return (1);
1005     }
1006   else
1007     return (0);
1008 }
1009
1010 int
1011 signal_is_trapped (sig)
1012      int sig;
1013 {
1014   return (sigmodes[sig] & SIG_TRAPPED);
1015 }
1016
1017 int
1018 signal_is_special (sig)
1019      int sig;
1020 {
1021   return (sigmodes[sig] & SIG_SPECIAL);
1022 }
1023
1024 int
1025 signal_is_ignored (sig)
1026      int sig;
1027 {
1028   return (sigmodes[sig] & SIG_IGNORED);
1029 }
1030
1031 void
1032 set_signal_ignored (sig)
1033      int sig;
1034 {
1035   sigmodes[sig] |= SIG_HARD_IGNORE;
1036   original_signals[sig] = SIG_IGN;
1037 }
1038
1039 int
1040 signal_in_progress (sig)
1041      int sig;
1042 {
1043   return (sigmodes[sig] & SIG_INPROGRESS);
1044 }