Imported from ../bash-2.0.tar.gz.
[platform/upstream/bash.git] / lib / 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 #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 #if defined (__GO32__)
44 #  undef HANDLE_SIGNALS
45 #endif /* __GO32__ */
46
47 #if defined (HANDLE_SIGNALS)
48 /* Some standard library routines. */
49 #include "readline.h"
50 #include "history.h"
51
52 extern int readline_echoing_p;
53 extern int rl_pending_input;
54 extern int _rl_meta_flag;
55
56 extern void free_undo_list ();
57 extern void _rl_get_screen_size ();
58 extern void _rl_redisplay_after_sigwinch ();
59 extern void _rl_clean_up_for_exit ();
60 extern void _rl_kill_kbd_macro ();
61 extern void _rl_init_argument ();
62 extern void rl_deprep_terminal (), rl_prep_terminal ();
63
64 #if !defined (RETSIGTYPE)
65 #  if defined (VOID_SIGHANDLER)
66 #    define RETSIGTYPE void
67 #  else
68 #    define RETSIGTYPE int
69 #  endif /* !VOID_SIGHANDLER */
70 #endif /* !RETSIGTYPE */
71
72 #if defined (VOID_SIGHANDLER)
73 #  define SIGHANDLER_RETURN return
74 #else
75 #  define SIGHANDLER_RETURN return (0)
76 #endif
77
78 /* This typedef is equivalant to the one for Function; it allows us
79    to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
80 typedef RETSIGTYPE SigHandler ();
81
82 static SigHandler *rl_set_sighandler ();
83
84 /* **************************************************************** */
85 /*                                                                  */
86 /*                         Signal Handling                          */
87 /*                                                                  */
88 /* **************************************************************** */
89
90 #if defined (HAVE_POSIX_SIGNALS)
91 typedef struct sigaction sighandler_cxt;
92 #  define rl_sigaction(s, nh, oh)       sigaction(s, nh, oh)
93 #else
94 typedef struct { SigHandler *sa_handler; } sighandler_cxt;
95 #  define sigemptyset(m)
96 #endif /* !HAVE_POSIX_SIGNALS */
97
98 static sighandler_cxt old_int, old_alrm;
99
100 #if !defined (SHELL)
101 static sighandler_cxt old_tstp, old_ttou, old_ttin, old_term;
102 #endif /* !SHELL */
103
104 #if defined (SIGWINCH)
105 static sighandler_cxt old_winch;
106 #endif
107
108 /* Readline signal handler functions. */
109
110 static RETSIGTYPE
111 rl_signal_handler (sig)
112      int sig;
113 {
114 #if defined (HAVE_POSIX_SIGNALS)
115   sigset_t set;
116 #else /* !HAVE_POSIX_SIGNALS */
117 #  if defined (HAVE_BSD_SIGNALS)
118   long omask;
119 #  endif /* HAVE_BSD_SIGNALS */
120 #endif /* !HAVE_POSIX_SIGNALS */
121
122 #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
123   /* Since the signal will not be blocked while we are in the signal
124      handler, ignore it until rl_clear_signals resets the catcher. */
125   if (sig == SIGINT || sig == SIGALRM)
126     rl_set_sighandler (sig, SIG_IGN, (sighandler_cxt *)NULL);
127 #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
128
129   switch (sig)
130     {
131     case SIGINT:
132       {
133         register HIST_ENTRY *entry;
134
135         free_undo_list ();
136
137         entry = current_history ();
138         if (entry)
139           entry->data = (char *)NULL;
140       }
141       _rl_kill_kbd_macro ();
142       rl_clear_message ();
143       _rl_init_argument ();
144
145 #if defined (SIGTSTP)
146     case SIGTSTP:
147     case SIGTTOU:
148     case SIGTTIN:
149 #endif /* SIGTSTP */
150     case SIGALRM:
151     case SIGTERM:
152       _rl_clean_up_for_exit ();
153       (*rl_deprep_term_function) ();
154       rl_clear_signals ();
155       rl_pending_input = 0;
156
157 #if defined (HAVE_POSIX_SIGNALS)
158       sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
159       sigdelset (&set, sig);
160 #else /* !HAVE_POSIX_SIGNALS */
161 #  if defined (HAVE_BSD_SIGNALS)
162       omask = sigblock (0);
163 #  endif /* HAVE_BSD_SIGNALS */
164 #endif /* !HAVE_POSIX_SIGNALS */
165
166       kill (getpid (), sig);
167
168       /* Let the signal that we just sent through.  */
169 #if defined (HAVE_POSIX_SIGNALS)
170       sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
171 #else /* !HAVE_POSIX_SIGNALS */
172 #  if defined (HAVE_BSD_SIGNALS)
173       sigsetmask (omask & ~(sigmask (sig)));
174 #  endif /* HAVE_BSD_SIGNALS */
175 #endif /* !HAVE_POSIX_SIGNALS */
176
177       (*rl_prep_term_function) (_rl_meta_flag);
178       rl_set_signals ();
179     }
180
181   SIGHANDLER_RETURN;
182 }
183
184 #if defined (SIGWINCH)
185 static RETSIGTYPE
186 rl_handle_sigwinch (sig)
187      int sig;
188 {
189   SigHandler *oh;
190
191   if (readline_echoing_p)
192     {
193       _rl_get_screen_size (fileno (rl_instream), 1);
194       _rl_redisplay_after_sigwinch ();
195     }
196
197   /* If another sigwinch handler has been installed, call it. */
198   oh = (SigHandler *)old_winch.sa_handler;
199   if (oh &&  oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
200     (*oh) (sig);
201
202   SIGHANDLER_RETURN;
203 }
204 #endif  /* SIGWINCH */
205
206 /* Functions to manage signal handling. */
207
208 #if !defined (HAVE_POSIX_SIGNALS)
209 static int
210 rl_sigaction (sig, nh, oh)
211      int sig;
212      sighandler_cxt *nh, *oh;
213 {
214   oh->sa_handler = signal (sig, nh->sa_handler);
215   return 0;
216 }
217 #endif /* !HAVE_POSIX_SIGNALS */
218
219 /* Set up a readline-specific signal handler, saving the old signal
220    information in OHANDLER.  Return the old signal handler, like
221    signal(). */
222 static SigHandler *
223 rl_set_sighandler (sig, handler, ohandler)
224      int sig;
225      SigHandler *handler;
226      sighandler_cxt *ohandler;
227 {
228 #if defined (HAVE_POSIX_SIGNALS)
229   struct sigaction act;
230
231   act.sa_handler = handler;
232   act.sa_flags = 0;
233   sigemptyset (&act.sa_mask);
234   sigemptyset (&ohandler->sa_mask);
235   sigaction (sig, &act, ohandler);
236 #else
237   ohandler->sa_handler = (SigHandler *)signal (sig, handler);
238 #endif /* !HAVE_POSIX_SIGNALS */
239   return (ohandler->sa_handler);
240 }
241
242 int
243 rl_set_signals ()
244 {
245   sighandler_cxt dummy;
246   SigHandler *oh;
247
248 #if defined (HAVE_POSIX_SIGNALS)
249   sigemptyset (&dummy.sa_mask);
250 #endif
251
252   oh = rl_set_sighandler (SIGINT, rl_signal_handler, &old_int);
253   if (oh == (SigHandler *)SIG_IGN)
254     rl_sigaction (SIGINT, &old_int, &dummy);
255
256   oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
257   if (oh == (SigHandler *)SIG_IGN)
258     rl_sigaction (SIGALRM, &old_alrm, &dummy);
259 #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
260   /* If the application using readline has already installed a signal
261      handler with SA_RESTART, SIGALRM will cause reads to be restarted
262      automatically, so readline should just get out of the way.  Since
263      we tested for SIG_IGN above, we can just test for SIG_DFL here. */
264   if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
265     rl_sigaction (SIGALRM, &old_alrm, &dummy);
266 #endif /* HAVE_POSIX_SIGNALS */
267
268 #if !defined (SHELL)
269
270 #if defined (SIGTSTP)
271   oh = rl_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
272   if (oh == (SigHandler *)SIG_IGN)
273     rl_sigaction (SIGTSTP, &old_tstp, &dummy);
274 #else
275   oh = (SigHandler *)NULL;
276 #endif /* SIGTSTP */
277
278 #if defined (SIGTTOU)
279   rl_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
280   rl_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
281
282   if (oh == (SigHandler *)SIG_IGN)
283     {
284       rl_set_sighandler (SIGTTOU, SIG_IGN, &dummy);
285       rl_set_sighandler (SIGTTIN, SIG_IGN, &dummy);
286     }
287 #endif /* SIGTTOU */
288
289   /* Handle SIGTERM if we're not being compiled as part of bash. */
290   rl_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
291 #endif /* !SHELL */
292
293 #if defined (SIGWINCH)
294   rl_set_sighandler (SIGWINCH, rl_handle_sigwinch, &old_winch);
295 #endif /* SIGWINCH */
296
297   return 0;
298 }
299
300 int
301 rl_clear_signals ()
302 {
303   sighandler_cxt dummy;
304
305 #if defined (HAVE_POSIX_SIGNALS)
306   sigemptyset (&dummy.sa_mask);
307 #endif
308
309   rl_sigaction (SIGINT, &old_int, &dummy);
310   rl_sigaction (SIGALRM, &old_alrm, &dummy);
311
312 #if !defined (SHELL)
313
314 #if defined (SIGTSTP)
315   rl_sigaction (SIGTSTP, &old_tstp, &dummy);
316 #endif
317
318 #if defined (SIGTTOU)
319   rl_sigaction (SIGTTOU, &old_ttou, &dummy);
320   rl_sigaction (SIGTTIN, &old_ttin, &dummy);
321 #endif /* SIGTTOU */
322
323   rl_sigaction (SIGTERM, &old_term, &dummy);
324
325 #endif /* !SHELL */
326
327 #if defined (SIGWINCH)
328   sigemptyset (&dummy.sa_mask);
329   rl_sigaction (SIGWINCH, &old_winch, &dummy);
330 #endif
331
332   return 0;
333 }
334 #endif  /* HANDLE_SIGNALS */