Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / lib / readline / signals.c
1 /* signals.c -- signal handling support for readline. */
2
3 /* Copyright (C) 1987-2011 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       /* FALLTHROUGH */
217
218     case SIGTERM:
219     case SIGHUP:
220 #if defined (SIGTSTP)
221     case SIGTSTP:
222     case SIGTTOU:
223     case SIGTTIN:
224 #endif /* SIGTSTP */
225 #if defined (SIGALRM)
226     case SIGALRM:
227 #endif
228 #if defined (SIGQUIT)
229     case SIGQUIT:
230 #endif
231       rl_echo_signal_char (sig);
232       rl_cleanup_after_signal ();
233
234 #if defined (HAVE_POSIX_SIGNALS)
235       sigemptyset (&set);
236       sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
237       sigdelset (&set, sig);
238 #else /* !HAVE_POSIX_SIGNALS */
239 #  if defined (HAVE_BSD_SIGNALS)
240       omask = sigblock (0);
241 #  endif /* HAVE_BSD_SIGNALS */
242 #endif /* !HAVE_POSIX_SIGNALS */
243
244 #if defined (__EMX__)
245       signal (sig, SIG_ACK);
246 #endif
247
248 #if defined (HAVE_KILL)
249       kill (getpid (), sig);
250 #else
251       raise (sig);              /* assume we have raise */
252 #endif
253
254       /* Let the signal that we just sent through.  */
255 #if defined (HAVE_POSIX_SIGNALS)
256       sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
257 #else /* !HAVE_POSIX_SIGNALS */
258 #  if defined (HAVE_BSD_SIGNALS)
259       sigsetmask (omask & ~(sigmask (sig)));
260 #  endif /* HAVE_BSD_SIGNALS */
261 #endif /* !HAVE_POSIX_SIGNALS */
262
263       rl_reset_after_signal ();      
264     }
265
266   RL_UNSETSTATE(RL_STATE_SIGHANDLER);
267   SIGHANDLER_RETURN;
268 }
269
270 #if defined (SIGWINCH)
271 static RETSIGTYPE
272 rl_sigwinch_handler (sig)
273      int sig;
274 {
275   SigHandler *oh;
276
277 #if defined (MUST_REINSTALL_SIGHANDLERS)
278   sighandler_cxt dummy_winch;
279
280   /* We don't want to change old_winch -- it holds the state of SIGWINCH
281      disposition set by the calling application.  We need this state
282      because we call the application's SIGWINCH handler after updating
283      our own idea of the screen size. */
284   rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
285 #endif
286
287   RL_SETSTATE(RL_STATE_SIGHANDLER);
288   _rl_caught_signal = sig;
289
290   /* If another sigwinch handler has been installed, call it. */
291   oh = (SigHandler *)old_winch.sa_handler;
292   if (oh &&  oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
293     (*oh) (sig);
294
295   RL_UNSETSTATE(RL_STATE_SIGHANDLER);
296   SIGHANDLER_RETURN;
297 }
298 #endif  /* SIGWINCH */
299
300 /* Functions to manage signal handling. */
301
302 #if !defined (HAVE_POSIX_SIGNALS)
303 static int
304 rl_sigaction (sig, nh, oh)
305      int sig;
306      sighandler_cxt *nh, *oh;
307 {
308   oh->sa_handler = signal (sig, nh->sa_handler);
309   return 0;
310 }
311 #endif /* !HAVE_POSIX_SIGNALS */
312
313 /* Set up a readline-specific signal handler, saving the old signal
314    information in OHANDLER.  Return the old signal handler, like
315    signal(). */
316 static SigHandler *
317 rl_set_sighandler (sig, handler, ohandler)
318      int sig;
319      SigHandler *handler;
320      sighandler_cxt *ohandler;
321 {
322   sighandler_cxt old_handler;
323 #if defined (HAVE_POSIX_SIGNALS)
324   struct sigaction act;
325
326   act.sa_handler = handler;
327 #  if defined (SIGWINCH)
328   act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
329 #  else
330   act.sa_flags = 0;
331 #  endif /* SIGWINCH */
332   sigemptyset (&act.sa_mask);
333   sigemptyset (&ohandler->sa_mask);
334   sigaction (sig, &act, &old_handler);
335 #else
336   old_handler.sa_handler = (SigHandler *)signal (sig, handler);
337 #endif /* !HAVE_POSIX_SIGNALS */
338
339   /* XXX -- assume we have memcpy */
340   /* If rl_set_signals is called twice in a row, don't set the old handler to
341      rl_signal_handler, because that would cause infinite recursion. */
342   if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
343     memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
344
345   return (ohandler->sa_handler);
346 }
347
348 /* Set disposition of SIG to HANDLER, returning old state in OHANDLER.  Don't
349    change disposition if OHANDLER indicates the signal was ignored. */
350 static void
351 rl_maybe_set_sighandler (sig, handler, ohandler)
352      int sig;
353      SigHandler *handler;
354      sighandler_cxt *ohandler;
355 {
356   sighandler_cxt dummy;
357   SigHandler *oh;
358
359   sigemptyset (&dummy.sa_mask);
360   dummy.sa_flags = 0;
361   oh = rl_set_sighandler (sig, handler, ohandler);
362   if (oh == (SigHandler *)SIG_IGN)
363     rl_sigaction (sig, ohandler, &dummy);
364 }
365
366 /* Set the disposition of SIG to HANDLER, if HANDLER->sa_handler indicates the
367    signal was not being ignored.  MUST only be called for signals whose
368    disposition was changed using rl_maybe_set_sighandler or for which the
369    SIG_IGN check was performed inline (e.g., SIGALRM below). */
370 static void
371 rl_maybe_restore_sighandler (sig, handler)
372      int sig;
373      sighandler_cxt *handler;
374 {
375   sighandler_cxt dummy;
376
377   sigemptyset (&dummy.sa_mask);
378   dummy.sa_flags = 0;
379   if (handler->sa_handler != SIG_IGN)
380     rl_sigaction (sig, handler, &dummy);
381 }
382
383 int
384 rl_set_signals ()
385 {
386   sighandler_cxt dummy;
387   SigHandler *oh;
388 #if defined (HAVE_POSIX_SIGNALS)
389   static int sigmask_set = 0;
390   static sigset_t bset, oset;
391 #endif
392
393 #if defined (HAVE_POSIX_SIGNALS)
394   if (rl_catch_signals && sigmask_set == 0)
395     {
396       sigemptyset (&bset);
397
398       sigaddset (&bset, SIGINT);
399       sigaddset (&bset, SIGTERM);
400       sigaddset (&bset, SIGHUP);
401 #if defined (SIGQUIT)
402       sigaddset (&bset, SIGQUIT);
403 #endif
404 #if defined (SIGALRM)
405       sigaddset (&bset, SIGALRM);
406 #endif
407 #if defined (SIGTSTP)
408       sigaddset (&bset, SIGTSTP);
409 #endif
410 #if defined (SIGTTIN)
411       sigaddset (&bset, SIGTTIN);
412 #endif
413 #if defined (SIGTTOU)
414       sigaddset (&bset, SIGTTOU);
415 #endif
416       sigmask_set = 1;
417     }      
418 #endif /* HAVE_POSIX_SIGNALS */
419
420   if (rl_catch_signals && signals_set_flag == 0)
421     {
422 #if defined (HAVE_POSIX_SIGNALS)
423       sigemptyset (&oset);
424       sigprocmask (SIG_BLOCK, &bset, &oset);
425 #endif
426
427       rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
428       rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
429       rl_maybe_set_sighandler (SIGHUP, rl_signal_handler, &old_hup);
430 #if defined (SIGQUIT)
431       rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
432 #endif
433
434 #if defined (SIGALRM)
435       oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
436       if (oh == (SigHandler *)SIG_IGN)
437         rl_sigaction (SIGALRM, &old_alrm, &dummy);
438 #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
439       /* If the application using readline has already installed a signal
440          handler with SA_RESTART, SIGALRM will cause reads to be restarted
441          automatically, so readline should just get out of the way.  Since
442          we tested for SIG_IGN above, we can just test for SIG_DFL here. */
443       if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
444         rl_sigaction (SIGALRM, &old_alrm, &dummy);
445 #endif /* HAVE_POSIX_SIGNALS */
446 #endif /* SIGALRM */
447
448 #if defined (SIGTSTP)
449       rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
450 #endif /* SIGTSTP */
451
452 #if defined (SIGTTOU)
453       rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
454 #endif /* SIGTTOU */
455
456 #if defined (SIGTTIN)
457       rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
458 #endif /* SIGTTIN */
459
460       signals_set_flag = 1;
461
462 #if defined (HAVE_POSIX_SIGNALS)
463       sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
464 #endif
465     }
466
467 #if defined (SIGWINCH)
468   if (rl_catch_sigwinch && sigwinch_set_flag == 0)
469     {
470       rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
471       sigwinch_set_flag = 1;
472     }
473 #endif /* SIGWINCH */
474
475   return 0;
476 }
477
478 int
479 rl_clear_signals ()
480 {
481   sighandler_cxt dummy;
482
483   if (rl_catch_signals && signals_set_flag == 1)
484     {
485       sigemptyset (&dummy.sa_mask);
486
487       /* Since rl_maybe_set_sighandler doesn't override a SIG_IGN handler,
488          we should in theory not have to restore a handler where
489          old_xxx.sa_handler == SIG_IGN.  That's what rl_maybe_restore_sighandler
490          does.  Fewer system calls should reduce readline's per-line
491          overhead */
492       rl_maybe_restore_sighandler (SIGINT, &old_int);
493       rl_maybe_restore_sighandler (SIGTERM, &old_term);
494       rl_maybe_restore_sighandler (SIGHUP, &old_hup);
495 #if defined (SIGQUIT)
496       rl_maybe_restore_sighandler (SIGQUIT, &old_quit);
497 #endif
498 #if defined (SIGALRM)
499       rl_maybe_restore_sighandler (SIGALRM, &old_alrm);
500 #endif
501
502 #if defined (SIGTSTP)
503       rl_maybe_restore_sighandler (SIGTSTP, &old_tstp);
504 #endif /* SIGTSTP */
505
506 #if defined (SIGTTOU)
507       rl_maybe_restore_sighandler (SIGTTOU, &old_ttou);
508 #endif /* SIGTTOU */
509
510 #if defined (SIGTTIN)
511       rl_maybe_restore_sighandler (SIGTTIN, &old_ttin);
512 #endif /* SIGTTIN */
513
514       signals_set_flag = 0;
515     }
516
517 #if defined (SIGWINCH)
518   if (rl_catch_sigwinch && sigwinch_set_flag == 1)
519     {
520       sigemptyset (&dummy.sa_mask);
521       rl_sigaction (SIGWINCH, &old_winch, &dummy);
522       sigwinch_set_flag = 0;
523     }
524 #endif
525
526   return 0;
527 }
528
529 /* Clean up the terminal and readline state after catching a signal, before
530    resending it to the calling application. */
531 void
532 rl_cleanup_after_signal ()
533 {
534   _rl_clean_up_for_exit ();
535   if (rl_deprep_term_function)
536     (*rl_deprep_term_function) ();
537   rl_clear_pending_input ();
538   rl_clear_signals ();
539 }
540
541 /* Reset the terminal and readline state after a signal handler returns. */
542 void
543 rl_reset_after_signal ()
544 {
545   if (rl_prep_term_function)
546     (*rl_prep_term_function) (_rl_meta_flag);
547   rl_set_signals ();
548 }
549
550 /* Free up the readline variable line state for the current line (undo list,
551    any partial history entry, any keyboard macros in progress, and any
552    numeric arguments in process) after catching a signal, before calling
553    rl_cleanup_after_signal(). */ 
554 void
555 rl_free_line_state ()
556 {
557   register HIST_ENTRY *entry;
558
559   rl_free_undo_list ();
560
561   entry = current_history ();
562   if (entry)
563     entry->data = (char *)NULL;
564
565   _rl_kill_kbd_macro ();
566   rl_clear_message ();
567   _rl_reset_argument ();
568 }
569
570 #endif  /* HANDLE_SIGNALS */
571
572 /* **************************************************************** */
573 /*                                                                  */
574 /*                         SIGINT Management                        */
575 /*                                                                  */
576 /* **************************************************************** */
577
578 #if defined (HAVE_POSIX_SIGNALS)
579 static sigset_t sigint_set, sigint_oset;
580 static sigset_t sigwinch_set, sigwinch_oset;
581 #else /* !HAVE_POSIX_SIGNALS */
582 #  if defined (HAVE_BSD_SIGNALS)
583 static int sigint_oldmask;
584 static int sigwinch_oldmask;
585 #  endif /* HAVE_BSD_SIGNALS */
586 #endif /* !HAVE_POSIX_SIGNALS */
587
588 static int sigint_blocked;
589 static int sigwinch_blocked;
590
591 /* Cause SIGINT to not be delivered until the corresponding call to
592    release_sigint(). */
593 void
594 _rl_block_sigint ()
595 {
596   if (sigint_blocked)
597     return;
598
599   sigint_blocked = 1;
600 }
601
602 /* Allow SIGINT to be delivered. */
603 void
604 _rl_release_sigint ()
605 {
606   if (sigint_blocked == 0)
607     return;
608
609   sigint_blocked = 0;
610   RL_CHECK_SIGNALS ();
611 }
612
613 /* Cause SIGWINCH to not be delivered until the corresponding call to
614    release_sigwinch(). */
615 void
616 _rl_block_sigwinch ()
617 {
618   if (sigwinch_blocked)
619     return;
620
621 #if defined (SIGWINCH)
622
623 #if defined (HAVE_POSIX_SIGNALS)
624   sigemptyset (&sigwinch_set);
625   sigemptyset (&sigwinch_oset);
626   sigaddset (&sigwinch_set, SIGWINCH);
627   sigprocmask (SIG_BLOCK, &sigwinch_set, &sigwinch_oset);
628 #else /* !HAVE_POSIX_SIGNALS */
629 #  if defined (HAVE_BSD_SIGNALS)
630   sigwinch_oldmask = sigblock (sigmask (SIGWINCH));
631 #  else /* !HAVE_BSD_SIGNALS */
632 #    if defined (HAVE_USG_SIGHOLD)
633   sighold (SIGWINCH);
634 #    endif /* HAVE_USG_SIGHOLD */
635 #  endif /* !HAVE_BSD_SIGNALS */
636 #endif /* !HAVE_POSIX_SIGNALS */
637
638 #endif /* SIGWINCH */
639
640   sigwinch_blocked = 1;
641 }
642
643 /* Allow SIGWINCH to be delivered. */
644 void
645 _rl_release_sigwinch ()
646 {
647   if (sigwinch_blocked == 0)
648     return;
649
650 #if defined (SIGWINCH)
651
652 #if defined (HAVE_POSIX_SIGNALS)
653   sigprocmask (SIG_SETMASK, &sigwinch_oset, (sigset_t *)NULL);
654 #else
655 #  if defined (HAVE_BSD_SIGNALS)
656   sigsetmask (sigwinch_oldmask);
657 #  else /* !HAVE_BSD_SIGNALS */
658 #    if defined (HAVE_USG_SIGHOLD)
659   sigrelse (SIGWINCH);
660 #    endif /* HAVE_USG_SIGHOLD */
661 #  endif /* !HAVE_BSD_SIGNALS */
662 #endif /* !HAVE_POSIX_SIGNALS */
663
664 #endif /* SIGWINCH */
665
666   sigwinch_blocked = 0;
667 }
668
669 /* **************************************************************** */
670 /*                                                                  */
671 /*              Echoing special control characters                  */
672 /*                                                                  */
673 /* **************************************************************** */
674 void
675 rl_echo_signal_char (sig)
676      int sig;
677 {
678   char cstr[3];
679   int cslen, c;
680
681   if (_rl_echoctl == 0 || _rl_echo_control_chars == 0)
682     return;
683
684   switch (sig)
685     {
686     case SIGINT:  c = _rl_intr_char; break;
687 #if defined (SIGQUIT)
688     case SIGQUIT: c = _rl_quit_char; break;
689 #endif
690 #if defined (SIGTSTP)
691     case SIGTSTP: c = _rl_susp_char; break;
692 #endif
693     default: return;
694     }
695
696   if (CTRL_CHAR (c) || c == RUBOUT)
697     {
698       cstr[0] = '^';
699       cstr[1] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
700       cstr[cslen = 2] = '\0';
701     }
702   else
703     {
704       cstr[0] = c;
705       cstr[cslen = 1] = '\0';
706     }
707
708   _rl_output_some_chars (cstr, cslen);
709 }