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