A few tweaks required to use Readline as part of the DJGPP port of GDB.
[deliverable/binutils-gdb.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 equivalant 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 #ifdef SIGWINCH
91 static int sigwinch_set_flag;
92 #endif
93
94 /* **************************************************************** */
95 /* */
96 /* Signal Handling */
97 /* */
98 /* **************************************************************** */
99
100 static sighandler_cxt old_int, old_term, old_alrm, old_quit;
101 #if defined (SIGTSTP)
102 static sighandler_cxt old_tstp, old_ttou, old_ttin;
103 #endif
104 #if defined (SIGWINCH)
105 static sighandler_cxt old_winch;
106 #endif
107
108 /* Readline signal handler functions. */
109
110 static RETSIGTYPE
111 rl_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:
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 SIGHANDLER_RETURN;
175 }
176
177 #if defined (SIGWINCH)
178 static RETSIGTYPE
179 rl_sigwinch_handler (sig)
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. */
191 rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
192 #endif
193
194 rl_resize_terminal ();
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)
208 static int
209 rl_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(). */
221 static SigHandler *
222 rl_set_sighandler (sig, handler, ohandler)
223 int sig;
224 SigHandler *handler;
225 sighandler_cxt *ohandler;
226 {
227 sighandler_cxt old_handler;
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);
235 sigaction (sig, &act, &old_handler);
236 #else
237 old_handler.sa_handler = (SigHandler *)signal (sig, handler);
238 #endif /* !HAVE_POSIX_SIGNALS */
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
246 return (ohandler->sa_handler);
247 }
248
249 static void
250 rl_maybe_set_sighandler (sig, handler, ohandler)
251 int sig;
252 SigHandler *handler;
253 sighandler_cxt *ohandler;
254 {
255 sighandler_cxt dummy;
256 SigHandler *oh;
257
258 sigemptyset (&dummy.sa_mask);
259 oh = rl_set_sighandler (sig, handler, ohandler);
260 if (oh == (SigHandler *)SIG_IGN)
261 rl_sigaction (sig, ohandler, &dummy);
262 }
263
264 int
265 rl_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);
279 #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
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);
286 #endif /* HAVE_POSIX_SIGNALS */
287
288 #if defined (SIGTSTP)
289 rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
290 #endif /* SIGTSTP */
291
292 #if defined (SIGTTOU)
293 rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
294 #endif /* SIGTTOU */
295
296 #if defined (SIGTTIN)
297 rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
298 #endif /* SIGTTIN */
299
300 signals_set_flag = 1;
301 }
302
303 #if defined (SIGWINCH)
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 }
309 #endif /* SIGWINCH */
310
311 return 0;
312 }
313
314 int
315 rl_clear_signals ()
316 {
317 sighandler_cxt dummy;
318
319 if (rl_catch_signals && signals_set_flag == 1)
320 {
321 sigemptyset (&dummy.sa_mask);
322
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);
327
328 #if defined (SIGTSTP)
329 rl_sigaction (SIGTSTP, &old_tstp, &dummy);
330 #endif /* SIGTSTP */
331
332 #if defined (SIGTTOU)
333 rl_sigaction (SIGTTOU, &old_ttou, &dummy);
334 #endif /* SIGTTOU */
335
336 #if defined (SIGTTIN)
337 rl_sigaction (SIGTTIN, &old_ttin, &dummy);
338 #endif /* SIGTTIN */
339
340 signals_set_flag = 0;
341 }
342
343 #if defined (SIGWINCH)
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 }
350 #endif
351
352 return 0;
353 }
354
355 /* Clean up the terminal and readline state after catching a signal, before
356 resending it to the calling application. */
357 void
358 rl_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. */
367 void
368 rl_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(). */
378 void
379 rl_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
394 #endif /* HANDLE_SIGNALS */
This page took 0.044057 seconds and 4 git commands to generate.