1 /* 2 * Copyright (C) 1984-2002 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$ */ 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 */ 29 public int sigs; 30 31 extern int sc_width, sc_height; 32 extern int screen_trashed; 33 extern int lnloop; 34 extern int linenums; 35 extern int wscroll; 36 extern int reading; 37 extern int more_mode; 38 39 /* 40 * Interrupt signal handler. 41 */ 42 /* ARGSUSED*/ 43 static RETSIGTYPE 44 u_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 (more_mode) 62 quit(0); 63 if (reading) 64 intread(); 65 } 66 67 #ifdef SIGTSTP 68 /* 69 * "Stop" (^Z) signal handler. 70 */ 71 /* ARGSUSED*/ 72 static RETSIGTYPE 73 stop(type) 74 int type; 75 { 76 LSIGNAL(SIGTSTP, stop); 77 sigs |= S_STOP; 78 if (reading) 79 intread(); 80 } 81 #endif 82 83 #ifdef SIGWINCH 84 /* 85 * "Window" change handler 86 */ 87 /* ARGSUSED*/ 88 public RETSIGTYPE 89 winch(type) 90 int type; 91 { 92 LSIGNAL(SIGWINCH, winch); 93 sigs |= S_WINCH; 94 if (reading) 95 intread(); 96 } 97 #else 98 #ifdef SIGWIND 99 /* 100 * "Window" change handler 101 */ 102 /* ARGSUSED*/ 103 public RETSIGTYPE 104 winch(type) 105 int type; 106 { 107 LSIGNAL(SIGWIND, winch); 108 sigs |= S_WINCH; 109 if (reading) 110 intread(); 111 } 112 #endif 113 #endif 114 115 #if MSDOS_COMPILER==WIN32C 116 /* 117 * Handle CTRL-C and CTRL-BREAK keys. 118 */ 119 #include "windows.h" 120 121 static BOOL WINAPI 122 wbreak_handler(dwCtrlType) 123 DWORD dwCtrlType; 124 { 125 switch (dwCtrlType) 126 { 127 case CTRL_C_EVENT: 128 case CTRL_BREAK_EVENT: 129 sigs |= S_INTERRUPT; 130 return (TRUE); 131 default: 132 break; 133 } 134 return (FALSE); 135 } 136 #endif 137 138 /* 139 * Set up the signal handlers. 140 */ 141 public void 142 init_signals(on) 143 int on; 144 { 145 if (on) 146 { 147 /* 148 * Set signal handlers. 149 */ 150 (void) LSIGNAL(SIGINT, u_interrupt); 151 #if MSDOS_COMPILER==WIN32C 152 SetConsoleCtrlHandler(wbreak_handler, TRUE); 153 #endif 154 #ifdef SIGTSTP 155 (void) LSIGNAL(SIGTSTP, stop); 156 #endif 157 #ifdef SIGWINCH 158 (void) LSIGNAL(SIGWINCH, winch); 159 #else 160 #ifdef SIGWIND 161 (void) LSIGNAL(SIGWIND, winch); 162 #endif 163 #ifdef SIGQUIT 164 (void) LSIGNAL(SIGQUIT, SIG_IGN); 165 #endif 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 196 psignals() 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 screen_trashed = 1; 249 } 250 } 251 #endif 252 if (tsignals & S_INTERRUPT) 253 { 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