1146520Sru/* signals.c -- install and maintain signal handlers. 2146520Sru $Id: signals.c,v 1.7 2004/04/11 17:56:46 karl Exp $ 321495Sjmacd 4146520Sru Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003, 2004 Free Software 5114478Sru Foundation, Inc. 621495Sjmacd 721495Sjmacd This program is free software; you can redistribute it and/or modify 821495Sjmacd it under the terms of the GNU General Public License as published by 921495Sjmacd the Free Software Foundation; either version 2, or (at your option) 1021495Sjmacd any later version. 1121495Sjmacd 1221495Sjmacd This program is distributed in the hope that it will be useful, 1321495Sjmacd but WITHOUT ANY WARRANTY; without even the implied warranty of 1421495Sjmacd MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1521495Sjmacd GNU General Public License for more details. 1621495Sjmacd 1721495Sjmacd You should have received a copy of the GNU General Public License 1821495Sjmacd along with this program; if not, write to the Free Software 1921495Sjmacd Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 2021495Sjmacd 21146520Sru Originally written by Brian Fox (bfox@ai.mit.edu). */ 2221495Sjmacd 2321495Sjmacd#include "info.h" 2421495Sjmacd#include "signals.h" 2521495Sjmacd 26146520Sruvoid initialize_info_signal_handler (void); 27146520Sru 2821495Sjmacd/* **************************************************************** */ 2942664Smarkm/* */ 3042664Smarkm/* Pretending That We Have POSIX Signals */ 3142664Smarkm/* */ 3221495Sjmacd/* **************************************************************** */ 3321495Sjmacd 3421495Sjmacd#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK) 3521495Sjmacd/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */ 3621495Sjmacdstatic void 37146520Srusigprocmask (int operation, int *newset, int *oldset) 3821495Sjmacd{ 3921495Sjmacd switch (operation) 4021495Sjmacd { 4121495Sjmacd case SIG_UNBLOCK: 4221495Sjmacd sigsetmask (sigblock (0) & ~(*newset)); 4321495Sjmacd break; 4421495Sjmacd 4521495Sjmacd case SIG_BLOCK: 4621495Sjmacd *oldset = sigblock (*newset); 4721495Sjmacd break; 4821495Sjmacd 4921495Sjmacd case SIG_SETMASK: 5021495Sjmacd sigsetmask (*newset); 5121495Sjmacd break; 5221495Sjmacd 5321495Sjmacd default: 5421495Sjmacd abort (); 5521495Sjmacd } 5621495Sjmacd} 5721495Sjmacd#endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */ 5821495Sjmacd 5921495Sjmacd/* **************************************************************** */ 6042664Smarkm/* */ 6142664Smarkm/* Signal Handling for Info */ 6242664Smarkm/* */ 6321495Sjmacd/* **************************************************************** */ 6421495Sjmacd 65114478Sru#if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\ 66114478Sru defined (HAVE_SIGSETMASK) 67114478Srustatic void 68146520Srumask_termsig (sigset_t *set) 69114478Sru{ 70114478Sru# if defined (SIGTSTP) 71114478Sru sigaddset (set, SIGTSTP); 72114478Sru sigaddset (set, SIGTTOU); 73114478Sru sigaddset (set, SIGTTIN); 74114478Sru# endif 75114478Sru# if defined (SIGWINCH) 76114478Sru sigaddset (set, SIGWINCH); 77114478Sru# endif 78146520Sru#if defined (SIGQUIT) 79146520Sru sigaddset (set, SIGQUIT); 80146520Sru#endif 81114478Sru#if defined (SIGINT) 82114478Sru sigaddset (set, SIGINT); 83114478Sru#endif 84114478Sru# if defined (SIGUSR1) 85114478Sru sigaddset (set, SIGUSR1); 86114478Sru# endif 87114478Sru} 88114478Sru#endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */ 8921495Sjmacd 90146520Srustatic RETSIGTYPE info_signal_proc (int sig); 91114478Sru#if defined (HAVE_SIGACTION) 92114478Srutypedef struct sigaction signal_info; 93114478Srusignal_info info_signal_handler; 9421495Sjmacd 95114478Srustatic void 96146520Sruset_termsig (int sig, signal_info *old) 97114478Sru{ 98114478Sru sigaction (sig, &info_signal_handler, old); 99114478Sru} 100114478Sru 101114478Srustatic void 102146520Srurestore_termsig (int sig, const signal_info *saved) 103114478Sru{ 104114478Sru sigaction (sig, saved, NULL); 105114478Sru} 106114478Sru#else /* !HAVE_SIGACTION */ 107114478Srutypedef RETSIGTYPE (*signal_info) (); 108114478Sru#define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc)) 109114478Sru#define restore_termsig(sig, saved) (void)signal (sig, *(saved)) 110114478Sru#define info_signal_handler info_signal_proc 111114478Srustatic int term_conf_busy = 0; 112114478Sru#endif /* !HAVE_SIGACTION */ 113114478Sru 114114478Srustatic signal_info old_TSTP, old_TTOU, old_TTIN; 115116535Srustatic signal_info old_WINCH, old_INT, old_USR1; 116146520Srustatic signal_info old_QUIT; 117114478Sru 11821495Sjmacdvoid 119146520Sruinitialize_info_signal_handler (void) 12021495Sjmacd{ 121146520Sru#ifdef SA_NOCLDSTOP 122146520Sru /* (Based on info from Paul Eggert found in coreutils.) Don't use 123146520Sru HAVE_SIGACTION to decide whether to use the sa_handler, sa_flags, 124146520Sru sa_mask members, as some systems (Solaris 7+) don't define them. Use 125146520Sru SA_NOCLDSTOP instead; it's been part of POSIX.1 since day 1 (in 1988). */ 126114478Sru info_signal_handler.sa_handler = info_signal_proc; 127114478Sru info_signal_handler.sa_flags = 0; 128114478Sru mask_termsig (&info_signal_handler.sa_mask); 129146520Sru#endif /* SA_NOCLDSTOP */ 130114478Sru 13121495Sjmacd#if defined (SIGTSTP) 132114478Sru set_termsig (SIGTSTP, &old_TSTP); 133114478Sru set_termsig (SIGTTOU, &old_TTOU); 134114478Sru set_termsig (SIGTTIN, &old_TTIN); 13521495Sjmacd#endif /* SIGTSTP */ 13621495Sjmacd 13721495Sjmacd#if defined (SIGWINCH) 138114478Sru set_termsig (SIGWINCH, &old_WINCH); 13942664Smarkm#endif 14021495Sjmacd 141146520Sru#if defined (SIGQUIT) 142146520Sru set_termsig (SIGQUIT, &old_QUIT); 143146520Sru#endif 144146520Sru 14521495Sjmacd#if defined (SIGINT) 146114478Sru set_termsig (SIGINT, &old_INT); 14721495Sjmacd#endif 14856165Sru 14956165Sru#if defined (SIGUSR1) 15056165Sru /* Used by DJGPP to simulate SIGTSTP on Ctrl-Z. */ 151114478Sru set_termsig (SIGUSR1, &old_USR1); 15256165Sru#endif 15321495Sjmacd} 15421495Sjmacd 15521495Sjmacdstatic void 156146520Sruredisplay_after_signal (void) 15721495Sjmacd{ 15821495Sjmacd terminal_clear_screen (); 15921495Sjmacd display_clear_display (the_display); 16021495Sjmacd window_mark_chain (windows, W_UpdateWindow); 16121495Sjmacd display_update_display (windows); 16221495Sjmacd display_cursor_at_point (active_window); 16321495Sjmacd fflush (stdout); 16421495Sjmacd} 16521495Sjmacd 16656165Srustatic void 167146520Srureset_info_window_sizes (void) 16856165Sru{ 16956165Sru terminal_goto_xy (0, 0); 17056165Sru fflush (stdout); 17156165Sru terminal_unprep_terminal (); 17256165Sru terminal_get_screen_size (); 17356165Sru terminal_prep_terminal (); 17456165Sru display_initialize_display (screenwidth, screenheight); 175146520Sru window_new_screen_size (screenwidth, screenheight); 17656165Sru redisplay_after_signal (); 17756165Sru} 17856165Sru 17942664Smarkmstatic RETSIGTYPE 180146520Sruinfo_signal_proc (int sig) 18121495Sjmacd{ 182146520Sru signal_info *old_signal_handler = NULL; 18321495Sjmacd 184114478Sru#if !defined (HAVE_SIGACTION) 185114478Sru /* best effort: first increment this counter and later block signals */ 186114478Sru if (term_conf_busy) 187114478Sru return; 188114478Sru term_conf_busy++; 189114478Sru#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK) 190114478Sru { 191114478Sru sigset_t nvar, ovar; 192114478Sru sigemptyset (&nvar); 193114478Sru mask_termsig (&nvar); 194114478Sru sigprocmask (SIG_BLOCK, &nvar, &ovar); 195114478Sru } 196114478Sru#endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */ 197114478Sru#endif /* !HAVE_SIGACTION */ 19821495Sjmacd switch (sig) 19921495Sjmacd { 20021495Sjmacd#if defined (SIGTSTP) 20121495Sjmacd case SIGTSTP: 20221495Sjmacd case SIGTTOU: 20321495Sjmacd case SIGTTIN: 20421495Sjmacd#endif 205146520Sru#if defined (SIGQUIT) 206146520Sru case SIGQUIT: 207146520Sru#endif 20821495Sjmacd#if defined (SIGINT) 20921495Sjmacd case SIGINT: 21021495Sjmacd#endif 21121495Sjmacd { 21221495Sjmacd#if defined (SIGTSTP) 21342664Smarkm if (sig == SIGTSTP) 21442664Smarkm old_signal_handler = &old_TSTP; 21542664Smarkm if (sig == SIGTTOU) 21642664Smarkm old_signal_handler = &old_TTOU; 21742664Smarkm if (sig == SIGTTIN) 21842664Smarkm old_signal_handler = &old_TTIN; 21921495Sjmacd#endif /* SIGTSTP */ 220146520Sru#if defined (SIGQUIT) 221146520Sru if (sig == SIGQUIT) 222146520Sru old_signal_handler = &old_QUIT; 223146520Sru#endif /* SIGQUIT */ 224114478Sru#if defined (SIGINT) 22542664Smarkm if (sig == SIGINT) 22642664Smarkm old_signal_handler = &old_INT; 227114478Sru#endif /* SIGINT */ 22821495Sjmacd 22942664Smarkm /* For stop signals, restore the terminal IO, leave the cursor 23042664Smarkm at the bottom of the window, and stop us. */ 23142664Smarkm terminal_goto_xy (0, screenheight - 1); 23242664Smarkm terminal_clear_to_eol (); 23342664Smarkm fflush (stdout); 23442664Smarkm terminal_unprep_terminal (); 235114478Sru restore_termsig (sig, old_signal_handler); 236114478Sru UNBLOCK_SIGNAL (sig); 237114478Sru kill (getpid (), sig); 23821495Sjmacd 23942664Smarkm /* The program is returning now. Restore our signal handler, 24042664Smarkm turn on terminal handling, redraw the screen, and place the 24142664Smarkm cursor where it belongs. */ 24242664Smarkm terminal_prep_terminal (); 243114478Sru set_termsig (sig, old_signal_handler); 244114478Sru /* window size might be changed while sleeping */ 245114478Sru reset_info_window_sizes (); 24621495Sjmacd } 24721495Sjmacd break; 24821495Sjmacd 24956165Sru#if defined (SIGWINCH) || defined (SIGUSR1) 25056165Sru#ifdef SIGWINCH 25121495Sjmacd case SIGWINCH: 25256165Sru#endif 25356165Sru#ifdef SIGUSR1 25456165Sru case SIGUSR1: 25556165Sru#endif 25621495Sjmacd { 257114478Sru /* Turn off terminal IO, tell our parent that the window has changed, 258114478Sru then reinitialize the terminal and rebuild our windows. */ 25956165Sru#ifdef SIGWINCH 260114478Sru if (sig == SIGWINCH) 261114478Sru old_signal_handler = &old_WINCH; 26256165Sru#endif 26356165Sru#ifdef SIGUSR1 264114478Sru if (sig == SIGUSR1) 265114478Sru old_signal_handler = &old_USR1; 26656165Sru#endif 267114478Sru terminal_goto_xy (0, 0); 268114478Sru fflush (stdout); 269114478Sru terminal_unprep_terminal (); /* needless? */ 270114478Sru restore_termsig (sig, old_signal_handler); 271114478Sru UNBLOCK_SIGNAL (sig); 272114478Sru kill (getpid (), sig); 27321495Sjmacd 274114478Sru /* After our old signal handler returns... */ 275114478Sru set_termsig (sig, old_signal_handler); /* needless? */ 276114478Sru terminal_prep_terminal (); 277114478Sru reset_info_window_sizes (); 27821495Sjmacd } 27921495Sjmacd break; 28056165Sru#endif /* SIGWINCH || SIGUSR1 */ 28121495Sjmacd } 282114478Sru#if !defined (HAVE_SIGACTION) 283114478Sru /* at this time it is safer to perform unblock after decrement */ 284114478Sru term_conf_busy--; 285114478Sru#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK) 286114478Sru { 287114478Sru sigset_t nvar, ovar; 288114478Sru sigemptyset (&nvar); 289114478Sru mask_termsig (&nvar); 290114478Sru sigprocmask (SIG_UNBLOCK, &nvar, &ovar); 291114478Sru } 292114478Sru#endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */ 293114478Sru#endif /* !HAVE_SIGACTION */ 29421495Sjmacd} 295114478Sru/* vim: set sw=2 cino={1s>2sn-s^-se-s: */ 296