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