signal.c revision 60787
1/* 2 * Copyright (C) 1984-2000 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; 36 37/* 38 * Interrupt signal handler. 39 */ 40 /* ARGSUSED*/ 41 static RETSIGTYPE 42u_interrupt(type) 43 int type; 44{ 45#if OS2 46 LSIGNAL(SIGINT, SIG_ACK); 47#endif 48 LSIGNAL(SIGINT, u_interrupt); 49 sigs |= S_INTERRUPT; 50#if MSDOS_COMPILER==DJGPPC 51 /* 52 * If a keyboard has been hit, it must be Ctrl-C 53 * (as opposed to Ctrl-Break), so consume it. 54 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 55 */ 56 if (kbhit()) 57 getkey(); 58#endif 59 if (reading) 60 intread(); 61} 62 63#ifdef SIGTSTP 64/* 65 * "Stop" (^Z) signal handler. 66 */ 67 /* ARGSUSED*/ 68 static RETSIGTYPE 69stop(type) 70 int type; 71{ 72 LSIGNAL(SIGTSTP, stop); 73 sigs |= S_STOP; 74 if (reading) 75 intread(); 76} 77#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