646d6822e6789a95509683b269bd3d02956c45ba
[platform/upstream/bash.git] / sig.c
1 /* sig.c - interface for shell signal handlers and signal initialization. */
2
3 /* Copyright (C) 1994 Free Software Foundation, Inc.
4
5    This file is part of GNU Bash, the Bourne Again SHell.
6
7    Bash is free software; you can redistribute it and/or modify it under
8    the terms of the GNU General Public License as published by the Free
9    Software Foundation; either version 2, or (at your option) any later
10    version.
11
12    Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13    WARRANTY; without even the implied warranty of MERCHANTABILITY or
14    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15    for more details.
16
17    You should have received a copy of the GNU General Public License along
18    with Bash; see the file COPYING.  If not, write to the Free Software
19    Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21 #include "config.h"
22
23 #include "bashtypes.h"
24
25 #if defined (HAVE_UNISTD_H)
26 #  ifdef _MINIX
27 #    include <sys/types.h>
28 #  endif
29 #  include <unistd.h>
30 #endif
31
32 #include <stdio.h>
33 #include <signal.h>
34
35 #include "shell.h"
36 #if defined (JOB_CONTROL)
37 #include "jobs.h"
38 #endif /* JOB_CONTROL */
39 #include "siglist.h"
40 #include "sig.h"
41 #include "trap.h"
42
43 #include "builtins/common.h"
44
45 #if defined (READLINE)
46 #  include "bashline.h"
47 #endif
48
49 #if defined (HISTORY)
50 #  include "bashhist.h"
51 #endif
52
53 extern int last_command_exit_value;
54 extern int return_catch_flag;
55 extern int loop_level, continuing, breaking;
56 extern int parse_and_execute_level, shell_initialized;
57 extern int startup_state;
58
59 /* Non-zero after SIGINT. */
60 int interrupt_state;
61
62 /* The environment at the top-level R-E loop.  We use this in
63    the case of error return. */
64 procenv_t top_level;
65
66 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
67 /* The signal masks that this shell runs with. */
68 sigset_t top_level_mask;
69 #endif /* JOB_CONTROL */
70
71 /* When non-zero, we throw_to_top_level (). */
72 int interrupt_immediately = 0;
73
74 static void initialize_shell_signals __P((void));
75
76 void
77 initialize_signals ()
78 {
79   initialize_shell_signals ();
80   initialize_job_signals ();
81 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
82   initialize_siglist ();
83 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
84 }
85
86 void
87 reinitialize_signals ()
88 {
89   initialize_shell_signals ();
90   initialize_job_signals ();
91 }
92
93 /* A structure describing a signal that terminates the shell if not
94    caught.  The orig_handler member is present so children can reset
95    these signals back to their original handlers. */
96 struct termsig {
97      int signum;
98      SigHandler *orig_handler;
99 };
100
101 #define NULL_HANDLER (SigHandler *)SIG_DFL
102
103 /* The list of signals that would terminate the shell if not caught.
104    We catch them, but just so that we can write the history file,
105    and so forth. */
106 static struct termsig terminating_signals[] = {
107 #ifdef SIGHUP
108 {  SIGHUP, NULL_HANDLER },
109 #endif
110
111 #ifdef SIGINT
112 {  SIGINT, NULL_HANDLER },
113 #endif
114
115 #ifdef SIGILL
116 {  SIGILL, NULL_HANDLER },
117 #endif
118
119 #ifdef SIGTRAP
120 {  SIGTRAP, NULL_HANDLER },
121 #endif
122
123 #ifdef SIGIOT
124 {  SIGIOT, NULL_HANDLER },
125 #endif
126
127 #ifdef SIGDANGER
128 {  SIGDANGER, NULL_HANDLER },
129 #endif
130
131 #ifdef SIGEMT
132 {  SIGEMT, NULL_HANDLER },
133 #endif
134
135 #ifdef SIGFPE
136 {  SIGFPE, NULL_HANDLER },
137 #endif
138
139 #ifdef SIGBUS
140 {  SIGBUS, NULL_HANDLER },
141 #endif
142
143 #ifdef SIGSEGV
144 {  SIGSEGV, NULL_HANDLER },
145 #endif
146
147 #ifdef SIGSYS
148 {  SIGSYS, NULL_HANDLER },
149 #endif
150
151 #ifdef SIGPIPE
152 {  SIGPIPE, NULL_HANDLER },
153 #endif
154
155 #ifdef SIGALRM
156 {  SIGALRM, NULL_HANDLER },
157 #endif
158
159 #ifdef SIGTERM
160 {  SIGTERM, NULL_HANDLER },
161 #endif
162
163 #ifdef SIGXCPU
164 {  SIGXCPU, NULL_HANDLER },
165 #endif
166
167 #ifdef SIGXFSZ
168 {  SIGXFSZ, NULL_HANDLER },
169 #endif
170
171 #ifdef SIGVTALRM
172 {  SIGVTALRM, NULL_HANDLER },
173 #endif
174
175 #if 0
176 #ifdef SIGPROF
177 {  SIGPROF, NULL_HANDLER },
178 #endif
179 #endif
180
181 #ifdef SIGLOST
182 {  SIGLOST, NULL_HANDLER },
183 #endif
184
185 #ifdef SIGUSR1
186 {  SIGUSR1, NULL_HANDLER },
187 #endif
188
189 #ifdef SIGUSR2
190 {  SIGUSR2, NULL_HANDLER },
191 #endif
192 };
193
194 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
195
196 #define XSIG(x) (terminating_signals[x].signum)
197 #define XHANDLER(x) (terminating_signals[x].orig_handler)
198
199 static int termsigs_initialized = 0;
200
201 /* Initialize signals that will terminate the shell to do some
202    unwind protection.  For non-interactive shells, we only call
203    this when a trap is defined for EXIT (0). */
204 void
205 initialize_terminating_signals ()
206 {
207   register int i;
208 #if defined (HAVE_POSIX_SIGNALS)
209   struct sigaction act, oact;
210 #endif
211
212   if (termsigs_initialized)
213     return;
214
215   /* The following code is to avoid an expensive call to
216      set_signal_handler () for each terminating_signals.  Fortunately,
217      this is possible in Posix.  Unfortunately, we have to call signal ()
218      on non-Posix systems for each signal in terminating_signals. */
219 #if defined (HAVE_POSIX_SIGNALS)
220   act.sa_handler = termination_unwind_protect;
221   act.sa_flags = 0;
222   sigemptyset (&act.sa_mask);
223   sigemptyset (&oact.sa_mask);
224   for (i = 0; i < TERMSIGS_LENGTH; i++)
225     sigaddset (&act.sa_mask, XSIG (i));
226   for (i = 0; i < TERMSIGS_LENGTH; i++)
227     {
228       sigaction (XSIG (i), &act, &oact);
229       XHANDLER(i) = oact.sa_handler;
230       /* Don't do anything with signals that are ignored at shell entry
231          if the shell is not interactive. */
232       if (!interactive_shell && XHANDLER (i) == SIG_IGN)
233         {
234           sigaction (XSIG (i), &oact, &act);
235           set_signal_ignored (XSIG (i));
236         }
237 #if defined (SIGPROF) && !defined (_MINIX)
238       if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
239         sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
240 #endif /* SIGPROF && !_MINIX */
241     }
242
243 #else /* !HAVE_POSIX_SIGNALS */
244
245   for (i = 0; i < TERMSIGS_LENGTH; i++)
246     {
247       XHANDLER(i) = signal (XSIG (i), termination_unwind_protect);
248       /* Don't do anything with signals that are ignored at shell entry
249          if the shell is not interactive. */
250       if (!interactive_shell && XHANDLER (i) == SIG_IGN)
251         {
252           signal (XSIG (i), SIG_IGN);
253           set_signal_ignored (XSIG (i));
254         }
255 #ifdef SIGPROF
256       if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
257         signal (XSIG (i), XHANDLER (i));
258 #endif
259     }
260
261 #endif /* !HAVE_POSIX_SIGNALS */
262
263   termsigs_initialized = 1;
264 }
265
266 static void
267 initialize_shell_signals ()
268 {
269   if (interactive)
270     initialize_terminating_signals ();
271
272 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
273   /* All shells use the signal mask they inherit, and pass it along
274      to child processes.  Children will never block SIGCHLD, though. */
275   sigemptyset (&top_level_mask);
276   sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
277 #  if defined (SIGCHLD)
278   sigdelset (&top_level_mask, SIGCHLD);
279 #  endif
280 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
281
282   /* And, some signals that are specifically ignored by the shell. */
283   set_signal_handler (SIGQUIT, SIG_IGN);
284
285   if (interactive)
286     {
287       set_signal_handler (SIGINT, sigint_sighandler);
288       set_signal_handler (SIGTERM, SIG_IGN);
289     }
290 }
291
292 void
293 reset_terminating_signals ()
294 {
295   register int i;
296 #if defined (HAVE_POSIX_SIGNALS)
297   struct sigaction act;
298 #endif
299
300   if (termsigs_initialized == 0)
301     return;
302
303 #if defined (HAVE_POSIX_SIGNALS)
304   act.sa_flags = 0;
305   sigemptyset (&act.sa_mask);
306   for (i = 0; i < TERMSIGS_LENGTH; i++)
307     {
308       /* Skip a signal if it's trapped or handled specially, because the
309          trap code will restore the correct value. */
310       if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
311         continue;
312
313       act.sa_handler = XHANDLER (i);
314       sigaction (XSIG (i), &act, (struct sigaction *) NULL);
315     }
316 #else /* !HAVE_POSIX_SIGNALS */
317   for (i = 0; i < TERMSIGS_LENGTH; i++)
318     {
319       if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
320         continue;
321
322       signal (XSIG (i), XHANDLER (i));
323     }
324 #endif /* !HAVE_POSIX_SIGNALS */
325 }
326 #undef XSIG
327 #undef XHANDLER
328
329 /* What to do when we've been interrupted, and it is safe to handle it. */
330 void
331 throw_to_top_level ()
332 {
333   int print_newline = 0;
334
335   if (interrupt_state)
336     {
337       print_newline = 1;
338       DELINTERRUPT;
339     }
340
341   if (interrupt_state)
342     return;
343
344   last_command_exit_value |= 128;
345
346   /* Run any traps set on SIGINT. */
347   run_interrupt_trap ();
348
349   /* Cleanup string parser environment. */
350   while (parse_and_execute_level)
351     parse_and_execute_cleanup ();
352
353 #if defined (JOB_CONTROL)
354   give_terminal_to (shell_pgrp, 0);
355 #endif /* JOB_CONTROL */
356
357 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
358   /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
359   sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
360 #endif
361
362   reset_parser ();
363
364 #if defined (READLINE)
365   if (interactive)
366     bashline_reinitialize ();
367 #endif /* READLINE */
368
369 #if defined (PROCESS_SUBSTITUTION)
370   unlink_fifo_list ();
371 #endif /* PROCESS_SUBSTITUTION */
372
373   run_unwind_protects ();
374   loop_level = continuing = breaking = 0;
375   return_catch_flag = 0;
376
377   if (interactive && print_newline)
378     {
379       fflush (stdout);
380       fprintf (stderr, "\n");
381       fflush (stderr);
382     }
383
384   /* An interrupted `wait' command in a script does not exit the script. */
385   if (interactive || (interactive_shell && !shell_initialized) ||
386       (print_newline && signal_is_trapped (SIGINT)))
387     jump_to_top_level (DISCARD);
388   else
389     jump_to_top_level (EXITPROG);
390 }
391
392 /* This is just here to isolate the longjmp calls. */
393 void
394 jump_to_top_level (value)
395      int value;
396 {
397   longjmp (top_level, value);
398 }
399
400 sighandler
401 termination_unwind_protect (sig)
402      int sig;
403 {
404   if (sig == SIGINT && signal_is_trapped (SIGINT))
405     run_interrupt_trap ();
406
407 #if defined (HISTORY)
408   if (interactive_shell && sig != SIGABRT)
409     maybe_save_shell_history ();
410 #endif /* HISTORY */
411
412 #if defined (JOB_CONTROL)
413   if (interactive && sig == SIGHUP)
414     hangup_all_jobs ();
415   end_job_control ();
416 #endif /* JOB_CONTROL */
417
418 #if defined (PROCESS_SUBSTITUTION)
419   unlink_fifo_list ();
420 #endif /* PROCESS_SUBSTITUTION */
421
422   run_exit_trap ();
423   set_signal_handler (sig, SIG_DFL);
424   kill (getpid (), sig);
425
426   SIGRETURN (0);
427 }
428
429 /* What we really do when SIGINT occurs. */
430 sighandler
431 sigint_sighandler (sig)
432      int sig;
433 {
434 #if defined (MUST_REINSTALL_SIGHANDLERS)
435   signal (sig, sigint_sighandler);
436 #endif
437
438   /* interrupt_state needs to be set for the stack of interrupts to work
439      right.  Should it be set unconditionally? */
440   if (interrupt_state == 0)
441     ADDINTERRUPT;
442
443   if (interrupt_immediately)
444     {
445       interrupt_immediately = 0;
446       throw_to_top_level ();
447     }
448
449   SIGRETURN (0);
450 }
451
452 /* Signal functions used by the rest of the code. */
453 #if !defined (HAVE_POSIX_SIGNALS)
454
455 #if defined (JOB_CONTROL)
456 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
457 sigprocmask (operation, newset, oldset)
458      int operation, *newset, *oldset;
459 {
460   int old, new;
461
462   if (newset)
463     new = *newset;
464   else
465     new = 0;
466
467   switch (operation)
468     {
469     case SIG_BLOCK:
470       old = sigblock (new);
471       break;
472
473     case SIG_SETMASK:
474       sigsetmask (new);
475       break;
476
477     default:
478       internal_error ("Bad code in sig.c: sigprocmask");
479     }
480
481   if (oldset)
482     *oldset = old;
483 }
484 #endif /* JOB_CONTROL */
485
486 #else
487
488 #if !defined (SA_INTERRUPT)
489 #  define SA_INTERRUPT 0
490 #endif
491
492 #if !defined (SA_RESTART)
493 #  define SA_RESTART 0
494 #endif
495
496 SigHandler *
497 set_signal_handler (sig, handler)
498      int sig;
499      SigHandler *handler;
500 {
501   struct sigaction act, oact;
502
503   act.sa_handler = handler;
504   act.sa_flags = 0;
505 #if 0
506   if (sig == SIGALRM)
507     act.sa_flags |= SA_INTERRUPT;       /* XXX */
508   else
509     act.sa_flags |= SA_RESTART;         /* XXX */
510 #endif
511   sigemptyset (&act.sa_mask);
512   sigemptyset (&oact.sa_mask);
513   sigaction (sig, &act, &oact);
514   return (oact.sa_handler);
515 }
516 #endif /* HAVE_POSIX_SIGNALS */