signals.c revision 136644
121308Sache/* signals.c -- signal handling support for readline. */ 221308Sache 321308Sache/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 421308Sache 521308Sache This file is part of the GNU Readline Library, a library for 621308Sache reading lines of text with interactive input and history editing. 721308Sache 821308Sache The GNU Readline Library is free software; you can redistribute it 921308Sache and/or modify it under the terms of the GNU General Public License 1058310Sache as published by the Free Software Foundation; either version 2, or 1121308Sache (at your option) any later version. 1221308Sache 1321308Sache The GNU Readline Library is distributed in the hope that it will be 1421308Sache useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1521308Sache of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1621308Sache GNU General Public License for more details. 1721308Sache 1821308Sache The GNU General Public License is often shipped with GNU software, and 1921308Sache is generally kept in a file called COPYING or LICENSE. If you do not 2021308Sache have a copy of the license, write to the Free Software Foundation, 2158310Sache 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 2221308Sache#define READLINE_LIBRARY 2321308Sache 2421308Sache#if defined (HAVE_CONFIG_H) 2521308Sache# include <config.h> 2621308Sache#endif 2721308Sache 2821308Sache#include <stdio.h> /* Just for NULL. Yuck. */ 2921308Sache#include <sys/types.h> 3021308Sache#include <signal.h> 3121308Sache 3221308Sache#if defined (HAVE_UNISTD_H) 3321308Sache# include <unistd.h> 3421308Sache#endif /* HAVE_UNISTD_H */ 3521308Sache 3621308Sache/* System-specific feature definitions and include files. */ 3721308Sache#include "rldefs.h" 3821308Sache 3921308Sache#if defined (GWINSZ_IN_SYS_IOCTL) 4021308Sache# include <sys/ioctl.h> 4121308Sache#endif /* GWINSZ_IN_SYS_IOCTL */ 4221308Sache 4321308Sache#if defined (HANDLE_SIGNALS) 4421308Sache/* Some standard library routines. */ 4521308Sache#include "readline.h" 4621308Sache#include "history.h" 4721308Sache 4858310Sache#include "rlprivate.h" 4958310Sache 5021308Sache#if !defined (RETSIGTYPE) 5121308Sache# if defined (VOID_SIGHANDLER) 5221308Sache# define RETSIGTYPE void 5321308Sache# else 5421308Sache# define RETSIGTYPE int 5521308Sache# endif /* !VOID_SIGHANDLER */ 5621308Sache#endif /* !RETSIGTYPE */ 5721308Sache 5821308Sache#if defined (VOID_SIGHANDLER) 5921308Sache# define SIGHANDLER_RETURN return 6021308Sache#else 6121308Sache# define SIGHANDLER_RETURN return (0) 6221308Sache#endif 6321308Sache 6475406Sache/* This typedef is equivalent to the one for Function; it allows us 6521308Sache to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ 6621308Sachetypedef RETSIGTYPE SigHandler (); 6721308Sache 6858310Sache#if defined (HAVE_POSIX_SIGNALS) 6958310Sachetypedef struct sigaction sighandler_cxt; 7058310Sache# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh) 7158310Sache#else 7258310Sachetypedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt; 7358310Sache# define sigemptyset(m) 7458310Sache#endif /* !HAVE_POSIX_SIGNALS */ 7547558Sache 76136644Sache#ifndef SA_RESTART 77136644Sache# define SA_RESTART 0 78136644Sache#endif 79136644Sache 80119610Sachestatic SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); 81119610Sachestatic void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); 8247558Sache 8347558Sache/* Exported variables for use by applications. */ 8447558Sache 8547558Sache/* If non-zero, readline will install its own signal handlers for 8647558Sache SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ 8747558Sacheint rl_catch_signals = 1; 8847558Sache 8947558Sache/* If non-zero, readline will install a signal handler for SIGWINCH. */ 9047558Sache#ifdef SIGWINCH 9147558Sacheint rl_catch_sigwinch = 1; 92136644Sache#else 93136644Sacheint rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */ 9447558Sache#endif 9547558Sache 9647558Sachestatic int signals_set_flag; 9747558Sachestatic int sigwinch_set_flag; 9847558Sache 9921308Sache/* **************************************************************** */ 10021308Sache/* */ 10121308Sache/* Signal Handling */ 10221308Sache/* */ 10321308Sache/* **************************************************************** */ 10421308Sache 10547558Sachestatic sighandler_cxt old_int, old_term, old_alrm, old_quit; 10647558Sache#if defined (SIGTSTP) 10726497Sachestatic sighandler_cxt old_tstp, old_ttou, old_ttin; 10826497Sache#endif 10921308Sache#if defined (SIGWINCH) 11021308Sachestatic sighandler_cxt old_winch; 11121308Sache#endif 11221308Sache 11321308Sache/* Readline signal handler functions. */ 11421308Sache 11521308Sachestatic RETSIGTYPE 11621308Sacherl_signal_handler (sig) 11721308Sache int sig; 11821308Sache{ 11921308Sache#if defined (HAVE_POSIX_SIGNALS) 12021308Sache sigset_t set; 12121308Sache#else /* !HAVE_POSIX_SIGNALS */ 12221308Sache# if defined (HAVE_BSD_SIGNALS) 12321308Sache long omask; 12426497Sache# else /* !HAVE_BSD_SIGNALS */ 12526497Sache sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */ 12626497Sache# endif /* !HAVE_BSD_SIGNALS */ 12721308Sache#endif /* !HAVE_POSIX_SIGNALS */ 12821308Sache 12975406Sache RL_SETSTATE(RL_STATE_SIGHANDLER); 13075406Sache 13121308Sache#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) 13221308Sache /* Since the signal will not be blocked while we are in the signal 13321308Sache handler, ignore it until rl_clear_signals resets the catcher. */ 13421308Sache if (sig == SIGINT || sig == SIGALRM) 13526497Sache rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); 13621308Sache#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ 13721308Sache 13821308Sache switch (sig) 13921308Sache { 14021308Sache case SIGINT: 14147558Sache rl_free_line_state (); 14247558Sache /* FALLTHROUGH */ 14321308Sache 14421308Sache#if defined (SIGTSTP) 14521308Sache case SIGTSTP: 14621308Sache case SIGTTOU: 14721308Sache case SIGTTIN: 14821308Sache#endif /* SIGTSTP */ 14921308Sache case SIGALRM: 15021308Sache case SIGTERM: 15147558Sache case SIGQUIT: 15247558Sache rl_cleanup_after_signal (); 15321308Sache 15421308Sache#if defined (HAVE_POSIX_SIGNALS) 15521308Sache sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); 15621308Sache sigdelset (&set, sig); 15721308Sache#else /* !HAVE_POSIX_SIGNALS */ 15821308Sache# if defined (HAVE_BSD_SIGNALS) 15921308Sache omask = sigblock (0); 16021308Sache# endif /* HAVE_BSD_SIGNALS */ 16121308Sache#endif /* !HAVE_POSIX_SIGNALS */ 16221308Sache 16358310Sache#if defined (__EMX__) 16458310Sache signal (sig, SIG_ACK); 16558310Sache#endif 16658310Sache 16721308Sache kill (getpid (), sig); 16821308Sache 16921308Sache /* Let the signal that we just sent through. */ 17021308Sache#if defined (HAVE_POSIX_SIGNALS) 17121308Sache sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); 17221308Sache#else /* !HAVE_POSIX_SIGNALS */ 17321308Sache# if defined (HAVE_BSD_SIGNALS) 17421308Sache sigsetmask (omask & ~(sigmask (sig))); 17521308Sache# endif /* HAVE_BSD_SIGNALS */ 17621308Sache#endif /* !HAVE_POSIX_SIGNALS */ 17721308Sache 17847558Sache rl_reset_after_signal (); 17921308Sache } 18021308Sache 18175406Sache RL_UNSETSTATE(RL_STATE_SIGHANDLER); 18221308Sache SIGHANDLER_RETURN; 18321308Sache} 18421308Sache 18521308Sache#if defined (SIGWINCH) 18621308Sachestatic RETSIGTYPE 18747558Sacherl_sigwinch_handler (sig) 18821308Sache int sig; 18921308Sache{ 19021308Sache SigHandler *oh; 19121308Sache 19226497Sache#if defined (MUST_REINSTALL_SIGHANDLERS) 19326497Sache sighandler_cxt dummy_winch; 19426497Sache 19526497Sache /* We don't want to change old_winch -- it holds the state of SIGWINCH 19626497Sache disposition set by the calling application. We need this state 19726497Sache because we call the application's SIGWINCH handler after updating 19826497Sache our own idea of the screen size. */ 19947558Sache rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch); 20026497Sache#endif 20126497Sache 20275406Sache RL_SETSTATE(RL_STATE_SIGHANDLER); 20347558Sache rl_resize_terminal (); 20421308Sache 20521308Sache /* If another sigwinch handler has been installed, call it. */ 20621308Sache oh = (SigHandler *)old_winch.sa_handler; 20721308Sache if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL) 20821308Sache (*oh) (sig); 20921308Sache 21075406Sache RL_UNSETSTATE(RL_STATE_SIGHANDLER); 21121308Sache SIGHANDLER_RETURN; 21221308Sache} 21321308Sache#endif /* SIGWINCH */ 21421308Sache 21521308Sache/* Functions to manage signal handling. */ 21621308Sache 21721308Sache#if !defined (HAVE_POSIX_SIGNALS) 21821308Sachestatic int 21921308Sacherl_sigaction (sig, nh, oh) 22021308Sache int sig; 22121308Sache sighandler_cxt *nh, *oh; 22221308Sache{ 22321308Sache oh->sa_handler = signal (sig, nh->sa_handler); 22421308Sache return 0; 22521308Sache} 22621308Sache#endif /* !HAVE_POSIX_SIGNALS */ 22721308Sache 22821308Sache/* Set up a readline-specific signal handler, saving the old signal 22921308Sache information in OHANDLER. Return the old signal handler, like 23021308Sache signal(). */ 23121308Sachestatic SigHandler * 23221308Sacherl_set_sighandler (sig, handler, ohandler) 23321308Sache int sig; 23421308Sache SigHandler *handler; 23521308Sache sighandler_cxt *ohandler; 23621308Sache{ 23758310Sache sighandler_cxt old_handler; 23821308Sache#if defined (HAVE_POSIX_SIGNALS) 23921308Sache struct sigaction act; 24021308Sache 24121308Sache act.sa_handler = handler; 242136644Sache act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0; 24321308Sache sigemptyset (&act.sa_mask); 24421308Sache sigemptyset (&ohandler->sa_mask); 24558310Sache sigaction (sig, &act, &old_handler); 24621308Sache#else 24758310Sache old_handler.sa_handler = (SigHandler *)signal (sig, handler); 24821308Sache#endif /* !HAVE_POSIX_SIGNALS */ 24958310Sache 25058310Sache /* XXX -- assume we have memcpy */ 25158310Sache /* If rl_set_signals is called twice in a row, don't set the old handler to 25258310Sache rl_signal_handler, because that would cause infinite recursion. */ 25358310Sache if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler) 25458310Sache memcpy (ohandler, &old_handler, sizeof (sighandler_cxt)); 25558310Sache 25621308Sache return (ohandler->sa_handler); 25721308Sache} 25821308Sache 25947558Sachestatic void 26047558Sacherl_maybe_set_sighandler (sig, handler, ohandler) 26147558Sache int sig; 26247558Sache SigHandler *handler; 26347558Sache sighandler_cxt *ohandler; 26447558Sache{ 26547558Sache sighandler_cxt dummy; 26647558Sache SigHandler *oh; 26747558Sache 26847558Sache sigemptyset (&dummy.sa_mask); 26947558Sache oh = rl_set_sighandler (sig, handler, ohandler); 27047558Sache if (oh == (SigHandler *)SIG_IGN) 27147558Sache rl_sigaction (sig, ohandler, &dummy); 27247558Sache} 27347558Sache 27421308Sacheint 27521308Sacherl_set_signals () 27621308Sache{ 27721308Sache sighandler_cxt dummy; 27821308Sache SigHandler *oh; 27921308Sache 28047558Sache if (rl_catch_signals && signals_set_flag == 0) 28147558Sache { 28247558Sache rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); 28347558Sache rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); 28447558Sache rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); 28521308Sache 28647558Sache oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm); 28747558Sache if (oh == (SigHandler *)SIG_IGN) 28847558Sache rl_sigaction (SIGALRM, &old_alrm, &dummy); 28921308Sache#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART) 29047558Sache /* If the application using readline has already installed a signal 29147558Sache handler with SA_RESTART, SIGALRM will cause reads to be restarted 29247558Sache automatically, so readline should just get out of the way. Since 29347558Sache we tested for SIG_IGN above, we can just test for SIG_DFL here. */ 29447558Sache if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART)) 29547558Sache rl_sigaction (SIGALRM, &old_alrm, &dummy); 29621308Sache#endif /* HAVE_POSIX_SIGNALS */ 29721308Sache 29821308Sache#if defined (SIGTSTP) 29947558Sache rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp); 30021308Sache#endif /* SIGTSTP */ 30121308Sache 30221308Sache#if defined (SIGTTOU) 30347558Sache rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou); 30421308Sache#endif /* SIGTTOU */ 30521308Sache 30647558Sache#if defined (SIGTTIN) 30747558Sache rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin); 30847558Sache#endif /* SIGTTIN */ 30926497Sache 31047558Sache signals_set_flag = 1; 31147558Sache } 31221308Sache 31321308Sache#if defined (SIGWINCH) 31447558Sache if (rl_catch_sigwinch && sigwinch_set_flag == 0) 31547558Sache { 31647558Sache rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch); 31747558Sache sigwinch_set_flag = 1; 31847558Sache } 31921308Sache#endif /* SIGWINCH */ 32021308Sache 32121308Sache return 0; 32221308Sache} 32321308Sache 32421308Sacheint 32521308Sacherl_clear_signals () 32621308Sache{ 32721308Sache sighandler_cxt dummy; 32821308Sache 32947558Sache if (rl_catch_signals && signals_set_flag == 1) 33047558Sache { 33147558Sache sigemptyset (&dummy.sa_mask); 33221308Sache 33347558Sache rl_sigaction (SIGINT, &old_int, &dummy); 33447558Sache rl_sigaction (SIGTERM, &old_term, &dummy); 33547558Sache rl_sigaction (SIGQUIT, &old_quit, &dummy); 33647558Sache rl_sigaction (SIGALRM, &old_alrm, &dummy); 33721308Sache 33821308Sache#if defined (SIGTSTP) 33947558Sache rl_sigaction (SIGTSTP, &old_tstp, &dummy); 34047558Sache#endif /* SIGTSTP */ 34121308Sache 34221308Sache#if defined (SIGTTOU) 34347558Sache rl_sigaction (SIGTTOU, &old_ttou, &dummy); 34421308Sache#endif /* SIGTTOU */ 34521308Sache 34647558Sache#if defined (SIGTTIN) 34747558Sache rl_sigaction (SIGTTIN, &old_ttin, &dummy); 34847558Sache#endif /* SIGTTIN */ 34926497Sache 35047558Sache signals_set_flag = 0; 35147558Sache } 35221308Sache 35321308Sache#if defined (SIGWINCH) 35447558Sache if (rl_catch_sigwinch && sigwinch_set_flag == 1) 35547558Sache { 35647558Sache sigemptyset (&dummy.sa_mask); 35747558Sache rl_sigaction (SIGWINCH, &old_winch, &dummy); 35847558Sache sigwinch_set_flag = 0; 35947558Sache } 36021308Sache#endif 36121308Sache 36221308Sache return 0; 36321308Sache} 36447558Sache 36547558Sache/* Clean up the terminal and readline state after catching a signal, before 36647558Sache resending it to the calling application. */ 36747558Sachevoid 36847558Sacherl_cleanup_after_signal () 36947558Sache{ 37047558Sache _rl_clean_up_for_exit (); 37147558Sache (*rl_deprep_term_function) (); 37247558Sache rl_clear_signals (); 37375406Sache rl_clear_pending_input (); 37447558Sache} 37547558Sache 37647558Sache/* Reset the terminal and readline state after a signal handler returns. */ 37747558Sachevoid 37847558Sacherl_reset_after_signal () 37947558Sache{ 38047558Sache (*rl_prep_term_function) (_rl_meta_flag); 38147558Sache rl_set_signals (); 38247558Sache} 38347558Sache 38447558Sache/* Free up the readline variable line state for the current line (undo list, 38547558Sache any partial history entry, any keyboard macros in progress, and any 38647558Sache numeric arguments in process) after catching a signal, before calling 38747558Sache rl_cleanup_after_signal(). */ 38847558Sachevoid 38947558Sacherl_free_line_state () 39047558Sache{ 39147558Sache register HIST_ENTRY *entry; 39247558Sache 39375406Sache rl_free_undo_list (); 39447558Sache 39547558Sache entry = current_history (); 39647558Sache if (entry) 39747558Sache entry->data = (char *)NULL; 39847558Sache 39947558Sache _rl_kill_kbd_macro (); 40047558Sache rl_clear_message (); 40147558Sache _rl_init_argument (); 40247558Sache} 40347558Sache 40421308Sache#endif /* HANDLE_SIGNALS */ 405