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