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 } 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 #endif 160 #ifdef SIGWIND 161 (void) LSIGNAL(SIGWIND, winch); 162 #endif 163 #ifdef SIGQUIT 164 (void) LSIGNAL(SIGQUIT, SIG_IGN); 165 #endif 166 } else 167 { 168 /* 169 * Restore signals to defaults. 170 */ 171 (void) LSIGNAL(SIGINT, SIG_DFL); 172 #if MSDOS_COMPILER==WIN32C 173 SetConsoleCtrlHandler(wbreak_handler, FALSE); 174 #endif 175 #ifdef SIGTSTP 176 (void) LSIGNAL(SIGTSTP, SIG_DFL); 177 #endif 178 #ifdef SIGWINCH 179 (void) LSIGNAL(SIGWINCH, SIG_IGN); 180 #endif 181 #ifdef SIGWIND 182 (void) LSIGNAL(SIGWIND, SIG_IGN); 183 #endif 184 #ifdef SIGQUIT 185 (void) LSIGNAL(SIGQUIT, SIG_DFL); 186 #endif 187 } 188 } 189 190 /* 191 * Process any signals we have received. 192 * A received signal cause a bit to be set in "sigs". 193 */ 194 public void 195 psignals() 196 { 197 register int tsignals; 198 199 if ((tsignals = sigs) == 0) 200 return; 201 sigs = 0; 202 203 #ifdef SIGTSTP 204 if (tsignals & S_STOP) 205 { 206 /* 207 * Clean up the terminal. 208 */ 209 #ifdef SIGTTOU 210 LSIGNAL(SIGTTOU, SIG_IGN); 211 #endif 212 clear_bot(); 213 deinit(); 214 flush(); 215 raw_mode(0); 216 #ifdef SIGTTOU 217 LSIGNAL(SIGTTOU, SIG_DFL); 218 #endif 219 LSIGNAL(SIGTSTP, SIG_DFL); 220 kill(getpid(), SIGTSTP); 221 /* 222 * ... Bye bye. ... 223 * Hopefully we'll be back later and resume here... 224 * Reset the terminal and arrange to repaint the 225 * screen when we get back to the main command loop. 226 */ 227 LSIGNAL(SIGTSTP, stop); 228 raw_mode(1); 229 init(); 230 screen_trashed = 1; 231 tsignals |= S_WINCH; 232 } 233 #endif 234 #ifdef S_WINCH 235 if (tsignals & S_WINCH) 236 { 237 int old_width, old_height; 238 /* 239 * Re-execute scrsize() to read the new window size. 240 */ 241 old_width = sc_width; 242 old_height = sc_height; 243 get_term(); 244 if (sc_width != old_width || sc_height != old_height) 245 { 246 wscroll = (sc_height + 1) / 2; 247 calc_jump_sline(); 248 screen_trashed = 1; 249 } 250 } 251 #endif 252 if (tsignals & S_INTERRUPT) 253 { 254 if (quit_on_intr) 255 quit(QUIT_OK); 256 bell(); 257 /* 258 * {{ You may wish to replace the bell() with 259 * error("Interrupt", NULL_PARG); }} 260 */ 261 262 /* 263 * If we were interrupted while in the "calculating 264 * line numbers" loop, turn off line numbers. 265 */ 266 if (lnloop) 267 { 268 lnloop = 0; 269 if (linenums == 2) 270 screen_trashed = 1; 271 linenums = 0; 272 error("Line numbers turned off", NULL_PARG); 273 } 274 275 } 276 } 277