Imported from ../bash-3.2.tar.gz.
[platform/upstream/bash.git] / sig.c
1 /* sig.c - interface for shell signal handlers and signal initialization. */
2
3 /* Copyright (C) 1994-2006 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 "bashintl.h"
36
37 #include "shell.h"
38 #if defined (JOB_CONTROL)
39 #include "jobs.h"
40 #endif /* JOB_CONTROL */
41 #include "siglist.h"
42 #include "sig.h"
43 #include "trap.h"
44
45 #include "builtins/common.h"
46
47 #if defined (READLINE)
48 #  include "bashline.h"
49 #endif
50
51 #if defined (HISTORY)
52 #  include "bashhist.h"
53 #endif
54
55 extern int last_command_exit_value;
56 extern int last_command_exit_signal;
57 extern int return_catch_flag;
58 extern int loop_level, continuing, breaking;
59 extern int parse_and_execute_level, shell_initialized;
60
61 /* Non-zero after SIGINT. */
62 volatile int interrupt_state = 0;
63
64 /* Non-zero after SIGWINCH */
65 volatile int sigwinch_received = 0;
66
67 /* Set to the value of any terminating signal received. */
68 volatile int terminating_signal = 0;
69
70 /* The environment at the top-level R-E loop.  We use this in
71    the case of error return. */
72 procenv_t top_level;
73
74 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
75 /* The signal masks that this shell runs with. */
76 sigset_t top_level_mask;
77 #endif /* JOB_CONTROL */
78
79 /* When non-zero, we throw_to_top_level (). */
80 int interrupt_immediately = 0;
81
82 /* When non-zero, we call the terminating signal handler immediately. */
83 int terminate_immediately = 0;
84
85 #if defined (SIGWINCH)
86 static SigHandler *old_winch = (SigHandler *)SIG_DFL;
87 #endif
88
89 static void initialize_shell_signals __P((void));
90
91 void
92 initialize_signals (reinit)
93      int reinit;
94 {
95   initialize_shell_signals ();
96   initialize_job_signals ();
97 #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
98   if (reinit == 0)
99     initialize_siglist ();
100 #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
101 }
102
103 /* A structure describing a signal that terminates the shell if not
104    caught.  The orig_handler member is present so children can reset
105    these signals back to their original handlers. */
106 struct termsig {
107      int signum;
108      SigHandler *orig_handler;
109      int orig_flags;
110 };
111
112 #define NULL_HANDLER (SigHandler *)SIG_DFL
113
114 /* The list of signals that would terminate the shell if not caught.
115    We catch them, but just so that we can write the history file,
116    and so forth. */
117 static struct termsig terminating_signals[] = {
118 #ifdef SIGHUP
119 {  SIGHUP, NULL_HANDLER, 0 },
120 #endif
121
122 #ifdef SIGINT
123 {  SIGINT, NULL_HANDLER, 0 },
124 #endif
125
126 #ifdef SIGILL
127 {  SIGILL, NULL_HANDLER, 0 },
128 #endif
129
130 #ifdef SIGTRAP
131 {  SIGTRAP, NULL_HANDLER, 0 },
132 #endif
133
134 #ifdef SIGIOT
135 {  SIGIOT, NULL_HANDLER, 0 },
136 #endif
137
138 #ifdef SIGDANGER
139 {  SIGDANGER, NULL_HANDLER, 0 },
140 #endif
141
142 #ifdef SIGEMT
143 {  SIGEMT, NULL_HANDLER, 0 },
144 #endif
145
146 #ifdef SIGFPE
147 {  SIGFPE, NULL_HANDLER, 0 },
148 #endif
149
150 #ifdef SIGBUS
151 {  SIGBUS, NULL_HANDLER, 0 },
152 #endif
153
154 #ifdef SIGSEGV
155 {  SIGSEGV, NULL_HANDLER, 0 },
156 #endif
157
158 #ifdef SIGSYS
159 {  SIGSYS, NULL_HANDLER, 0 },
160 #endif
161
162 #ifdef SIGPIPE
163 {  SIGPIPE, NULL_HANDLER, 0 },
164 #endif
165
166 #ifdef SIGALRM
167 {  SIGALRM, NULL_HANDLER, 0 },
168 #endif
169
170 #ifdef SIGTERM
171 {  SIGTERM, NULL_HANDLER, 0 },
172 #endif
173
174 #ifdef SIGXCPU
175 {  SIGXCPU, NULL_HANDLER, 0 },
176 #endif
177
178 #ifdef SIGXFSZ
179 {  SIGXFSZ, NULL_HANDLER, 0 },
180 #endif
181
182 #ifdef SIGVTALRM
183 {  SIGVTALRM, NULL_HANDLER, 0 },
184 #endif
185
186 #if 0
187 #ifdef SIGPROF
188 {  SIGPROF, NULL_HANDLER, 0 },
189 #endif
190 #endif
191
192 #ifdef SIGLOST
193 {  SIGLOST, NULL_HANDLER, 0 },
194 #endif
195
196 #ifdef SIGUSR1
197 {  SIGUSR1, NULL_HANDLER, 0 },
198 #endif
199
200 #ifdef SIGUSR2
201 {  SIGUSR2, NULL_HANDLER, 0 },
202 #endif
203 };
204
205 #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
206
207 #define XSIG(x) (terminating_signals[x].signum)
208 #define XHANDLER(x) (terminating_signals[x].orig_handler)
209 #define XSAFLAGS(x) (terminating_signals[x].orig_flags)
210
211 static int termsigs_initialized = 0;
212
213 /* Initialize signals that will terminate the shell to do some
214    unwind protection.  For non-interactive shells, we only call
215    this when a trap is defined for EXIT (0). */
216 void
217 initialize_terminating_signals ()
218 {
219   register int i;
220 #if defined (HAVE_POSIX_SIGNALS)
221   struct sigaction act, oact;
222 #endif
223
224   if (termsigs_initialized)
225     return;
226
227   /* The following code is to avoid an expensive call to
228      set_signal_handler () for each terminating_signals.  Fortunately,
229      this is possible in Posix.  Unfortunately, we have to call signal ()
230      on non-Posix systems for each signal in terminating_signals. */
231 #if defined (HAVE_POSIX_SIGNALS)
232   act.sa_handler = termsig_sighandler;
233   act.sa_flags = 0;
234   sigemptyset (&act.sa_mask);
235   sigemptyset (&oact.sa_mask);
236   for (i = 0; i < TERMSIGS_LENGTH; i++)
237     sigaddset (&act.sa_mask, XSIG (i));
238   for (i = 0; i < TERMSIGS_LENGTH; i++)
239     {
240       /* If we've already trapped it, don't do anything. */
241       if (signal_is_trapped (XSIG (i)))
242         continue;
243
244       sigaction (XSIG (i), &act, &oact);
245       XHANDLER(i) = oact.sa_handler;
246       XSAFLAGS(i) = oact.sa_flags;
247       /* Don't do anything with signals that are ignored at shell entry
248          if the shell is not interactive. */
249       if (!interactive_shell && XHANDLER (i) == SIG_IGN)
250         {
251           sigaction (XSIG (i), &oact, &act);
252           set_signal_ignored (XSIG (i));
253         }
254 #if defined (SIGPROF) && !defined (_MINIX)
255       if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
256         sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
257 #endif /* SIGPROF && !_MINIX */
258     }
259
260 #else /* !HAVE_POSIX_SIGNALS */
261
262   for (i = 0; i < TERMSIGS_LENGTH; i++)
263     {
264       /* If we've already trapped it, don't do anything. */
265       if (signal_is_trapped (XSIG (i)))
266         continue;
267
268       XHANDLER(i) = signal (XSIG (i), termsig_sighandler);
269       XSAFLAGS(i) = 0;
270       /* Don't do anything with signals that are ignored at shell entry
271          if the shell is not interactive. */
272       if (!interactive_shell && XHANDLER (i) == SIG_IGN)
273         {
274           signal (XSIG (i), SIG_IGN);
275           set_signal_ignored (XSIG (i));
276         }
277 #ifdef SIGPROF
278       if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
279         signal (XSIG (i), XHANDLER (i));
280 #endif
281     }
282
283 #endif /* !HAVE_POSIX_SIGNALS */
284
285   termsigs_initialized = 1;
286 }
287
288 static void
289 initialize_shell_signals ()
290 {
291   if (interactive)
292     initialize_terminating_signals ();
293
294 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
295   /* All shells use the signal mask they inherit, and pass it along
296      to child processes.  Children will never block SIGCHLD, though. */
297   sigemptyset (&top_level_mask);
298   sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
299 #  if defined (SIGCHLD)
300   sigdelset (&top_level_mask, SIGCHLD);
301 #  endif
302 #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
303
304   /* And, some signals that are specifically ignored by the shell. */
305   set_signal_handler (SIGQUIT, SIG_IGN);
306
307   if (interactive)
308     {
309       set_signal_handler (SIGINT, sigint_sighandler);
310       set_signal_handler (SIGTERM, SIG_IGN);
311       set_sigwinch_handler ();
312     }
313 }
314
315 void
316 reset_terminating_signals ()
317 {
318   register int i;
319 #if defined (HAVE_POSIX_SIGNALS)
320   struct sigaction act;
321 #endif
322
323   if (termsigs_initialized == 0)
324     return;
325
326 #if defined (HAVE_POSIX_SIGNALS)
327   act.sa_flags = 0;
328   sigemptyset (&act.sa_mask);
329   for (i = 0; i < TERMSIGS_LENGTH; i++)
330     {
331       /* Skip a signal if it's trapped or handled specially, because the
332          trap code will restore the correct value. */
333       if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
334         continue;
335
336       act.sa_handler = XHANDLER (i);
337       act.sa_flags = XSAFLAGS (i);
338       sigaction (XSIG (i), &act, (struct sigaction *) NULL);
339     }
340 #else /* !HAVE_POSIX_SIGNALS */
341   for (i = 0; i < TERMSIGS_LENGTH; i++)
342     {
343       if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
344         continue;
345
346       signal (XSIG (i), XHANDLER (i));
347     }
348 #endif /* !HAVE_POSIX_SIGNALS */
349 }
350 #undef XSIG
351 #undef XHANDLER
352
353 /* What to do when we've been interrupted, and it is safe to handle it. */
354 void
355 throw_to_top_level ()
356 {
357   int print_newline = 0;
358
359   if (interrupt_state)
360     {
361       print_newline = 1;
362       DELINTERRUPT;
363     }
364
365   if (interrupt_state)
366     return;
367
368   last_command_exit_signal = (last_command_exit_value > 128) ?
369                                 (last_command_exit_value - 128) : 0;
370   last_command_exit_value |= 128;
371
372   /* Run any traps set on SIGINT. */
373   run_interrupt_trap ();
374
375   /* Cleanup string parser environment. */
376   while (parse_and_execute_level)
377     parse_and_execute_cleanup ();
378
379 #if defined (JOB_CONTROL)
380   give_terminal_to (shell_pgrp, 0);
381 #endif /* JOB_CONTROL */
382
383 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
384   /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
385   sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
386 #endif
387
388   reset_parser ();
389
390 #if defined (READLINE)
391   if (interactive)
392     bashline_reinitialize ();
393 #endif /* READLINE */
394
395 #if defined (PROCESS_SUBSTITUTION)
396   unlink_fifo_list ();
397 #endif /* PROCESS_SUBSTITUTION */
398
399   run_unwind_protects ();
400   loop_level = continuing = breaking = 0;
401   return_catch_flag = 0;
402
403   if (interactive && print_newline)
404     {
405       fflush (stdout);
406       fprintf (stderr, "\n");
407       fflush (stderr);
408     }
409
410   /* An interrupted `wait' command in a script does not exit the script. */
411   if (interactive || (interactive_shell && !shell_initialized) ||
412       (print_newline && signal_is_trapped (SIGINT)))
413     jump_to_top_level (DISCARD);
414   else
415     jump_to_top_level (EXITPROG);
416 }
417
418 /* This is just here to isolate the longjmp calls. */
419 void
420 jump_to_top_level (value)
421      int value;
422 {
423   longjmp (top_level, value);
424 }
425
426 sighandler
427 termsig_sighandler (sig)
428      int sig;
429 {
430   terminating_signal = sig;
431
432   if (terminate_immediately)
433     {
434       terminate_immediately = 0;
435       termsig_handler (sig);
436     }
437
438   SIGRETURN (0);
439 }
440
441 void
442 termsig_handler (sig)
443      int sig;
444 {
445   static int handling_termsig = 0;
446
447   /* Simple semaphore to keep this function from being executed multiple
448      times.  Since we no longer are running as a signal handler, we don't
449      block multiple occurrences of the terminating signals while running. */
450   if (handling_termsig)
451     return;
452   handling_termsig = 1;
453   terminating_signal = 0;       /* keep macro from re-testing true. */
454
455   /* I don't believe this condition ever tests true. */
456   if (sig == SIGINT && signal_is_trapped (SIGINT))
457     run_interrupt_trap ();
458
459 #if defined (HISTORY)
460   if (interactive_shell && sig != SIGABRT)
461     maybe_save_shell_history ();
462 #endif /* HISTORY */
463
464 #if defined (JOB_CONTROL)
465   if (interactive && sig == SIGHUP)
466     hangup_all_jobs ();
467   end_job_control ();
468 #endif /* JOB_CONTROL */
469
470 #if defined (PROCESS_SUBSTITUTION)
471   unlink_fifo_list ();
472 #endif /* PROCESS_SUBSTITUTION */
473
474   run_exit_trap ();
475   set_signal_handler (sig, SIG_DFL);
476   kill (getpid (), sig);
477 }
478
479 /* What we really do when SIGINT occurs. */
480 sighandler
481 sigint_sighandler (sig)
482      int sig;
483 {
484 #if defined (MUST_REINSTALL_SIGHANDLERS)
485   signal (sig, sigint_sighandler);
486 #endif
487
488   /* interrupt_state needs to be set for the stack of interrupts to work
489      right.  Should it be set unconditionally? */
490   if (interrupt_state == 0)
491     ADDINTERRUPT;
492
493   if (interrupt_immediately)
494     {
495       interrupt_immediately = 0;
496       throw_to_top_level ();
497     }
498
499   SIGRETURN (0);
500 }
501
502 #if defined (SIGWINCH)
503 sighandler
504 sigwinch_sighandler (sig)
505      int sig;
506 {
507 #if defined (MUST_REINSTALL_SIGHANDLERS)
508   set_signal_handler (SIGWINCH, sigwinch_sighandler);
509 #endif /* MUST_REINSTALL_SIGHANDLERS */
510   sigwinch_received = 1;
511   SIGRETURN (0);
512 }
513 #endif /* SIGWINCH */
514
515 void
516 set_sigwinch_handler ()
517 {
518 #if defined (SIGWINCH)
519  old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
520 #endif
521 }
522
523 void
524 unset_sigwinch_handler ()
525 {
526 #if defined (SIGWINCH)
527   set_signal_handler (SIGWINCH, old_winch);
528 #endif
529 }
530
531 /* Signal functions used by the rest of the code. */
532 #if !defined (HAVE_POSIX_SIGNALS)
533
534 #if defined (JOB_CONTROL)
535 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
536 sigprocmask (operation, newset, oldset)
537      int operation, *newset, *oldset;
538 {
539   int old, new;
540
541   if (newset)
542     new = *newset;
543   else
544     new = 0;
545
546   switch (operation)
547     {
548     case SIG_BLOCK:
549       old = sigblock (new);
550       break;
551
552     case SIG_SETMASK:
553       sigsetmask (new);
554       break;
555
556     default:
557       internal_error (_("sigprocmask: %d: invalid operation"), operation);
558     }
559
560   if (oldset)
561     *oldset = old;
562 }
563 #endif /* JOB_CONTROL */
564
565 #else
566
567 #if !defined (SA_INTERRUPT)
568 #  define SA_INTERRUPT 0
569 #endif
570
571 #if !defined (SA_RESTART)
572 #  define SA_RESTART 0
573 #endif
574
575 SigHandler *
576 set_signal_handler (sig, handler)
577      int sig;
578      SigHandler *handler;
579 {
580   struct sigaction act, oact;
581
582   act.sa_handler = handler;
583   act.sa_flags = 0;
584 #if 0
585   if (sig == SIGALRM)
586     act.sa_flags |= SA_INTERRUPT;       /* XXX */
587   else
588     act.sa_flags |= SA_RESTART;         /* XXX */
589 #endif
590   sigemptyset (&act.sa_mask);
591   sigemptyset (&oact.sa_mask);
592   sigaction (sig, &act, &oact);
593   return (oact.sa_handler);
594 }
595 #endif /* HAVE_POSIX_SIGNALS */