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