signal.c revision 128348
1/* 2 * Copyright (C) 1984-2002 Mark Nudelman 3 * 4 * You may distribute under the terms of either the GNU General Public 5 * License or the Less License, as specified in the README file. 6 * 7 * For more information about less, or for information on how to 8 * contact the author, see the README file. 9 */ 10 11/* $FreeBSD: head/contrib/less/signal.c 128348 2004-04-17 07:24:09Z tjr $ */ 12 13/* 14 * Routines dealing with signals. 15 * 16 * A signal usually merely causes a bit to be set in the "signals" word. 17 * At some convenient time, the mainline code checks to see if any 18 * signals need processing by calling psignal(). 19 * If we happen to be reading from a file [in iread()] at the time 20 * the signal is received, we call intread to interrupt the iread. 21 */ 22 23#include "less.h" 24#include <signal.h> 25 26/* 27 * "sigs" contains bits indicating signals which need to be processed. 28 */ 29public int sigs; 30 31extern int sc_width, sc_height; 32extern int screen_trashed; 33extern int lnloop; 34extern int linenums; 35extern int wscroll; 36extern int reading; 37extern int more_mode; 38 39/* 40 * Interrupt signal handler. 41 */ 42 /* ARGSUSED*/ 43 static RETSIGTYPE 44u_interrupt(type) 45 int type; 46{ 47#if OS2 48 LSIGNAL(SIGINT, SIG_ACK); 49#endif 50 LSIGNAL(SIGINT, u_interrupt); 51 sigs |= S_INTERRUPT; 52#if MSDOS_COMPILER==DJGPPC 53 /* 54 * If a keyboard has been hit, it must be Ctrl-C 55 * (as opposed to Ctrl-Break), so consume it. 56 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 57 */ 58 if (kbhit()) 59 getkey(); 60#endif 61 if (more_mode) 62 quit(0); 63 if (reading) 64 intread(); 65} 66 67#ifdef SIGTSTP 68/* 69 * "Stop" (^Z) signal handler. 70 */ 71 /* ARGSUSED*/ 72 static RETSIGTYPE 73stop(type) 74 int type; 75{ 76 LSIGNAL(SIGTSTP, stop); 77 sigs |= S_STOP; 78 if (reading) 79 intread(); 80} 81#endif 82 83#ifdef SIGWINCH 84/* 85 * "Window" change handler 86 */ 87 /* ARGSUSED*/ 88 public RETSIGTYPE 89winch(type) 90 int type; 91{ 92 LSIGNAL(SIGWINCH, winch); 93 sigs |= S_WINCH; 94 if (reading) 95 intread(); 96} 97#else 98#ifdef SIGWIND 99/* 100 * "Window" change handler 101 */ 102 /* ARGSUSED*/ 103 public RETSIGTYPE 104winch(type) 105 int type; 106{ 107 LSIGNAL(SIGWIND, winch); 108 sigs |= S_WINCH; 109 if (reading) 110 intread(); 111} 112#endif 113#endif 114 115#if MSDOS_COMPILER==WIN32C 116/* 117 * Handle CTRL-C and CTRL-BREAK keys. 118 */ 119#include "windows.h" 120 121 static BOOL WINAPI 122wbreak_handler(dwCtrlType) 123 DWORD dwCtrlType; 124{ 125 switch (dwCtrlType) 126 { 127 case CTRL_C_EVENT: 128 case CTRL_BREAK_EVENT: 129 sigs |= S_INTERRUPT; 130 return (TRUE); 131 default: 132 break; 133 } 134 return (FALSE); 135} 136#endif 137 138/* 139 * Set up the signal handlers. 140 */ 141 public void 142init_signals(on) 143 int on; 144{ 145 if (on) 146 { 147 /* 148 * Set signal handlers. 149 */ 150 (void) LSIGNAL(SIGINT, u_interrupt); 151#if MSDOS_COMPILER==WIN32C 152 SetConsoleCtrlHandler(wbreak_handler, TRUE); 153#endif 154#ifdef SIGTSTP 155 (void) LSIGNAL(SIGTSTP, stop); 156#endif 157#ifdef SIGWINCH 158 (void) LSIGNAL(SIGWINCH, winch); 159#else 160#ifdef SIGWIND 161 (void) LSIGNAL(SIGWIND, winch); 162#endif 163#ifdef SIGQUIT 164 (void) LSIGNAL(SIGQUIT, SIG_IGN); 165#endif 166#endif 167 } else 168 { 169 /* 170 * Restore signals to defaults. 171 */ 172 (void) LSIGNAL(SIGINT, SIG_DFL); 173#if MSDOS_COMPILER==WIN32C 174 SetConsoleCtrlHandler(wbreak_handler, FALSE); 175#endif 176#ifdef SIGTSTP 177 (void) LSIGNAL(SIGTSTP, SIG_DFL); 178#endif 179#ifdef SIGWINCH 180 (void) LSIGNAL(SIGWINCH, SIG_IGN); 181#endif 182#ifdef SIGWIND 183 (void) LSIGNAL(SIGWIND, SIG_IGN); 184#endif 185#ifdef SIGQUIT 186 (void) LSIGNAL(SIGQUIT, SIG_DFL); 187#endif 188 } 189} 190 191/* 192 * Process any signals we have received. 193 * A received signal cause a bit to be set in "sigs". 194 */ 195 public void 196psignals() 197{ 198 register int tsignals; 199 200 if ((tsignals = sigs) == 0) 201 return; 202 sigs = 0; 203 204#ifdef SIGTSTP 205 if (tsignals & S_STOP) 206 { 207 /* 208 * Clean up the terminal. 209 */ 210#ifdef SIGTTOU 211 LSIGNAL(SIGTTOU, SIG_IGN); 212#endif 213 clear_bot(); 214 deinit(); 215 flush(); 216 raw_mode(0); 217#ifdef SIGTTOU 218 LSIGNAL(SIGTTOU, SIG_DFL); 219#endif 220 LSIGNAL(SIGTSTP, SIG_DFL); 221 kill(getpid(), SIGTSTP); 222 /* 223 * ... Bye bye. ... 224 * Hopefully we'll be back later and resume here... 225 * Reset the terminal and arrange to repaint the 226 * screen when we get back to the main command loop. 227 */ 228 LSIGNAL(SIGTSTP, stop); 229 raw_mode(1); 230 init(); 231 screen_trashed = 1; 232 tsignals |= S_WINCH; 233 } 234#endif 235#ifdef S_WINCH 236 if (tsignals & S_WINCH) 237 { 238 int old_width, old_height; 239 /* 240 * Re-execute scrsize() to read the new window size. 241 */ 242 old_width = sc_width; 243 old_height = sc_height; 244 get_term(); 245 if (sc_width != old_width || sc_height != old_height) 246 { 247 wscroll = (sc_height + 1) / 2; 248 screen_trashed = 1; 249 } 250 } 251#endif 252 if (tsignals & S_INTERRUPT) 253 { 254 bell(); 255 /* 256 * {{ You may wish to replace the bell() with 257 * error("Interrupt", NULL_PARG); }} 258 */ 259 260 /* 261 * If we were interrupted while in the "calculating 262 * line numbers" loop, turn off line numbers. 263 */ 264 if (lnloop) 265 { 266 lnloop = 0; 267 if (linenums == 2) 268 screen_trashed = 1; 269 linenums = 0; 270 error("Line numbers turned off", NULL_PARG); 271 } 272 273 } 274} 275