LCOV - code coverage report
Current view: top level - bash-4.4.23 - sig.c (source / functions) Hit Total Coverage
Test: cov-bash.info Lines: 66 178 37.1 %
Date: 2020-10-29 14:49:28 Functions: 7 15 46.7 %

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

Generated by: LCOV version 1.14.0.6.4058