| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* sig.c - interface for shell signal handlers and signal initialization. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Copyright (C) 1994 Free Software Foundation, Inc.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    This file is part of GNU Bash, the Bourne Again SHell. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Bash is free software; you can redistribute it and/or modify it under | 
					
						
							|  |  |  |    the terms of the GNU General Public License as published by the Free | 
					
						
							|  |  |  |    Software Foundation; either version 2, or (at your option) any later | 
					
						
							|  |  |  |    version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    Bash is distributed in the hope that it will be useful, but WITHOUT ANY | 
					
						
							|  |  |  |    WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
					
						
							|  |  |  |    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
					
						
							|  |  |  |    for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    You should have received a copy of the GNU General Public License along | 
					
						
							|  |  |  |    with Bash; see the file COPYING.  If not, write to the Free Software | 
					
						
							|  |  |  |    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "bashtypes.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_UNISTD_H)
 | 
					
						
							|  |  |  | #  include <unistd.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "shell.h"
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL)
 | 
					
						
							|  |  |  | #include "jobs.h"
 | 
					
						
							|  |  |  | #endif /* JOB_CONTROL */
 | 
					
						
							|  |  |  | #include "siglist.h"
 | 
					
						
							|  |  |  | #include "sig.h"
 | 
					
						
							|  |  |  | #include "trap.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "builtins/common.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  | #  include "bashline.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  | #  include "bashhist.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern int last_command_exit_value; | 
					
						
							|  |  |  | extern int return_catch_flag; | 
					
						
							|  |  |  | extern int loop_level, continuing, breaking; | 
					
						
							|  |  |  | extern int parse_and_execute_level, shell_initialized; | 
					
						
							|  |  |  | extern int interactive, interactive_shell, login_shell, startup_state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Non-zero after SIGINT. */ | 
					
						
							|  |  |  | int interrupt_state; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The environment at the top-level R-E loop.  We use this in
 | 
					
						
							|  |  |  |    the case of error return. */ | 
					
						
							|  |  |  | procenv_t top_level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
 | 
					
						
							|  |  |  | /* The signal masks that this shell runs with. */ | 
					
						
							|  |  |  | sigset_t top_level_mask; | 
					
						
							|  |  |  | #endif /* JOB_CONTROL */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* When non-zero, we throw_to_top_level (). */ | 
					
						
							|  |  |  | int interrupt_immediately = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | static void initialize_shell_signals (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | initialize_signals () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   initialize_shell_signals (); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   initialize_job_signals (); | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  | #if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   initialize_siglist (); | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  | #endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | reinitialize_signals () | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   initialize_shell_signals (1); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   initialize_job_signals (); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* A structure describing a signal that terminates the shell if not
 | 
					
						
							|  |  |  |    caught.  The orig_handler member is present so children can reset | 
					
						
							|  |  |  |    these signals back to their original handlers. */ | 
					
						
							|  |  |  | struct termsig { | 
					
						
							|  |  |  |      int signum; | 
					
						
							|  |  |  |      SigHandler *orig_handler; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define NULL_HANDLER (SigHandler *)SIG_DFL
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The list of signals that would terminate the shell if not caught.
 | 
					
						
							|  |  |  |    We catch them, but just so that we can write the history file, | 
					
						
							|  |  |  |    and so forth. */ | 
					
						
							|  |  |  | static struct termsig terminating_signals[] = { | 
					
						
							|  |  |  | #ifdef SIGHUP
 | 
					
						
							|  |  |  |   SIGHUP, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGINT
 | 
					
						
							|  |  |  |   SIGINT, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGILL
 | 
					
						
							|  |  |  |   SIGILL, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGTRAP
 | 
					
						
							|  |  |  |   SIGTRAP, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGIOT
 | 
					
						
							|  |  |  |   SIGIOT, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGDANGER
 | 
					
						
							|  |  |  |   SIGDANGER, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGEMT
 | 
					
						
							|  |  |  |   SIGEMT, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGFPE
 | 
					
						
							|  |  |  |   SIGFPE, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGBUS
 | 
					
						
							|  |  |  |   SIGBUS, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGSEGV
 | 
					
						
							|  |  |  |   SIGSEGV, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGSYS
 | 
					
						
							|  |  |  |   SIGSYS, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGPIPE
 | 
					
						
							|  |  |  |   SIGPIPE, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGALRM
 | 
					
						
							|  |  |  |   SIGALRM, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGTERM
 | 
					
						
							|  |  |  |   SIGTERM, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGXCPU
 | 
					
						
							|  |  |  |   SIGXCPU, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGXFSZ
 | 
					
						
							|  |  |  |   SIGXFSZ, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGVTALRM
 | 
					
						
							|  |  |  |   SIGVTALRM, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGPROF
 | 
					
						
							|  |  |  |   SIGPROF, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGLOST
 | 
					
						
							|  |  |  |   SIGLOST, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGUSR1
 | 
					
						
							|  |  |  |   SIGUSR1, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef SIGUSR2
 | 
					
						
							|  |  |  |   SIGUSR2, NULL_HANDLER, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define XSIG(x) (terminating_signals[x].signum)
 | 
					
						
							|  |  |  | #define XHANDLER(x) (terminating_signals[x].orig_handler)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | static int termsigs_initialized = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | /* Initialize signals that will terminate the shell to do some
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |    unwind protection.  For non-interactive shells, we only call | 
					
						
							|  |  |  |    this when a trap is defined for EXIT (0). */ | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | initialize_terminating_signals () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #if defined (HAVE_POSIX_SIGNALS)
 | 
					
						
							|  |  |  |   struct sigaction act, oact; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (termsigs_initialized) | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* The following code is to avoid an expensive call to
 | 
					
						
							|  |  |  |      set_signal_handler () for each terminating_signals.  Fortunately, | 
					
						
							|  |  |  |      this is possible in Posix.  Unfortunately, we have to call signal () | 
					
						
							|  |  |  |      on non-Posix systems for each signal in terminating_signals. */ | 
					
						
							|  |  |  | #if defined (HAVE_POSIX_SIGNALS)
 | 
					
						
							|  |  |  |   act.sa_handler = termination_unwind_protect; | 
					
						
							|  |  |  |   act.sa_flags = 0; | 
					
						
							|  |  |  |   sigemptyset (&act.sa_mask); | 
					
						
							|  |  |  |   sigemptyset (&oact.sa_mask); | 
					
						
							|  |  |  |   for (i = 0; i < TERMSIGS_LENGTH; i++) | 
					
						
							|  |  |  |     sigaddset (&act.sa_mask, XSIG (i)); | 
					
						
							|  |  |  |   for (i = 0; i < TERMSIGS_LENGTH; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       sigaction (XSIG (i), &act, &oact); | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       XHANDLER(i) = oact.sa_handler; | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       /* Don't do anything with signals that are ignored at shell entry
 | 
					
						
							|  |  |  | 	 if the shell is not interactive. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (!interactive_shell && XHANDLER (i) == SIG_IGN) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |         { | 
					
						
							|  |  |  | 	  sigaction (XSIG (i), &oact, &act); | 
					
						
							|  |  |  | 	  set_signal_ignored (XSIG (i)); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  | #if defined (SIGPROF)
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN) | 
					
						
							|  |  |  |         sigaction (XSIG (i), &oact, (struct sigaction *)NULL); | 
					
						
							| 
									
										
										
										
											1997-09-22 20:22:27 +00:00
										 |  |  | #endif /* SIGPROF */
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else /* !HAVE_POSIX_SIGNALS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (i = 0; i < TERMSIGS_LENGTH; i++) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       XHANDLER(i) = signal (XSIG (i), termination_unwind_protect); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |       /* Don't do anything with signals that are ignored at shell entry
 | 
					
						
							|  |  |  | 	 if the shell is not interactive. */ | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (!interactive_shell && XHANDLER (i) == SIG_IGN) | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  |           signal (XSIG (i), SIG_IGN); | 
					
						
							|  |  |  |           set_signal_ignored (XSIG (i)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |       if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN) | 
					
						
							|  |  |  |         signal (XSIG (i), XHANDLER (i)); | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* !HAVE_POSIX_SIGNALS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   termsigs_initialized = 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | initialize_shell_signals () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (interactive) | 
					
						
							|  |  |  |     initialize_terminating_signals (); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
 | 
					
						
							|  |  |  |   /* All shells use the signal mask they inherit, and pass it along
 | 
					
						
							|  |  |  |      to child processes.  Children will never block SIGCHLD, though. */ | 
					
						
							|  |  |  |   sigemptyset (&top_level_mask); | 
					
						
							|  |  |  |   sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask); | 
					
						
							|  |  |  |   sigdelset (&top_level_mask, SIGCHLD); | 
					
						
							|  |  |  | #endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* And, some signals that are specifically ignored by the shell. */ | 
					
						
							|  |  |  |   set_signal_handler (SIGQUIT, SIG_IGN); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (interactive) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       set_signal_handler (SIGINT, sigint_sighandler); | 
					
						
							|  |  |  |       set_signal_handler (SIGTERM, SIG_IGN); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | reset_terminating_signals () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   register int i; | 
					
						
							|  |  |  | #if defined (HAVE_POSIX_SIGNALS)
 | 
					
						
							|  |  |  |   struct sigaction act; | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-06-05 14:59:13 +00:00
										 |  |  |   if (termsigs_initialized == 0) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HAVE_POSIX_SIGNALS)
 | 
					
						
							| 
									
										
										
										
											1996-12-23 17:02:34 +00:00
										 |  |  |   act.sa_flags = 0; | 
					
						
							|  |  |  |   sigemptyset (&act.sa_mask); | 
					
						
							|  |  |  |   for (i = 0; i < TERMSIGS_LENGTH; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* Skip a signal if it's trapped or handled specially, because the
 | 
					
						
							|  |  |  | 	 trap code will restore the correct value. */ | 
					
						
							|  |  |  |       if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i))) | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       act.sa_handler = XHANDLER (i); | 
					
						
							|  |  |  |       sigaction (XSIG (i), &act, (struct sigaction *) NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #else /* !HAVE_POSIX_SIGNALS */
 | 
					
						
							|  |  |  |   for (i = 0; i < TERMSIGS_LENGTH; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i))) | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       signal (XSIG (i), XHANDLER (i)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif /* !HAVE_POSIX_SIGNALS */
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #undef XSIG
 | 
					
						
							|  |  |  | #undef XHANDLER
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* What to do when we've been interrupted, and it is safe to handle it. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | throw_to_top_level () | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int print_newline = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (interrupt_state) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       print_newline = 1; | 
					
						
							|  |  |  |       DELINTERRUPT; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (interrupt_state) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   last_command_exit_value |= 128; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Run any traps set on SIGINT. */ | 
					
						
							|  |  |  |   run_interrupt_trap (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Cleanup string parser environment. */ | 
					
						
							|  |  |  |   while (parse_and_execute_level) | 
					
						
							|  |  |  |     parse_and_execute_cleanup (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL)
 | 
					
						
							|  |  |  |   give_terminal_to (shell_pgrp); | 
					
						
							|  |  |  | #endif /* JOB_CONTROL */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
 | 
					
						
							|  |  |  |   /* This should not be necessary on systems using sigsetjmp/siglongjmp. */ | 
					
						
							|  |  |  |   sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   reset_parser (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (READLINE)
 | 
					
						
							|  |  |  |   if (interactive) | 
					
						
							|  |  |  |     bashline_reinitialize (); | 
					
						
							|  |  |  | #endif /* READLINE */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (PROCESS_SUBSTITUTION)
 | 
					
						
							|  |  |  |   unlink_fifo_list (); | 
					
						
							|  |  |  | #endif /* PROCESS_SUBSTITUTION */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   run_unwind_protects (); | 
					
						
							|  |  |  |   loop_level = continuing = breaking = 0; | 
					
						
							|  |  |  |   return_catch_flag = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (interactive && print_newline) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       fflush (stdout); | 
					
						
							|  |  |  |       fprintf (stderr, "\n"); | 
					
						
							|  |  |  |       fflush (stderr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* An interrupted `wait' command in a script does not exit the script. */ | 
					
						
							|  |  |  |   if (interactive || (interactive_shell && !shell_initialized) || | 
					
						
							|  |  |  |       (print_newline && signal_is_trapped (SIGINT))) | 
					
						
							|  |  |  |     jump_to_top_level (DISCARD); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     jump_to_top_level (EXITPROG); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This is just here to isolate the longjmp calls. */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | jump_to_top_level (value) | 
					
						
							|  |  |  |      int value; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   longjmp (top_level, value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | sighandler | 
					
						
							|  |  |  | termination_unwind_protect (sig) | 
					
						
							|  |  |  |      int sig; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (sig == SIGINT && signal_is_trapped (SIGINT)) | 
					
						
							|  |  |  |     run_interrupt_trap (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (HISTORY)
 | 
					
						
							|  |  |  |   if (interactive_shell && sig != SIGABRT) | 
					
						
							|  |  |  |     maybe_save_shell_history (); | 
					
						
							|  |  |  | #endif /* HISTORY */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL)
 | 
					
						
							|  |  |  |   if (interactive && sig == SIGHUP) | 
					
						
							|  |  |  |     hangup_all_jobs (); | 
					
						
							|  |  |  |   end_job_control (); | 
					
						
							|  |  |  | #endif /* JOB_CONTROL */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (PROCESS_SUBSTITUTION)
 | 
					
						
							|  |  |  |   unlink_fifo_list (); | 
					
						
							|  |  |  | #endif /* PROCESS_SUBSTITUTION */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   run_exit_trap (); | 
					
						
							|  |  |  |   set_signal_handler (sig, SIG_DFL); | 
					
						
							|  |  |  |   kill (getpid (), sig); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SIGRETURN (0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* What we really do when SIGINT occurs. */ | 
					
						
							|  |  |  | sighandler | 
					
						
							|  |  |  | sigint_sighandler (sig) | 
					
						
							|  |  |  |      int sig; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #if defined (MUST_REINSTALL_SIGHANDLERS)
 | 
					
						
							|  |  |  |   signal (sig, sigint_sighandler); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* interrupt_state needs to be set for the stack of interrupts to work
 | 
					
						
							|  |  |  |      right.  Should it be set unconditionally? */ | 
					
						
							|  |  |  |   if (interrupt_state == 0) | 
					
						
							|  |  |  |     ADDINTERRUPT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (interrupt_immediately) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       interrupt_immediately = 0; | 
					
						
							|  |  |  |       throw_to_top_level (); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   SIGRETURN (0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Signal functions used by the rest of the code. */ | 
					
						
							|  |  |  | #if !defined (HAVE_POSIX_SIGNALS)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined (JOB_CONTROL)
 | 
					
						
							|  |  |  | /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */ | 
					
						
							|  |  |  | sigprocmask (operation, newset, oldset) | 
					
						
							|  |  |  |      int operation, *newset, *oldset; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int old, new; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (newset) | 
					
						
							|  |  |  |     new = *newset; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     new = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (operation) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case SIG_BLOCK: | 
					
						
							|  |  |  |       old = sigblock (new); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case SIG_SETMASK: | 
					
						
							|  |  |  |       sigsetmask (new); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       internal_error ("Bad code in sig.c: sigprocmask"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (oldset) | 
					
						
							|  |  |  |     *oldset = old; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* JOB_CONTROL */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined (SA_INTERRUPT)
 | 
					
						
							|  |  |  | #  define SA_INTERRUPT 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined (SA_RESTART)
 | 
					
						
							|  |  |  | #  define SA_RESTART 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SigHandler * | 
					
						
							|  |  |  | set_signal_handler (sig, handler) | 
					
						
							|  |  |  |      int sig; | 
					
						
							|  |  |  |      SigHandler *handler; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   struct sigaction act, oact; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   act.sa_handler = handler; | 
					
						
							|  |  |  |   act.sa_flags = 0; | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  |   if (sig == SIGALRM) | 
					
						
							|  |  |  |     act.sa_flags |= SA_INTERRUPT;	/* XXX */ | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     act.sa_flags |= SA_RESTART;		/* XXX */ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |   sigemptyset (&act.sa_mask); | 
					
						
							|  |  |  |   sigemptyset (&oact.sa_mask); | 
					
						
							|  |  |  |   sigaction (sig, &act, &oact); | 
					
						
							|  |  |  |   return (oact.sa_handler); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* HAVE_POSIX_SIGNALS */
 |