]> git.ipfire.org Git - thirdparty/bash.git/blob - sig.c
Imported from ../bash-3.2.48.tar.gz.
[thirdparty/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 /* Run some of the cleanups that should be performed when we run
354 jump_to_top_level from a builtin command context. XXX - might want to
355 also call reset_parser here. */
356 void
357 top_level_cleanup ()
358 {
359 /* Clean up string parser environment. */
360 while (parse_and_execute_level)
361 parse_and_execute_cleanup ();
362
363 #if defined (PROCESS_SUBSTITUTION)
364 unlink_fifo_list ();
365 #endif /* PROCESS_SUBSTITUTION */
366
367 run_unwind_protects ();
368 loop_level = continuing = breaking = 0;
369 return_catch_flag = 0;
370 }
371
372 /* What to do when we've been interrupted, and it is safe to handle it. */
373 void
374 throw_to_top_level ()
375 {
376 int print_newline = 0;
377
378 if (interrupt_state)
379 {
380 print_newline = 1;
381 DELINTERRUPT;
382 }
383
384 if (interrupt_state)
385 return;
386
387 last_command_exit_signal = (last_command_exit_value > 128) ?
388 (last_command_exit_value - 128) : 0;
389 last_command_exit_value |= 128;
390
391 /* Run any traps set on SIGINT. */
392 run_interrupt_trap ();
393
394 /* Cleanup string parser environment. */
395 while (parse_and_execute_level)
396 parse_and_execute_cleanup ();
397
398 #if defined (JOB_CONTROL)
399 give_terminal_to (shell_pgrp, 0);
400 #endif /* JOB_CONTROL */
401
402 #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
403 /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
404 sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
405 #endif
406
407 reset_parser ();
408
409 #if defined (READLINE)
410 if (interactive)
411 bashline_reinitialize ();
412 #endif /* READLINE */
413
414 #if defined (PROCESS_SUBSTITUTION)
415 unlink_fifo_list ();
416 #endif /* PROCESS_SUBSTITUTION */
417
418 run_unwind_protects ();
419 loop_level = continuing = breaking = 0;
420 return_catch_flag = 0;
421
422 if (interactive && print_newline)
423 {
424 fflush (stdout);
425 fprintf (stderr, "\n");
426 fflush (stderr);
427 }
428
429 /* An interrupted `wait' command in a script does not exit the script. */
430 if (interactive || (interactive_shell && !shell_initialized) ||
431 (print_newline && signal_is_trapped (SIGINT)))
432 jump_to_top_level (DISCARD);
433 else
434 jump_to_top_level (EXITPROG);
435 }
436
437 /* This is just here to isolate the longjmp calls. */
438 void
439 jump_to_top_level (value)
440 int value;
441 {
442 longjmp (top_level, value);
443 }
444
445 sighandler
446 termsig_sighandler (sig)
447 int sig;
448 {
449 terminating_signal = sig;
450
451 if (terminate_immediately)
452 {
453 terminate_immediately = 0;
454 termsig_handler (sig);
455 }
456
457 SIGRETURN (0);
458 }
459
460 void
461 termsig_handler (sig)
462 int sig;
463 {
464 static int handling_termsig = 0;
465
466 /* Simple semaphore to keep this function from being executed multiple
467 times. Since we no longer are running as a signal handler, we don't
468 block multiple occurrences of the terminating signals while running. */
469 if (handling_termsig)
470 return;
471 handling_termsig = 1;
472 terminating_signal = 0; /* keep macro from re-testing true. */
473
474 /* I don't believe this condition ever tests true. */
475 if (sig == SIGINT && signal_is_trapped (SIGINT))
476 run_interrupt_trap ();
477
478 #if defined (HISTORY)
479 if (interactive_shell && sig != SIGABRT)
480 maybe_save_shell_history ();
481 #endif /* HISTORY */
482
483 #if defined (JOB_CONTROL)
484 if (interactive && sig == SIGHUP)
485 hangup_all_jobs ();
486 end_job_control ();
487 #endif /* JOB_CONTROL */
488
489 #if defined (PROCESS_SUBSTITUTION)
490 unlink_fifo_list ();
491 #endif /* PROCESS_SUBSTITUTION */
492
493 run_exit_trap ();
494 set_signal_handler (sig, SIG_DFL);
495 kill (getpid (), sig);
496 }
497
498 /* What we really do when SIGINT occurs. */
499 sighandler
500 sigint_sighandler (sig)
501 int sig;
502 {
503 #if defined (MUST_REINSTALL_SIGHANDLERS)
504 signal (sig, sigint_sighandler);
505 #endif
506
507 /* interrupt_state needs to be set for the stack of interrupts to work
508 right. Should it be set unconditionally? */
509 if (interrupt_state == 0)
510 ADDINTERRUPT;
511
512 if (interrupt_immediately)
513 {
514 interrupt_immediately = 0;
515 throw_to_top_level ();
516 }
517
518 SIGRETURN (0);
519 }
520
521 #if defined (SIGWINCH)
522 sighandler
523 sigwinch_sighandler (sig)
524 int sig;
525 {
526 #if defined (MUST_REINSTALL_SIGHANDLERS)
527 set_signal_handler (SIGWINCH, sigwinch_sighandler);
528 #endif /* MUST_REINSTALL_SIGHANDLERS */
529 sigwinch_received = 1;
530 SIGRETURN (0);
531 }
532 #endif /* SIGWINCH */
533
534 void
535 set_sigwinch_handler ()
536 {
537 #if defined (SIGWINCH)
538 old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
539 #endif
540 }
541
542 void
543 unset_sigwinch_handler ()
544 {
545 #if defined (SIGWINCH)
546 set_signal_handler (SIGWINCH, old_winch);
547 #endif
548 }
549
550 /* Signal functions used by the rest of the code. */
551 #if !defined (HAVE_POSIX_SIGNALS)
552
553 #if defined (JOB_CONTROL)
554 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
555 sigprocmask (operation, newset, oldset)
556 int operation, *newset, *oldset;
557 {
558 int old, new;
559
560 if (newset)
561 new = *newset;
562 else
563 new = 0;
564
565 switch (operation)
566 {
567 case SIG_BLOCK:
568 old = sigblock (new);
569 break;
570
571 case SIG_SETMASK:
572 sigsetmask (new);
573 break;
574
575 default:
576 internal_error (_("sigprocmask: %d: invalid operation"), operation);
577 }
578
579 if (oldset)
580 *oldset = old;
581 }
582 #endif /* JOB_CONTROL */
583
584 #else
585
586 #if !defined (SA_INTERRUPT)
587 # define SA_INTERRUPT 0
588 #endif
589
590 #if !defined (SA_RESTART)
591 # define SA_RESTART 0
592 #endif
593
594 SigHandler *
595 set_signal_handler (sig, handler)
596 int sig;
597 SigHandler *handler;
598 {
599 struct sigaction act, oact;
600
601 act.sa_handler = handler;
602 act.sa_flags = 0;
603 #if 0
604 if (sig == SIGALRM)
605 act.sa_flags |= SA_INTERRUPT; /* XXX */
606 else
607 act.sa_flags |= SA_RESTART; /* XXX */
608 #endif
609 sigemptyset (&act.sa_mask);
610 sigemptyset (&oact.sa_mask);
611 sigaction (sig, &act, &oact);
612 return (oact.sa_handler);
613 }
614 #endif /* HAVE_POSIX_SIGNALS */