11acd27e7Smillert /* signals.c -- signal handling support for readline. */
21acd27e7Smillert
31acd27e7Smillert /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
41acd27e7Smillert
51acd27e7Smillert This file is part of the GNU Readline Library, a library for
61acd27e7Smillert reading lines of text with interactive input and history editing.
71acd27e7Smillert
81acd27e7Smillert The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert (at your option) any later version.
121acd27e7Smillert
131acd27e7Smillert The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
161acd27e7Smillert GNU General Public License for more details.
171acd27e7Smillert
181acd27e7Smillert The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert is generally kept in a file called COPYING or LICENSE. If you do not
201acd27e7Smillert have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert # include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert
281acd27e7Smillert #include <stdio.h> /* Just for NULL. Yuck. */
291acd27e7Smillert #include <sys/types.h>
301acd27e7Smillert #include <signal.h>
311acd27e7Smillert
321acd27e7Smillert #if defined (HAVE_UNISTD_H)
331acd27e7Smillert # include <unistd.h>
341acd27e7Smillert #endif /* HAVE_UNISTD_H */
351acd27e7Smillert
361acd27e7Smillert /* System-specific feature definitions and include files. */
371acd27e7Smillert #include "rldefs.h"
381acd27e7Smillert
391acd27e7Smillert #if defined (GWINSZ_IN_SYS_IOCTL)
401acd27e7Smillert # include <sys/ioctl.h>
411acd27e7Smillert #endif /* GWINSZ_IN_SYS_IOCTL */
421acd27e7Smillert
431acd27e7Smillert #if defined (HANDLE_SIGNALS)
441acd27e7Smillert /* Some standard library routines. */
451acd27e7Smillert #include "readline.h"
461acd27e7Smillert #include "history.h"
471acd27e7Smillert
481acd27e7Smillert #include "rlprivate.h"
491acd27e7Smillert
501acd27e7Smillert #if !defined (RETSIGTYPE)
511acd27e7Smillert # if defined (VOID_SIGHANDLER)
521acd27e7Smillert # define RETSIGTYPE void
531acd27e7Smillert # else
541acd27e7Smillert # define RETSIGTYPE int
551acd27e7Smillert # endif /* !VOID_SIGHANDLER */
561acd27e7Smillert #endif /* !RETSIGTYPE */
571acd27e7Smillert
581acd27e7Smillert #if defined (VOID_SIGHANDLER)
591acd27e7Smillert # define SIGHANDLER_RETURN return
601acd27e7Smillert #else
611acd27e7Smillert # define SIGHANDLER_RETURN return (0)
621acd27e7Smillert #endif
631acd27e7Smillert
64*15b117eaSkettenis /* This typedef is equivalent to the one for Function; it allows us
651acd27e7Smillert to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
661acd27e7Smillert typedef RETSIGTYPE SigHandler ();
671acd27e7Smillert
681acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
691acd27e7Smillert typedef struct sigaction sighandler_cxt;
701acd27e7Smillert # define rl_sigaction(s, nh, oh) sigaction(s, nh, oh)
711acd27e7Smillert #else
721acd27e7Smillert typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
731acd27e7Smillert # define sigemptyset(m)
741acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
751acd27e7Smillert
76*15b117eaSkettenis static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
77*15b117eaSkettenis static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
781acd27e7Smillert
791acd27e7Smillert /* Exported variables for use by applications. */
801acd27e7Smillert
811acd27e7Smillert /* If non-zero, readline will install its own signal handlers for
821acd27e7Smillert SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
831acd27e7Smillert int rl_catch_signals = 1;
841acd27e7Smillert
851acd27e7Smillert /* If non-zero, readline will install a signal handler for SIGWINCH. */
861acd27e7Smillert #ifdef SIGWINCH
871acd27e7Smillert int rl_catch_sigwinch = 1;
881acd27e7Smillert #endif
891acd27e7Smillert
901acd27e7Smillert static int signals_set_flag;
911acd27e7Smillert static int sigwinch_set_flag;
921acd27e7Smillert
931acd27e7Smillert /* **************************************************************** */
941acd27e7Smillert /* */
951acd27e7Smillert /* Signal Handling */
961acd27e7Smillert /* */
971acd27e7Smillert /* **************************************************************** */
981acd27e7Smillert
991acd27e7Smillert static sighandler_cxt old_int, old_term, old_alrm, old_quit;
1001acd27e7Smillert #if defined (SIGTSTP)
1011acd27e7Smillert static sighandler_cxt old_tstp, old_ttou, old_ttin;
1021acd27e7Smillert #endif
1031acd27e7Smillert #if defined (SIGWINCH)
1041acd27e7Smillert static sighandler_cxt old_winch;
1051acd27e7Smillert #endif
1061acd27e7Smillert
1071acd27e7Smillert /* Readline signal handler functions. */
1081acd27e7Smillert
1091acd27e7Smillert static RETSIGTYPE
rl_signal_handler(sig)1101acd27e7Smillert rl_signal_handler (sig)
1111acd27e7Smillert int sig;
1121acd27e7Smillert {
1131acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
1141acd27e7Smillert sigset_t set;
1151acd27e7Smillert #else /* !HAVE_POSIX_SIGNALS */
1161acd27e7Smillert # if defined (HAVE_BSD_SIGNALS)
1171acd27e7Smillert long omask;
1181acd27e7Smillert # else /* !HAVE_BSD_SIGNALS */
1191acd27e7Smillert sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
1201acd27e7Smillert # endif /* !HAVE_BSD_SIGNALS */
1211acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
1221acd27e7Smillert
123*15b117eaSkettenis RL_SETSTATE(RL_STATE_SIGHANDLER);
124*15b117eaSkettenis
1251acd27e7Smillert #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
1261acd27e7Smillert /* Since the signal will not be blocked while we are in the signal
1271acd27e7Smillert handler, ignore it until rl_clear_signals resets the catcher. */
1281acd27e7Smillert if (sig == SIGINT || sig == SIGALRM)
1291acd27e7Smillert rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
1301acd27e7Smillert #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
1311acd27e7Smillert
1321acd27e7Smillert switch (sig)
1331acd27e7Smillert {
1341acd27e7Smillert case SIGINT:
1351acd27e7Smillert rl_free_line_state ();
1361acd27e7Smillert /* FALLTHROUGH */
1371acd27e7Smillert
1381acd27e7Smillert #if defined (SIGTSTP)
1391acd27e7Smillert case SIGTSTP:
1401acd27e7Smillert case SIGTTOU:
1411acd27e7Smillert case SIGTTIN:
1421acd27e7Smillert #endif /* SIGTSTP */
1431acd27e7Smillert case SIGALRM:
1441acd27e7Smillert case SIGTERM:
1451acd27e7Smillert case SIGQUIT:
1461acd27e7Smillert rl_cleanup_after_signal ();
1471acd27e7Smillert
1481acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
1491acd27e7Smillert sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
1501acd27e7Smillert sigdelset (&set, sig);
1511acd27e7Smillert #else /* !HAVE_POSIX_SIGNALS */
1521acd27e7Smillert # if defined (HAVE_BSD_SIGNALS)
1531acd27e7Smillert omask = sigblock (0);
1541acd27e7Smillert # endif /* HAVE_BSD_SIGNALS */
1551acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
1561acd27e7Smillert
1571acd27e7Smillert #if defined (__EMX__)
1581acd27e7Smillert signal (sig, SIG_ACK);
1591acd27e7Smillert #endif
1601acd27e7Smillert
1611acd27e7Smillert kill (getpid (), sig);
1621acd27e7Smillert
1631acd27e7Smillert /* Let the signal that we just sent through. */
1641acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
1651acd27e7Smillert sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
1661acd27e7Smillert #else /* !HAVE_POSIX_SIGNALS */
1671acd27e7Smillert # if defined (HAVE_BSD_SIGNALS)
1681acd27e7Smillert sigsetmask (omask & ~(sigmask (sig)));
1691acd27e7Smillert # endif /* HAVE_BSD_SIGNALS */
1701acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
1711acd27e7Smillert
1721acd27e7Smillert rl_reset_after_signal ();
1731acd27e7Smillert }
1741acd27e7Smillert
175*15b117eaSkettenis RL_UNSETSTATE(RL_STATE_SIGHANDLER);
1761acd27e7Smillert SIGHANDLER_RETURN;
1771acd27e7Smillert }
1781acd27e7Smillert
1791acd27e7Smillert #if defined (SIGWINCH)
1801acd27e7Smillert static RETSIGTYPE
rl_sigwinch_handler(sig)1811acd27e7Smillert rl_sigwinch_handler (sig)
1821acd27e7Smillert int sig;
1831acd27e7Smillert {
1841acd27e7Smillert SigHandler *oh;
1851acd27e7Smillert
1861acd27e7Smillert #if defined (MUST_REINSTALL_SIGHANDLERS)
1871acd27e7Smillert sighandler_cxt dummy_winch;
1881acd27e7Smillert
1891acd27e7Smillert /* We don't want to change old_winch -- it holds the state of SIGWINCH
1901acd27e7Smillert disposition set by the calling application. We need this state
1911acd27e7Smillert because we call the application's SIGWINCH handler after updating
1921acd27e7Smillert our own idea of the screen size. */
1931acd27e7Smillert rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
1941acd27e7Smillert #endif
1951acd27e7Smillert
196*15b117eaSkettenis RL_SETSTATE(RL_STATE_SIGHANDLER);
1971acd27e7Smillert rl_resize_terminal ();
1981acd27e7Smillert
1991acd27e7Smillert /* If another sigwinch handler has been installed, call it. */
2001acd27e7Smillert oh = (SigHandler *)old_winch.sa_handler;
2011acd27e7Smillert if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
2021acd27e7Smillert (*oh) (sig);
2031acd27e7Smillert
204*15b117eaSkettenis RL_UNSETSTATE(RL_STATE_SIGHANDLER);
2051acd27e7Smillert SIGHANDLER_RETURN;
2061acd27e7Smillert }
2071acd27e7Smillert #endif /* SIGWINCH */
2081acd27e7Smillert
2091acd27e7Smillert /* Functions to manage signal handling. */
2101acd27e7Smillert
2111acd27e7Smillert #if !defined (HAVE_POSIX_SIGNALS)
2121acd27e7Smillert static int
rl_sigaction(sig,nh,oh)2131acd27e7Smillert rl_sigaction (sig, nh, oh)
2141acd27e7Smillert int sig;
2151acd27e7Smillert sighandler_cxt *nh, *oh;
2161acd27e7Smillert {
2171acd27e7Smillert oh->sa_handler = signal (sig, nh->sa_handler);
2181acd27e7Smillert return 0;
2191acd27e7Smillert }
2201acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
2211acd27e7Smillert
2221acd27e7Smillert /* Set up a readline-specific signal handler, saving the old signal
2231acd27e7Smillert information in OHANDLER. Return the old signal handler, like
2241acd27e7Smillert signal(). */
2251acd27e7Smillert static SigHandler *
rl_set_sighandler(sig,handler,ohandler)2261acd27e7Smillert rl_set_sighandler (sig, handler, ohandler)
2271acd27e7Smillert int sig;
2281acd27e7Smillert SigHandler *handler;
2291acd27e7Smillert sighandler_cxt *ohandler;
2301acd27e7Smillert {
2311acd27e7Smillert sighandler_cxt old_handler;
2321acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS)
2331acd27e7Smillert struct sigaction act;
2341acd27e7Smillert
2351acd27e7Smillert act.sa_handler = handler;
236*15b117eaSkettenis act.sa_flags = 0; /* XXX - should we set SA_RESTART for SIGWINCH? */
2371acd27e7Smillert sigemptyset (&act.sa_mask);
2381acd27e7Smillert sigemptyset (&ohandler->sa_mask);
2391acd27e7Smillert sigaction (sig, &act, &old_handler);
2401acd27e7Smillert #else
2411acd27e7Smillert old_handler.sa_handler = (SigHandler *)signal (sig, handler);
2421acd27e7Smillert #endif /* !HAVE_POSIX_SIGNALS */
2431acd27e7Smillert
2441acd27e7Smillert /* XXX -- assume we have memcpy */
2451acd27e7Smillert /* If rl_set_signals is called twice in a row, don't set the old handler to
2461acd27e7Smillert rl_signal_handler, because that would cause infinite recursion. */
2471acd27e7Smillert if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
2481acd27e7Smillert memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
2491acd27e7Smillert
2501acd27e7Smillert return (ohandler->sa_handler);
2511acd27e7Smillert }
2521acd27e7Smillert
2531acd27e7Smillert static void
rl_maybe_set_sighandler(sig,handler,ohandler)2541acd27e7Smillert rl_maybe_set_sighandler (sig, handler, ohandler)
2551acd27e7Smillert int sig;
2561acd27e7Smillert SigHandler *handler;
2571acd27e7Smillert sighandler_cxt *ohandler;
2581acd27e7Smillert {
2591acd27e7Smillert sighandler_cxt dummy;
2601acd27e7Smillert SigHandler *oh;
2611acd27e7Smillert
2621acd27e7Smillert sigemptyset (&dummy.sa_mask);
2631acd27e7Smillert oh = rl_set_sighandler (sig, handler, ohandler);
2641acd27e7Smillert if (oh == (SigHandler *)SIG_IGN)
2651acd27e7Smillert rl_sigaction (sig, ohandler, &dummy);
2661acd27e7Smillert }
2671acd27e7Smillert
2681acd27e7Smillert int
rl_set_signals()2691acd27e7Smillert rl_set_signals ()
2701acd27e7Smillert {
2711acd27e7Smillert sighandler_cxt dummy;
2721acd27e7Smillert SigHandler *oh;
2731acd27e7Smillert
2741acd27e7Smillert if (rl_catch_signals && signals_set_flag == 0)
2751acd27e7Smillert {
2761acd27e7Smillert rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
2771acd27e7Smillert rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
2781acd27e7Smillert rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
2791acd27e7Smillert
2801acd27e7Smillert oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
2811acd27e7Smillert if (oh == (SigHandler *)SIG_IGN)
2821acd27e7Smillert rl_sigaction (SIGALRM, &old_alrm, &dummy);
2831acd27e7Smillert #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
2841acd27e7Smillert /* If the application using readline has already installed a signal
2851acd27e7Smillert handler with SA_RESTART, SIGALRM will cause reads to be restarted
2861acd27e7Smillert automatically, so readline should just get out of the way. Since
2871acd27e7Smillert we tested for SIG_IGN above, we can just test for SIG_DFL here. */
2881acd27e7Smillert if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
2891acd27e7Smillert rl_sigaction (SIGALRM, &old_alrm, &dummy);
2901acd27e7Smillert #endif /* HAVE_POSIX_SIGNALS */
2911acd27e7Smillert
2921acd27e7Smillert #if defined (SIGTSTP)
2931acd27e7Smillert rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
2941acd27e7Smillert #endif /* SIGTSTP */
2951acd27e7Smillert
2961acd27e7Smillert #if defined (SIGTTOU)
2971acd27e7Smillert rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
2981acd27e7Smillert #endif /* SIGTTOU */
2991acd27e7Smillert
3001acd27e7Smillert #if defined (SIGTTIN)
3011acd27e7Smillert rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
3021acd27e7Smillert #endif /* SIGTTIN */
3031acd27e7Smillert
3041acd27e7Smillert signals_set_flag = 1;
3051acd27e7Smillert }
3061acd27e7Smillert
3071acd27e7Smillert #if defined (SIGWINCH)
3081acd27e7Smillert if (rl_catch_sigwinch && sigwinch_set_flag == 0)
3091acd27e7Smillert {
3101acd27e7Smillert rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
3111acd27e7Smillert sigwinch_set_flag = 1;
3121acd27e7Smillert }
3131acd27e7Smillert #endif /* SIGWINCH */
3141acd27e7Smillert
3151acd27e7Smillert return 0;
3161acd27e7Smillert }
3171acd27e7Smillert
3181acd27e7Smillert int
rl_clear_signals()3191acd27e7Smillert rl_clear_signals ()
3201acd27e7Smillert {
3211acd27e7Smillert sighandler_cxt dummy;
3221acd27e7Smillert
3231acd27e7Smillert if (rl_catch_signals && signals_set_flag == 1)
3241acd27e7Smillert {
3251acd27e7Smillert sigemptyset (&dummy.sa_mask);
3261acd27e7Smillert
3271acd27e7Smillert rl_sigaction (SIGINT, &old_int, &dummy);
3281acd27e7Smillert rl_sigaction (SIGTERM, &old_term, &dummy);
3291acd27e7Smillert rl_sigaction (SIGQUIT, &old_quit, &dummy);
3301acd27e7Smillert rl_sigaction (SIGALRM, &old_alrm, &dummy);
3311acd27e7Smillert
3321acd27e7Smillert #if defined (SIGTSTP)
3331acd27e7Smillert rl_sigaction (SIGTSTP, &old_tstp, &dummy);
3341acd27e7Smillert #endif /* SIGTSTP */
3351acd27e7Smillert
3361acd27e7Smillert #if defined (SIGTTOU)
3371acd27e7Smillert rl_sigaction (SIGTTOU, &old_ttou, &dummy);
3381acd27e7Smillert #endif /* SIGTTOU */
3391acd27e7Smillert
3401acd27e7Smillert #if defined (SIGTTIN)
3411acd27e7Smillert rl_sigaction (SIGTTIN, &old_ttin, &dummy);
3421acd27e7Smillert #endif /* SIGTTIN */
3431acd27e7Smillert
3441acd27e7Smillert signals_set_flag = 0;
3451acd27e7Smillert }
3461acd27e7Smillert
3471acd27e7Smillert #if defined (SIGWINCH)
3481acd27e7Smillert if (rl_catch_sigwinch && sigwinch_set_flag == 1)
3491acd27e7Smillert {
3501acd27e7Smillert sigemptyset (&dummy.sa_mask);
3511acd27e7Smillert rl_sigaction (SIGWINCH, &old_winch, &dummy);
3521acd27e7Smillert sigwinch_set_flag = 0;
3531acd27e7Smillert }
3541acd27e7Smillert #endif
3551acd27e7Smillert
3561acd27e7Smillert return 0;
3571acd27e7Smillert }
3581acd27e7Smillert
3591acd27e7Smillert /* Clean up the terminal and readline state after catching a signal, before
3601acd27e7Smillert resending it to the calling application. */
3611acd27e7Smillert void
rl_cleanup_after_signal()3621acd27e7Smillert rl_cleanup_after_signal ()
3631acd27e7Smillert {
3641acd27e7Smillert _rl_clean_up_for_exit ();
3651acd27e7Smillert (*rl_deprep_term_function) ();
3661acd27e7Smillert rl_clear_signals ();
367*15b117eaSkettenis rl_clear_pending_input ();
3681acd27e7Smillert }
3691acd27e7Smillert
3701acd27e7Smillert /* Reset the terminal and readline state after a signal handler returns. */
3711acd27e7Smillert void
rl_reset_after_signal()3721acd27e7Smillert rl_reset_after_signal ()
3731acd27e7Smillert {
3741acd27e7Smillert (*rl_prep_term_function) (_rl_meta_flag);
3751acd27e7Smillert rl_set_signals ();
3761acd27e7Smillert }
3771acd27e7Smillert
3781acd27e7Smillert /* Free up the readline variable line state for the current line (undo list,
3791acd27e7Smillert any partial history entry, any keyboard macros in progress, and any
3801acd27e7Smillert numeric arguments in process) after catching a signal, before calling
3811acd27e7Smillert rl_cleanup_after_signal(). */
3821acd27e7Smillert void
rl_free_line_state()3831acd27e7Smillert rl_free_line_state ()
3841acd27e7Smillert {
3851acd27e7Smillert register HIST_ENTRY *entry;
3861acd27e7Smillert
387*15b117eaSkettenis rl_free_undo_list ();
3881acd27e7Smillert
3891acd27e7Smillert entry = current_history ();
3901acd27e7Smillert if (entry)
3911acd27e7Smillert entry->data = (char *)NULL;
3921acd27e7Smillert
3931acd27e7Smillert _rl_kill_kbd_macro ();
3941acd27e7Smillert rl_clear_message ();
3951acd27e7Smillert _rl_init_argument ();
3961acd27e7Smillert }
3971acd27e7Smillert
3981acd27e7Smillert #endif /* HANDLE_SIGNALS */
399