1 /* signals.c -- install and maintain signal handlers.
2 $Id: signals.c,v 1.7 2004/04/11 17:56:46 karl Exp $
4 Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003, 2004 Free Software
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 2, or (at your option)
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, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 Originally written by Brian Fox (bfox@ai.mit.edu). */
26 void initialize_info_signal_handler (void);
28 /* **************************************************************** */
30 /* Pretending That We Have POSIX Signals */
32 /* **************************************************************** */
34 #if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
35 /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
37 sigprocmask (int operation
, int *newset
, int *oldset
)
42 sigsetmask (sigblock (0) & ~(*newset
));
46 *oldset
= sigblock (*newset
);
57 #endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
59 /* **************************************************************** */
61 /* Signal Handling for Info */
63 /* **************************************************************** */
65 #if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\
66 defined (HAVE_SIGSETMASK)
68 mask_termsig (sigset_t
*set
)
70 # if defined (SIGTSTP)
71 sigaddset (set
, SIGTSTP
);
72 sigaddset (set
, SIGTTOU
);
73 sigaddset (set
, SIGTTIN
);
75 # if defined (SIGWINCH)
76 sigaddset (set
, SIGWINCH
);
79 sigaddset (set
, SIGQUIT
);
82 sigaddset (set
, SIGINT
);
84 # if defined (SIGUSR1)
85 sigaddset (set
, SIGUSR1
);
88 #endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
90 static RETSIGTYPE
info_signal_proc (int sig
);
91 #if defined (HAVE_SIGACTION)
92 typedef struct sigaction signal_info
;
93 signal_info info_signal_handler
;
96 set_termsig (int sig
, signal_info
*old
)
98 sigaction (sig
, &info_signal_handler
, old
);
102 restore_termsig (int sig
, const signal_info
*saved
)
104 sigaction (sig
, saved
, NULL
);
106 #else /* !HAVE_SIGACTION */
107 typedef RETSIGTYPE (*signal_info
) ();
108 #define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc))
109 #define restore_termsig(sig, saved) (void)signal (sig, *(saved))
110 #define info_signal_handler info_signal_proc
111 static int term_conf_busy
= 0;
112 #endif /* !HAVE_SIGACTION */
114 static signal_info old_TSTP
, old_TTOU
, old_TTIN
;
115 static signal_info old_WINCH
, old_INT
, old_USR1
;
116 static signal_info old_QUIT
;
119 initialize_info_signal_handler (void)
122 /* (Based on info from Paul Eggert found in coreutils.) Don't use
123 HAVE_SIGACTION to decide whether to use the sa_handler, sa_flags,
124 sa_mask members, as some systems (Solaris 7+) don't define them. Use
125 SA_NOCLDSTOP instead; it's been part of POSIX.1 since day 1 (in 1988). */
126 info_signal_handler
.sa_handler
= info_signal_proc
;
127 info_signal_handler
.sa_flags
= 0;
128 mask_termsig (&info_signal_handler
.sa_mask
);
129 #endif /* SA_NOCLDSTOP */
131 #if defined (SIGTSTP)
132 set_termsig (SIGTSTP
, &old_TSTP
);
133 set_termsig (SIGTTOU
, &old_TTOU
);
134 set_termsig (SIGTTIN
, &old_TTIN
);
137 #if defined (SIGWINCH)
138 set_termsig (SIGWINCH
, &old_WINCH
);
141 #if defined (SIGQUIT)
142 set_termsig (SIGQUIT
, &old_QUIT
);
146 set_termsig (SIGINT
, &old_INT
);
149 #if defined (SIGUSR1)
150 /* Used by DJGPP to simulate SIGTSTP on Ctrl-Z. */
151 set_termsig (SIGUSR1
, &old_USR1
);
156 redisplay_after_signal (void)
158 terminal_clear_screen ();
159 display_clear_display (the_display
);
160 window_mark_chain (windows
, W_UpdateWindow
);
161 display_update_display (windows
);
162 display_cursor_at_point (active_window
);
167 reset_info_window_sizes (void)
169 terminal_goto_xy (0, 0);
171 terminal_unprep_terminal ();
172 terminal_get_screen_size ();
173 terminal_prep_terminal ();
174 display_initialize_display (screenwidth
, screenheight
);
175 window_new_screen_size (screenwidth
, screenheight
);
176 redisplay_after_signal ();
180 info_signal_proc (int sig
)
182 signal_info
*old_signal_handler
= NULL
;
184 #if !defined (HAVE_SIGACTION)
185 /* best effort: first increment this counter and later block signals */
189 #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
193 mask_termsig (&nvar
);
194 sigprocmask (SIG_BLOCK
, &nvar
, &ovar
);
196 #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
197 #endif /* !HAVE_SIGACTION */
200 #if defined (SIGTSTP)
205 #if defined (SIGQUIT)
212 #if defined (SIGTSTP)
214 old_signal_handler
= &old_TSTP
;
216 old_signal_handler
= &old_TTOU
;
218 old_signal_handler
= &old_TTIN
;
220 #if defined (SIGQUIT)
222 old_signal_handler
= &old_QUIT
;
226 old_signal_handler
= &old_INT
;
229 /* For stop signals, restore the terminal IO, leave the cursor
230 at the bottom of the window, and stop us. */
231 terminal_goto_xy (0, screenheight
- 1);
232 terminal_clear_to_eol ();
234 terminal_unprep_terminal ();
235 restore_termsig (sig
, old_signal_handler
);
236 UNBLOCK_SIGNAL (sig
);
237 kill (getpid (), sig
);
239 /* The program is returning now. Restore our signal handler,
240 turn on terminal handling, redraw the screen, and place the
241 cursor where it belongs. */
242 terminal_prep_terminal ();
243 set_termsig (sig
, old_signal_handler
);
244 /* window size might be changed while sleeping */
245 reset_info_window_sizes ();
249 #if defined (SIGWINCH) || defined (SIGUSR1)
257 /* Turn off terminal IO, tell our parent that the window has changed,
258 then reinitialize the terminal and rebuild our windows. */
261 old_signal_handler
= &old_WINCH
;
265 old_signal_handler
= &old_USR1
;
267 terminal_goto_xy (0, 0);
269 terminal_unprep_terminal (); /* needless? */
270 restore_termsig (sig
, old_signal_handler
);
271 UNBLOCK_SIGNAL (sig
);
272 kill (getpid (), sig
);
274 /* After our old signal handler returns... */
275 set_termsig (sig
, old_signal_handler
); /* needless? */
276 terminal_prep_terminal ();
277 reset_info_window_sizes ();
280 #endif /* SIGWINCH || SIGUSR1 */
282 #if !defined (HAVE_SIGACTION)
283 /* at this time it is safer to perform unblock after decrement */
285 #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
289 mask_termsig (&nvar
);
290 sigprocmask (SIG_UNBLOCK
, &nvar
, &ovar
);
292 #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
293 #endif /* !HAVE_SIGACTION */
295 /* vim: set sw=2 cino={1s>2sn-s^-se-s: */