]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/readline/signals.c
Imported from ../bash-2.05.tar.gz.
[thirdparty/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 */