00001 /* signals.c -- signal handling support for readline. */ 00002 00003 /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc. 00004 00005 This file is part of the GNU Readline Library, a library for 00006 reading lines of text with interactive input and history editing. 00007 00008 The GNU Readline Library is free software; you can redistribute it 00009 and/or modify it under the terms of the GNU General Public License 00010 as published by the Free Software Foundation; either version 2, or 00011 (at your option) any later version. 00012 00013 The GNU Readline Library is distributed in the hope that it will be 00014 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00015 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 The GNU General Public License is often shipped with GNU software, and 00019 is generally kept in a file called COPYING or LICENSE. If you do not 00020 have a copy of the license, write to the Free Software Foundation, 00021 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ 00022 #define READLINE_LIBRARY 00023 00024 #include "config_readline.h" 00025 00026 #include <stdio.h> /* Just for NULL. Yuck. */ 00027 #include <sys/types.h> 00028 #include <signal.h> 00029 00030 #if defined (HAVE_UNISTD_H) 00031 # include <unistd.h> 00032 #endif /* HAVE_UNISTD_H */ 00033 00034 /* System-specific feature definitions and include files. */ 00035 #include "rldefs.h" 00036 00037 #if defined (GWINSZ_IN_SYS_IOCTL) 00038 # include <sys/ioctl.h> 00039 #endif /* GWINSZ_IN_SYS_IOCTL */ 00040 00041 #if defined (HANDLE_SIGNALS) 00042 /* Some standard library routines. */ 00043 #include "readline.h" 00044 #include "history.h" 00045 00046 #include "rlprivate.h" 00047 00048 #if !defined (RETSIGTYPE) 00049 # if defined (VOID_SIGHANDLER) 00050 # define RETSIGTYPE void 00051 # else 00052 # define RETSIGTYPE int 00053 # endif /* !VOID_SIGHANDLER */ 00054 #endif /* !RETSIGTYPE */ 00055 00056 #if defined (VOID_SIGHANDLER) 00057 # define SIGHANDLER_RETURN return 00058 #else 00059 # define SIGHANDLER_RETURN return (0) 00060 #endif 00061 00062 /* This typedef is equivalent to the one for Function; it allows us 00063 to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ 00064 typedef RETSIGTYPE SigHandler (); 00065 00066 #if defined (HAVE_POSIX_SIGNALS) 00067 typedef struct sigaction sighandler_cxt; 00068 # define rl_sigaction(s, nh, oh) sigaction(s, nh, oh) 00069 #else 00070 typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt; 00071 # define sigemptyset(m) 00072 #endif /* !HAVE_POSIX_SIGNALS */ 00073 00074 #ifndef SA_RESTART 00075 # define SA_RESTART 0 00076 #endif 00077 00078 static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); 00079 static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); 00080 00081 /* Exported variables for use by applications. */ 00082 00083 /* If non-zero, readline will install its own signal handlers for 00084 SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ 00085 int rl_catch_signals = 1; 00086 00087 /* If non-zero, readline will install a signal handler for SIGWINCH. */ 00088 #ifdef SIGWINCH 00089 int rl_catch_sigwinch = 1; 00090 #else 00091 int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */ 00092 #endif 00093 00094 static int signals_set_flag; 00095 static int sigwinch_set_flag; 00096 00097 /* **************************************************************** */ 00098 /* */ 00099 /* Signal Handling */ 00100 /* */ 00101 /* **************************************************************** */ 00102 00103 static sighandler_cxt old_int, old_term, old_alrm, old_quit; 00104 #if defined (SIGTSTP) 00105 static sighandler_cxt old_tstp, old_ttou, old_ttin; 00106 #endif 00107 #if defined (SIGWINCH) 00108 static sighandler_cxt old_winch; 00109 #endif 00110 00111 /* Readline signal handler functions. */ 00112 00113 static RETSIGTYPE 00114 rl_signal_handler (sig) 00115 int sig; 00116 { 00117 #if defined (HAVE_POSIX_SIGNALS) 00118 sigset_t set; 00119 #else /* !HAVE_POSIX_SIGNALS */ 00120 # if defined (HAVE_BSD_SIGNALS) 00121 long omask; 00122 # else /* !HAVE_BSD_SIGNALS */ 00123 sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */ 00124 # endif /* !HAVE_BSD_SIGNALS */ 00125 #endif /* !HAVE_POSIX_SIGNALS */ 00126 00127 RL_SETSTATE(RL_STATE_SIGHANDLER); 00128 00129 #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) 00130 /* Since the signal will not be blocked while we are in the signal 00131 handler, ignore it until rl_clear_signals resets the catcher. */ 00132 if (sig == SIGINT || sig == SIGALRM) 00133 rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); 00134 #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ 00135 00136 switch (sig) 00137 { 00138 case SIGINT: 00139 rl_free_line_state (); 00140 /* FALLTHROUGH */ 00141 00142 #if defined (SIGTSTP) 00143 case SIGTSTP: 00144 case SIGTTOU: 00145 case SIGTTIN: 00146 #endif /* SIGTSTP */ 00147 case SIGALRM: 00148 case SIGTERM: 00149 case SIGQUIT: 00150 rl_cleanup_after_signal (); 00151 00152 #if defined (HAVE_POSIX_SIGNALS) 00153 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); 00154 sigdelset (&set, sig); 00155 #else /* !HAVE_POSIX_SIGNALS */ 00156 # if defined (HAVE_BSD_SIGNALS) 00157 omask = sigblock (0); 00158 # endif /* HAVE_BSD_SIGNALS */ 00159 #endif /* !HAVE_POSIX_SIGNALS */ 00160 00161 #if defined (__EMX__) 00162 signal (sig, SIG_ACK); 00163 #endif 00164 00165 kill (getpid (), sig); 00166 00167 /* Let the signal that we just sent through. */ 00168 #if defined (HAVE_POSIX_SIGNALS) 00169 sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); 00170 #else /* !HAVE_POSIX_SIGNALS */ 00171 # if defined (HAVE_BSD_SIGNALS) 00172 sigsetmask (omask & ~(sigmask (sig))); 00173 # endif /* HAVE_BSD_SIGNALS */ 00174 #endif /* !HAVE_POSIX_SIGNALS */ 00175 00176 rl_reset_after_signal (); 00177 } 00178 00179 RL_UNSETSTATE(RL_STATE_SIGHANDLER); 00180 SIGHANDLER_RETURN; 00181 } 00182 00183 #if defined (SIGWINCH) 00184 static RETSIGTYPE 00185 rl_sigwinch_handler (sig) 00186 int sig; 00187 { 00188 SigHandler *oh; 00189 00190 #if defined (MUST_REINSTALL_SIGHANDLERS) 00191 sighandler_cxt dummy_winch; 00192 00193 /* We don't want to change old_winch -- it holds the state of SIGWINCH 00194 disposition set by the calling application. We need this state 00195 because we call the application's SIGWINCH handler after updating 00196 our own idea of the screen size. */ 00197 rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch); 00198 #endif 00199 00200 RL_SETSTATE(RL_STATE_SIGHANDLER); 00201 rl_resize_terminal (); 00202 00203 /* If another sigwinch handler has been installed, call it. */ 00204 oh = (SigHandler *)old_winch.sa_handler; 00205 if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL) 00206 (*oh) (sig); 00207 00208 RL_UNSETSTATE(RL_STATE_SIGHANDLER); 00209 SIGHANDLER_RETURN; 00210 } 00211 #endif /* SIGWINCH */ 00212 00213 /* Functions to manage signal handling. */ 00214 00215 #if !defined (HAVE_POSIX_SIGNALS) 00216 static int 00217 rl_sigaction (sig, nh, oh) 00218 int sig; 00219 sighandler_cxt *nh, *oh; 00220 { 00221 oh->sa_handler = signal (sig, nh->sa_handler); 00222 return 0; 00223 } 00224 #endif /* !HAVE_POSIX_SIGNALS */ 00225 00226 /* Set up a readline-specific signal handler, saving the old signal 00227 information in OHANDLER. Return the old signal handler, like 00228 signal(). */ 00229 static SigHandler * 00230 rl_set_sighandler (sig, handler, ohandler) 00231 int sig; 00232 SigHandler *handler; 00233 sighandler_cxt *ohandler; 00234 { 00235 sighandler_cxt old_handler; 00236 #if defined (HAVE_POSIX_SIGNALS) 00237 struct sigaction act; 00238 00239 act.sa_handler = handler; 00240 act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0; 00241 sigemptyset (&act.sa_mask); 00242 sigemptyset (&ohandler->sa_mask); 00243 sigaction (sig, &act, &old_handler); 00244 #else 00245 old_handler.sa_handler = (SigHandler *)signal (sig, handler); 00246 #endif /* !HAVE_POSIX_SIGNALS */ 00247 00248 /* XXX -- assume we have memcpy */ 00249 /* If rl_set_signals is called twice in a row, don't set the old handler to 00250 rl_signal_handler, because that would cause infinite recursion. */ 00251 if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler) 00252 memcpy (ohandler, &old_handler, sizeof (sighandler_cxt)); 00253 00254 return (ohandler->sa_handler); 00255 } 00256 00257 static void 00258 rl_maybe_set_sighandler (sig, handler, ohandler) 00259 int sig; 00260 SigHandler *handler; 00261 sighandler_cxt *ohandler; 00262 { 00263 sighandler_cxt dummy; 00264 SigHandler *oh; 00265 00266 sigemptyset (&dummy.sa_mask); 00267 oh = rl_set_sighandler (sig, handler, ohandler); 00268 if (oh == (SigHandler *)SIG_IGN) 00269 rl_sigaction (sig, ohandler, &dummy); 00270 } 00271 00272 int 00273 rl_set_signals () 00274 { 00275 sighandler_cxt dummy; 00276 SigHandler *oh; 00277 00278 if (rl_catch_signals && signals_set_flag == 0) 00279 { 00280 rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); 00281 rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); 00282 rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); 00283 00284 oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm); 00285 if (oh == (SigHandler *)SIG_IGN) 00286 rl_sigaction (SIGALRM, &old_alrm, &dummy); 00287 #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART) 00288 /* If the application using readline has already installed a signal 00289 handler with SA_RESTART, SIGALRM will cause reads to be restarted 00290 automatically, so readline should just get out of the way. Since 00291 we tested for SIG_IGN above, we can just test for SIG_DFL here. */ 00292 if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART)) 00293 rl_sigaction (SIGALRM, &old_alrm, &dummy); 00294 #endif /* HAVE_POSIX_SIGNALS */ 00295 00296 #if defined (SIGTSTP) 00297 rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp); 00298 #endif /* SIGTSTP */ 00299 00300 #if defined (SIGTTOU) 00301 rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou); 00302 #endif /* SIGTTOU */ 00303 00304 #if defined (SIGTTIN) 00305 rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin); 00306 #endif /* SIGTTIN */ 00307 00308 signals_set_flag = 1; 00309 } 00310 00311 #if defined (SIGWINCH) 00312 if (rl_catch_sigwinch && sigwinch_set_flag == 0) 00313 { 00314 rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch); 00315 sigwinch_set_flag = 1; 00316 } 00317 #endif /* SIGWINCH */ 00318 00319 return 0; 00320 } 00321 00322 int 00323 rl_clear_signals () 00324 { 00325 sighandler_cxt dummy; 00326 00327 if (rl_catch_signals && signals_set_flag == 1) 00328 { 00329 sigemptyset (&dummy.sa_mask); 00330 00331 rl_sigaction (SIGINT, &old_int, &dummy); 00332 rl_sigaction (SIGTERM, &old_term, &dummy); 00333 rl_sigaction (SIGQUIT, &old_quit, &dummy); 00334 rl_sigaction (SIGALRM, &old_alrm, &dummy); 00335 00336 #if defined (SIGTSTP) 00337 rl_sigaction (SIGTSTP, &old_tstp, &dummy); 00338 #endif /* SIGTSTP */ 00339 00340 #if defined (SIGTTOU) 00341 rl_sigaction (SIGTTOU, &old_ttou, &dummy); 00342 #endif /* SIGTTOU */ 00343 00344 #if defined (SIGTTIN) 00345 rl_sigaction (SIGTTIN, &old_ttin, &dummy); 00346 #endif /* SIGTTIN */ 00347 00348 signals_set_flag = 0; 00349 } 00350 00351 #if defined (SIGWINCH) 00352 if (rl_catch_sigwinch && sigwinch_set_flag == 1) 00353 { 00354 sigemptyset (&dummy.sa_mask); 00355 rl_sigaction (SIGWINCH, &old_winch, &dummy); 00356 sigwinch_set_flag = 0; 00357 } 00358 #endif 00359 00360 return 0; 00361 } 00362 00363 /* Clean up the terminal and readline state after catching a signal, before 00364 resending it to the calling application. */ 00365 void 00366 rl_cleanup_after_signal () 00367 { 00368 _rl_clean_up_for_exit (); 00369 (*rl_deprep_term_function) (); 00370 rl_clear_signals (); 00371 rl_clear_pending_input (); 00372 } 00373 00374 /* Reset the terminal and readline state after a signal handler returns. */ 00375 void 00376 rl_reset_after_signal () 00377 { 00378 (*rl_prep_term_function) (_rl_meta_flag); 00379 rl_set_signals (); 00380 } 00381 00382 /* Free up the readline variable line state for the current line (undo list, 00383 any partial history entry, any keyboard macros in progress, and any 00384 numeric arguments in process) after catching a signal, before calling 00385 rl_cleanup_after_signal(). */ 00386 void 00387 rl_free_line_state () 00388 { 00389 register HIST_ENTRY *entry; 00390 00391 rl_free_undo_list (); 00392 00393 entry = current_history (); 00394 if (entry) 00395 entry->data = (char *)NULL; 00396 00397 _rl_kill_kbd_macro (); 00398 rl_clear_message (); 00399 _rl_init_argument (); 00400 } 00401 00402 #endif /* HANDLE_SIGNALS */
1.4.7

