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 /* $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 less_is_more; 39 extern long jump_sline_fraction; 40 41 /* 42 * Interrupt signal handler. 43 */ 44 /* ARGSUSED*/ 45 static RETSIGTYPE 46 u_interrupt(type) 47 int type; 48 { 49 #if OS2 50 LSIGNAL(SIGINT, SIG_ACK); 51 #endif 52 LSIGNAL(SIGINT, u_interrupt); 53 sigs |= S_INTERRUPT; 54 #if MSDOS_COMPILER==DJGPPC 55 /* 56 * If a keyboard has been hit, it must be Ctrl-C 57 * (as opposed to Ctrl-Break), so consume it. 58 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 59 */ 60 if (kbhit()) 61 getkey(); 62 #endif 63 if (less_is_more) 64 quit(0); 65 if (reading) 66 intread(); 67 } 68 69 #ifdef SIGTSTP 70 /* 71 * "Stop" (^Z) signal handler. 72 */ 73 /* ARGSUSED*/ 74 static RETSIGTYPE 75 stop(type) 76 int type; 77 { 78 LSIGNAL(SIGTSTP, stop); 79 sigs |= S_STOP; 80 if (reading) 81 intread(); 82 } 83 #endif 84 85 #ifdef SIGWINCH 86 /* 87 * "Window" change handler 88 */ 89 /* ARGSUSED*/ 90 public RETSIGTYPE 91 winch(type) 92 int type; 93 { 94 LSIGNAL(SIGWINCH, winch); 95 sigs |= S_WINCH; 96 if (reading) 97 intread(); 98 } 99 #else 100 #ifdef SIGWIND 101 /* 102 * "Window" change handler 103 */ 104 /* ARGSUSED*/ 105 public RETSIGTYPE 106 winch(type) 107 int type; 108 { 109 LSIGNAL(SIGWIND, winch); 110 sigs |= S_WINCH; 111 if (reading) 112 intread(); 113 } 114 #endif 115 #endif 116 117 #if MSDOS_COMPILER==WIN32C 118 /* 119 * Handle CTRL-C and CTRL-BREAK keys. 120 */ 121 #include "windows.h" 122 123 static BOOL WINAPI 124 wbreak_handler(dwCtrlType) 125 DWORD dwCtrlType; 126 { 127 switch (dwCtrlType) 128 { 129 case CTRL_C_EVENT: 130 case CTRL_BREAK_EVENT: 131 sigs |= S_INTERRUPT; 132 return (TRUE); 133 default: 134 break; 135 } 136 return (FALSE); 137 } 138 #endif 139 140 /* 141 * Set up the signal handlers. 142 */ 143 public void 144 init_signals(on) 145 int on; 146 { 147 if (on) 148 { 149 /* 150 * Set signal handlers. 151 */ 152 (void) LSIGNAL(SIGINT, u_interrupt); 153 #if MSDOS_COMPILER==WIN32C 154 SetConsoleCtrlHandler(wbreak_handler, TRUE); 155 #endif 156 #ifdef SIGTSTP 157 (void) LSIGNAL(SIGTSTP, stop); 158 #endif 159 #ifdef SIGWINCH 160 (void) LSIGNAL(SIGWINCH, winch); 161 #endif 162 #ifdef SIGWIND 163 (void) LSIGNAL(SIGWIND, winch); 164 #endif 165 #ifdef SIGQUIT 166 (void) LSIGNAL(SIGQUIT, SIG_IGN); 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 calc_jump_sline(); 250 screen_trashed = 1; 251 } 252 } 253 #endif 254 if (tsignals & S_INTERRUPT) 255 { 256 if (quit_on_intr) 257 quit(QUIT_OK); 258 bell(); 259 /* 260 * {{ You may wish to replace the bell() with 261 * error("Interrupt", NULL_PARG); }} 262 */ 263 264 /* 265 * If we were interrupted while in the "calculating 266 * line numbers" loop, turn off line numbers. 267 */ 268 if (lnloop) 269 { 270 lnloop = 0; 271 if (linenums == 2) 272 screen_trashed = 1; 273 linenums = 0; 274 error("Line numbers turned off", NULL_PARG); 275 } 276 277 } 278 } 279