]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/libreadline/signals.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / libreadline / signals.c
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    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); */
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
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
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
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 *
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
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
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
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
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
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
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 */