2001-06-15 Elena Zannoni <ezannoni@redhat.com>
[deliverable/binutils-gdb.git] / readline / signals.c
CommitLineData
d60d9f65
SS
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
1b17e766 10 as published by the Free Software Foundation; either version 2, or
d60d9f65
SS
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,
1b17e766 21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
d60d9f65
SS
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
d60d9f65
SS
43#if defined (HANDLE_SIGNALS)
44/* Some standard library routines. */
45#include "readline.h"
46#include "history.h"
47
1b17e766
EZ
48#include "rlprivate.h"
49
d60d9f65
SS
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 equivalant to the one for Function; it allows us
65 to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
66typedef RETSIGTYPE SigHandler ();
67
1b17e766
EZ
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 */
c862e87b 75
1b17e766 76static SigHandler *rl_set_sighandler __P((int, SigHandler *, sighandler_cxt *));
d60d9f65 77
c862e87b
JM
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;
a66f60a2 90#ifdef SIGWINCH
c862e87b 91static int sigwinch_set_flag;
a66f60a2 92#endif
c862e87b 93
d60d9f65
SS
94/* **************************************************************** */
95/* */
96/* Signal Handling */
97/* */
98/* **************************************************************** */
99
c862e87b
JM
100static sighandler_cxt old_int, old_term, old_alrm, old_quit;
101#if defined (SIGTSTP)
d60d9f65 102static sighandler_cxt old_tstp, old_ttou, old_ttin;
d60d9f65 103#endif
d60d9f65
SS
104#if defined (SIGWINCH)
105static sighandler_cxt old_winch;
106#endif
107
108/* Readline signal handler functions. */
109
110static RETSIGTYPE
111rl_signal_handler (sig)
112 int sig;
113{
114#if defined (HAVE_POSIX_SIGNALS)
115 sigset_t set;
116#else /* !HAVE_POSIX_SIGNALS */
117# if defined (HAVE_BSD_SIGNALS)
118 long omask;
119# else /* !HAVE_BSD_SIGNALS */
120 sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
121# endif /* !HAVE_BSD_SIGNALS */
122#endif /* !HAVE_POSIX_SIGNALS */
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:
c862e87b
JM
134 rl_free_line_state ();
135 /* FALLTHROUGH */
d60d9f65
SS
136
137#if defined (SIGTSTP)
138 case SIGTSTP:
139 case SIGTTOU:
140 case SIGTTIN:
141#endif /* SIGTSTP */
142 case SIGALRM:
143 case SIGTERM:
c862e87b
JM
144 case SIGQUIT:
145 rl_cleanup_after_signal ();
d60d9f65
SS
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
1b17e766
EZ
156#if defined (__EMX__)
157 signal (sig, SIG_ACK);
158#endif
159
d60d9f65
SS
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
c862e87b 171 rl_reset_after_signal ();
d60d9f65
SS
172 }
173
174 SIGHANDLER_RETURN;
175}
176
177#if defined (SIGWINCH)
178static RETSIGTYPE
c862e87b 179rl_sigwinch_handler (sig)
d60d9f65
SS
180 int sig;
181{
182 SigHandler *oh;
183
184#if defined (MUST_REINSTALL_SIGHANDLERS)
185 sighandler_cxt dummy_winch;
186
187 /* We don't want to change old_winch -- it holds the state of SIGWINCH
188 disposition set by the calling application. We need this state
189 because we call the application's SIGWINCH handler after updating
190 our own idea of the screen size. */
c862e87b 191 rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
d60d9f65
SS
192#endif
193
c862e87b 194 rl_resize_terminal ();
d60d9f65
SS
195
196 /* If another sigwinch handler has been installed, call it. */
197 oh = (SigHandler *)old_winch.sa_handler;
198 if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
199 (*oh) (sig);
200
201 SIGHANDLER_RETURN;
202}
203#endif /* SIGWINCH */
204
205/* Functions to manage signal handling. */
206
207#if !defined (HAVE_POSIX_SIGNALS)
208static int
209rl_sigaction (sig, nh, oh)
210 int sig;
211 sighandler_cxt *nh, *oh;
212{
213 oh->sa_handler = signal (sig, nh->sa_handler);
214 return 0;
215}
216#endif /* !HAVE_POSIX_SIGNALS */
217
218/* Set up a readline-specific signal handler, saving the old signal
219 information in OHANDLER. Return the old signal handler, like
220 signal(). */
221static SigHandler *
222rl_set_sighandler (sig, handler, ohandler)
223 int sig;
224 SigHandler *handler;
225 sighandler_cxt *ohandler;
226{
1b17e766 227 sighandler_cxt old_handler;
d60d9f65
SS
228#if defined (HAVE_POSIX_SIGNALS)
229 struct sigaction act;
230
231 act.sa_handler = handler;
232 act.sa_flags = 0;
233 sigemptyset (&act.sa_mask);
234 sigemptyset (&ohandler->sa_mask);
1b17e766 235 sigaction (sig, &act, &old_handler);
d60d9f65 236#else
1b17e766 237 old_handler.sa_handler = (SigHandler *)signal (sig, handler);
d60d9f65 238#endif /* !HAVE_POSIX_SIGNALS */
1b17e766
EZ
239
240 /* XXX -- assume we have memcpy */
241 /* If rl_set_signals is called twice in a row, don't set the old handler to
242 rl_signal_handler, because that would cause infinite recursion. */
243 if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
244 memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
245
d60d9f65
SS
246 return (ohandler->sa_handler);
247}
248
c862e87b
JM
249static void
250rl_maybe_set_sighandler (sig, handler, ohandler)
251 int sig;
252 SigHandler *handler;
253 sighandler_cxt *ohandler;
d60d9f65
SS
254{
255 sighandler_cxt dummy;
256 SigHandler *oh;
257
d60d9f65 258 sigemptyset (&dummy.sa_mask);
c862e87b 259 oh = rl_set_sighandler (sig, handler, ohandler);
d60d9f65 260 if (oh == (SigHandler *)SIG_IGN)
c862e87b
JM
261 rl_sigaction (sig, ohandler, &dummy);
262}
d60d9f65 263
c862e87b
JM
264int
265rl_set_signals ()
266{
267 sighandler_cxt dummy;
268 SigHandler *oh;
269
270 if (rl_catch_signals && signals_set_flag == 0)
271 {
272 rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
273 rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
274 rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
275
276 oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
277 if (oh == (SigHandler *)SIG_IGN)
278 rl_sigaction (SIGALRM, &old_alrm, &dummy);
d60d9f65 279#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
c862e87b
JM
280 /* If the application using readline has already installed a signal
281 handler with SA_RESTART, SIGALRM will cause reads to be restarted
282 automatically, so readline should just get out of the way. Since
283 we tested for SIG_IGN above, we can just test for SIG_DFL here. */
284 if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
285 rl_sigaction (SIGALRM, &old_alrm, &dummy);
d60d9f65
SS
286#endif /* HAVE_POSIX_SIGNALS */
287
d60d9f65 288#if defined (SIGTSTP)
c862e87b 289 rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
d60d9f65
SS
290#endif /* SIGTSTP */
291
292#if defined (SIGTTOU)
c862e87b 293 rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
d60d9f65
SS
294#endif /* SIGTTOU */
295
c862e87b
JM
296#if defined (SIGTTIN)
297 rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
298#endif /* SIGTTIN */
d60d9f65 299
c862e87b
JM
300 signals_set_flag = 1;
301 }
d60d9f65
SS
302
303#if defined (SIGWINCH)
c862e87b
JM
304 if (rl_catch_sigwinch && sigwinch_set_flag == 0)
305 {
306 rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
307 sigwinch_set_flag = 1;
308 }
d60d9f65
SS
309#endif /* SIGWINCH */
310
311 return 0;
312}
313
314int
315rl_clear_signals ()
316{
317 sighandler_cxt dummy;
318
c862e87b
JM
319 if (rl_catch_signals && signals_set_flag == 1)
320 {
321 sigemptyset (&dummy.sa_mask);
d60d9f65 322
c862e87b
JM
323 rl_sigaction (SIGINT, &old_int, &dummy);
324 rl_sigaction (SIGTERM, &old_term, &dummy);
325 rl_sigaction (SIGQUIT, &old_quit, &dummy);
326 rl_sigaction (SIGALRM, &old_alrm, &dummy);
d60d9f65
SS
327
328#if defined (SIGTSTP)
c862e87b
JM
329 rl_sigaction (SIGTSTP, &old_tstp, &dummy);
330#endif /* SIGTSTP */
d60d9f65
SS
331
332#if defined (SIGTTOU)
c862e87b 333 rl_sigaction (SIGTTOU, &old_ttou, &dummy);
d60d9f65
SS
334#endif /* SIGTTOU */
335
c862e87b
JM
336#if defined (SIGTTIN)
337 rl_sigaction (SIGTTIN, &old_ttin, &dummy);
338#endif /* SIGTTIN */
d60d9f65 339
c862e87b
JM
340 signals_set_flag = 0;
341 }
d60d9f65
SS
342
343#if defined (SIGWINCH)
c862e87b
JM
344 if (rl_catch_sigwinch && sigwinch_set_flag == 1)
345 {
346 sigemptyset (&dummy.sa_mask);
347 rl_sigaction (SIGWINCH, &old_winch, &dummy);
348 sigwinch_set_flag = 0;
349 }
d60d9f65
SS
350#endif
351
352 return 0;
353}
c862e87b
JM
354
355/* Clean up the terminal and readline state after catching a signal, before
356 resending it to the calling application. */
357void
358rl_cleanup_after_signal ()
359{
360 _rl_clean_up_for_exit ();
361 (*rl_deprep_term_function) ();
362 rl_clear_signals ();
363 rl_pending_input = 0;
364}
365
366/* Reset the terminal and readline state after a signal handler returns. */
367void
368rl_reset_after_signal ()
369{
370 (*rl_prep_term_function) (_rl_meta_flag);
371 rl_set_signals ();
372}
373
374/* Free up the readline variable line state for the current line (undo list,
375 any partial history entry, any keyboard macros in progress, and any
376 numeric arguments in process) after catching a signal, before calling
377 rl_cleanup_after_signal(). */
378void
379rl_free_line_state ()
380{
381 register HIST_ENTRY *entry;
382
383 free_undo_list ();
384
385 entry = current_history ();
386 if (entry)
387 entry->data = (char *)NULL;
388
389 _rl_kill_kbd_macro ();
390 rl_clear_message ();
391 _rl_init_argument ();
392}
393
d60d9f65 394#endif /* HANDLE_SIGNALS */
This page took 0.086712 seconds and 4 git commands to generate.