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