]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
1 | /* signals.c -- signal handling support for readline. */ |
2 | ||
d233b485 | 3 | /* Copyright (C) 1987-2017 Free Software Foundation, Inc. |
726f6388 | 4 | |
3185942a JA |
5 | This file is part of the GNU Readline Library (Readline), a library |
6 | for reading lines of text with interactive input and history editing. | |
726f6388 | 7 | |
3185942a JA |
8 | Readline is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation, either version 3 of the License, or | |
726f6388 JA |
11 | (at your option) any later version. |
12 | ||
3185942a JA |
13 | Readline is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
726f6388 JA |
16 | GNU General Public License for more details. |
17 | ||
3185942a JA |
18 | You should have received a copy of the GNU General Public License |
19 | along with Readline. If not, see <http://www.gnu.org/licenses/>. | |
20 | */ | |
21 | ||
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 | ||
43 | /* Some standard library routines. */ | |
44 | #include "readline.h" | |
45 | #include "history.h" | |
46 | ||
bb70624e JA |
47 | #include "rlprivate.h" |
48 | ||
3185942a JA |
49 | #if defined (HANDLE_SIGNALS) |
50 | ||
ccc6cda3 JA |
51 | #if !defined (RETSIGTYPE) |
52 | # if defined (VOID_SIGHANDLER) | |
53 | # define RETSIGTYPE void | |
54 | # else | |
55 | # define RETSIGTYPE int | |
56 | # endif /* !VOID_SIGHANDLER */ | |
57 | #endif /* !RETSIGTYPE */ | |
726f6388 JA |
58 | |
59 | #if defined (VOID_SIGHANDLER) | |
ccc6cda3 | 60 | # define SIGHANDLER_RETURN return |
726f6388 | 61 | #else |
ccc6cda3 JA |
62 | # define SIGHANDLER_RETURN return (0) |
63 | #endif | |
726f6388 | 64 | |
28ef6c31 | 65 | /* This typedef is equivalent to the one for Function; it allows us |
726f6388 | 66 | to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */ |
ccc6cda3 | 67 | typedef RETSIGTYPE SigHandler (); |
726f6388 | 68 | |
bb70624e JA |
69 | #if defined (HAVE_POSIX_SIGNALS) |
70 | typedef struct sigaction sighandler_cxt; | |
71 | # define rl_sigaction(s, nh, oh) sigaction(s, nh, oh) | |
72 | #else | |
73 | typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt; | |
74 | # define sigemptyset(m) | |
75 | #endif /* !HAVE_POSIX_SIGNALS */ | |
b72432fd | 76 | |
b80f6443 JA |
77 | #ifndef SA_RESTART |
78 | # define SA_RESTART 0 | |
79 | #endif | |
80 | ||
f73dda09 | 81 | static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); |
7117c2d2 | 82 | static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *)); |
ac50fbac | 83 | static void rl_maybe_restore_sighandler PARAMS((int, sighandler_cxt *)); |
726f6388 | 84 | |
17345e5a JA |
85 | static RETSIGTYPE rl_signal_handler PARAMS((int)); |
86 | static RETSIGTYPE _rl_handle_signal PARAMS((int)); | |
87 | ||
b72432fd JA |
88 | /* Exported variables for use by applications. */ |
89 | ||
90 | /* If non-zero, readline will install its own signal handlers for | |
ac50fbac | 91 | SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */ |
b72432fd JA |
92 | int rl_catch_signals = 1; |
93 | ||
94 | /* If non-zero, readline will install a signal handler for SIGWINCH. */ | |
95 | #ifdef SIGWINCH | |
96 | int rl_catch_sigwinch = 1; | |
b80f6443 JA |
97 | #else |
98 | int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */ | |
b72432fd JA |
99 | #endif |
100 | ||
3185942a | 101 | /* Private variables. */ |
17345e5a JA |
102 | int volatile _rl_caught_signal = 0; /* should be sig_atomic_t, but that requires including <signal.h> everywhere */ |
103 | ||
0001803f CR |
104 | /* If non-zero, print characters corresponding to received signals as long as |
105 | the user has indicated his desire to do so (_rl_echo_control_chars). */ | |
3185942a JA |
106 | int _rl_echoctl = 0; |
107 | ||
108 | int _rl_intr_char = 0; | |
109 | int _rl_quit_char = 0; | |
110 | int _rl_susp_char = 0; | |
111 | ||
b72432fd JA |
112 | static int signals_set_flag; |
113 | static int sigwinch_set_flag; | |
114 | ||
d233b485 CR |
115 | #if defined (HAVE_POSIX_SIGNALS) |
116 | sigset_t _rl_orig_sigset; | |
117 | #endif /* !HAVE_POSIX_SIGNALS */ | |
118 | ||
726f6388 JA |
119 | /* **************************************************************** */ |
120 | /* */ | |
121 | /* Signal Handling */ | |
122 | /* */ | |
123 | /* **************************************************************** */ | |
124 | ||
ac50fbac | 125 | static sighandler_cxt old_int, old_term, old_hup, old_alrm, old_quit; |
b72432fd | 126 | #if defined (SIGTSTP) |
d166f048 | 127 | static sighandler_cxt old_tstp, old_ttou, old_ttin; |
d166f048 | 128 | #endif |
ccc6cda3 JA |
129 | #if defined (SIGWINCH) |
130 | static sighandler_cxt old_winch; | |
131 | #endif | |
132 | ||
ac50fbac CR |
133 | _rl_sigcleanup_func_t *_rl_sigcleanup; |
134 | void *_rl_sigcleanarg; | |
135 | ||
ccc6cda3 JA |
136 | /* Readline signal handler functions. */ |
137 | ||
8868edaf | 138 | /* Called from RL_CHECK_SIGNALS() macro to run signal handling code. */ |
17345e5a | 139 | RETSIGTYPE |
d233b485 | 140 | _rl_signal_handler (int sig) |
17345e5a JA |
141 | { |
142 | _rl_caught_signal = 0; /* XXX */ | |
143 | ||
ac50fbac CR |
144 | #if defined (SIGWINCH) |
145 | if (sig == SIGWINCH) | |
146 | { | |
8868edaf CR |
147 | RL_SETSTATE(RL_STATE_SIGHANDLER); |
148 | ||
ac50fbac CR |
149 | rl_resize_terminal (); |
150 | /* XXX - experimental for now */ | |
151 | /* Call a signal hook because though we called the original signal handler | |
152 | in rl_sigwinch_handler below, we will not resend the signal to | |
153 | ourselves. */ | |
154 | if (rl_signal_event_hook) | |
155 | (*rl_signal_event_hook) (); | |
8868edaf CR |
156 | |
157 | RL_UNSETSTATE(RL_STATE_SIGHANDLER); | |
ac50fbac CR |
158 | } |
159 | else | |
160 | #endif | |
161 | _rl_handle_signal (sig); | |
162 | ||
17345e5a JA |
163 | SIGHANDLER_RETURN; |
164 | } | |
165 | ||
ccc6cda3 | 166 | static RETSIGTYPE |
d233b485 | 167 | rl_signal_handler (int sig) |
17345e5a | 168 | { |
8868edaf | 169 | _rl_caught_signal = sig; |
17345e5a JA |
170 | SIGHANDLER_RETURN; |
171 | } | |
172 | ||
8868edaf CR |
173 | /* This is called to handle a signal when it is safe to do so (out of the |
174 | signal handler execution path). Called by _rl_signal_handler for all the | |
175 | signals readline catches except SIGWINCH. */ | |
17345e5a | 176 | static RETSIGTYPE |
d233b485 | 177 | _rl_handle_signal (int sig) |
726f6388 | 178 | { |
8868edaf CR |
179 | int block_sig; |
180 | ||
726f6388 | 181 | #if defined (HAVE_POSIX_SIGNALS) |
8868edaf | 182 | sigset_t set, oset; |
726f6388 JA |
183 | #else /* !HAVE_POSIX_SIGNALS */ |
184 | # if defined (HAVE_BSD_SIGNALS) | |
185 | long omask; | |
d166f048 JA |
186 | # else /* !HAVE_BSD_SIGNALS */ |
187 | sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */ | |
188 | # endif /* !HAVE_BSD_SIGNALS */ | |
726f6388 JA |
189 | #endif /* !HAVE_POSIX_SIGNALS */ |
190 | ||
28ef6c31 JA |
191 | RL_SETSTATE(RL_STATE_SIGHANDLER); |
192 | ||
726f6388 JA |
193 | #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS) |
194 | /* Since the signal will not be blocked while we are in the signal | |
195 | handler, ignore it until rl_clear_signals resets the catcher. */ | |
95732b49 | 196 | # if defined (SIGALRM) |
ccc6cda3 | 197 | if (sig == SIGINT || sig == SIGALRM) |
95732b49 JA |
198 | # else |
199 | if (sig == SIGINT) | |
200 | # endif | |
d166f048 | 201 | rl_set_sighandler (sig, SIG_IGN, &dummy_cxt); |
ccc6cda3 | 202 | #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */ |
726f6388 | 203 | |
ac50fbac CR |
204 | /* If there's a sig cleanup function registered, call it and `deregister' |
205 | the cleanup function to avoid multiple calls */ | |
206 | if (_rl_sigcleanup) | |
207 | { | |
208 | (*_rl_sigcleanup) (sig, _rl_sigcleanarg); | |
209 | _rl_sigcleanup = 0; | |
210 | _rl_sigcleanarg = 0; | |
211 | } | |
8868edaf CR |
212 | |
213 | #if defined (HAVE_POSIX_SIGNALS) | |
214 | /* Get the current set of blocked signals. If we want to block a signal for | |
215 | the duration of the cleanup functions, make sure to add it to SET and | |
216 | set block_sig = 1 (see the SIGHUP case below). */ | |
217 | block_sig = 0; /* sentinel to block signals with sigprocmask */ | |
218 | sigemptyset (&set); | |
219 | sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); | |
220 | #endif | |
221 | ||
726f6388 JA |
222 | switch (sig) |
223 | { | |
224 | case SIGINT: | |
3185942a | 225 | _rl_reset_completion_state (); |
b72432fd | 226 | rl_free_line_state (); |
a0c0a00f CR |
227 | #if defined (READLINE_CALLBACKS) |
228 | rl_callback_sigcleanup (); | |
229 | #endif | |
230 | ||
b72432fd | 231 | /* FALLTHROUGH */ |
726f6388 JA |
232 | |
233 | #if defined (SIGTSTP) | |
234 | case SIGTSTP: | |
726f6388 | 235 | case SIGTTIN: |
8868edaf | 236 | case SIGTTOU: |
a0c0a00f CR |
237 | # if defined (HAVE_POSIX_SIGNALS) |
238 | /* Block SIGTTOU so we can restore the terminal settings to something | |
239 | sane without stopping on SIGTTOU if we have been placed into the | |
240 | background. Even trying to get the current terminal pgrp with | |
8868edaf CR |
241 | tcgetpgrp() will generate SIGTTOU, so we don't bother. We still do |
242 | this even if we've been stopped on SIGTTOU, since we handle signals | |
243 | when we have returned from the signal handler and the signal is no | |
244 | longer blocked. */ | |
a0c0a00f | 245 | sigaddset (&set, SIGTTOU); |
8868edaf | 246 | block_sig = 1; |
a0c0a00f | 247 | # endif |
726f6388 | 248 | #endif /* SIGTSTP */ |
8868edaf | 249 | /* Any signals that should be blocked during cleanup should go here. */ |
a0c0a00f CR |
250 | #if defined (SIGHUP) |
251 | case SIGHUP: | |
8868edaf CR |
252 | # if defined (_AIX) |
253 | if (block_sig == 0) | |
254 | { | |
255 | sigaddset (&set, sig); | |
256 | block_sig = 1; | |
257 | } | |
258 | # endif // _AIX | |
a0c0a00f | 259 | #endif |
8868edaf CR |
260 | /* Signals that don't require blocking during cleanup should go here. */ |
261 | case SIGTERM: | |
95732b49 | 262 | #if defined (SIGALRM) |
726f6388 | 263 | case SIGALRM: |
95732b49 JA |
264 | #endif |
265 | #if defined (SIGQUIT) | |
b72432fd | 266 | case SIGQUIT: |
95732b49 | 267 | #endif |
8868edaf CR |
268 | |
269 | if (block_sig) | |
270 | sigprocmask (SIG_BLOCK, &set, &oset); | |
271 | ||
3185942a | 272 | rl_echo_signal_char (sig); |
b72432fd | 273 | rl_cleanup_after_signal (); |
726f6388 | 274 | |
8868edaf CR |
275 | /* At this point, the application's signal handler, if any, is the |
276 | current handler. */ | |
277 | ||
726f6388 | 278 | #if defined (HAVE_POSIX_SIGNALS) |
8868edaf CR |
279 | /* Unblock any signal(s) blocked above */ |
280 | if (block_sig) | |
281 | sigprocmask (SIG_UNBLOCK, &oset, (sigset_t *)NULL); | |
282 | #endif | |
a0c0a00f | 283 | |
8868edaf CR |
284 | /* We don't have to bother unblocking the signal because we are not |
285 | running in a signal handler context. */ | |
286 | #if 0 | |
287 | #if defined (HAVE_POSIX_SIGNALS) | |
288 | /* Make sure this signal is not blocked when we resend it to the | |
289 | calling application. */ | |
0628567a | 290 | sigemptyset (&set); |
726f6388 JA |
291 | sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set); |
292 | sigdelset (&set, sig); | |
293 | #else /* !HAVE_POSIX_SIGNALS */ | |
294 | # if defined (HAVE_BSD_SIGNALS) | |
295 | omask = sigblock (0); | |
296 | # endif /* HAVE_BSD_SIGNALS */ | |
297 | #endif /* !HAVE_POSIX_SIGNALS */ | |
8868edaf | 298 | #endif |
726f6388 | 299 | |
bb70624e JA |
300 | #if defined (__EMX__) |
301 | signal (sig, SIG_ACK); | |
302 | #endif | |
303 | ||
95732b49 | 304 | #if defined (HAVE_KILL) |
726f6388 | 305 | kill (getpid (), sig); |
95732b49 JA |
306 | #else |
307 | raise (sig); /* assume we have raise */ | |
308 | #endif | |
726f6388 | 309 | |
8868edaf CR |
310 | /* We don't need to modify the signal mask now that this is not run in |
311 | a signal handler context. */ | |
312 | #if 0 | |
313 | /* Let the signal that we just sent through if it is blocked. */ | |
726f6388 JA |
314 | #if defined (HAVE_POSIX_SIGNALS) |
315 | sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL); | |
316 | #else /* !HAVE_POSIX_SIGNALS */ | |
317 | # if defined (HAVE_BSD_SIGNALS) | |
318 | sigsetmask (omask & ~(sigmask (sig))); | |
319 | # endif /* HAVE_BSD_SIGNALS */ | |
320 | #endif /* !HAVE_POSIX_SIGNALS */ | |
8868edaf | 321 | #endif |
726f6388 | 322 | |
ac50fbac | 323 | rl_reset_after_signal (); |
726f6388 JA |
324 | } |
325 | ||
28ef6c31 | 326 | RL_UNSETSTATE(RL_STATE_SIGHANDLER); |
ccc6cda3 | 327 | SIGHANDLER_RETURN; |
726f6388 JA |
328 | } |
329 | ||
ccc6cda3 JA |
330 | #if defined (SIGWINCH) |
331 | static RETSIGTYPE | |
d233b485 | 332 | rl_sigwinch_handler (int sig) |
ccc6cda3 JA |
333 | { |
334 | SigHandler *oh; | |
335 | ||
d166f048 JA |
336 | #if defined (MUST_REINSTALL_SIGHANDLERS) |
337 | sighandler_cxt dummy_winch; | |
338 | ||
339 | /* We don't want to change old_winch -- it holds the state of SIGWINCH | |
340 | disposition set by the calling application. We need this state | |
341 | because we call the application's SIGWINCH handler after updating | |
342 | our own idea of the screen size. */ | |
b72432fd | 343 | rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch); |
d166f048 JA |
344 | #endif |
345 | ||
28ef6c31 | 346 | RL_SETSTATE(RL_STATE_SIGHANDLER); |
ac50fbac | 347 | _rl_caught_signal = sig; |
ccc6cda3 JA |
348 | |
349 | /* If another sigwinch handler has been installed, call it. */ | |
350 | oh = (SigHandler *)old_winch.sa_handler; | |
351 | if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL) | |
352 | (*oh) (sig); | |
353 | ||
28ef6c31 | 354 | RL_UNSETSTATE(RL_STATE_SIGHANDLER); |
ccc6cda3 JA |
355 | SIGHANDLER_RETURN; |
356 | } | |
357 | #endif /* SIGWINCH */ | |
358 | ||
359 | /* Functions to manage signal handling. */ | |
360 | ||
361 | #if !defined (HAVE_POSIX_SIGNALS) | |
362 | static int | |
d233b485 | 363 | rl_sigaction (int sig, sighandler_cxt *nh, sighandler_cxt *oh) |
ccc6cda3 JA |
364 | { |
365 | oh->sa_handler = signal (sig, nh->sa_handler); | |
366 | return 0; | |
367 | } | |
368 | #endif /* !HAVE_POSIX_SIGNALS */ | |
369 | ||
370 | /* Set up a readline-specific signal handler, saving the old signal | |
371 | information in OHANDLER. Return the old signal handler, like | |
372 | signal(). */ | |
726f6388 | 373 | static SigHandler * |
d233b485 | 374 | rl_set_sighandler (int sig, SigHandler *handler, sighandler_cxt *ohandler) |
726f6388 | 375 | { |
bb70624e | 376 | sighandler_cxt old_handler; |
ccc6cda3 JA |
377 | #if defined (HAVE_POSIX_SIGNALS) |
378 | struct sigaction act; | |
726f6388 JA |
379 | |
380 | act.sa_handler = handler; | |
3185942a | 381 | # if defined (SIGWINCH) |
b80f6443 | 382 | act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0; |
3185942a JA |
383 | # else |
384 | act.sa_flags = 0; | |
385 | # endif /* SIGWINCH */ | |
726f6388 | 386 | sigemptyset (&act.sa_mask); |
ccc6cda3 | 387 | sigemptyset (&ohandler->sa_mask); |
bb70624e | 388 | sigaction (sig, &act, &old_handler); |
ccc6cda3 | 389 | #else |
bb70624e | 390 | old_handler.sa_handler = (SigHandler *)signal (sig, handler); |
726f6388 | 391 | #endif /* !HAVE_POSIX_SIGNALS */ |
bb70624e JA |
392 | |
393 | /* XXX -- assume we have memcpy */ | |
394 | /* If rl_set_signals is called twice in a row, don't set the old handler to | |
395 | rl_signal_handler, because that would cause infinite recursion. */ | |
396 | if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler) | |
397 | memcpy (ohandler, &old_handler, sizeof (sighandler_cxt)); | |
398 | ||
ccc6cda3 JA |
399 | return (ohandler->sa_handler); |
400 | } | |
726f6388 | 401 | |
ac50fbac CR |
402 | /* Set disposition of SIG to HANDLER, returning old state in OHANDLER. Don't |
403 | change disposition if OHANDLER indicates the signal was ignored. */ | |
b72432fd | 404 | static void |
d233b485 | 405 | rl_maybe_set_sighandler (int sig, SigHandler *handler, sighandler_cxt *ohandler) |
726f6388 | 406 | { |
ccc6cda3 JA |
407 | sighandler_cxt dummy; |
408 | SigHandler *oh; | |
409 | ||
ccc6cda3 | 410 | sigemptyset (&dummy.sa_mask); |
ac50fbac | 411 | dummy.sa_flags = 0; |
b72432fd | 412 | oh = rl_set_sighandler (sig, handler, ohandler); |
ccc6cda3 | 413 | if (oh == (SigHandler *)SIG_IGN) |
b72432fd JA |
414 | rl_sigaction (sig, ohandler, &dummy); |
415 | } | |
ccc6cda3 | 416 | |
ac50fbac CR |
417 | /* Set the disposition of SIG to HANDLER, if HANDLER->sa_handler indicates the |
418 | signal was not being ignored. MUST only be called for signals whose | |
419 | disposition was changed using rl_maybe_set_sighandler or for which the | |
420 | SIG_IGN check was performed inline (e.g., SIGALRM below). */ | |
421 | static void | |
d233b485 | 422 | rl_maybe_restore_sighandler (int sig, sighandler_cxt *handler) |
ac50fbac CR |
423 | { |
424 | sighandler_cxt dummy; | |
425 | ||
426 | sigemptyset (&dummy.sa_mask); | |
427 | dummy.sa_flags = 0; | |
428 | if (handler->sa_handler != SIG_IGN) | |
429 | rl_sigaction (sig, handler, &dummy); | |
430 | } | |
431 | ||
b72432fd | 432 | int |
d233b485 | 433 | rl_set_signals (void) |
b72432fd JA |
434 | { |
435 | sighandler_cxt dummy; | |
436 | SigHandler *oh; | |
0628567a JA |
437 | #if defined (HAVE_POSIX_SIGNALS) |
438 | static int sigmask_set = 0; | |
439 | static sigset_t bset, oset; | |
440 | #endif | |
441 | ||
442 | #if defined (HAVE_POSIX_SIGNALS) | |
443 | if (rl_catch_signals && sigmask_set == 0) | |
444 | { | |
445 | sigemptyset (&bset); | |
446 | ||
447 | sigaddset (&bset, SIGINT); | |
3185942a | 448 | sigaddset (&bset, SIGTERM); |
a0c0a00f | 449 | #if defined (SIGHUP) |
ac50fbac | 450 | sigaddset (&bset, SIGHUP); |
a0c0a00f | 451 | #endif |
0628567a JA |
452 | #if defined (SIGQUIT) |
453 | sigaddset (&bset, SIGQUIT); | |
454 | #endif | |
455 | #if defined (SIGALRM) | |
456 | sigaddset (&bset, SIGALRM); | |
457 | #endif | |
458 | #if defined (SIGTSTP) | |
459 | sigaddset (&bset, SIGTSTP); | |
460 | #endif | |
461 | #if defined (SIGTTIN) | |
462 | sigaddset (&bset, SIGTTIN); | |
463 | #endif | |
464 | #if defined (SIGTTOU) | |
465 | sigaddset (&bset, SIGTTOU); | |
466 | #endif | |
467 | sigmask_set = 1; | |
468 | } | |
469 | #endif /* HAVE_POSIX_SIGNALS */ | |
b72432fd JA |
470 | |
471 | if (rl_catch_signals && signals_set_flag == 0) | |
472 | { | |
0628567a | 473 | #if defined (HAVE_POSIX_SIGNALS) |
d233b485 CR |
474 | sigemptyset (&_rl_orig_sigset); |
475 | sigprocmask (SIG_BLOCK, &bset, &_rl_orig_sigset); | |
0628567a JA |
476 | #endif |
477 | ||
b72432fd JA |
478 | rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int); |
479 | rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term); | |
a0c0a00f | 480 | #if defined (SIGHUP) |
ac50fbac | 481 | rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup); |
a0c0a00f | 482 | #endif |
95732b49 | 483 | #if defined (SIGQUIT) |
b72432fd | 484 | rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit); |
95732b49 | 485 | #endif |
b72432fd | 486 | |
95732b49 | 487 | #if defined (SIGALRM) |
b72432fd JA |
488 | oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm); |
489 | if (oh == (SigHandler *)SIG_IGN) | |
490 | rl_sigaction (SIGALRM, &old_alrm, &dummy); | |
ccc6cda3 | 491 | #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART) |
b72432fd JA |
492 | /* If the application using readline has already installed a signal |
493 | handler with SA_RESTART, SIGALRM will cause reads to be restarted | |
494 | automatically, so readline should just get out of the way. Since | |
495 | we tested for SIG_IGN above, we can just test for SIG_DFL here. */ | |
496 | if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART)) | |
497 | rl_sigaction (SIGALRM, &old_alrm, &dummy); | |
ccc6cda3 | 498 | #endif /* HAVE_POSIX_SIGNALS */ |
95732b49 | 499 | #endif /* SIGALRM */ |
726f6388 | 500 | |
726f6388 | 501 | #if defined (SIGTSTP) |
b72432fd | 502 | rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp); |
726f6388 | 503 | #endif /* SIGTSTP */ |
ccc6cda3 | 504 | |
726f6388 | 505 | #if defined (SIGTTOU) |
b72432fd | 506 | rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou); |
726f6388 JA |
507 | #endif /* SIGTTOU */ |
508 | ||
b72432fd JA |
509 | #if defined (SIGTTIN) |
510 | rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin); | |
511 | #endif /* SIGTTIN */ | |
d166f048 | 512 | |
b72432fd | 513 | signals_set_flag = 1; |
0628567a JA |
514 | |
515 | #if defined (HAVE_POSIX_SIGNALS) | |
d233b485 CR |
516 | sigprocmask (SIG_SETMASK, &_rl_orig_sigset, (sigset_t *)NULL); |
517 | #endif | |
518 | } | |
519 | else if (rl_catch_signals == 0) | |
520 | { | |
521 | #if defined (HAVE_POSIX_SIGNALS) | |
522 | sigemptyset (&_rl_orig_sigset); | |
523 | sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &_rl_orig_sigset); | |
0628567a | 524 | #endif |
b72432fd | 525 | } |
726f6388 JA |
526 | |
527 | #if defined (SIGWINCH) | |
b72432fd JA |
528 | if (rl_catch_sigwinch && sigwinch_set_flag == 0) |
529 | { | |
530 | rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch); | |
531 | sigwinch_set_flag = 1; | |
532 | } | |
726f6388 | 533 | #endif /* SIGWINCH */ |
ccc6cda3 | 534 | |
726f6388 JA |
535 | return 0; |
536 | } | |
537 | ||
ccc6cda3 | 538 | int |
d233b485 | 539 | rl_clear_signals (void) |
726f6388 | 540 | { |
ccc6cda3 JA |
541 | sighandler_cxt dummy; |
542 | ||
b72432fd JA |
543 | if (rl_catch_signals && signals_set_flag == 1) |
544 | { | |
ac50fbac CR |
545 | /* Since rl_maybe_set_sighandler doesn't override a SIG_IGN handler, |
546 | we should in theory not have to restore a handler where | |
547 | old_xxx.sa_handler == SIG_IGN. That's what rl_maybe_restore_sighandler | |
548 | does. Fewer system calls should reduce readline's per-line | |
549 | overhead */ | |
550 | rl_maybe_restore_sighandler (SIGINT, &old_int); | |
551 | rl_maybe_restore_sighandler (SIGTERM, &old_term); | |
a0c0a00f | 552 | #if defined (SIGHUP) |
ac50fbac | 553 | rl_maybe_restore_sighandler (SIGHUP, &old_hup); |
a0c0a00f | 554 | #endif |
95732b49 | 555 | #if defined (SIGQUIT) |
ac50fbac | 556 | rl_maybe_restore_sighandler (SIGQUIT, &old_quit); |
95732b49 JA |
557 | #endif |
558 | #if defined (SIGALRM) | |
ac50fbac | 559 | rl_maybe_restore_sighandler (SIGALRM, &old_alrm); |
95732b49 | 560 | #endif |
726f6388 JA |
561 | |
562 | #if defined (SIGTSTP) | |
ac50fbac | 563 | rl_maybe_restore_sighandler (SIGTSTP, &old_tstp); |
b72432fd | 564 | #endif /* SIGTSTP */ |
726f6388 JA |
565 | |
566 | #if defined (SIGTTOU) | |
ac50fbac | 567 | rl_maybe_restore_sighandler (SIGTTOU, &old_ttou); |
726f6388 JA |
568 | #endif /* SIGTTOU */ |
569 | ||
b72432fd | 570 | #if defined (SIGTTIN) |
ac50fbac | 571 | rl_maybe_restore_sighandler (SIGTTIN, &old_ttin); |
b72432fd | 572 | #endif /* SIGTTIN */ |
ccc6cda3 | 573 | |
b72432fd JA |
574 | signals_set_flag = 0; |
575 | } | |
726f6388 JA |
576 | |
577 | #if defined (SIGWINCH) | |
b72432fd JA |
578 | if (rl_catch_sigwinch && sigwinch_set_flag == 1) |
579 | { | |
580 | sigemptyset (&dummy.sa_mask); | |
581 | rl_sigaction (SIGWINCH, &old_winch, &dummy); | |
582 | sigwinch_set_flag = 0; | |
583 | } | |
726f6388 JA |
584 | #endif |
585 | ||
586 | return 0; | |
587 | } | |
b72432fd JA |
588 | |
589 | /* Clean up the terminal and readline state after catching a signal, before | |
590 | resending it to the calling application. */ | |
591 | void | |
d233b485 | 592 | rl_cleanup_after_signal (void) |
b72432fd JA |
593 | { |
594 | _rl_clean_up_for_exit (); | |
95732b49 JA |
595 | if (rl_deprep_term_function) |
596 | (*rl_deprep_term_function) (); | |
28ef6c31 | 597 | rl_clear_pending_input (); |
0628567a | 598 | rl_clear_signals (); |
b72432fd JA |
599 | } |
600 | ||
601 | /* Reset the terminal and readline state after a signal handler returns. */ | |
602 | void | |
d233b485 | 603 | rl_reset_after_signal (void) |
b72432fd | 604 | { |
95732b49 JA |
605 | if (rl_prep_term_function) |
606 | (*rl_prep_term_function) (_rl_meta_flag); | |
b72432fd JA |
607 | rl_set_signals (); |
608 | } | |
609 | ||
610 | /* Free up the readline variable line state for the current line (undo list, | |
611 | any partial history entry, any keyboard macros in progress, and any | |
612 | numeric arguments in process) after catching a signal, before calling | |
613 | rl_cleanup_after_signal(). */ | |
614 | void | |
d233b485 | 615 | rl_free_line_state (void) |
b72432fd JA |
616 | { |
617 | register HIST_ENTRY *entry; | |
618 | ||
28ef6c31 | 619 | rl_free_undo_list (); |
b72432fd JA |
620 | |
621 | entry = current_history (); | |
622 | if (entry) | |
623 | entry->data = (char *)NULL; | |
624 | ||
625 | _rl_kill_kbd_macro (); | |
626 | rl_clear_message (); | |
95732b49 | 627 | _rl_reset_argument (); |
b72432fd JA |
628 | } |
629 | ||
a0c0a00f | 630 | int |
d233b485 | 631 | rl_pending_signal (void) |
a0c0a00f CR |
632 | { |
633 | return (_rl_caught_signal); | |
634 | } | |
d233b485 CR |
635 | |
636 | void | |
637 | rl_check_signals (void) | |
638 | { | |
639 | RL_CHECK_SIGNALS (); | |
640 | } | |
726f6388 | 641 | #endif /* HANDLE_SIGNALS */ |
3185942a JA |
642 | |
643 | /* **************************************************************** */ | |
644 | /* */ | |
645 | /* SIGINT Management */ | |
646 | /* */ | |
647 | /* **************************************************************** */ | |
648 | ||
649 | #if defined (HAVE_POSIX_SIGNALS) | |
650 | static sigset_t sigint_set, sigint_oset; | |
0001803f | 651 | static sigset_t sigwinch_set, sigwinch_oset; |
3185942a JA |
652 | #else /* !HAVE_POSIX_SIGNALS */ |
653 | # if defined (HAVE_BSD_SIGNALS) | |
654 | static int sigint_oldmask; | |
0001803f | 655 | static int sigwinch_oldmask; |
3185942a JA |
656 | # endif /* HAVE_BSD_SIGNALS */ |
657 | #endif /* !HAVE_POSIX_SIGNALS */ | |
658 | ||
659 | static int sigint_blocked; | |
0001803f | 660 | static int sigwinch_blocked; |
3185942a JA |
661 | |
662 | /* Cause SIGINT to not be delivered until the corresponding call to | |
663 | release_sigint(). */ | |
664 | void | |
d233b485 | 665 | _rl_block_sigint (void) |
3185942a JA |
666 | { |
667 | if (sigint_blocked) | |
668 | return; | |
669 | ||
3185942a JA |
670 | sigint_blocked = 1; |
671 | } | |
672 | ||
673 | /* Allow SIGINT to be delivered. */ | |
674 | void | |
d233b485 | 675 | _rl_release_sigint (void) |
3185942a JA |
676 | { |
677 | if (sigint_blocked == 0) | |
678 | return; | |
679 | ||
3185942a | 680 | sigint_blocked = 0; |
ac50fbac | 681 | RL_CHECK_SIGNALS (); |
3185942a JA |
682 | } |
683 | ||
0001803f CR |
684 | /* Cause SIGWINCH to not be delivered until the corresponding call to |
685 | release_sigwinch(). */ | |
686 | void | |
d233b485 | 687 | _rl_block_sigwinch (void) |
0001803f CR |
688 | { |
689 | if (sigwinch_blocked) | |
690 | return; | |
691 | ||
ac50fbac CR |
692 | #if defined (SIGWINCH) |
693 | ||
0001803f CR |
694 | #if defined (HAVE_POSIX_SIGNALS) |
695 | sigemptyset (&sigwinch_set); | |
696 | sigemptyset (&sigwinch_oset); | |
697 | sigaddset (&sigwinch_set, SIGWINCH); | |
698 | sigprocmask (SIG_BLOCK, &sigwinch_set, &sigwinch_oset); | |
699 | #else /* !HAVE_POSIX_SIGNALS */ | |
700 | # if defined (HAVE_BSD_SIGNALS) | |
701 | sigwinch_oldmask = sigblock (sigmask (SIGWINCH)); | |
702 | # else /* !HAVE_BSD_SIGNALS */ | |
703 | # if defined (HAVE_USG_SIGHOLD) | |
704 | sighold (SIGWINCH); | |
705 | # endif /* HAVE_USG_SIGHOLD */ | |
706 | # endif /* !HAVE_BSD_SIGNALS */ | |
707 | #endif /* !HAVE_POSIX_SIGNALS */ | |
708 | ||
ac50fbac CR |
709 | #endif /* SIGWINCH */ |
710 | ||
0001803f CR |
711 | sigwinch_blocked = 1; |
712 | } | |
713 | ||
714 | /* Allow SIGWINCH to be delivered. */ | |
715 | void | |
d233b485 | 716 | _rl_release_sigwinch (void) |
0001803f CR |
717 | { |
718 | if (sigwinch_blocked == 0) | |
719 | return; | |
720 | ||
ac50fbac CR |
721 | #if defined (SIGWINCH) |
722 | ||
0001803f CR |
723 | #if defined (HAVE_POSIX_SIGNALS) |
724 | sigprocmask (SIG_SETMASK, &sigwinch_oset, (sigset_t *)NULL); | |
725 | #else | |
726 | # if defined (HAVE_BSD_SIGNALS) | |
727 | sigsetmask (sigwinch_oldmask); | |
728 | # else /* !HAVE_BSD_SIGNALS */ | |
729 | # if defined (HAVE_USG_SIGHOLD) | |
730 | sigrelse (SIGWINCH); | |
731 | # endif /* HAVE_USG_SIGHOLD */ | |
732 | # endif /* !HAVE_BSD_SIGNALS */ | |
733 | #endif /* !HAVE_POSIX_SIGNALS */ | |
734 | ||
ac50fbac CR |
735 | #endif /* SIGWINCH */ |
736 | ||
0001803f CR |
737 | sigwinch_blocked = 0; |
738 | } | |
739 | ||
3185942a JA |
740 | /* **************************************************************** */ |
741 | /* */ | |
742 | /* Echoing special control characters */ | |
743 | /* */ | |
744 | /* **************************************************************** */ | |
745 | void | |
d233b485 | 746 | rl_echo_signal_char (int sig) |
3185942a JA |
747 | { |
748 | char cstr[3]; | |
749 | int cslen, c; | |
750 | ||
0001803f | 751 | if (_rl_echoctl == 0 || _rl_echo_control_chars == 0) |
3185942a JA |
752 | return; |
753 | ||
754 | switch (sig) | |
755 | { | |
756 | case SIGINT: c = _rl_intr_char; break; | |
0001803f | 757 | #if defined (SIGQUIT) |
3185942a | 758 | case SIGQUIT: c = _rl_quit_char; break; |
0001803f CR |
759 | #endif |
760 | #if defined (SIGTSTP) | |
3185942a | 761 | case SIGTSTP: c = _rl_susp_char; break; |
0001803f | 762 | #endif |
3185942a JA |
763 | default: return; |
764 | } | |
765 | ||
766 | if (CTRL_CHAR (c) || c == RUBOUT) | |
767 | { | |
768 | cstr[0] = '^'; | |
769 | cstr[1] = CTRL_CHAR (c) ? UNCTRL (c) : '?'; | |
770 | cstr[cslen = 2] = '\0'; | |
771 | } | |
772 | else | |
773 | { | |
774 | cstr[0] = c; | |
775 | cstr[cslen = 1] = '\0'; | |
776 | } | |
777 | ||
778 | _rl_output_some_chars (cstr, cslen); | |
779 | } |