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