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