1/* 2 * Copyright (C) 1984-2007 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 12/* 13 * Routines dealing with signals. 14 * 15 * A signal usually merely causes a bit to be set in the "signals" word. 16 * At some convenient time, the mainline code checks to see if any 17 * signals need processing by calling psignal(). 18 * If we happen to be reading from a file [in iread()] at the time 19 * the signal is received, we call intread to interrupt the iread. 20 */ 21 22#include "less.h" 23#include <signal.h> 24 25/* 26 * "sigs" contains bits indicating signals which need to be processed. 27 */ 28public int sigs; 29 30extern int sc_width, sc_height; 31extern int screen_trashed; 32extern int lnloop; 33extern int linenums; 34extern int wscroll; 35extern int reading; 36extern int quit_on_intr; 37extern long jump_sline_fraction; 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 (reading) 62 intread(); 63} 64 65#ifdef SIGTSTP 66/* 67 * "Stop" (^Z) signal handler. 68 */ 69 /* ARGSUSED*/ 70 static RETSIGTYPE 71stop(type) 72 int type; 73{ 74 LSIGNAL(SIGTSTP, stop); 75 sigs |= S_STOP; 76 if (reading) 77 intread(); 78} 79#endif 80 81#ifdef SIGWINCH 82/* 83 * "Window" change handler 84 */ 85 /* ARGSUSED*/ 86 public RETSIGTYPE 87winch(type) 88 int type; 89{ 90 LSIGNAL(SIGWINCH, winch); 91 sigs |= S_WINCH; 92 if (reading) 93 intread(); 94} 95#else 96#ifdef SIGWIND 97/* 98 * "Window" change handler 99 */ 100 /* ARGSUSED*/ 101 public RETSIGTYPE 102winch(type) 103 int type; 104{ 105 LSIGNAL(SIGWIND, winch); 106 sigs |= S_WINCH; 107 if (reading) 108 intread(); 109} 110#endif 111#endif 112 113#if MSDOS_COMPILER==WIN32C 114/* 115 * Handle CTRL-C and CTRL-BREAK keys. 116 */ 117#include "windows.h" 118 119 static BOOL WINAPI 120wbreak_handler(dwCtrlType) 121 DWORD dwCtrlType; 122{ 123 switch (dwCtrlType) 124 { 125 case CTRL_C_EVENT: 126 case CTRL_BREAK_EVENT: 127 sigs |= S_INTERRUPT; 128 return (TRUE); 129 default: 130 break; 131 } 132 return (FALSE); 133} 134#endif 135 136/* 137 * Set up the signal handlers. 138 */ 139 public void 140init_signals(on) 141 int on; 142{ 143 if (on) 144 { 145 /* 146 * Set signal handlers. 147 */ 148 (void) LSIGNAL(SIGINT, u_interrupt); 149#if MSDOS_COMPILER==WIN32C 150 SetConsoleCtrlHandler(wbreak_handler, TRUE); 151#endif 152#ifdef SIGTSTP 153 (void) LSIGNAL(SIGTSTP, stop); 154#endif 155#ifdef SIGWINCH 156 (void) LSIGNAL(SIGWINCH, winch); 157#endif 158#ifdef SIGWIND 159 (void) LSIGNAL(SIGWIND, winch); 160#endif 161#ifdef SIGQUIT 162 (void) LSIGNAL(SIGQUIT, SIG_IGN); 163#endif 164 } else 165 { 166 /* 167 * Restore signals to defaults. 168 */ 169 (void) LSIGNAL(SIGINT, SIG_DFL); 170#if MSDOS_COMPILER==WIN32C 171 SetConsoleCtrlHandler(wbreak_handler, FALSE); 172#endif 173#ifdef SIGTSTP 174 (void) LSIGNAL(SIGTSTP, SIG_DFL); 175#endif 176#ifdef SIGWINCH 177 (void) LSIGNAL(SIGWINCH, SIG_IGN); 178#endif 179#ifdef SIGWIND 180 (void) LSIGNAL(SIGWIND, SIG_IGN); 181#endif 182#ifdef SIGQUIT 183 (void) LSIGNAL(SIGQUIT, SIG_DFL); 184#endif 185 } 186} 187 188/* 189 * Process any signals we have received. 190 * A received signal cause a bit to be set in "sigs". 191 */ 192 public void 193psignals() 194{ 195 register int tsignals; 196 197 if ((tsignals = sigs) == 0) 198 return; 199 sigs = 0; 200 201#ifdef SIGTSTP 202 if (tsignals & S_STOP) 203 { 204 /* 205 * Clean up the terminal. 206 */ 207#ifdef SIGTTOU 208 LSIGNAL(SIGTTOU, SIG_IGN); 209#endif 210 clear_bot(); 211 deinit(); 212 flush(); 213 raw_mode(0); 214#ifdef SIGTTOU 215 LSIGNAL(SIGTTOU, SIG_DFL); 216#endif 217 LSIGNAL(SIGTSTP, SIG_DFL); 218 kill(getpid(), SIGTSTP); 219 /* 220 * ... Bye bye. ... 221 * Hopefully we'll be back later and resume here... 222 * Reset the terminal and arrange to repaint the 223 * screen when we get back to the main command loop. 224 */ 225 LSIGNAL(SIGTSTP, stop); 226 raw_mode(1); 227 init(); 228 screen_trashed = 1; 229 tsignals |= S_WINCH; 230 } 231#endif 232#ifdef S_WINCH 233 if (tsignals & S_WINCH) 234 { 235 int old_width, old_height; 236 /* 237 * Re-execute scrsize() to read the new window size. 238 */ 239 old_width = sc_width; 240 old_height = sc_height; 241 get_term(); 242 if (sc_width != old_width || sc_height != old_height) 243 { 244 wscroll = (sc_height + 1) / 2; 245 calc_jump_sline(); 246 screen_trashed = 1; 247 } 248 } 249#endif 250 if (tsignals & S_INTERRUPT) 251 { 252 if (quit_on_intr) 253 quit(QUIT_OK); 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