signals.c revision 75406
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 __P((int, SigHandler *, sighandler_cxt *)); 77 78/* Exported variables for use by applications. */ 79 80/* If non-zero, readline will install its own signal handlers for 81 SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ 82int rl_catch_signals = 1; 83 84/* If non-zero, readline will install a signal handler for SIGWINCH. */ 85#ifdef SIGWINCH 86int rl_catch_sigwinch = 1; 87#endif 88 89static int signals_set_flag; 90static int sigwinch_set_flag; 91 92/* **************************************************************** */ 93/* */ 94/* Signal Handling */ 95/* */ 96/* **************************************************************** */ 97 98static sighandler_cxt old_int, old_term, old_alrm, old_quit; 99#if defined (SIGTSTP) 100static sighandler_cxt old_tstp, old_ttou, old_ttin; 101#endif 102#if defined (SIGWINCH) 103static sighandler_cxt old_winch; 104#endif 105 106/* Readline signal handler functions. */ 107 108static RETSIGTYPE 109rl_signal_handler (sig) 110 int sig; 111{ 112#if defined (HAVE_POSIX_SIGNALS) 113 sigset_t set; 114#else /* !HAVE_POSIX_SIGNALS */ 115# if defined (HAVE_BSD_SIGNALS) 116 long omask; 117# else /* !HAVE_BSD_SIGNALS */ 118 sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */ 119# endif /* !HAVE_BSD_SIGNALS */ 120#endif /* !HAVE_POSIX_SIGNALS */ 121 122 RL_SETSTATE(RL_STATE_SIGHANDLER); 123 124#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) 125 /* Since the signal will not be blocked while we are in the signal 126 handler, ignore it until rl_clear_signals resets the catcher. */ 127 if (sig == SIGINT || sig == SIGALRM) 128 rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); 129#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ 130 131 switch (sig) 132 { 133 case SIGINT: 134 rl_free_line_state (); 135 /* FALLTHROUGH */ 136 137#if defined (SIGTSTP) 138 case SIGTSTP: 139 case SIGTTOU: 140 case SIGTTIN: 141#endif /* SIGTSTP */ 142 case SIGALRM: 143 case SIGTERM: 144 case SIGQUIT: 145 rl_cleanup_after_signal (); 146 147#if defined (HAVE_POSIX_SIGNALS) 148 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); 149 sigdelset (&set, sig); 150#else /* !HAVE_POSIX_SIGNALS */ 151# if defined (HAVE_BSD_SIGNALS) 152 omask = sigblock (0); 153# endif /* HAVE_BSD_SIGNALS */ 154#endif /* !HAVE_POSIX_SIGNALS */ 155 156#if defined (__EMX__) 157 signal (sig, SIG_ACK); 158#endif 159 160 kill (getpid (), sig); 161 162 /* Let the signal that we just sent through. */ 163#if defined (HAVE_POSIX_SIGNALS) 164 sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); 165#else /* !HAVE_POSIX_SIGNALS */ 166# if defined (HAVE_BSD_SIGNALS) 167 sigsetmask (omask & ~(sigmask (sig))); 168# endif /* HAVE_BSD_SIGNALS */ 169#endif /* !HAVE_POSIX_SIGNALS */ 170 171 rl_reset_after_signal (); 172 } 173 174 RL_UNSETSTATE(RL_STATE_SIGHANDLER); 175 SIGHANDLER_RETURN; 176} 177 178#if defined (SIGWINCH) 179static RETSIGTYPE 180rl_sigwinch_handler (sig) 181 int sig; 182{ 183 SigHandler *oh; 184 185#if defined (MUST_REINSTALL_SIGHANDLERS) 186 sighandler_cxt dummy_winch; 187 188 /* We don't want to change old_winch -- it holds the state of SIGWINCH 189 disposition set by the calling application. We need this state 190 because we call the application's SIGWINCH handler after updating 191 our own idea of the screen size. */ 192 rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch); 193#endif 194 195 RL_SETSTATE(RL_STATE_SIGHANDLER); 196 rl_resize_terminal (); 197 198 /* If another sigwinch handler has been installed, call it. */ 199 oh = (SigHandler *)old_winch.sa_handler; 200 if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL) 201 (*oh) (sig); 202 203 RL_UNSETSTATE(RL_STATE_SIGHANDLER); 204 SIGHANDLER_RETURN; 205} 206#endif /* SIGWINCH */ 207 208/* Functions to manage signal handling. */ 209 210#if !defined (HAVE_POSIX_SIGNALS) 211static int 212rl_sigaction (sig, nh, oh) 213 int sig; 214 sighandler_cxt *nh, *oh; 215{ 216 oh->sa_handler = signal (sig, nh->sa_handler); 217 return 0; 218} 219#endif /* !HAVE_POSIX_SIGNALS */ 220 221/* Set up a readline-specific signal handler, saving the old signal 222 information in OHANDLER. Return the old signal handler, like 223 signal(). */ 224static SigHandler * 225rl_set_sighandler (sig, handler, ohandler) 226 int sig; 227 SigHandler *handler; 228 sighandler_cxt *ohandler; 229{ 230 sighandler_cxt old_handler; 231#if defined (HAVE_POSIX_SIGNALS) 232 struct sigaction act; 233 234 act.sa_handler = handler; 235 act.sa_flags = 0; 236 sigemptyset (&act.sa_mask); 237 sigemptyset (&ohandler->sa_mask); 238 sigaction (sig, &act, &old_handler); 239#else 240 old_handler.sa_handler = (SigHandler *)signal (sig, handler); 241#endif /* !HAVE_POSIX_SIGNALS */ 242 243 /* XXX -- assume we have memcpy */ 244 /* If rl_set_signals is called twice in a row, don't set the old handler to 245 rl_signal_handler, because that would cause infinite recursion. */ 246 if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler) 247 memcpy (ohandler, &old_handler, sizeof (sighandler_cxt)); 248 249 return (ohandler->sa_handler); 250} 251 252static void 253rl_maybe_set_sighandler (sig, handler, ohandler) 254 int sig; 255 SigHandler *handler; 256 sighandler_cxt *ohandler; 257{ 258 sighandler_cxt dummy; 259 SigHandler *oh; 260 261 sigemptyset (&dummy.sa_mask); 262 oh = rl_set_sighandler (sig, handler, ohandler); 263 if (oh == (SigHandler *)SIG_IGN) 264 rl_sigaction (sig, ohandler, &dummy); 265} 266 267int 268rl_set_signals () 269{ 270 sighandler_cxt dummy; 271 SigHandler *oh; 272 273 if (rl_catch_signals && signals_set_flag == 0) 274 { 275 rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); 276 rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); 277 rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); 278 279 oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm); 280 if (oh == (SigHandler *)SIG_IGN) 281 rl_sigaction (SIGALRM, &old_alrm, &dummy); 282#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART) 283 /* If the application using readline has already installed a signal 284 handler with SA_RESTART, SIGALRM will cause reads to be restarted 285 automatically, so readline should just get out of the way. Since 286 we tested for SIG_IGN above, we can just test for SIG_DFL here. */ 287 if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART)) 288 rl_sigaction (SIGALRM, &old_alrm, &dummy); 289#endif /* HAVE_POSIX_SIGNALS */ 290 291#if defined (SIGTSTP) 292 rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp); 293#endif /* SIGTSTP */ 294 295#if defined (SIGTTOU) 296 rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou); 297#endif /* SIGTTOU */ 298 299#if defined (SIGTTIN) 300 rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin); 301#endif /* SIGTTIN */ 302 303 signals_set_flag = 1; 304 } 305 306#if defined (SIGWINCH) 307 if (rl_catch_sigwinch && sigwinch_set_flag == 0) 308 { 309 rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch); 310 sigwinch_set_flag = 1; 311 } 312#endif /* SIGWINCH */ 313 314 return 0; 315} 316 317int 318rl_clear_signals () 319{ 320 sighandler_cxt dummy; 321 322 if (rl_catch_signals && signals_set_flag == 1) 323 { 324 sigemptyset (&dummy.sa_mask); 325 326 rl_sigaction (SIGINT, &old_int, &dummy); 327 rl_sigaction (SIGTERM, &old_term, &dummy); 328 rl_sigaction (SIGQUIT, &old_quit, &dummy); 329 rl_sigaction (SIGALRM, &old_alrm, &dummy); 330 331#if defined (SIGTSTP) 332 rl_sigaction (SIGTSTP, &old_tstp, &dummy); 333#endif /* SIGTSTP */ 334 335#if defined (SIGTTOU) 336 rl_sigaction (SIGTTOU, &old_ttou, &dummy); 337#endif /* SIGTTOU */ 338 339#if defined (SIGTTIN) 340 rl_sigaction (SIGTTIN, &old_ttin, &dummy); 341#endif /* SIGTTIN */ 342 343 signals_set_flag = 0; 344 } 345 346#if defined (SIGWINCH) 347 if (rl_catch_sigwinch && sigwinch_set_flag == 1) 348 { 349 sigemptyset (&dummy.sa_mask); 350 rl_sigaction (SIGWINCH, &old_winch, &dummy); 351 sigwinch_set_flag = 0; 352 } 353#endif 354 355 return 0; 356} 357 358/* Clean up the terminal and readline state after catching a signal, before 359 resending it to the calling application. */ 360void 361rl_cleanup_after_signal () 362{ 363 _rl_clean_up_for_exit (); 364 (*rl_deprep_term_function) (); 365 rl_clear_signals (); 366 rl_clear_pending_input (); 367} 368 369/* Reset the terminal and readline state after a signal handler returns. */ 370void 371rl_reset_after_signal () 372{ 373 (*rl_prep_term_function) (_rl_meta_flag); 374 rl_set_signals (); 375} 376 377/* Free up the readline variable line state for the current line (undo list, 378 any partial history entry, any keyboard macros in progress, and any 379 numeric arguments in process) after catching a signal, before calling 380 rl_cleanup_after_signal(). */ 381void 382rl_free_line_state () 383{ 384 register HIST_ENTRY *entry; 385 386 rl_free_undo_list (); 387 388 entry = current_history (); 389 if (entry) 390 entry->data = (char *)NULL; 391 392 _rl_kill_kbd_macro (); 393 rl_clear_message (); 394 _rl_init_argument (); 395} 396 397#endif /* HANDLE_SIGNALS */ 398