]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/readline/signals.c
48dd885fbcd052aff1e255799b0b053cabd9316a
[thirdparty/bash.git] / lib / readline / signals.c
1 /* signals.c -- signal handling support for readline. */
2
3 /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
4
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.
7
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
11 (at your option) any later version.
12
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
16 GNU General Public License for more details.
17
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
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 /* Some standard library routines. */
44 #include "readline.h"
45 #include "history.h"
46
47 #include "rlprivate.h"
48
49 #if defined (HANDLE_SIGNALS)
50
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
65 /* This typedef is equivalent to the one for Function; it allows us
66 to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
67 typedef RETSIGTYPE SigHandler ();
68
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 */
76
77 #ifndef SA_RESTART
78 # define SA_RESTART 0
79 #endif
80
81 static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
82 static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
83
84 /* Exported variables for use by applications. */
85
86 /* If non-zero, readline will install its own signal handlers for
87 SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
88 int rl_catch_signals = 1;
89
90 /* If non-zero, readline will install a signal handler for SIGWINCH. */
91 #ifdef SIGWINCH
92 int rl_catch_sigwinch = 1;
93 #else
94 int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
95 #endif
96
97 /* Private variables. */
98 /* If non-zero, print characters corresponding to received signals. */
99 int _rl_echoctl = 0;
100
101 int _rl_intr_char = 0;
102 int _rl_quit_char = 0;
103 int _rl_susp_char = 0;
104
105 static int signals_set_flag;
106 static int sigwinch_set_flag;
107
108 /* **************************************************************** */
109 /* */
110 /* Signal Handling */
111 /* */
112 /* **************************************************************** */
113
114 static sighandler_cxt old_int, old_term, old_alrm, old_quit;
115 #if defined (SIGTSTP)
116 static sighandler_cxt old_tstp, old_ttou, old_ttin;
117 #endif
118 #if defined (SIGWINCH)
119 static sighandler_cxt old_winch;
120 #endif
121
122 /* Readline signal handler functions. */
123
124 static RETSIGTYPE
125 rl_signal_handler (sig)
126 int sig;
127 {
128 #if defined (HAVE_POSIX_SIGNALS)
129 sigset_t set;
130 #else /* !HAVE_POSIX_SIGNALS */
131 # if defined (HAVE_BSD_SIGNALS)
132 long omask;
133 # else /* !HAVE_BSD_SIGNALS */
134 sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
135 # endif /* !HAVE_BSD_SIGNALS */
136 #endif /* !HAVE_POSIX_SIGNALS */
137
138 RL_SETSTATE(RL_STATE_SIGHANDLER);
139
140 #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
141 /* Since the signal will not be blocked while we are in the signal
142 handler, ignore it until rl_clear_signals resets the catcher. */
143 # if defined (SIGALRM)
144 if (sig == SIGINT || sig == SIGALRM)
145 # else
146 if (sig == SIGINT)
147 # endif
148 rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
149 #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
150
151 switch (sig)
152 {
153 case SIGINT:
154 _rl_reset_completion_state ();
155 rl_free_line_state ();
156 /* FALLTHROUGH */
157
158 case SIGTERM:
159 #if defined (SIGTSTP)
160 case SIGTSTP:
161 case SIGTTOU:
162 case SIGTTIN:
163 #endif /* SIGTSTP */
164 #if defined (SIGALRM)
165 case SIGALRM:
166 #endif
167 #if defined (SIGQUIT)
168 case SIGQUIT:
169 #endif
170 rl_echo_signal_char (sig);
171 rl_cleanup_after_signal ();
172
173 #if defined (HAVE_POSIX_SIGNALS)
174 sigemptyset (&set);
175 sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
176 sigdelset (&set, sig);
177 #else /* !HAVE_POSIX_SIGNALS */
178 # if defined (HAVE_BSD_SIGNALS)
179 omask = sigblock (0);
180 # endif /* HAVE_BSD_SIGNALS */
181 #endif /* !HAVE_POSIX_SIGNALS */
182
183 #if defined (__EMX__)
184 signal (sig, SIG_ACK);
185 #endif
186
187 #if defined (HAVE_KILL)
188 kill (getpid (), sig);
189 #else
190 raise (sig); /* assume we have raise */
191 #endif
192
193 /* Let the signal that we just sent through. */
194 #if defined (HAVE_POSIX_SIGNALS)
195 sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
196 #else /* !HAVE_POSIX_SIGNALS */
197 # if defined (HAVE_BSD_SIGNALS)
198 sigsetmask (omask & ~(sigmask (sig)));
199 # endif /* HAVE_BSD_SIGNALS */
200 #endif /* !HAVE_POSIX_SIGNALS */
201
202 rl_reset_after_signal ();
203 }
204
205 RL_UNSETSTATE(RL_STATE_SIGHANDLER);
206 SIGHANDLER_RETURN;
207 }
208
209 #if defined (SIGWINCH)
210 static RETSIGTYPE
211 rl_sigwinch_handler (sig)
212 int sig;
213 {
214 SigHandler *oh;
215
216 #if defined (MUST_REINSTALL_SIGHANDLERS)
217 sighandler_cxt dummy_winch;
218
219 /* We don't want to change old_winch -- it holds the state of SIGWINCH
220 disposition set by the calling application. We need this state
221 because we call the application's SIGWINCH handler after updating
222 our own idea of the screen size. */
223 rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
224 #endif
225
226 RL_SETSTATE(RL_STATE_SIGHANDLER);
227 rl_resize_terminal ();
228
229 /* If another sigwinch handler has been installed, call it. */
230 oh = (SigHandler *)old_winch.sa_handler;
231 if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
232 (*oh) (sig);
233
234 RL_UNSETSTATE(RL_STATE_SIGHANDLER);
235 SIGHANDLER_RETURN;
236 }
237 #endif /* SIGWINCH */
238
239 /* Functions to manage signal handling. */
240
241 #if !defined (HAVE_POSIX_SIGNALS)
242 static int
243 rl_sigaction (sig, nh, oh)
244 int sig;
245 sighandler_cxt *nh, *oh;
246 {
247 oh->sa_handler = signal (sig, nh->sa_handler);
248 return 0;
249 }
250 #endif /* !HAVE_POSIX_SIGNALS */
251
252 /* Set up a readline-specific signal handler, saving the old signal
253 information in OHANDLER. Return the old signal handler, like
254 signal(). */
255 static SigHandler *
256 rl_set_sighandler (sig, handler, ohandler)
257 int sig;
258 SigHandler *handler;
259 sighandler_cxt *ohandler;
260 {
261 sighandler_cxt old_handler;
262 #if defined (HAVE_POSIX_SIGNALS)
263 struct sigaction act;
264
265 act.sa_handler = handler;
266 # if defined (SIGWINCH)
267 act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
268 # else
269 act.sa_flags = 0;
270 # endif /* SIGWINCH */
271 sigemptyset (&act.sa_mask);
272 sigemptyset (&ohandler->sa_mask);
273 sigaction (sig, &act, &old_handler);
274 #else
275 old_handler.sa_handler = (SigHandler *)signal (sig, handler);
276 #endif /* !HAVE_POSIX_SIGNALS */
277
278 /* XXX -- assume we have memcpy */
279 /* If rl_set_signals is called twice in a row, don't set the old handler to
280 rl_signal_handler, because that would cause infinite recursion. */
281 if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
282 memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
283
284 return (ohandler->sa_handler);
285 }
286
287 static void
288 rl_maybe_set_sighandler (sig, handler, ohandler)
289 int sig;
290 SigHandler *handler;
291 sighandler_cxt *ohandler;
292 {
293 sighandler_cxt dummy;
294 SigHandler *oh;
295
296 sigemptyset (&dummy.sa_mask);
297 oh = rl_set_sighandler (sig, handler, ohandler);
298 if (oh == (SigHandler *)SIG_IGN)
299 rl_sigaction (sig, ohandler, &dummy);
300 }
301
302 int
303 rl_set_signals ()
304 {
305 sighandler_cxt dummy;
306 SigHandler *oh;
307 #if defined (HAVE_POSIX_SIGNALS)
308 static int sigmask_set = 0;
309 static sigset_t bset, oset;
310 #endif
311
312 #if defined (HAVE_POSIX_SIGNALS)
313 if (rl_catch_signals && sigmask_set == 0)
314 {
315 sigemptyset (&bset);
316
317 sigaddset (&bset, SIGINT);
318 sigaddset (&bset, SIGTERM);
319 #if defined (SIGQUIT)
320 sigaddset (&bset, SIGQUIT);
321 #endif
322 #if defined (SIGALRM)
323 sigaddset (&bset, SIGALRM);
324 #endif
325 #if defined (SIGTSTP)
326 sigaddset (&bset, SIGTSTP);
327 #endif
328 #if defined (SIGTTIN)
329 sigaddset (&bset, SIGTTIN);
330 #endif
331 #if defined (SIGTTOU)
332 sigaddset (&bset, SIGTTOU);
333 #endif
334 sigmask_set = 1;
335 }
336 #endif /* HAVE_POSIX_SIGNALS */
337
338 if (rl_catch_signals && signals_set_flag == 0)
339 {
340 #if defined (HAVE_POSIX_SIGNALS)
341 sigemptyset (&oset);
342 sigprocmask (SIG_BLOCK, &bset, &oset);
343 #endif
344
345 rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
346 rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
347 #if defined (SIGQUIT)
348 rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
349 #endif
350
351 #if defined (SIGALRM)
352 oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
353 if (oh == (SigHandler *)SIG_IGN)
354 rl_sigaction (SIGALRM, &old_alrm, &dummy);
355 #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
356 /* If the application using readline has already installed a signal
357 handler with SA_RESTART, SIGALRM will cause reads to be restarted
358 automatically, so readline should just get out of the way. Since
359 we tested for SIG_IGN above, we can just test for SIG_DFL here. */
360 if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
361 rl_sigaction (SIGALRM, &old_alrm, &dummy);
362 #endif /* HAVE_POSIX_SIGNALS */
363 #endif /* SIGALRM */
364
365 #if defined (SIGTSTP)
366 rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
367 #endif /* SIGTSTP */
368
369 #if defined (SIGTTOU)
370 rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
371 #endif /* SIGTTOU */
372
373 #if defined (SIGTTIN)
374 rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
375 #endif /* SIGTTIN */
376
377 signals_set_flag = 1;
378
379 #if defined (HAVE_POSIX_SIGNALS)
380 sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
381 #endif
382 }
383
384 #if defined (SIGWINCH)
385 if (rl_catch_sigwinch && sigwinch_set_flag == 0)
386 {
387 rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
388 sigwinch_set_flag = 1;
389 }
390 #endif /* SIGWINCH */
391
392 return 0;
393 }
394
395 int
396 rl_clear_signals ()
397 {
398 sighandler_cxt dummy;
399
400 if (rl_catch_signals && signals_set_flag == 1)
401 {
402 sigemptyset (&dummy.sa_mask);
403
404 rl_sigaction (SIGINT, &old_int, &dummy);
405 rl_sigaction (SIGTERM, &old_term, &dummy);
406 #if defined (SIGQUIT)
407 rl_sigaction (SIGQUIT, &old_quit, &dummy);
408 #endif
409 #if defined (SIGALRM)
410 rl_sigaction (SIGALRM, &old_alrm, &dummy);
411 #endif
412
413 #if defined (SIGTSTP)
414 rl_sigaction (SIGTSTP, &old_tstp, &dummy);
415 #endif /* SIGTSTP */
416
417 #if defined (SIGTTOU)
418 rl_sigaction (SIGTTOU, &old_ttou, &dummy);
419 #endif /* SIGTTOU */
420
421 #if defined (SIGTTIN)
422 rl_sigaction (SIGTTIN, &old_ttin, &dummy);
423 #endif /* SIGTTIN */
424
425 signals_set_flag = 0;
426 }
427
428 #if defined (SIGWINCH)
429 if (rl_catch_sigwinch && sigwinch_set_flag == 1)
430 {
431 sigemptyset (&dummy.sa_mask);
432 rl_sigaction (SIGWINCH, &old_winch, &dummy);
433 sigwinch_set_flag = 0;
434 }
435 #endif
436
437 return 0;
438 }
439
440 /* Clean up the terminal and readline state after catching a signal, before
441 resending it to the calling application. */
442 void
443 rl_cleanup_after_signal ()
444 {
445 _rl_clean_up_for_exit ();
446 if (rl_deprep_term_function)
447 (*rl_deprep_term_function) ();
448 rl_clear_pending_input ();
449 rl_clear_signals ();
450 }
451
452 /* Reset the terminal and readline state after a signal handler returns. */
453 void
454 rl_reset_after_signal ()
455 {
456 if (rl_prep_term_function)
457 (*rl_prep_term_function) (_rl_meta_flag);
458 rl_set_signals ();
459 }
460
461 /* Free up the readline variable line state for the current line (undo list,
462 any partial history entry, any keyboard macros in progress, and any
463 numeric arguments in process) after catching a signal, before calling
464 rl_cleanup_after_signal(). */
465 void
466 rl_free_line_state ()
467 {
468 register HIST_ENTRY *entry;
469
470 rl_free_undo_list ();
471
472 entry = current_history ();
473 if (entry)
474 entry->data = (char *)NULL;
475
476 _rl_kill_kbd_macro ();
477 rl_clear_message ();
478 _rl_reset_argument ();
479 }
480
481 #endif /* HANDLE_SIGNALS */
482
483 /* **************************************************************** */
484 /* */
485 /* SIGINT Management */
486 /* */
487 /* **************************************************************** */
488
489 #if defined (HAVE_POSIX_SIGNALS)
490 static sigset_t sigint_set, sigint_oset;
491 #else /* !HAVE_POSIX_SIGNALS */
492 # if defined (HAVE_BSD_SIGNALS)
493 static int sigint_oldmask;
494 # endif /* HAVE_BSD_SIGNALS */
495 #endif /* !HAVE_POSIX_SIGNALS */
496
497 static int sigint_blocked;
498
499 /* Cause SIGINT to not be delivered until the corresponding call to
500 release_sigint(). */
501 void
502 _rl_block_sigint ()
503 {
504 if (sigint_blocked)
505 return;
506
507 #if defined (HAVE_POSIX_SIGNALS)
508 sigemptyset (&sigint_set);
509 sigemptyset (&sigint_oset);
510 sigaddset (&sigint_set, SIGINT);
511 sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
512 #else /* !HAVE_POSIX_SIGNALS */
513 # if defined (HAVE_BSD_SIGNALS)
514 sigint_oldmask = sigblock (sigmask (SIGINT));
515 # else /* !HAVE_BSD_SIGNALS */
516 # if defined (HAVE_USG_SIGHOLD)
517 sighold (SIGINT);
518 # endif /* HAVE_USG_SIGHOLD */
519 # endif /* !HAVE_BSD_SIGNALS */
520 #endif /* !HAVE_POSIX_SIGNALS */
521
522 sigint_blocked = 1;
523 }
524
525 /* Allow SIGINT to be delivered. */
526 void
527 _rl_release_sigint ()
528 {
529 if (sigint_blocked == 0)
530 return;
531
532 #if defined (HAVE_POSIX_SIGNALS)
533 sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
534 #else
535 # if defined (HAVE_BSD_SIGNALS)
536 sigsetmask (sigint_oldmask);
537 # else /* !HAVE_BSD_SIGNALS */
538 # if defined (HAVE_USG_SIGHOLD)
539 sigrelse (SIGINT);
540 # endif /* HAVE_USG_SIGHOLD */
541 # endif /* !HAVE_BSD_SIGNALS */
542 #endif /* !HAVE_POSIX_SIGNALS */
543
544 sigint_blocked = 0;
545 }
546
547 /* **************************************************************** */
548 /* */
549 /* Echoing special control characters */
550 /* */
551 /* **************************************************************** */
552 void
553 rl_echo_signal_char (sig)
554 int sig;
555 {
556 char cstr[3];
557 int cslen, c;
558
559 if (_rl_echoctl == 0)
560 return;
561
562 switch (sig)
563 {
564 case SIGINT: c = _rl_intr_char; break;
565 case SIGQUIT: c = _rl_quit_char; break;
566 case SIGTSTP: c = _rl_susp_char; break;
567 default: return;
568 }
569
570 if (CTRL_CHAR (c) || c == RUBOUT)
571 {
572 cstr[0] = '^';
573 cstr[1] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
574 cstr[cslen = 2] = '\0';
575 }
576 else
577 {
578 cstr[0] = c;
579 cstr[cslen = 1] = '\0';
580 }
581
582 _rl_output_some_chars (cstr, cslen);
583 }