1 /* signals.c -- install and maintain signal handlers.
2 $Id: signals.c,v 1.10 2007/07/01 21:20:31 karl Exp $
4 Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003, 2004, 2007
5 Free Software Foundation, Inc.
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 Originally written by Brian Fox (bfox@ai.mit.edu). */
25 void initialize_info_signal_handler (void);
27 /* **************************************************************** */
29 /* Pretending That We Have POSIX Signals */
31 /* **************************************************************** */
33 #if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
34 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
36 sigprocmask (int operation, int *newset, int *oldset)
41 sigsetmask (sigblock (0) & ~(*newset));
45 *oldset = sigblock (*newset);
56 #endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
58 /* **************************************************************** */
60 /* Signal Handling for Info */
62 /* **************************************************************** */
64 #if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\
65 defined (HAVE_SIGSETMASK)
67 mask_termsig (sigset_t *set)
69 # if defined (SIGTSTP)
70 sigaddset (set, SIGTSTP);
71 sigaddset (set, SIGTTOU);
72 sigaddset (set, SIGTTIN);
74 # if defined (SIGWINCH)
75 sigaddset (set, SIGWINCH);
78 sigaddset (set, SIGQUIT);
81 sigaddset (set, SIGINT);
83 # if defined (SIGUSR1)
84 sigaddset (set, SIGUSR1);
87 #endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
89 static RETSIGTYPE info_signal_proc (int sig);
90 #if defined (HAVE_SIGACTION)
91 typedef struct sigaction signal_info;
92 signal_info info_signal_handler;
95 set_termsig (int sig, signal_info *old)
97 sigaction (sig, &info_signal_handler, old);
101 restore_termsig (int sig, const signal_info *saved)
103 sigaction (sig, saved, NULL);
105 #else /* !HAVE_SIGACTION */
106 typedef RETSIGTYPE (*signal_info) ();
107 #define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc))
108 #define restore_termsig(sig, saved) (void)signal (sig, *(saved))
109 #define info_signal_handler info_signal_proc
110 static int term_conf_busy = 0;
111 #endif /* !HAVE_SIGACTION */
113 static signal_info old_TSTP, old_TTOU, old_TTIN;
114 static signal_info old_WINCH, old_INT, old_USR1;
115 static signal_info old_QUIT;
118 initialize_info_signal_handler (void)
121 /* (Based on info from Paul Eggert found in coreutils.) Don't use
122 HAVE_SIGACTION to decide whether to use the sa_handler, sa_flags,
123 sa_mask members, as some systems (Solaris 7+) don't define them. Use
124 SA_NOCLDSTOP instead; it's been part of POSIX.1 since day 1 (in 1988). */
125 info_signal_handler.sa_handler = info_signal_proc;
126 info_signal_handler.sa_flags = 0;
127 mask_termsig (&info_signal_handler.sa_mask);
128 #endif /* SA_NOCLDSTOP */
130 #if defined (SIGTSTP)
131 set_termsig (SIGTSTP, &old_TSTP);
132 set_termsig (SIGTTOU, &old_TTOU);
133 set_termsig (SIGTTIN, &old_TTIN);
136 #if defined (SIGWINCH)
137 set_termsig (SIGWINCH, &old_WINCH);
140 #if defined (SIGQUIT)
141 set_termsig (SIGQUIT, &old_QUIT);
145 set_termsig (SIGINT, &old_INT);
148 #if defined (SIGUSR1)
149 /* Used by DJGPP to simulate SIGTSTP on Ctrl-Z. */
150 set_termsig (SIGUSR1, &old_USR1);
155 redisplay_after_signal (void)
157 terminal_clear_screen ();
158 display_clear_display (the_display);
159 window_mark_chain (windows, W_UpdateWindow);
160 display_update_display (windows);
161 display_cursor_at_point (active_window);
166 reset_info_window_sizes (void)
168 terminal_goto_xy (0, 0);
170 terminal_unprep_terminal ();
171 terminal_get_screen_size ();
172 terminal_prep_terminal ();
173 display_initialize_display (screenwidth, screenheight);
174 window_new_screen_size (screenwidth, screenheight);
175 redisplay_after_signal ();
179 info_signal_proc (int sig)
181 signal_info *old_signal_handler = NULL;
183 #if !defined (HAVE_SIGACTION)
184 /* best effort: first increment this counter and later block signals */
188 #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
192 mask_termsig (&nvar);
193 sigprocmask (SIG_BLOCK, &nvar, &ovar);
195 #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
196 #endif /* !HAVE_SIGACTION */
199 #if defined (SIGTSTP)
204 #if defined (SIGQUIT)
211 #if defined (SIGTSTP)
213 old_signal_handler = &old_TSTP;
215 old_signal_handler = &old_TTOU;
217 old_signal_handler = &old_TTIN;
219 #if defined (SIGQUIT)
221 old_signal_handler = &old_QUIT;
225 old_signal_handler = &old_INT;
228 /* For stop signals, restore the terminal IO, leave the cursor
229 at the bottom of the window, and stop us. */
230 terminal_goto_xy (0, screenheight - 1);
231 terminal_clear_to_eol ();
233 terminal_unprep_terminal ();
234 restore_termsig (sig, old_signal_handler);
235 UNBLOCK_SIGNAL (sig);
236 kill (getpid (), sig);
238 /* The program is returning now. Restore our signal handler,
239 turn on terminal handling, redraw the screen, and place the
240 cursor where it belongs. */
241 terminal_prep_terminal ();
242 set_termsig (sig, old_signal_handler);
243 /* window size might be changed while sleeping */
244 reset_info_window_sizes ();
248 #if defined (SIGWINCH) || defined (SIGUSR1)
256 /* Turn off terminal IO, tell our parent that the window has changed,
257 then reinitialize the terminal and rebuild our windows. */
260 old_signal_handler = &old_WINCH;
264 old_signal_handler = &old_USR1;
266 terminal_goto_xy (0, 0);
268 terminal_unprep_terminal (); /* needless? */
269 restore_termsig (sig, old_signal_handler);
270 UNBLOCK_SIGNAL (sig);
271 kill (getpid (), sig);
273 /* After our old signal handler returns... */
274 set_termsig (sig, old_signal_handler); /* needless? */
275 terminal_prep_terminal ();
276 reset_info_window_sizes ();
279 #endif /* SIGWINCH || SIGUSR1 */
281 #if !defined (HAVE_SIGACTION)
282 /* at this time it is safer to perform unblock after decrement */
284 #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
288 mask_termsig (&nvar);
289 sigprocmask (SIG_UNBLOCK, &nvar, &ovar);
291 #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
292 #endif /* !HAVE_SIGACTION */
294 /* vim: set sw=2 cino={1s>2sn-s^-se-s: */