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