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