1 /* 2 * Copyright (C) 1984-2004 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 quit_on_intr; 38 extern int more_mode; 39 40 /* 41 * Interrupt signal handler. 42 */ 43 /* ARGSUSED*/ 44 static RETSIGTYPE 45 u_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 (more_mode) 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 74 stop(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 90 winch(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 105 winch(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 123 wbreak_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 143 init_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 #else 161 #ifdef SIGWIND 162 (void) LSIGNAL(SIGWIND, winch); 163 #endif 164 #ifdef SIGQUIT 165 (void) LSIGNAL(SIGQUIT, SIG_IGN); 166 #endif 167 #endif 168 } else 169 { 170 /* 171 * Restore signals to defaults. 172 */ 173 (void) LSIGNAL(SIGINT, SIG_DFL); 174 #if MSDOS_COMPILER==WIN32C 175 SetConsoleCtrlHandler(wbreak_handler, FALSE); 176 #endif 177 #ifdef SIGTSTP 178 (void) LSIGNAL(SIGTSTP, SIG_DFL); 179 #endif 180 #ifdef SIGWINCH 181 (void) LSIGNAL(SIGWINCH, SIG_IGN); 182 #endif 183 #ifdef SIGWIND 184 (void) LSIGNAL(SIGWIND, SIG_IGN); 185 #endif 186 #ifdef SIGQUIT 187 (void) LSIGNAL(SIGQUIT, SIG_DFL); 188 #endif 189 } 190 } 191 192 /* 193 * Process any signals we have received. 194 * A received signal cause a bit to be set in "sigs". 195 */ 196 public void 197 psignals() 198 { 199 register int tsignals; 200 201 if ((tsignals = sigs) == 0) 202 return; 203 sigs = 0; 204 205 #ifdef SIGTSTP 206 if (tsignals & S_STOP) 207 { 208 /* 209 * Clean up the terminal. 210 */ 211 #ifdef SIGTTOU 212 LSIGNAL(SIGTTOU, SIG_IGN); 213 #endif 214 clear_bot(); 215 deinit(); 216 flush(); 217 raw_mode(0); 218 #ifdef SIGTTOU 219 LSIGNAL(SIGTTOU, SIG_DFL); 220 #endif 221 LSIGNAL(SIGTSTP, SIG_DFL); 222 kill(getpid(), SIGTSTP); 223 /* 224 * ... Bye bye. ... 225 * Hopefully we'll be back later and resume here... 226 * Reset the terminal and arrange to repaint the 227 * screen when we get back to the main command loop. 228 */ 229 LSIGNAL(SIGTSTP, stop); 230 raw_mode(1); 231 init(); 232 screen_trashed = 1; 233 tsignals |= S_WINCH; 234 } 235 #endif 236 #ifdef S_WINCH 237 if (tsignals & S_WINCH) 238 { 239 int old_width, old_height; 240 /* 241 * Re-execute scrsize() to read the new window size. 242 */ 243 old_width = sc_width; 244 old_height = sc_height; 245 get_term(); 246 if (sc_width != old_width || sc_height != old_height) 247 { 248 wscroll = (sc_height + 1) / 2; 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