1 1.1 christos /* $NetBSD: signals.c,v 1.1.1.1 2016/01/14 00:11:29 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* signals.c -- install and maintain signal handlers. 4 1.1 christos Id: signals.c,v 1.7 2004/04/11 17:56:46 karl Exp 5 1.1 christos 6 1.1 christos Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003, 2004 Free Software 7 1.1 christos Foundation, Inc. 8 1.1 christos 9 1.1 christos This program is free software; you can redistribute it and/or modify 10 1.1 christos it under the terms of the GNU General Public License as published by 11 1.1 christos the Free Software Foundation; either version 2, or (at your option) 12 1.1 christos any later version. 13 1.1 christos 14 1.1 christos This program is distributed in the hope that it will be useful, 15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 1.1 christos GNU General Public License for more details. 18 1.1 christos 19 1.1 christos You should have received a copy of the GNU General Public License 20 1.1 christos along with this program; if not, write to the Free Software 21 1.1 christos Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 1.1 christos 23 1.1 christos Originally written by Brian Fox (bfox (at) ai.mit.edu). */ 24 1.1 christos 25 1.1 christos #include "info.h" 26 1.1 christos #include "signals.h" 27 1.1 christos 28 1.1 christos void initialize_info_signal_handler (void); 29 1.1 christos 30 1.1 christos /* **************************************************************** */ 31 1.1 christos /* */ 32 1.1 christos /* Pretending That We Have POSIX Signals */ 33 1.1 christos /* */ 34 1.1 christos /* **************************************************************** */ 35 1.1 christos 36 1.1 christos #if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK) 37 1.1 christos /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */ 38 1.1 christos static void 39 1.1 christos sigprocmask (int operation, int *newset, int *oldset) 40 1.1 christos { 41 1.1 christos switch (operation) 42 1.1 christos { 43 1.1 christos case SIG_UNBLOCK: 44 1.1 christos sigsetmask (sigblock (0) & ~(*newset)); 45 1.1 christos break; 46 1.1 christos 47 1.1 christos case SIG_BLOCK: 48 1.1 christos *oldset = sigblock (*newset); 49 1.1 christos break; 50 1.1 christos 51 1.1 christos case SIG_SETMASK: 52 1.1 christos sigsetmask (*newset); 53 1.1 christos break; 54 1.1 christos 55 1.1 christos default: 56 1.1 christos abort (); 57 1.1 christos } 58 1.1 christos } 59 1.1 christos #endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */ 60 1.1 christos 61 1.1 christos /* **************************************************************** */ 62 1.1 christos /* */ 63 1.1 christos /* Signal Handling for Info */ 64 1.1 christos /* */ 65 1.1 christos /* **************************************************************** */ 66 1.1 christos 67 1.1 christos #if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\ 68 1.1 christos defined (HAVE_SIGSETMASK) 69 1.1 christos static void 70 1.1 christos mask_termsig (sigset_t *set) 71 1.1 christos { 72 1.1 christos # if defined (SIGTSTP) 73 1.1 christos sigaddset (set, SIGTSTP); 74 1.1 christos sigaddset (set, SIGTTOU); 75 1.1 christos sigaddset (set, SIGTTIN); 76 1.1 christos # endif 77 1.1 christos # if defined (SIGWINCH) 78 1.1 christos sigaddset (set, SIGWINCH); 79 1.1 christos # endif 80 1.1 christos #if defined (SIGQUIT) 81 1.1 christos sigaddset (set, SIGQUIT); 82 1.1 christos #endif 83 1.1 christos #if defined (SIGINT) 84 1.1 christos sigaddset (set, SIGINT); 85 1.1 christos #endif 86 1.1 christos # if defined (SIGUSR1) 87 1.1 christos sigaddset (set, SIGUSR1); 88 1.1 christos # endif 89 1.1 christos } 90 1.1 christos #endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */ 91 1.1 christos 92 1.1 christos static RETSIGTYPE info_signal_proc (int sig); 93 1.1 christos #if defined (HAVE_SIGACTION) 94 1.1 christos typedef struct sigaction signal_info; 95 1.1 christos signal_info info_signal_handler; 96 1.1 christos 97 1.1 christos static void 98 1.1 christos set_termsig (int sig, signal_info *old) 99 1.1 christos { 100 1.1 christos sigaction (sig, &info_signal_handler, old); 101 1.1 christos } 102 1.1 christos 103 1.1 christos static void 104 1.1 christos restore_termsig (int sig, const signal_info *saved) 105 1.1 christos { 106 1.1 christos sigaction (sig, saved, NULL); 107 1.1 christos } 108 1.1 christos #else /* !HAVE_SIGACTION */ 109 1.1 christos typedef RETSIGTYPE (*signal_info) (); 110 1.1 christos #define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc)) 111 1.1 christos #define restore_termsig(sig, saved) (void)signal (sig, *(saved)) 112 1.1 christos #define info_signal_handler info_signal_proc 113 1.1 christos static int term_conf_busy = 0; 114 1.1 christos #endif /* !HAVE_SIGACTION */ 115 1.1 christos 116 1.1 christos static signal_info old_TSTP, old_TTOU, old_TTIN; 117 1.1 christos static signal_info old_WINCH, old_INT, old_USR1; 118 1.1 christos static signal_info old_QUIT; 119 1.1 christos 120 1.1 christos void 121 1.1 christos initialize_info_signal_handler (void) 122 1.1 christos { 123 1.1 christos #ifdef SA_NOCLDSTOP 124 1.1 christos /* (Based on info from Paul Eggert found in coreutils.) Don't use 125 1.1 christos HAVE_SIGACTION to decide whether to use the sa_handler, sa_flags, 126 1.1 christos sa_mask members, as some systems (Solaris 7+) don't define them. Use 127 1.1 christos SA_NOCLDSTOP instead; it's been part of POSIX.1 since day 1 (in 1988). */ 128 1.1 christos info_signal_handler.sa_handler = info_signal_proc; 129 1.1 christos info_signal_handler.sa_flags = 0; 130 1.1 christos mask_termsig (&info_signal_handler.sa_mask); 131 1.1 christos #endif /* SA_NOCLDSTOP */ 132 1.1 christos 133 1.1 christos #if defined (SIGTSTP) 134 1.1 christos set_termsig (SIGTSTP, &old_TSTP); 135 1.1 christos set_termsig (SIGTTOU, &old_TTOU); 136 1.1 christos set_termsig (SIGTTIN, &old_TTIN); 137 1.1 christos #endif /* SIGTSTP */ 138 1.1 christos 139 1.1 christos #if defined (SIGWINCH) 140 1.1 christos set_termsig (SIGWINCH, &old_WINCH); 141 1.1 christos #endif 142 1.1 christos 143 1.1 christos #if defined (SIGQUIT) 144 1.1 christos set_termsig (SIGQUIT, &old_QUIT); 145 1.1 christos #endif 146 1.1 christos 147 1.1 christos #if defined (SIGINT) 148 1.1 christos set_termsig (SIGINT, &old_INT); 149 1.1 christos #endif 150 1.1 christos 151 1.1 christos #if defined (SIGUSR1) 152 1.1 christos /* Used by DJGPP to simulate SIGTSTP on Ctrl-Z. */ 153 1.1 christos set_termsig (SIGUSR1, &old_USR1); 154 1.1 christos #endif 155 1.1 christos } 156 1.1 christos 157 1.1 christos static void 158 1.1 christos redisplay_after_signal (void) 159 1.1 christos { 160 1.1 christos terminal_clear_screen (); 161 1.1 christos display_clear_display (the_display); 162 1.1 christos window_mark_chain (windows, W_UpdateWindow); 163 1.1 christos display_update_display (windows); 164 1.1 christos display_cursor_at_point (active_window); 165 1.1 christos fflush (stdout); 166 1.1 christos } 167 1.1 christos 168 1.1 christos static void 169 1.1 christos reset_info_window_sizes (void) 170 1.1 christos { 171 1.1 christos terminal_goto_xy (0, 0); 172 1.1 christos fflush (stdout); 173 1.1 christos terminal_unprep_terminal (); 174 1.1 christos terminal_get_screen_size (); 175 1.1 christos terminal_prep_terminal (); 176 1.1 christos display_initialize_display (screenwidth, screenheight); 177 1.1 christos window_new_screen_size (screenwidth, screenheight); 178 1.1 christos redisplay_after_signal (); 179 1.1 christos } 180 1.1 christos 181 1.1 christos static RETSIGTYPE 182 1.1 christos info_signal_proc (int sig) 183 1.1 christos { 184 1.1 christos signal_info *old_signal_handler = NULL; 185 1.1 christos 186 1.1 christos #if !defined (HAVE_SIGACTION) 187 1.1 christos /* best effort: first increment this counter and later block signals */ 188 1.1 christos if (term_conf_busy) 189 1.1 christos return; 190 1.1 christos term_conf_busy++; 191 1.1 christos #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK) 192 1.1 christos { 193 1.1 christos sigset_t nvar, ovar; 194 1.1 christos sigemptyset (&nvar); 195 1.1 christos mask_termsig (&nvar); 196 1.1 christos sigprocmask (SIG_BLOCK, &nvar, &ovar); 197 1.1 christos } 198 1.1 christos #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */ 199 1.1 christos #endif /* !HAVE_SIGACTION */ 200 1.1 christos switch (sig) 201 1.1 christos { 202 1.1 christos #if defined (SIGTSTP) 203 1.1 christos case SIGTSTP: 204 1.1 christos case SIGTTOU: 205 1.1 christos case SIGTTIN: 206 1.1 christos #endif 207 1.1 christos #if defined (SIGQUIT) 208 1.1 christos case SIGQUIT: 209 1.1 christos #endif 210 1.1 christos #if defined (SIGINT) 211 1.1 christos case SIGINT: 212 1.1 christos #endif 213 1.1 christos { 214 1.1 christos #if defined (SIGTSTP) 215 1.1 christos if (sig == SIGTSTP) 216 1.1 christos old_signal_handler = &old_TSTP; 217 1.1 christos if (sig == SIGTTOU) 218 1.1 christos old_signal_handler = &old_TTOU; 219 1.1 christos if (sig == SIGTTIN) 220 1.1 christos old_signal_handler = &old_TTIN; 221 1.1 christos #endif /* SIGTSTP */ 222 1.1 christos #if defined (SIGQUIT) 223 1.1 christos if (sig == SIGQUIT) 224 1.1 christos old_signal_handler = &old_QUIT; 225 1.1 christos #endif /* SIGQUIT */ 226 1.1 christos #if defined (SIGINT) 227 1.1 christos if (sig == SIGINT) 228 1.1 christos old_signal_handler = &old_INT; 229 1.1 christos #endif /* SIGINT */ 230 1.1 christos 231 1.1 christos /* For stop signals, restore the terminal IO, leave the cursor 232 1.1 christos at the bottom of the window, and stop us. */ 233 1.1 christos terminal_goto_xy (0, screenheight - 1); 234 1.1 christos terminal_clear_to_eol (); 235 1.1 christos fflush (stdout); 236 1.1 christos terminal_unprep_terminal (); 237 1.1 christos restore_termsig (sig, old_signal_handler); 238 1.1 christos UNBLOCK_SIGNAL (sig); 239 1.1 christos kill (getpid (), sig); 240 1.1 christos 241 1.1 christos /* The program is returning now. Restore our signal handler, 242 1.1 christos turn on terminal handling, redraw the screen, and place the 243 1.1 christos cursor where it belongs. */ 244 1.1 christos terminal_prep_terminal (); 245 1.1 christos set_termsig (sig, old_signal_handler); 246 1.1 christos /* window size might be changed while sleeping */ 247 1.1 christos reset_info_window_sizes (); 248 1.1 christos } 249 1.1 christos break; 250 1.1 christos 251 1.1 christos #if defined (SIGWINCH) || defined (SIGUSR1) 252 1.1 christos #ifdef SIGWINCH 253 1.1 christos case SIGWINCH: 254 1.1 christos #endif 255 1.1 christos #ifdef SIGUSR1 256 1.1 christos case SIGUSR1: 257 1.1 christos #endif 258 1.1 christos { 259 1.1 christos /* Turn off terminal IO, tell our parent that the window has changed, 260 1.1 christos then reinitialize the terminal and rebuild our windows. */ 261 1.1 christos #ifdef SIGWINCH 262 1.1 christos if (sig == SIGWINCH) 263 1.1 christos old_signal_handler = &old_WINCH; 264 1.1 christos #endif 265 1.1 christos #ifdef SIGUSR1 266 1.1 christos if (sig == SIGUSR1) 267 1.1 christos old_signal_handler = &old_USR1; 268 1.1 christos #endif 269 1.1 christos terminal_goto_xy (0, 0); 270 1.1 christos fflush (stdout); 271 1.1 christos terminal_unprep_terminal (); /* needless? */ 272 1.1 christos restore_termsig (sig, old_signal_handler); 273 1.1 christos UNBLOCK_SIGNAL (sig); 274 1.1 christos kill (getpid (), sig); 275 1.1 christos 276 1.1 christos /* After our old signal handler returns... */ 277 1.1 christos set_termsig (sig, old_signal_handler); /* needless? */ 278 1.1 christos terminal_prep_terminal (); 279 1.1 christos reset_info_window_sizes (); 280 1.1 christos } 281 1.1 christos break; 282 1.1 christos #endif /* SIGWINCH || SIGUSR1 */ 283 1.1 christos } 284 1.1 christos #if !defined (HAVE_SIGACTION) 285 1.1 christos /* at this time it is safer to perform unblock after decrement */ 286 1.1 christos term_conf_busy--; 287 1.1 christos #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK) 288 1.1 christos { 289 1.1 christos sigset_t nvar, ovar; 290 1.1 christos sigemptyset (&nvar); 291 1.1 christos mask_termsig (&nvar); 292 1.1 christos sigprocmask (SIG_UNBLOCK, &nvar, &ovar); 293 1.1 christos } 294 1.1 christos #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */ 295 1.1 christos #endif /* !HAVE_SIGACTION */ 296 1.1 christos } 297 1.1 christos /* vim: set sw=2 cino={1s>2sn-s^-se-s: */ 298