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