]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/readline/signals.c
Imported from ../bash-2.0.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 1, 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 675 Mass Ave, Cambridge, MA 02139, 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 (__GO32__)
44 # undef HANDLE_SIGNALS
45 #endif /* __GO32__ */
46
47 #if defined (HANDLE_SIGNALS)
48 /* Some standard library routines. */
49 #include "readline.h"
50 #include "history.h"
51
52 extern int readline_echoing_p;
53 extern int rl_pending_input;
54 extern int _rl_meta_flag;
55
56 extern void free_undo_list ();
57 extern void _rl_get_screen_size ();
58 extern void _rl_redisplay_after_sigwinch ();
59 extern void _rl_clean_up_for_exit ();
60 extern void _rl_kill_kbd_macro ();
61 extern void _rl_init_argument ();
62 extern void rl_deprep_terminal (), rl_prep_terminal ();
63
64 #if !defined (RETSIGTYPE)
65 # if defined (VOID_SIGHANDLER)
66 # define RETSIGTYPE void
67 # else
68 # define RETSIGTYPE int
69 # endif /* !VOID_SIGHANDLER */
70 #endif /* !RETSIGTYPE */
71
72 #if defined (VOID_SIGHANDLER)
73 # define SIGHANDLER_RETURN return
74 #else
75 # define SIGHANDLER_RETURN return (0)
76 #endif
77
78 /* This typedef is equivalant to the one for Function; it allows us
79 to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
80 typedef RETSIGTYPE SigHandler ();
81
82 static SigHandler *rl_set_sighandler ();
83
84 /* **************************************************************** */
85 /* */
86 /* Signal Handling */
87 /* */
88 /* **************************************************************** */
89
90 #if defined (HAVE_POSIX_SIGNALS)
91 typedef struct sigaction sighandler_cxt;
92 # define rl_sigaction(s, nh, oh) sigaction(s, nh, oh)
93 #else
94 typedef struct { SigHandler *sa_handler; } sighandler_cxt;
95 # define sigemptyset(m)
96 #endif /* !HAVE_POSIX_SIGNALS */
97
98 static sighandler_cxt old_int, old_alrm;
99
100 #if !defined (SHELL)
101 static sighandler_cxt old_tstp, old_ttou, old_ttin, old_term;
102 #endif /* !SHELL */
103
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 # endif /* HAVE_BSD_SIGNALS */
120 #endif /* !HAVE_POSIX_SIGNALS */
121
122 #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
123 /* Since the signal will not be blocked while we are in the signal
124 handler, ignore it until rl_clear_signals resets the catcher. */
125 if (sig == SIGINT || sig == SIGALRM)
126 rl_set_sighandler (sig, SIG_IGN, (sighandler_cxt *)NULL);
127 #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
128
129 switch (sig)
130 {
131 case SIGINT:
132 {
133 register HIST_ENTRY *entry;
134
135 free_undo_list ();
136
137 entry = current_history ();
138 if (entry)
139 entry->data = (char *)NULL;
140 }
141 _rl_kill_kbd_macro ();
142 rl_clear_message ();
143 _rl_init_argument ();
144
145 #if defined (SIGTSTP)
146 case SIGTSTP:
147 case SIGTTOU:
148 case SIGTTIN:
149 #endif /* SIGTSTP */
150 case SIGALRM:
151 case SIGTERM:
152 _rl_clean_up_for_exit ();
153 (*rl_deprep_term_function) ();
154 rl_clear_signals ();
155 rl_pending_input = 0;
156
157 #if defined (HAVE_POSIX_SIGNALS)
158 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
159 sigdelset (&set, sig);
160 #else /* !HAVE_POSIX_SIGNALS */
161 # if defined (HAVE_BSD_SIGNALS)
162 omask = sigblock (0);
163 # endif /* HAVE_BSD_SIGNALS */
164 #endif /* !HAVE_POSIX_SIGNALS */
165
166 kill (getpid (), sig);
167
168 /* Let the signal that we just sent through. */
169 #if defined (HAVE_POSIX_SIGNALS)
170 sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
171 #else /* !HAVE_POSIX_SIGNALS */
172 # if defined (HAVE_BSD_SIGNALS)
173 sigsetmask (omask & ~(sigmask (sig)));
174 # endif /* HAVE_BSD_SIGNALS */
175 #endif /* !HAVE_POSIX_SIGNALS */
176
177 (*rl_prep_term_function) (_rl_meta_flag);
178 rl_set_signals ();
179 }
180
181 SIGHANDLER_RETURN;
182 }
183
184 #if defined (SIGWINCH)
185 static RETSIGTYPE
186 rl_handle_sigwinch (sig)
187 int sig;
188 {
189 SigHandler *oh;
190
191 if (readline_echoing_p)
192 {
193 _rl_get_screen_size (fileno (rl_instream), 1);
194 _rl_redisplay_after_sigwinch ();
195 }
196
197 /* If another sigwinch handler has been installed, call it. */
198 oh = (SigHandler *)old_winch.sa_handler;
199 if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
200 (*oh) (sig);
201
202 SIGHANDLER_RETURN;
203 }
204 #endif /* SIGWINCH */
205
206 /* Functions to manage signal handling. */
207
208 #if !defined (HAVE_POSIX_SIGNALS)
209 static int
210 rl_sigaction (sig, nh, oh)
211 int sig;
212 sighandler_cxt *nh, *oh;
213 {
214 oh->sa_handler = signal (sig, nh->sa_handler);
215 return 0;
216 }
217 #endif /* !HAVE_POSIX_SIGNALS */
218
219 /* Set up a readline-specific signal handler, saving the old signal
220 information in OHANDLER. Return the old signal handler, like
221 signal(). */
222 static SigHandler *
223 rl_set_sighandler (sig, handler, ohandler)
224 int sig;
225 SigHandler *handler;
226 sighandler_cxt *ohandler;
227 {
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, ohandler);
236 #else
237 ohandler->sa_handler = (SigHandler *)signal (sig, handler);
238 #endif /* !HAVE_POSIX_SIGNALS */
239 return (ohandler->sa_handler);
240 }
241
242 int
243 rl_set_signals ()
244 {
245 sighandler_cxt dummy;
246 SigHandler *oh;
247
248 #if defined (HAVE_POSIX_SIGNALS)
249 sigemptyset (&dummy.sa_mask);
250 #endif
251
252 oh = rl_set_sighandler (SIGINT, rl_signal_handler, &old_int);
253 if (oh == (SigHandler *)SIG_IGN)
254 rl_sigaction (SIGINT, &old_int, &dummy);
255
256 oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
257 if (oh == (SigHandler *)SIG_IGN)
258 rl_sigaction (SIGALRM, &old_alrm, &dummy);
259 #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
260 /* If the application using readline has already installed a signal
261 handler with SA_RESTART, SIGALRM will cause reads to be restarted
262 automatically, so readline should just get out of the way. Since
263 we tested for SIG_IGN above, we can just test for SIG_DFL here. */
264 if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
265 rl_sigaction (SIGALRM, &old_alrm, &dummy);
266 #endif /* HAVE_POSIX_SIGNALS */
267
268 #if !defined (SHELL)
269
270 #if defined (SIGTSTP)
271 oh = rl_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
272 if (oh == (SigHandler *)SIG_IGN)
273 rl_sigaction (SIGTSTP, &old_tstp, &dummy);
274 #else
275 oh = (SigHandler *)NULL;
276 #endif /* SIGTSTP */
277
278 #if defined (SIGTTOU)
279 rl_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
280 rl_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
281
282 if (oh == (SigHandler *)SIG_IGN)
283 {
284 rl_set_sighandler (SIGTTOU, SIG_IGN, &dummy);
285 rl_set_sighandler (SIGTTIN, SIG_IGN, &dummy);
286 }
287 #endif /* SIGTTOU */
288
289 /* Handle SIGTERM if we're not being compiled as part of bash. */
290 rl_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
291 #endif /* !SHELL */
292
293 #if defined (SIGWINCH)
294 rl_set_sighandler (SIGWINCH, rl_handle_sigwinch, &old_winch);
295 #endif /* SIGWINCH */
296
297 return 0;
298 }
299
300 int
301 rl_clear_signals ()
302 {
303 sighandler_cxt dummy;
304
305 #if defined (HAVE_POSIX_SIGNALS)
306 sigemptyset (&dummy.sa_mask);
307 #endif
308
309 rl_sigaction (SIGINT, &old_int, &dummy);
310 rl_sigaction (SIGALRM, &old_alrm, &dummy);
311
312 #if !defined (SHELL)
313
314 #if defined (SIGTSTP)
315 rl_sigaction (SIGTSTP, &old_tstp, &dummy);
316 #endif
317
318 #if defined (SIGTTOU)
319 rl_sigaction (SIGTTOU, &old_ttou, &dummy);
320 rl_sigaction (SIGTTIN, &old_ttin, &dummy);
321 #endif /* SIGTTOU */
322
323 rl_sigaction (SIGTERM, &old_term, &dummy);
324
325 #endif /* !SHELL */
326
327 #if defined (SIGWINCH)
328 sigemptyset (&dummy.sa_mask);
329 rl_sigaction (SIGWINCH, &old_winch, &dummy);
330 #endif
331
332 return 0;
333 }
334 #endif /* HANDLE_SIGNALS */