1 /* 2 * Copyright (C) 1984-2009 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 bell(); 50 #if OS2 51 LSIGNAL(SIGINT, SIG_ACK); 52 #endif 53 LSIGNAL(SIGINT, u_interrupt); 54 sigs |= S_INTERRUPT; 55 #if MSDOS_COMPILER==DJGPPC 56 /* 57 * If a keyboard has been hit, it must be Ctrl-C 58 * (as opposed to Ctrl-Break), so consume it. 59 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 60 */ 61 if (kbhit()) 62 getkey(); 63 #endif 64 if (less_is_more) 65 quit(0); 66 if (reading) 67 intread(); /* May longjmp */ 68 } 69 70 #ifdef SIGTSTP 71 /* 72 * "Stop" (^Z) signal handler. 73 */ 74 /* ARGSUSED*/ 75 static RETSIGTYPE 76 stop(type) 77 int type; 78 { 79 LSIGNAL(SIGTSTP, stop); 80 sigs |= S_STOP; 81 if (reading) 82 intread(); 83 } 84 #endif 85 86 #ifdef SIGWINCH 87 /* 88 * "Window" change handler 89 */ 90 /* ARGSUSED*/ 91 public RETSIGTYPE 92 winch(type) 93 int type; 94 { 95 LSIGNAL(SIGWINCH, winch); 96 sigs |= S_WINCH; 97 if (reading) 98 intread(); 99 } 100 #else 101 #ifdef SIGWIND 102 /* 103 * "Window" change handler 104 */ 105 /* ARGSUSED*/ 106 public RETSIGTYPE 107 winch(type) 108 int type; 109 { 110 LSIGNAL(SIGWIND, winch); 111 sigs |= S_WINCH; 112 if (reading) 113 intread(); 114 } 115 #endif 116 #endif 117 118 #if MSDOS_COMPILER==WIN32C 119 /* 120 * Handle CTRL-C and CTRL-BREAK keys. 121 */ 122 #include "windows.h" 123 124 static BOOL WINAPI 125 wbreak_handler(dwCtrlType) 126 DWORD dwCtrlType; 127 { 128 switch (dwCtrlType) 129 { 130 case CTRL_C_EVENT: 131 case CTRL_BREAK_EVENT: 132 sigs |= S_INTERRUPT; 133 return (TRUE); 134 default: 135 break; 136 } 137 return (FALSE); 138 } 139 #endif 140 141 /* 142 * Set up the signal handlers. 143 */ 144 public void 145 init_signals(on) 146 int on; 147 { 148 if (on) 149 { 150 /* 151 * Set signal handlers. 152 */ 153 (void) LSIGNAL(SIGINT, u_interrupt); 154 #if MSDOS_COMPILER==WIN32C 155 SetConsoleCtrlHandler(wbreak_handler, TRUE); 156 #endif 157 #ifdef SIGTSTP 158 (void) LSIGNAL(SIGTSTP, stop); 159 #endif 160 #ifdef SIGWINCH 161 (void) LSIGNAL(SIGWINCH, winch); 162 #endif 163 #ifdef SIGWIND 164 (void) LSIGNAL(SIGWIND, winch); 165 #endif 166 #ifdef SIGQUIT 167 (void) LSIGNAL(SIGQUIT, SIG_IGN); 168 #endif 169 } else 170 { 171 /* 172 * Restore signals to defaults. 173 */ 174 (void) LSIGNAL(SIGINT, SIG_DFL); 175 #if MSDOS_COMPILER==WIN32C 176 SetConsoleCtrlHandler(wbreak_handler, FALSE); 177 #endif 178 #ifdef SIGTSTP 179 (void) LSIGNAL(SIGTSTP, SIG_DFL); 180 #endif 181 #ifdef SIGWINCH 182 (void) LSIGNAL(SIGWINCH, SIG_IGN); 183 #endif 184 #ifdef SIGWIND 185 (void) LSIGNAL(SIGWIND, SIG_IGN); 186 #endif 187 #ifdef SIGQUIT 188 (void) LSIGNAL(SIGQUIT, SIG_DFL); 189 #endif 190 } 191 } 192 193 /* 194 * Process any signals we have received. 195 * A received signal cause a bit to be set in "sigs". 196 */ 197 public void 198 psignals() 199 { 200 register int tsignals; 201 202 if ((tsignals = sigs) == 0) 203 return; 204 sigs = 0; 205 206 #ifdef SIGTSTP 207 if (tsignals & S_STOP) 208 { 209 /* 210 * Clean up the terminal. 211 */ 212 #ifdef SIGTTOU 213 LSIGNAL(SIGTTOU, SIG_IGN); 214 #endif 215 clear_bot(); 216 deinit(); 217 flush(); 218 raw_mode(0); 219 #ifdef SIGTTOU 220 LSIGNAL(SIGTTOU, SIG_DFL); 221 #endif 222 LSIGNAL(SIGTSTP, SIG_DFL); 223 kill(getpid(), SIGTSTP); 224 /* 225 * ... Bye bye. ... 226 * Hopefully we'll be back later and resume here... 227 * Reset the terminal and arrange to repaint the 228 * screen when we get back to the main command loop. 229 */ 230 LSIGNAL(SIGTSTP, stop); 231 raw_mode(1); 232 init(); 233 screen_trashed = 1; 234 tsignals |= S_WINCH; 235 } 236 #endif 237 #ifdef S_WINCH 238 if (tsignals & S_WINCH) 239 { 240 int old_width, old_height; 241 /* 242 * Re-execute scrsize() to read the new window size. 243 */ 244 old_width = sc_width; 245 old_height = sc_height; 246 get_term(); 247 if (sc_width != old_width || sc_height != old_height) 248 { 249 wscroll = (sc_height + 1) / 2; 250 calc_jump_sline(); 251 calc_shift_count(); 252 screen_trashed = 1; 253 } 254 } 255 #endif 256 if (tsignals & S_INTERRUPT) 257 { 258 if (quit_on_intr) 259 quit(QUIT_OK); 260 } 261 } 262