This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / readline / signals.c
1 /* signals.c -- signal handling support for readline. */
2
3 /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
4
5    This file is part of the GNU Readline Library, a library for
6    reading lines of text with interactive input and history editing.
7
8    The GNU Readline Library is free software; you can redistribute it
9    and/or modify it under the terms of the GNU General Public License
10    as published by the Free Software Foundation; either version 1, or
11    (at your option) any later version.
12
13    The GNU Readline Library is distributed in the hope that it will be
14    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    The GNU General Public License is often shipped with GNU software, and
19    is generally kept in a file called COPYING or LICENSE.  If you do not
20    have a copy of the license, write to the Free Software Foundation,
21    675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <fcntl.h>
26 #if !defined (NO_SYS_FILE)
27 #  include <sys/file.h>
28 #endif /* !NO_SYS_FILE */
29 #include <signal.h>
30
31 /* This is needed to include support for TIOCGWINSZ and window resizing. */
32 #if defined (OSF1) || defined (BSD386) || defined (_386BSD) || defined (__BSD_4_4__) || defined (AIX)
33 #  include <sys/ioctl.h>
34 #endif /* OSF1 || BSD386 || _386BSD || __BSD_4_4__ || AIX */
35
36 #include <errno.h>
37 /* Not all systems declare ERRNO in errno.h... and some systems #define it! */
38 #if !defined (errno)
39 extern int errno;
40 #endif /* !errno */
41
42 /* System-specific feature definitions and include files. */
43 #include "rldefs.h"
44
45 /* Some standard library routines. */
46 #include "readline.h"
47 #include "history.h"
48
49 static void cr ();
50
51 extern int readline_echoing_p;
52 extern int rl_pending_input;
53
54 extern int _rl_meta_flag;
55
56 #ifdef __STDC__
57 extern void _rl_output_character_function (int);
58 #else
59 extern void _rl_output_character_function ();
60 #endif
61
62 extern void free_undo_list ();
63
64 #if defined (VOID_SIGHANDLER)
65 #  define sighandler void
66 #else
67 #  define sighandler int
68 #endif /* VOID_SIGHANDLER */
69
70 /* This typedef is equivalant to the one for Function; it allows us
71    to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
72 typedef sighandler SigHandler ();
73
74 /* **************************************************************** */
75 /*                                                                  */
76 /*                         Signal Handling                          */
77 /*                                                                  */
78 /* **************************************************************** */
79
80 #if defined (HANDLE_SIGNALS)
81
82 #if defined (SIGWINCH)
83 static SigHandler *old_sigwinch = (SigHandler *)NULL;
84
85 static sighandler
86 rl_handle_sigwinch (sig)
87      int sig;
88 {
89   if (readline_echoing_p)
90     {
91       _rl_set_screen_size (fileno (rl_instream), 1);
92
93       cr ();                            /* was crlf () */
94       rl_forced_update_display ();
95     }
96
97   if (old_sigwinch &&
98       old_sigwinch != (SigHandler *)SIG_IGN &&
99       old_sigwinch != (SigHandler *)SIG_DFL)
100     (*old_sigwinch) (sig);
101 #if !defined (VOID_SIGHANDLER)
102   return (0);
103 #endif /* VOID_SIGHANDLER */
104 }
105 #endif  /* SIGWINCH */
106
107 /* Interrupt handling. */
108 static SigHandler
109   *old_int  = (SigHandler *)NULL,
110   *old_tstp = (SigHandler *)NULL,
111   *old_ttou = (SigHandler *)NULL,
112   *old_ttin = (SigHandler *)NULL,
113   *old_cont = (SigHandler *)NULL,
114   *old_alrm = (SigHandler *)NULL;
115
116 /* Handle an interrupt character. */
117 static sighandler
118 rl_signal_handler (sig)
119      int sig;
120 {
121 #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
122   /* Since the signal will not be blocked while we are in the signal
123      handler, ignore it until rl_clear_signals resets the catcher. */
124   if (sig == SIGINT)
125     signal (sig, SIG_IGN);
126 #endif /* !HAVE_BSD_SIGNALS */
127
128   switch (sig)
129     {
130     case SIGINT:
131       {
132         register HIST_ENTRY *entry;
133
134         free_undo_list ();
135
136         entry = current_history ();
137         if (entry)
138           entry->data = (char *)NULL;
139       }
140       _rl_kill_kbd_macro ();
141       rl_clear_message ();
142       rl_init_argument ();
143
144 #if defined (SIGTSTP)
145     case SIGTSTP:
146     case SIGTTOU:
147     case SIGTTIN:
148 #endif /* SIGTSTP */
149     case SIGALRM:
150       rl_clean_up_for_exit ();
151       rl_deprep_terminal ();
152       rl_clear_signals ();
153       rl_pending_input = 0;
154
155       kill (getpid (), sig);
156
157       SIGNALS_UNBLOCK;
158
159       rl_prep_terminal (_rl_meta_flag);
160       rl_set_signals ();
161     }
162
163 #if !defined (VOID_SIGHANDLER)
164   return (0);
165 #endif /* !VOID_SIGHANDLER */
166 }
167
168 #if defined (HAVE_POSIX_SIGNALS)
169 static SigHandler *
170 rl_set_sighandler (sig, handler)
171      int sig;
172      SigHandler *handler;
173 {
174   struct sigaction act, oact;
175
176   act.sa_handler = handler;
177   act.sa_flags = 0;
178   sigemptyset (&act.sa_mask);
179   sigemptyset (&oact.sa_mask);
180   sigaction (sig, &act, &oact);
181   return (oact.sa_handler);
182 }
183
184 #else /* !HAVE_POSIX_SIGNALS */
185 #  define rl_set_sighandler(sig, handler) (SigHandler *)signal (sig, handler)
186 #endif /* !HAVE_POSIX_SIGNALS */
187
188 rl_set_signals ()
189 {
190   old_int = (SigHandler *)rl_set_sighandler (SIGINT, rl_signal_handler);
191   if (old_int == (SigHandler *)SIG_IGN)
192     signal (SIGINT, SIG_IGN);
193
194   old_alrm = (SigHandler *)rl_set_sighandler (SIGALRM, rl_signal_handler);
195   if (old_alrm == (SigHandler *)SIG_IGN)
196     signal (SIGALRM, SIG_IGN);
197
198 #if defined (SIGTSTP)
199   old_tstp = (SigHandler *)rl_set_sighandler (SIGTSTP, rl_signal_handler);
200   if (old_tstp == (SigHandler *)SIG_IGN)
201     signal (SIGTSTP, SIG_IGN);
202 #endif
203 #if defined (SIGTTOU)
204   old_ttou = (SigHandler *)rl_set_sighandler (SIGTTOU, rl_signal_handler);
205   old_ttin = (SigHandler *)rl_set_sighandler (SIGTTIN, rl_signal_handler);
206
207   if (old_tstp == (SigHandler *)SIG_IGN)
208     {
209       signal (SIGTTOU, SIG_IGN);
210       signal (SIGTTIN, SIG_IGN);
211     }
212 #endif
213
214 #if defined (SIGWINCH)
215   old_sigwinch =
216     (SigHandler *) rl_set_sighandler (SIGWINCH, rl_handle_sigwinch);
217 #endif
218 }
219
220 rl_clear_signals ()
221 {
222   rl_set_sighandler (SIGINT, old_int);
223   rl_set_sighandler (SIGALRM, old_alrm);
224
225 #if defined (SIGTSTP)
226   signal (SIGTSTP, old_tstp);
227 #endif
228
229 #if defined (SIGTTOU)
230   signal (SIGTTOU, old_ttou);
231   signal (SIGTTIN, old_ttin);
232 #endif
233
234 #if defined (SIGWINCH)
235   signal (SIGWINCH, old_sigwinch);
236 #endif
237 }
238
239 /* Move to the start of the current line. */
240 static void
241 cr ()
242 {
243   extern char *term_cr;
244
245   if (term_cr)  
246     tputs (term_cr, 1, _rl_output_character_function);
247 }
248 #endif  /* HANDLE_SIGNALS */