signal.c revision 60787
10SN/A/* 20SN/A * Copyright (C) 1984-2000 Mark Nudelman 30SN/A * 40SN/A * You may distribute under the terms of either the GNU General Public 50SN/A * License or the Less License, as specified in the README file. 62362SN/A * 70SN/A * For more information about less, or for information on how to 82362SN/A * contact the author, see the README file. 90SN/A */ 100SN/A 110SN/A 120SN/A/* 130SN/A * Routines dealing with signals. 140SN/A * 150SN/A * A signal usually merely causes a bit to be set in the "signals" word. 160SN/A * At some convenient time, the mainline code checks to see if any 170SN/A * signals need processing by calling psignal(). 180SN/A * If we happen to be reading from a file [in iread()] at the time 190SN/A * the signal is received, we call intread to interrupt the iread. 202362SN/A */ 212362SN/A 222362SN/A#include "less.h" 230SN/A#include <signal.h> 240SN/A 250SN/A/* 260SN/A * "sigs" contains bits indicating signals which need to be processed. 270SN/A */ 280SN/Apublic int sigs; 290SN/A 300SN/Aextern int sc_width, sc_height; 310SN/Aextern int screen_trashed; 320SN/Aextern int lnloop; 330SN/Aextern int linenums; 341693SN/Aextern int wscroll; 351693SN/Aextern int reading; 361693SN/A 371693SN/A/* 381693SN/A * Interrupt signal handler. 390SN/A */ 400SN/A /* ARGSUSED*/ 410SN/A static RETSIGTYPE 420SN/Au_interrupt(type) 433171SN/A int type; 440SN/A{ 450SN/A#if OS2 460SN/A LSIGNAL(SIGINT, SIG_ACK); 470SN/A#endif 480SN/A LSIGNAL(SIGINT, u_interrupt); 491693SN/A sigs |= S_INTERRUPT; 501693SN/A#if MSDOS_COMPILER==DJGPPC 510SN/A /* 520SN/A * If a keyboard has been hit, it must be Ctrl-C 530SN/A * (as opposed to Ctrl-Break), so consume it. 546936SN/A * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 553171SN/A */ 563171SN/A if (kbhit()) 573171SN/A getkey(); 583171SN/A#endif 593171SN/A if (reading) 603171SN/A intread(); 610SN/A} 620SN/A 630SN/A#ifdef SIGTSTP 646936SN/A/* 653171SN/A * "Stop" (^Z) signal handler. 660SN/A */ 670SN/A /* ARGSUSED*/ 680SN/A static RETSIGTYPE 690SN/Astop(type) 700SN/A int type; 710SN/A{ 720SN/A LSIGNAL(SIGTSTP, stop); 730SN/A sigs |= S_STOP; 740SN/A if (reading) 750SN/A intread(); 761693SN/A} 770SN/A#endif 78 79#ifdef SIGWINCH 80/* 81 * "Window" change handler 82 */ 83 /* ARGSUSED*/ 84 public RETSIGTYPE 85winch(type) 86 int type; 87{ 88 LSIGNAL(SIGWINCH, winch); 89 sigs |= S_WINCH; 90 if (reading) 91 intread(); 92} 93#else 94#ifdef SIGWIND 95/* 96 * "Window" change handler 97 */ 98 /* ARGSUSED*/ 99 public RETSIGTYPE 100winch(type) 101 int type; 102{ 103 LSIGNAL(SIGWIND, winch); 104 sigs |= S_WINCH; 105 if (reading) 106 intread(); 107} 108#endif 109#endif 110 111#if MSDOS_COMPILER==WIN32C 112/* 113 * Handle CTRL-C and CTRL-BREAK keys. 114 */ 115#include "windows.h" 116 117 static BOOL WINAPI 118wbreak_handler(dwCtrlType) 119 DWORD dwCtrlType; 120{ 121 switch (dwCtrlType) 122 { 123 case CTRL_C_EVENT: 124 case CTRL_BREAK_EVENT: 125 sigs |= S_INTERRUPT; 126 return (TRUE); 127 default: 128 break; 129 } 130 return (FALSE); 131} 132#endif 133 134/* 135 * Set up the signal handlers. 136 */ 137 public void 138init_signals(on) 139 int on; 140{ 141 if (on) 142 { 143 /* 144 * Set signal handlers. 145 */ 146 (void) LSIGNAL(SIGINT, u_interrupt); 147#if MSDOS_COMPILER==WIN32C 148 SetConsoleCtrlHandler(wbreak_handler, TRUE); 149#endif 150#ifdef SIGTSTP 151 (void) LSIGNAL(SIGTSTP, stop); 152#endif 153#ifdef SIGWINCH 154 (void) LSIGNAL(SIGWINCH, winch); 155#else 156#ifdef SIGWIND 157 (void) LSIGNAL(SIGWIND, winch); 158#endif 159#ifdef SIGQUIT 160 (void) LSIGNAL(SIGQUIT, SIG_IGN); 161#endif 162#endif 163 } else 164 { 165 /* 166 * Restore signals to defaults. 167 */ 168 (void) LSIGNAL(SIGINT, SIG_DFL); 169#if MSDOS_COMPILER==WIN32C 170 SetConsoleCtrlHandler(wbreak_handler, FALSE); 171#endif 172#ifdef SIGTSTP 173 (void) LSIGNAL(SIGTSTP, SIG_DFL); 174#endif 175#ifdef SIGWINCH 176 (void) LSIGNAL(SIGWINCH, SIG_IGN); 177#endif 178#ifdef SIGWIND 179 (void) LSIGNAL(SIGWIND, SIG_IGN); 180#endif 181#ifdef SIGQUIT 182 (void) LSIGNAL(SIGQUIT, SIG_DFL); 183#endif 184 } 185} 186 187/* 188 * Process any signals we have received. 189 * A received signal cause a bit to be set in "sigs". 190 */ 191 public void 192psignals() 193{ 194 register int tsignals; 195 196 if ((tsignals = sigs) == 0) 197 return; 198 sigs = 0; 199 200#ifdef SIGTSTP 201 if (tsignals & S_STOP) 202 { 203 /* 204 * Clean up the terminal. 205 */ 206#ifdef SIGTTOU 207 LSIGNAL(SIGTTOU, SIG_IGN); 208#endif 209 clear_bot(); 210 deinit(); 211 flush(); 212 raw_mode(0); 213#ifdef SIGTTOU 214 LSIGNAL(SIGTTOU, SIG_DFL); 215#endif 216 LSIGNAL(SIGTSTP, SIG_DFL); 217 kill(getpid(), SIGTSTP); 218 /* 219 * ... Bye bye. ... 220 * Hopefully we'll be back later and resume here... 221 * Reset the terminal and arrange to repaint the 222 * screen when we get back to the main command loop. 223 */ 224 LSIGNAL(SIGTSTP, stop); 225 raw_mode(1); 226 init(); 227 screen_trashed = 1; 228 tsignals |= S_WINCH; 229 } 230#endif 231#ifdef S_WINCH 232 if (tsignals & S_WINCH) 233 { 234 int old_width, old_height; 235 /* 236 * Re-execute scrsize() to read the new window size. 237 */ 238 old_width = sc_width; 239 old_height = sc_height; 240 get_term(); 241 if (sc_width != old_width || sc_height != old_height) 242 { 243 wscroll = (sc_height + 1) / 2; 244 screen_trashed = 1; 245 } 246 } 247#endif 248 if (tsignals & S_INTERRUPT) 249 { 250 bell(); 251 /* 252 * {{ You may wish to replace the bell() with 253 * error("Interrupt", NULL_PARG); }} 254 */ 255 256 /* 257 * If we were interrupted while in the "calculating 258 * line numbers" loop, turn off line numbers. 259 */ 260 if (lnloop) 261 { 262 lnloop = 0; 263 if (linenums == 2) 264 screen_trashed = 1; 265 linenums = 0; 266 error("Line numbers turned off", NULL_PARG); 267 } 268 269 } 270} 271