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 int less_is_more; 38extern long jump_sline_fraction; 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 (less_is_more) 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#endif 161#ifdef SIGWIND 162 (void) LSIGNAL(SIGWIND, winch); 163#endif 164#ifdef SIGQUIT 165 (void) LSIGNAL(SIGQUIT, SIG_IGN); 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 calc_jump_sline(); 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