Imported from ../bash-2.05.tar.gz.
[platform/upstream/bash.git] / lib / readline / 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 static 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. */
82 int rl_catch_signals = 1;
83
84 /* If non-zero, readline will install a signal handler for SIGWINCH. */
85 #ifdef SIGWINCH
86 int rl_catch_sigwinch = 1;
87 #endif
88
89 static int signals_set_flag;
90 static int sigwinch_set_flag;
91
92 /* **************************************************************** */
93 /*                                                                  */
94 /*                         Signal Handling                          */
95 /*                                                                  */
96 /* **************************************************************** */
97
98 static sighandler_cxt old_int, old_term, old_alrm, old_quit;
99 #if defined (SIGTSTP)
100 static sighandler_cxt old_tstp, old_ttou, old_ttin;
101 #endif
102 #if defined (SIGWINCH)
103 static sighandler_cxt old_winch;
104 #endif
105
106 /* Readline signal handler functions. */
107
108 static RETSIGTYPE
109 rl_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)
179 static RETSIGTYPE
180 rl_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)
211 static int
212 rl_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(). */
224 static SigHandler *
225 rl_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
252 static void
253 rl_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
267 int
268 rl_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
317 int
318 rl_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. */
360 void
361 rl_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. */
370 void
371 rl_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(). */ 
381 void
382 rl_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 */