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