signals.c revision 21495
1/* signals.c -- Install and maintain Info signal handlers. */ 2 3/* This file is part of GNU Info, a program for reading online documentation 4 stored in Info format. 5 6 Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 22 Written by Brian Fox (bfox@ai.mit.edu). */ 23 24#include "info.h" 25#include "signals.h" 26 27/* **************************************************************** */ 28/* */ 29/* Pretending That We Have POSIX Signals */ 30/* */ 31/* **************************************************************** */ 32 33#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK) 34/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */ 35static void 36sigprocmask (operation, newset, oldset) 37 int operation, *newset, *oldset; 38{ 39 switch (operation) 40 { 41 case SIG_UNBLOCK: 42 sigsetmask (sigblock (0) & ~(*newset)); 43 break; 44 45 case SIG_BLOCK: 46 *oldset = sigblock (*newset); 47 break; 48 49 case SIG_SETMASK: 50 sigsetmask (*newset); 51 break; 52 53 default: 54 abort (); 55 } 56} 57#endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */ 58 59/* **************************************************************** */ 60/* */ 61/* Signal Handling for Info */ 62/* */ 63/* **************************************************************** */ 64 65typedef void SigHandlerType; 66typedef SigHandlerType SigHandler (); 67 68static SigHandlerType info_signal_handler (); 69static SigHandler *old_TSTP, *old_TTOU, *old_TTIN; 70static SigHandler *old_WINCH, *old_INT; 71 72void 73initialize_info_signal_handler () 74{ 75#if defined (SIGTSTP) 76 old_TSTP = (SigHandler *) signal (SIGTSTP, info_signal_handler); 77 old_TTOU = (SigHandler *) signal (SIGTTOU, info_signal_handler); 78 old_TTIN = (SigHandler *) signal (SIGTTIN, info_signal_handler); 79#endif /* SIGTSTP */ 80 81#if defined (SIGWINCH) 82 old_WINCH = (SigHandler *) signal (SIGWINCH, info_signal_handler); 83#endif 84 85#if defined (SIGINT) 86 old_INT = (SigHandler *) signal (SIGINT, info_signal_handler); 87#endif 88} 89 90static void 91redisplay_after_signal () 92{ 93 terminal_clear_screen (); 94 display_clear_display (the_display); 95 window_mark_chain (windows, W_UpdateWindow); 96 display_update_display (windows); 97 display_cursor_at_point (active_window); 98 fflush (stdout); 99} 100 101static SigHandlerType 102info_signal_handler (sig) 103 int sig; 104{ 105 SigHandler **old_signal_handler; 106 107 switch (sig) 108 { 109#if defined (SIGTSTP) 110 case SIGTSTP: 111 case SIGTTOU: 112 case SIGTTIN: 113#endif 114#if defined (SIGINT) 115 case SIGINT: 116#endif 117 { 118#if defined (SIGTSTP) 119 if (sig == SIGTSTP) 120 old_signal_handler = &old_TSTP; 121 if (sig == SIGTTOU) 122 old_signal_handler = &old_TTOU; 123 if (sig == SIGTTIN) 124 old_signal_handler = &old_TTIN; 125#endif /* SIGTSTP */ 126 if (sig == SIGINT) 127 old_signal_handler = &old_INT; 128 129 /* For stop signals, restore the terminal IO, leave the cursor 130 at the bottom of the window, and stop us. */ 131 terminal_goto_xy (0, screenheight - 1); 132 terminal_clear_to_eol (); 133 fflush (stdout); 134 terminal_unprep_terminal (); 135 signal (sig, *old_signal_handler); 136 UNBLOCK_SIGNAL (sig); 137 kill (getpid (), sig); 138 139 /* The program is returning now. Restore our signal handler, 140 turn on terminal handling, redraw the screen, and place the 141 cursor where it belongs. */ 142 terminal_prep_terminal (); 143 *old_signal_handler = (SigHandler *) signal (sig, info_signal_handler); 144 redisplay_after_signal (); 145 fflush (stdout); 146 } 147 break; 148 149#if defined (SIGWINCH) 150 case SIGWINCH: 151 { 152 /* Turn off terminal IO, tell our parent that the window has changed, 153 then reinitialize the terminal and rebuild our windows. */ 154 old_signal_handler = &old_WINCH; 155 terminal_goto_xy (0, 0); 156 fflush (stdout); 157 terminal_unprep_terminal (); 158 signal (sig, *old_signal_handler); 159 UNBLOCK_SIGNAL (sig); 160 kill (getpid (), sig); 161 162 /* After our old signal handler returns... */ 163 terminal_get_screen_size (); 164 terminal_prep_terminal (); 165 display_initialize_display (screenwidth, screenheight); 166 window_new_screen_size (screenwidth, screenheight, (VFunction *)NULL); 167 *old_signal_handler = (SigHandler *) signal (sig, info_signal_handler); 168 redisplay_after_signal (); 169 } 170 break; 171#endif /* SIGWINCH */ 172 } 173} 174