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