1/* signals.c -- signal handling support for readline. */ 2 3/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 4 5 This file is part of the GNU Readline Library, a library for 6 reading lines of text with interactive input and history editing. 7 8 The GNU Readline Library is free software; you can redistribute it 9 and/or modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2, or 11 (at your option) any later version. 12 13 The GNU Readline Library is distributed in the hope that it will be 14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 The GNU General Public License is often shipped with GNU software, and 19 is generally kept in a file called COPYING or LICENSE. If you do not 20 have a copy of the license, write to the Free Software Foundation, 21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 22#define READLINE_LIBRARY 23 24#if defined (HAVE_CONFIG_H) 25# include <config.h> 26#endif 27 28#include <stdio.h> /* Just for NULL. Yuck. */ 29#include <sys/types.h> 30#include <signal.h> 31 32#if defined (HAVE_UNISTD_H) 33# include <unistd.h> 34#endif /* HAVE_UNISTD_H */ 35 36/* System-specific feature definitions and include files. */ 37#include "rldefs.h" 38 39#if defined (GWINSZ_IN_SYS_IOCTL) 40# include <sys/ioctl.h> 41#endif /* GWINSZ_IN_SYS_IOCTL */ 42 43#if defined (HANDLE_SIGNALS) 44/* Some standard library routines. */ 45#include "readline.h" 46#include "history.h" 47 48#include "rlprivate.h" 49 50#if !defined (RETSIGTYPE) 51# if defined (VOID_SIGHANDLER) 52# define RETSIGTYPE void 53# else 54# define RETSIGTYPE int 55# endif /* !VOID_SIGHANDLER */ 56#endif /* !RETSIGTYPE */ 57 58#if defined (VOID_SIGHANDLER) 59# define SIGHANDLER_RETURN return 60#else 61# define SIGHANDLER_RETURN return (0) 62#endif 63 64/* This typedef is equivalent to the one for Function; it allows us 65 to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ 66typedef RETSIGTYPE SigHandler (); 67 68#if defined (HAVE_POSIX_SIGNALS) 69typedef struct sigaction sighandler_cxt; 70# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh) 71#else 72typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt; 73# define sigemptyset(m) 74#endif /* !HAVE_POSIX_SIGNALS */ 75 76static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); 77static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); 78 79/* Exported variables for use by applications. */ 80 81/* If non-zero, readline will install its own signal handlers for 82 SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ 83int rl_catch_signals = 1; 84 85/* If non-zero, readline will install a signal handler for SIGWINCH. */ 86#ifdef SIGWINCH 87int rl_catch_sigwinch = 1; 88#endif 89 90static int signals_set_flag; 91#ifdef SIGWINCH 92static int sigwinch_set_flag; 93#endif 94 95/* **************************************************************** */ 96/* */ 97/* Signal Handling */ 98/* */ 99/* **************************************************************** */ 100 101static sighandler_cxt old_int, old_term, old_alrm, old_quit; 102#if defined (SIGTSTP) 103static sighandler_cxt old_tstp, old_ttou, old_ttin; 104#endif 105#if defined (SIGWINCH) 106static sighandler_cxt old_winch; 107#endif 108 109/* Readline signal handler functions. */ 110 111static RETSIGTYPE 112rl_signal_handler (sig) 113 int sig; 114{ 115#if defined (HAVE_POSIX_SIGNALS) 116 sigset_t set; 117#else /* !HAVE_POSIX_SIGNALS */ 118# if defined (HAVE_BSD_SIGNALS) 119 long omask; 120# else /* !HAVE_BSD_SIGNALS */ 121 sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */ 122# endif /* !HAVE_BSD_SIGNALS */ 123#endif /* !HAVE_POSIX_SIGNALS */ 124 125 RL_SETSTATE(RL_STATE_SIGHANDLER); 126 127#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) 128 /* Since the signal will not be blocked while we are in the signal 129 handler, ignore it until rl_clear_signals resets the catcher. */ 130 if (sig == SIGINT || sig == SIGALRM) 131 rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); 132#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ 133 134 switch (sig) 135 { 136 case SIGINT: 137 rl_free_line_state (); 138 /* FALLTHROUGH */ 139 140#if defined (SIGTSTP) 141 case SIGTSTP: 142 case SIGTTOU: 143 case SIGTTIN: 144#endif /* SIGTSTP */ 145 case SIGALRM: 146 case SIGTERM: 147 case SIGQUIT: 148 rl_cleanup_after_signal (); 149 150#if defined (HAVE_POSIX_SIGNALS) 151 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); 152 sigdelset (&set, sig); 153#else /* !HAVE_POSIX_SIGNALS */ 154# if defined (HAVE_BSD_SIGNALS) 155 omask = sigblock (0); 156# endif /* HAVE_BSD_SIGNALS */ 157#endif /* !HAVE_POSIX_SIGNALS */ 158 159#if defined (__EMX__) 160 signal (sig, SIG_ACK); 161#endif 162 163 kill (getpid (), sig); 164 165 /* Let the signal that we just sent through. */ 166#if defined (HAVE_POSIX_SIGNALS) 167 sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); 168#else /* !HAVE_POSIX_SIGNALS */ 169# if defined (HAVE_BSD_SIGNALS) 170 sigsetmask (omask & ~(sigmask (sig))); 171# endif /* HAVE_BSD_SIGNALS */ 172#endif /* !HAVE_POSIX_SIGNALS */ 173 174 rl_reset_after_signal (); 175 } 176 177 RL_UNSETSTATE(RL_STATE_SIGHANDLER); 178 SIGHANDLER_RETURN; 179} 180 181#if defined (SIGWINCH) 182static RETSIGTYPE 183rl_sigwinch_handler (sig) 184 int sig; 185{ 186 SigHandler *oh; 187 188#if defined (MUST_REINSTALL_SIGHANDLERS) 189 sighandler_cxt dummy_winch; 190 191 /* We don't want to change old_winch -- it holds the state of SIGWINCH 192 disposition set by the calling application. We need this state 193 because we call the application's SIGWINCH handler after updating 194 our own idea of the screen size. */ 195 rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch); 196#endif 197 198 RL_SETSTATE(RL_STATE_SIGHANDLER); 199 rl_resize_terminal (); 200 201 /* If another sigwinch handler has been installed, call it. */ 202 oh = (SigHandler *)old_winch.sa_handler; 203 if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL) 204 (*oh) (sig); 205 206 RL_UNSETSTATE(RL_STATE_SIGHANDLER); 207 SIGHANDLER_RETURN; 208} 209#endif /* SIGWINCH */ 210 211/* Functions to manage signal handling. */ 212 213#if !defined (HAVE_POSIX_SIGNALS) 214static int 215rl_sigaction (sig, nh, oh) 216 int sig; 217 sighandler_cxt *nh, *oh; 218{ 219 oh->sa_handler = signal (sig, nh->sa_handler); 220 return 0; 221} 222#endif /* !HAVE_POSIX_SIGNALS */ 223 224/* Set up a readline-specific signal handler, saving the old signal 225 information in OHANDLER. Return the old signal handler, like 226 signal(). */ 227static SigHandler * 228rl_set_sighandler (sig, handler, ohandler) 229 int sig; 230 SigHandler *handler; 231 sighandler_cxt *ohandler; 232{ 233 sighandler_cxt old_handler; 234#if defined (HAVE_POSIX_SIGNALS) 235 struct sigaction act; 236 237 act.sa_handler = handler; 238 act.sa_flags = 0; /* XXX - should we set SA_RESTART for SIGWINCH? */ 239 sigemptyset (&act.sa_mask); 240 sigemptyset (&ohandler->sa_mask); 241 sigaction (sig, &act, &old_handler); 242#else 243 old_handler.sa_handler = (SigHandler *)signal (sig, handler); 244#endif /* !HAVE_POSIX_SIGNALS */ 245 246 /* XXX -- assume we have memcpy */ 247 /* If rl_set_signals is called twice in a row, don't set the old handler to 248 rl_signal_handler, because that would cause infinite recursion. */ 249 if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler) 250 memcpy (ohandler, &old_handler, sizeof (sighandler_cxt)); 251 252 return (ohandler->sa_handler); 253} 254 255static void 256rl_maybe_set_sighandler (sig, handler, ohandler) 257 int sig; 258 SigHandler *handler; 259 sighandler_cxt *ohandler; 260{ 261 sighandler_cxt dummy; 262 SigHandler *oh; 263 264 sigemptyset (&dummy.sa_mask); 265 oh = rl_set_sighandler (sig, handler, ohandler); 266 if (oh == (SigHandler *)SIG_IGN) 267 rl_sigaction (sig, ohandler, &dummy); 268} 269 270int 271rl_set_signals () 272{ 273 sighandler_cxt dummy; 274 SigHandler *oh; 275 276 if (rl_catch_signals && signals_set_flag == 0) 277 { 278 rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); 279 rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); 280 rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); 281 282 oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm); 283 if (oh == (SigHandler *)SIG_IGN) 284 rl_sigaction (SIGALRM, &old_alrm, &dummy); 285#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART) 286 /* If the application using readline has already installed a signal 287 handler with SA_RESTART, SIGALRM will cause reads to be restarted 288 automatically, so readline should just get out of the way. Since 289 we tested for SIG_IGN above, we can just test for SIG_DFL here. */ 290 if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART)) 291 rl_sigaction (SIGALRM, &old_alrm, &dummy); 292#endif /* HAVE_POSIX_SIGNALS */ 293 294#if defined (SIGTSTP) 295 rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp); 296#endif /* SIGTSTP */ 297 298#if defined (SIGTTOU) 299 rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou); 300#endif /* SIGTTOU */ 301 302#if defined (SIGTTIN) 303 rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin); 304#endif /* SIGTTIN */ 305 306 signals_set_flag = 1; 307 } 308 309#if defined (SIGWINCH) 310 if (rl_catch_sigwinch && sigwinch_set_flag == 0) 311 { 312 rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch); 313 sigwinch_set_flag = 1; 314 } 315#endif /* SIGWINCH */ 316 317 return 0; 318} 319 320int 321rl_clear_signals () 322{ 323 sighandler_cxt dummy; 324 325 if (rl_catch_signals && signals_set_flag == 1) 326 { 327 sigemptyset (&dummy.sa_mask); 328 329 rl_sigaction (SIGINT, &old_int, &dummy); 330 rl_sigaction (SIGTERM, &old_term, &dummy); 331 rl_sigaction (SIGQUIT, &old_quit, &dummy); 332 rl_sigaction (SIGALRM, &old_alrm, &dummy); 333 334#if defined (SIGTSTP) 335 rl_sigaction (SIGTSTP, &old_tstp, &dummy); 336#endif /* SIGTSTP */ 337 338#if defined (SIGTTOU) 339 rl_sigaction (SIGTTOU, &old_ttou, &dummy); 340#endif /* SIGTTOU */ 341 342#if defined (SIGTTIN) 343 rl_sigaction (SIGTTIN, &old_ttin, &dummy); 344#endif /* SIGTTIN */ 345 346 signals_set_flag = 0; 347 } 348 349#if defined (SIGWINCH) 350 if (rl_catch_sigwinch && sigwinch_set_flag == 1) 351 { 352 sigemptyset (&dummy.sa_mask); 353 rl_sigaction (SIGWINCH, &old_winch, &dummy); 354 sigwinch_set_flag = 0; 355 } 356#endif 357 358 return 0; 359} 360 361/* Clean up the terminal and readline state after catching a signal, before 362 resending it to the calling application. */ 363void 364rl_cleanup_after_signal () 365{ 366 _rl_clean_up_for_exit (); 367 (*rl_deprep_term_function) (); 368 rl_clear_signals (); 369 rl_clear_pending_input (); 370} 371 372/* Reset the terminal and readline state after a signal handler returns. */ 373void 374rl_reset_after_signal () 375{ 376 (*rl_prep_term_function) (_rl_meta_flag); 377 rl_set_signals (); 378} 379 380/* Free up the readline variable line state for the current line (undo list, 381 any partial history entry, any keyboard macros in progress, and any 382 numeric arguments in process) after catching a signal, before calling 383 rl_cleanup_after_signal(). */ 384void 385rl_free_line_state () 386{ 387 register HIST_ENTRY *entry; 388 389 rl_free_undo_list (); 390 391 entry = current_history (); 392 if (entry) 393 entry->data = (char *)NULL; 394 395 _rl_kill_kbd_macro (); 396 rl_clear_message (); 397 _rl_init_argument (); 398} 399 400#endif /* HANDLE_SIGNALS */ 401