version 1.1.1.1, 2014/07/30 08:16:45
|
version 1.1.1.2, 2021/03/17 01:01:01
|
Line 1
|
Line 1
|
/* signals.c -- signal handling support for readline. */ |
/* signals.c -- signal handling support for readline. */ |
|
|
/* Copyright (C) 1987-2011 Free Software Foundation, Inc. | /* Copyright (C) 1987-2017 Free Software Foundation, Inc. |
|
|
This file is part of the GNU Readline Library (Readline), a library |
This file is part of the GNU Readline Library (Readline), a library |
for reading lines of text with interactive input and history editing. |
for reading lines of text with interactive input and history editing. |
Line 99 int rl_catch_sigwinch = 0; /* for the readline state s
|
Line 99 int rl_catch_sigwinch = 0; /* for the readline state s
|
#endif |
#endif |
|
|
/* Private variables. */ |
/* Private variables. */ |
int _rl_interrupt_immediately = 0; |
|
int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including <signal.h> everywhere */ |
int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including <signal.h> everywhere */ |
|
|
/* If non-zero, print characters corresponding to received signals as long as |
/* If non-zero, print characters corresponding to received signals as long as |
Line 113 int _rl_susp_char = 0;
|
Line 112 int _rl_susp_char = 0;
|
static int signals_set_flag; |
static int signals_set_flag; |
static int sigwinch_set_flag; |
static int sigwinch_set_flag; |
|
|
|
#if defined (HAVE_POSIX_SIGNALS) |
|
sigset_t _rl_orig_sigset; |
|
#endif /* !HAVE_POSIX_SIGNALS */ |
|
|
/* **************************************************************** */ |
/* **************************************************************** */ |
/* */ |
/* */ |
/* Signal Handling */ |
/* Signal Handling */ |
Line 132 void *_rl_sigcleanarg;
|
Line 135 void *_rl_sigcleanarg;
|
|
|
/* Readline signal handler functions. */ |
/* Readline signal handler functions. */ |
|
|
/* Called from RL_CHECK_SIGNALS() macro */ | /* Called from RL_CHECK_SIGNALS() macro to run signal handling code. */ |
RETSIGTYPE |
RETSIGTYPE |
_rl_signal_handler (sig) | _rl_signal_handler (int sig) |
int sig; | |
{ |
{ |
_rl_caught_signal = 0; /* XXX */ |
_rl_caught_signal = 0; /* XXX */ |
|
|
#if defined (SIGWINCH) |
#if defined (SIGWINCH) |
if (sig == SIGWINCH) |
if (sig == SIGWINCH) |
{ |
{ |
|
RL_SETSTATE(RL_STATE_SIGHANDLER); |
|
|
rl_resize_terminal (); |
rl_resize_terminal (); |
/* XXX - experimental for now */ |
/* XXX - experimental for now */ |
/* Call a signal hook because though we called the original signal handler |
/* Call a signal hook because though we called the original signal handler |
Line 149 _rl_signal_handler (sig)
|
Line 153 _rl_signal_handler (sig)
|
ourselves. */ |
ourselves. */ |
if (rl_signal_event_hook) |
if (rl_signal_event_hook) |
(*rl_signal_event_hook) (); |
(*rl_signal_event_hook) (); |
|
|
|
RL_UNSETSTATE(RL_STATE_SIGHANDLER); |
} |
} |
else |
else |
#endif |
#endif |
Line 158 _rl_signal_handler (sig)
|
Line 164 _rl_signal_handler (sig)
|
} |
} |
|
|
static RETSIGTYPE |
static RETSIGTYPE |
rl_signal_handler (sig) | rl_signal_handler (int sig) |
int sig; | |
{ |
{ |
if (_rl_interrupt_immediately) | _rl_caught_signal = sig; |
{ | |
_rl_interrupt_immediately = 0; | |
_rl_handle_signal (sig); | |
} | |
else | |
_rl_caught_signal = sig; | |
| |
SIGHANDLER_RETURN; |
SIGHANDLER_RETURN; |
} |
} |
|
|
|
/* This is called to handle a signal when it is safe to do so (out of the |
|
signal handler execution path). Called by _rl_signal_handler for all the |
|
signals readline catches except SIGWINCH. */ |
static RETSIGTYPE |
static RETSIGTYPE |
_rl_handle_signal (sig) | _rl_handle_signal (int sig) |
int sig; | |
{ |
{ |
|
int block_sig; |
|
|
#if defined (HAVE_POSIX_SIGNALS) |
#if defined (HAVE_POSIX_SIGNALS) |
sigset_t set; | sigset_t set, oset; |
#else /* !HAVE_POSIX_SIGNALS */ |
#else /* !HAVE_POSIX_SIGNALS */ |
# if defined (HAVE_BSD_SIGNALS) |
# if defined (HAVE_BSD_SIGNALS) |
long omask; |
long omask; |
Line 207 _rl_handle_signal (sig)
|
Line 209 _rl_handle_signal (sig)
|
_rl_sigcleanup = 0; |
_rl_sigcleanup = 0; |
_rl_sigcleanarg = 0; |
_rl_sigcleanarg = 0; |
} |
} |
| |
| #if defined (HAVE_POSIX_SIGNALS) |
| /* Get the current set of blocked signals. If we want to block a signal for |
| the duration of the cleanup functions, make sure to add it to SET and |
| set block_sig = 1 (see the SIGHUP case below). */ |
| block_sig = 0; /* sentinel to block signals with sigprocmask */ |
| sigemptyset (&set); |
| sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); |
| #endif |
| |
switch (sig) |
switch (sig) |
{ |
{ |
case SIGINT: |
case SIGINT: |
_rl_reset_completion_state (); |
_rl_reset_completion_state (); |
rl_free_line_state (); |
rl_free_line_state (); |
|
#if defined (READLINE_CALLBACKS) |
|
rl_callback_sigcleanup (); |
|
#endif |
|
|
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
|
|
case SIGTERM: |
|
case SIGHUP: |
|
#if defined (SIGTSTP) |
#if defined (SIGTSTP) |
case SIGTSTP: |
case SIGTSTP: |
case SIGTTOU: |
|
case SIGTTIN: |
case SIGTTIN: |
|
case SIGTTOU: |
|
# if defined (HAVE_POSIX_SIGNALS) |
|
/* Block SIGTTOU so we can restore the terminal settings to something |
|
sane without stopping on SIGTTOU if we have been placed into the |
|
background. Even trying to get the current terminal pgrp with |
|
tcgetpgrp() will generate SIGTTOU, so we don't bother. We still do |
|
this even if we've been stopped on SIGTTOU, since we handle signals |
|
when we have returned from the signal handler and the signal is no |
|
longer blocked. */ |
|
sigaddset (&set, SIGTTOU); |
|
block_sig = 1; |
|
# endif |
#endif /* SIGTSTP */ |
#endif /* SIGTSTP */ |
|
/* Any signals that should be blocked during cleanup should go here. */ |
|
#if defined (SIGHUP) |
|
case SIGHUP: |
|
# if defined (_AIX) |
|
if (block_sig == 0) |
|
{ |
|
sigaddset (&set, sig); |
|
block_sig = 1; |
|
} |
|
# endif // _AIX |
|
#endif |
|
/* Signals that don't require blocking during cleanup should go here. */ |
|
case SIGTERM: |
#if defined (SIGALRM) |
#if defined (SIGALRM) |
case SIGALRM: |
case SIGALRM: |
#endif |
#endif |
#if defined (SIGQUIT) |
#if defined (SIGQUIT) |
case SIGQUIT: |
case SIGQUIT: |
#endif |
#endif |
|
|
|
if (block_sig) |
|
sigprocmask (SIG_BLOCK, &set, &oset); |
|
|
rl_echo_signal_char (sig); |
rl_echo_signal_char (sig); |
rl_cleanup_after_signal (); |
rl_cleanup_after_signal (); |
|
|
|
/* At this point, the application's signal handler, if any, is the |
|
current handler. */ |
|
|
#if defined (HAVE_POSIX_SIGNALS) |
#if defined (HAVE_POSIX_SIGNALS) |
|
/* Unblock any signal(s) blocked above */ |
|
if (block_sig) |
|
sigprocmask (SIG_UNBLOCK, &oset, (sigset_t *)NULL); |
|
#endif |
|
|
|
/* We don't have to bother unblocking the signal because we are not |
|
running in a signal handler context. */ |
|
#if 0 |
|
#if defined (HAVE_POSIX_SIGNALS) |
|
/* Make sure this signal is not blocked when we resend it to the |
|
calling application. */ |
sigemptyset (&set); |
sigemptyset (&set); |
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); |
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); |
sigdelset (&set, sig); |
sigdelset (&set, sig); |
Line 240 _rl_handle_signal (sig)
|
Line 295 _rl_handle_signal (sig)
|
omask = sigblock (0); |
omask = sigblock (0); |
# endif /* HAVE_BSD_SIGNALS */ |
# endif /* HAVE_BSD_SIGNALS */ |
#endif /* !HAVE_POSIX_SIGNALS */ |
#endif /* !HAVE_POSIX_SIGNALS */ |
|
#endif |
|
|
#if defined (__EMX__) |
#if defined (__EMX__) |
signal (sig, SIG_ACK); |
signal (sig, SIG_ACK); |
Line 251 _rl_handle_signal (sig)
|
Line 307 _rl_handle_signal (sig)
|
raise (sig); /* assume we have raise */ |
raise (sig); /* assume we have raise */ |
#endif |
#endif |
|
|
/* Let the signal that we just sent through. */ | /* We don't need to modify the signal mask now that this is not run in |
| a signal handler context. */ |
| #if 0 |
| /* Let the signal that we just sent through if it is blocked. */ |
#if defined (HAVE_POSIX_SIGNALS) |
#if defined (HAVE_POSIX_SIGNALS) |
sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); |
sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); |
#else /* !HAVE_POSIX_SIGNALS */ |
#else /* !HAVE_POSIX_SIGNALS */ |
Line 259 _rl_handle_signal (sig)
|
Line 318 _rl_handle_signal (sig)
|
sigsetmask (omask & ~(sigmask (sig))); |
sigsetmask (omask & ~(sigmask (sig))); |
# endif /* HAVE_BSD_SIGNALS */ |
# endif /* HAVE_BSD_SIGNALS */ |
#endif /* !HAVE_POSIX_SIGNALS */ |
#endif /* !HAVE_POSIX_SIGNALS */ |
|
#endif |
|
|
rl_reset_after_signal (); |
rl_reset_after_signal (); |
} |
} |
Line 269 _rl_handle_signal (sig)
|
Line 329 _rl_handle_signal (sig)
|
|
|
#if defined (SIGWINCH) |
#if defined (SIGWINCH) |
static RETSIGTYPE |
static RETSIGTYPE |
rl_sigwinch_handler (sig) | rl_sigwinch_handler (int sig) |
int sig; | |
{ |
{ |
SigHandler *oh; |
SigHandler *oh; |
|
|
Line 301 rl_sigwinch_handler (sig)
|
Line 360 rl_sigwinch_handler (sig)
|
|
|
#if !defined (HAVE_POSIX_SIGNALS) |
#if !defined (HAVE_POSIX_SIGNALS) |
static int |
static int |
rl_sigaction (sig, nh, oh) | rl_sigaction (int sig, sighandler_cxt *nh, sighandler_cxt *oh) |
int sig; | |
sighandler_cxt *nh, *oh; | |
{ |
{ |
oh->sa_handler = signal (sig, nh->sa_handler); |
oh->sa_handler = signal (sig, nh->sa_handler); |
return 0; |
return 0; |
Line 314 rl_sigaction (sig, nh, oh)
|
Line 371 rl_sigaction (sig, nh, oh)
|
information in OHANDLER. Return the old signal handler, like |
information in OHANDLER. Return the old signal handler, like |
signal(). */ |
signal(). */ |
static SigHandler * |
static SigHandler * |
rl_set_sighandler (sig, handler, ohandler) | rl_set_sighandler (int sig, SigHandler *handler, sighandler_cxt *ohandler) |
int sig; | |
SigHandler *handler; | |
sighandler_cxt *ohandler; | |
{ |
{ |
sighandler_cxt old_handler; |
sighandler_cxt old_handler; |
#if defined (HAVE_POSIX_SIGNALS) |
#if defined (HAVE_POSIX_SIGNALS) |
Line 348 rl_set_sighandler (sig, handler, ohandler)
|
Line 402 rl_set_sighandler (sig, handler, ohandler)
|
/* Set disposition of SIG to HANDLER, returning old state in OHANDLER. Don't |
/* Set disposition of SIG to HANDLER, returning old state in OHANDLER. Don't |
change disposition if OHANDLER indicates the signal was ignored. */ |
change disposition if OHANDLER indicates the signal was ignored. */ |
static void |
static void |
rl_maybe_set_sighandler (sig, handler, ohandler) | rl_maybe_set_sighandler (int sig, SigHandler *handler, sighandler_cxt *ohandler) |
int sig; | |
SigHandler *handler; | |
sighandler_cxt *ohandler; | |
{ |
{ |
sighandler_cxt dummy; |
sighandler_cxt dummy; |
SigHandler *oh; |
SigHandler *oh; |
Line 368 rl_maybe_set_sighandler (sig, handler, ohandler)
|
Line 419 rl_maybe_set_sighandler (sig, handler, ohandler)
|
disposition was changed using rl_maybe_set_sighandler or for which the |
disposition was changed using rl_maybe_set_sighandler or for which the |
SIG_IGN check was performed inline (e.g., SIGALRM below). */ |
SIG_IGN check was performed inline (e.g., SIGALRM below). */ |
static void |
static void |
rl_maybe_restore_sighandler (sig, handler) | rl_maybe_restore_sighandler (int sig, sighandler_cxt *handler) |
int sig; | |
sighandler_cxt *handler; | |
{ |
{ |
sighandler_cxt dummy; |
sighandler_cxt dummy; |
|
|
Line 381 rl_maybe_restore_sighandler (sig, handler)
|
Line 430 rl_maybe_restore_sighandler (sig, handler)
|
} |
} |
|
|
int |
int |
rl_set_signals () | rl_set_signals (void) |
{ |
{ |
sighandler_cxt dummy; |
sighandler_cxt dummy; |
SigHandler *oh; |
SigHandler *oh; |
Line 397 rl_set_signals ()
|
Line 446 rl_set_signals ()
|
|
|
sigaddset (&bset, SIGINT); |
sigaddset (&bset, SIGINT); |
sigaddset (&bset, SIGTERM); |
sigaddset (&bset, SIGTERM); |
|
#if defined (SIGHUP) |
sigaddset (&bset, SIGHUP); |
sigaddset (&bset, SIGHUP); |
|
#endif |
#if defined (SIGQUIT) |
#if defined (SIGQUIT) |
sigaddset (&bset, SIGQUIT); |
sigaddset (&bset, SIGQUIT); |
#endif |
#endif |
Line 420 rl_set_signals ()
|
Line 471 rl_set_signals ()
|
if (rl_catch_signals && signals_set_flag == 0) |
if (rl_catch_signals && signals_set_flag == 0) |
{ |
{ |
#if defined (HAVE_POSIX_SIGNALS) |
#if defined (HAVE_POSIX_SIGNALS) |
sigemptyset (&oset); | sigemptyset (&_rl_orig_sigset); |
sigprocmask (SIG_BLOCK, &bset, &oset); | sigprocmask (SIG_BLOCK, &bset, &_rl_orig_sigset); |
#endif |
#endif |
|
|
rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); |
rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); |
rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); |
rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); |
|
#if defined (SIGHUP) |
rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup); |
rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup); |
|
#endif |
#if defined (SIGQUIT) |
#if defined (SIGQUIT) |
rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); |
rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); |
#endif |
#endif |
Line 460 rl_set_signals ()
|
Line 513 rl_set_signals ()
|
signals_set_flag = 1; |
signals_set_flag = 1; |
|
|
#if defined (HAVE_POSIX_SIGNALS) |
#if defined (HAVE_POSIX_SIGNALS) |
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL); | sigprocmask (SIG_SETMASK, &_rl_orig_sigset, (sigset_t *)NULL); |
#endif |
#endif |
} |
} |
|
else if (rl_catch_signals == 0) |
|
{ |
|
#if defined (HAVE_POSIX_SIGNALS) |
|
sigemptyset (&_rl_orig_sigset); |
|
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &_rl_orig_sigset); |
|
#endif |
|
} |
|
|
#if defined (SIGWINCH) |
#if defined (SIGWINCH) |
if (rl_catch_sigwinch && sigwinch_set_flag == 0) |
if (rl_catch_sigwinch && sigwinch_set_flag == 0) |
Line 476 rl_set_signals ()
|
Line 536 rl_set_signals ()
|
} |
} |
|
|
int |
int |
rl_clear_signals () | rl_clear_signals (void) |
{ |
{ |
sighandler_cxt dummy; |
sighandler_cxt dummy; |
|
|
if (rl_catch_signals && signals_set_flag == 1) |
if (rl_catch_signals && signals_set_flag == 1) |
{ |
{ |
sigemptyset (&dummy.sa_mask); |
|
|
|
/* Since rl_maybe_set_sighandler doesn't override a SIG_IGN handler, |
/* Since rl_maybe_set_sighandler doesn't override a SIG_IGN handler, |
we should in theory not have to restore a handler where |
we should in theory not have to restore a handler where |
old_xxx.sa_handler == SIG_IGN. That's what rl_maybe_restore_sighandler |
old_xxx.sa_handler == SIG_IGN. That's what rl_maybe_restore_sighandler |
Line 491 rl_clear_signals ()
|
Line 549 rl_clear_signals ()
|
overhead */ |
overhead */ |
rl_maybe_restore_sighandler (SIGINT, &old_int); |
rl_maybe_restore_sighandler (SIGINT, &old_int); |
rl_maybe_restore_sighandler (SIGTERM, &old_term); |
rl_maybe_restore_sighandler (SIGTERM, &old_term); |
|
#if defined (SIGHUP) |
rl_maybe_restore_sighandler (SIGHUP, &old_hup); |
rl_maybe_restore_sighandler (SIGHUP, &old_hup); |
|
#endif |
#if defined (SIGQUIT) |
#if defined (SIGQUIT) |
rl_maybe_restore_sighandler (SIGQUIT, &old_quit); |
rl_maybe_restore_sighandler (SIGQUIT, &old_quit); |
#endif |
#endif |
Line 529 rl_clear_signals ()
|
Line 589 rl_clear_signals ()
|
/* Clean up the terminal and readline state after catching a signal, before |
/* Clean up the terminal and readline state after catching a signal, before |
resending it to the calling application. */ |
resending it to the calling application. */ |
void |
void |
rl_cleanup_after_signal () | rl_cleanup_after_signal (void) |
{ |
{ |
_rl_clean_up_for_exit (); |
_rl_clean_up_for_exit (); |
if (rl_deprep_term_function) |
if (rl_deprep_term_function) |
Line 540 rl_cleanup_after_signal ()
|
Line 600 rl_cleanup_after_signal ()
|
|
|
/* Reset the terminal and readline state after a signal handler returns. */ |
/* Reset the terminal and readline state after a signal handler returns. */ |
void |
void |
rl_reset_after_signal () | rl_reset_after_signal (void) |
{ |
{ |
if (rl_prep_term_function) |
if (rl_prep_term_function) |
(*rl_prep_term_function) (_rl_meta_flag); |
(*rl_prep_term_function) (_rl_meta_flag); |
Line 552 rl_reset_after_signal ()
|
Line 612 rl_reset_after_signal ()
|
numeric arguments in process) after catching a signal, before calling |
numeric arguments in process) after catching a signal, before calling |
rl_cleanup_after_signal(). */ |
rl_cleanup_after_signal(). */ |
void |
void |
rl_free_line_state () | rl_free_line_state (void) |
{ |
{ |
register HIST_ENTRY *entry; |
register HIST_ENTRY *entry; |
|
|
Line 567 rl_free_line_state ()
|
Line 627 rl_free_line_state ()
|
_rl_reset_argument (); |
_rl_reset_argument (); |
} |
} |
|
|
|
int |
|
rl_pending_signal (void) |
|
{ |
|
return (_rl_caught_signal); |
|
} |
|
|
|
void |
|
rl_check_signals (void) |
|
{ |
|
RL_CHECK_SIGNALS (); |
|
} |
#endif /* HANDLE_SIGNALS */ |
#endif /* HANDLE_SIGNALS */ |
|
|
/* **************************************************************** */ |
/* **************************************************************** */ |
Line 591 static int sigwinch_blocked;
|
Line 662 static int sigwinch_blocked;
|
/* Cause SIGINT to not be delivered until the corresponding call to |
/* Cause SIGINT to not be delivered until the corresponding call to |
release_sigint(). */ |
release_sigint(). */ |
void |
void |
_rl_block_sigint () | _rl_block_sigint (void) |
{ |
{ |
if (sigint_blocked) |
if (sigint_blocked) |
return; |
return; |
Line 601 _rl_block_sigint ()
|
Line 672 _rl_block_sigint ()
|
|
|
/* Allow SIGINT to be delivered. */ |
/* Allow SIGINT to be delivered. */ |
void |
void |
_rl_release_sigint () | _rl_release_sigint (void) |
{ |
{ |
if (sigint_blocked == 0) |
if (sigint_blocked == 0) |
return; |
return; |
Line 613 _rl_release_sigint ()
|
Line 684 _rl_release_sigint ()
|
/* Cause SIGWINCH to not be delivered until the corresponding call to |
/* Cause SIGWINCH to not be delivered until the corresponding call to |
release_sigwinch(). */ |
release_sigwinch(). */ |
void |
void |
_rl_block_sigwinch () | _rl_block_sigwinch (void) |
{ |
{ |
if (sigwinch_blocked) |
if (sigwinch_blocked) |
return; |
return; |
Line 642 _rl_block_sigwinch ()
|
Line 713 _rl_block_sigwinch ()
|
|
|
/* Allow SIGWINCH to be delivered. */ |
/* Allow SIGWINCH to be delivered. */ |
void |
void |
_rl_release_sigwinch () | _rl_release_sigwinch (void) |
{ |
{ |
if (sigwinch_blocked == 0) |
if (sigwinch_blocked == 0) |
return; |
return; |
Line 672 _rl_release_sigwinch ()
|
Line 743 _rl_release_sigwinch ()
|
/* */ |
/* */ |
/* **************************************************************** */ |
/* **************************************************************** */ |
void |
void |
rl_echo_signal_char (sig) | rl_echo_signal_char (int sig) |
int sig; | |
{ |
{ |
char cstr[3]; |
char cstr[3]; |
int cslen, c; |
int cslen, c; |