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