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