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