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