]> git.ipfire.org Git - thirdparty/bash.git/blame - lib/readline/signals.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/bash.git] / lib / readline / signals.c
CommitLineData
726f6388
JA
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
bb70624e 10 as published by the Free Software Foundation; either version 2, or
726f6388
JA
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,
bb70624e 21 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
726f6388
JA
22#define READLINE_LIBRARY
23
ccc6cda3
JA
24#if defined (HAVE_CONFIG_H)
25# include <config.h>
26#endif
27
28#include <stdio.h> /* Just for NULL. Yuck. */
726f6388 29#include <sys/types.h>
726f6388
JA
30#include <signal.h>
31
32#if defined (HAVE_UNISTD_H)
33# include <unistd.h>
34#endif /* HAVE_UNISTD_H */
35
726f6388
JA
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
ccc6cda3 43#if defined (HANDLE_SIGNALS)
726f6388
JA
44/* Some standard library routines. */
45#include "readline.h"
46#include "history.h"
47
bb70624e
JA
48#include "rlprivate.h"
49
ccc6cda3
JA
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 */
726f6388
JA
57
58#if defined (VOID_SIGHANDLER)
ccc6cda3 59# define SIGHANDLER_RETURN return
726f6388 60#else
ccc6cda3
JA
61# define SIGHANDLER_RETURN return (0)
62#endif
726f6388 63
28ef6c31 64/* This typedef is equivalent to the one for Function; it allows us
726f6388 65 to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
ccc6cda3 66typedef RETSIGTYPE SigHandler ();
726f6388 67
bb70624e
JA
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 */
b72432fd 75
bb70624e 76static SigHandler *rl_set_sighandler __P((int, SigHandler *, sighandler_cxt *));
726f6388 77
b72432fd
JA
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;
90static int sigwinch_set_flag;
91
726f6388
JA
92/* **************************************************************** */
93/* */
94/* Signal Handling */
95/* */
96/* **************************************************************** */
97
b72432fd
JA
98static sighandler_cxt old_int, old_term, old_alrm, old_quit;
99#if defined (SIGTSTP)
d166f048 100static sighandler_cxt old_tstp, old_ttou, old_ttin;
d166f048 101#endif
ccc6cda3
JA
102#if defined (SIGWINCH)
103static sighandler_cxt old_winch;
104#endif
105
106/* Readline signal handler functions. */
107
108static RETSIGTYPE
726f6388
JA
109rl_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;
d166f048
JA
117# else /* !HAVE_BSD_SIGNALS */
118 sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
119# endif /* !HAVE_BSD_SIGNALS */
726f6388
JA
120#endif /* !HAVE_POSIX_SIGNALS */
121
28ef6c31
JA
122 RL_SETSTATE(RL_STATE_SIGHANDLER);
123
726f6388
JA
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. */
ccc6cda3 127 if (sig == SIGINT || sig == SIGALRM)
d166f048 128 rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
ccc6cda3 129#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
726f6388
JA
130
131 switch (sig)
132 {
133 case SIGINT:
b72432fd
JA
134 rl_free_line_state ();
135 /* FALLTHROUGH */
726f6388
JA
136
137#if defined (SIGTSTP)
138 case SIGTSTP:
139 case SIGTTOU:
140 case SIGTTIN:
141#endif /* SIGTSTP */
142 case SIGALRM:
ccc6cda3 143 case SIGTERM:
b72432fd
JA
144 case SIGQUIT:
145 rl_cleanup_after_signal ();
726f6388
JA
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
bb70624e
JA
156#if defined (__EMX__)
157 signal (sig, SIG_ACK);
158#endif
159
726f6388
JA
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
b72432fd 171 rl_reset_after_signal ();
726f6388
JA
172 }
173
28ef6c31 174 RL_UNSETSTATE(RL_STATE_SIGHANDLER);
ccc6cda3 175 SIGHANDLER_RETURN;
726f6388
JA
176}
177
ccc6cda3
JA
178#if defined (SIGWINCH)
179static RETSIGTYPE
b72432fd 180rl_sigwinch_handler (sig)
ccc6cda3
JA
181 int sig;
182{
183 SigHandler *oh;
184
d166f048
JA
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. */
b72432fd 192 rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
d166f048
JA
193#endif
194
28ef6c31 195 RL_SETSTATE(RL_STATE_SIGHANDLER);
b72432fd 196 rl_resize_terminal ();
ccc6cda3
JA
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
28ef6c31 203 RL_UNSETSTATE(RL_STATE_SIGHANDLER);
ccc6cda3
JA
204 SIGHANDLER_RETURN;
205}
206#endif /* SIGWINCH */
207
208/* Functions to manage signal handling. */
209
210#if !defined (HAVE_POSIX_SIGNALS)
211static int
212rl_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(). */
726f6388 224static SigHandler *
ccc6cda3 225rl_set_sighandler (sig, handler, ohandler)
726f6388
JA
226 int sig;
227 SigHandler *handler;
ccc6cda3 228 sighandler_cxt *ohandler;
726f6388 229{
bb70624e 230 sighandler_cxt old_handler;
ccc6cda3
JA
231#if defined (HAVE_POSIX_SIGNALS)
232 struct sigaction act;
726f6388
JA
233
234 act.sa_handler = handler;
235 act.sa_flags = 0;
236 sigemptyset (&act.sa_mask);
ccc6cda3 237 sigemptyset (&ohandler->sa_mask);
bb70624e 238 sigaction (sig, &act, &old_handler);
ccc6cda3 239#else
bb70624e 240 old_handler.sa_handler = (SigHandler *)signal (sig, handler);
726f6388 241#endif /* !HAVE_POSIX_SIGNALS */
bb70624e
JA
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
ccc6cda3
JA
249 return (ohandler->sa_handler);
250}
726f6388 251
b72432fd
JA
252static void
253rl_maybe_set_sighandler (sig, handler, ohandler)
254 int sig;
255 SigHandler *handler;
256 sighandler_cxt *ohandler;
726f6388 257{
ccc6cda3
JA
258 sighandler_cxt dummy;
259 SigHandler *oh;
260
ccc6cda3 261 sigemptyset (&dummy.sa_mask);
b72432fd 262 oh = rl_set_sighandler (sig, handler, ohandler);
ccc6cda3 263 if (oh == (SigHandler *)SIG_IGN)
b72432fd
JA
264 rl_sigaction (sig, ohandler, &dummy);
265}
ccc6cda3 266
b72432fd
JA
267int
268rl_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);
ccc6cda3 282#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
b72432fd
JA
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);
ccc6cda3 289#endif /* HAVE_POSIX_SIGNALS */
726f6388 290
726f6388 291#if defined (SIGTSTP)
b72432fd 292 rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
726f6388 293#endif /* SIGTSTP */
ccc6cda3 294
726f6388 295#if defined (SIGTTOU)
b72432fd 296 rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
726f6388
JA
297#endif /* SIGTTOU */
298
b72432fd
JA
299#if defined (SIGTTIN)
300 rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
301#endif /* SIGTTIN */
d166f048 302
b72432fd
JA
303 signals_set_flag = 1;
304 }
726f6388
JA
305
306#if defined (SIGWINCH)
b72432fd
JA
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 }
726f6388 312#endif /* SIGWINCH */
ccc6cda3 313
726f6388
JA
314 return 0;
315}
316
ccc6cda3 317int
726f6388
JA
318rl_clear_signals ()
319{
ccc6cda3
JA
320 sighandler_cxt dummy;
321
b72432fd
JA
322 if (rl_catch_signals && signals_set_flag == 1)
323 {
324 sigemptyset (&dummy.sa_mask);
726f6388 325
b72432fd
JA
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);
726f6388
JA
330
331#if defined (SIGTSTP)
b72432fd
JA
332 rl_sigaction (SIGTSTP, &old_tstp, &dummy);
333#endif /* SIGTSTP */
726f6388
JA
334
335#if defined (SIGTTOU)
b72432fd 336 rl_sigaction (SIGTTOU, &old_ttou, &dummy);
726f6388
JA
337#endif /* SIGTTOU */
338
b72432fd
JA
339#if defined (SIGTTIN)
340 rl_sigaction (SIGTTIN, &old_ttin, &dummy);
341#endif /* SIGTTIN */
ccc6cda3 342
b72432fd
JA
343 signals_set_flag = 0;
344 }
726f6388
JA
345
346#if defined (SIGWINCH)
b72432fd
JA
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 }
726f6388
JA
353#endif
354
355 return 0;
356}
b72432fd
JA
357
358/* Clean up the terminal and readline state after catching a signal, before
359 resending it to the calling application. */
360void
361rl_cleanup_after_signal ()
362{
363 _rl_clean_up_for_exit ();
364 (*rl_deprep_term_function) ();
365 rl_clear_signals ();
28ef6c31 366 rl_clear_pending_input ();
b72432fd
JA
367}
368
369/* Reset the terminal and readline state after a signal handler returns. */
370void
371rl_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(). */
381void
382rl_free_line_state ()
383{
384 register HIST_ENTRY *entry;
385
28ef6c31 386 rl_free_undo_list ();
b72432fd
JA
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
726f6388 397#endif /* HANDLE_SIGNALS */