1 /* 2 * Copyright (C) 1984-2011 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 12 /* 13 * Routines dealing with signals. 14 * 15 * A signal usually merely causes a bit to be set in the "signals" word. 16 * At some convenient time, the mainline code checks to see if any 17 * signals need processing by calling psignal(). 18 * If we happen to be reading from a file [in iread()] at the time 19 * the signal is received, we call intread to interrupt the iread. 20 */ 21 22 #include "less.h" 23 #include <signal.h> 24 25 /* 26 * "sigs" contains bits indicating signals which need to be processed. 27 */ 28 public int sigs; 29 30 extern int sc_width, sc_height; 31 extern int screen_trashed; 32 extern int lnloop; 33 extern int linenums; 34 extern int wscroll; 35 extern int reading; 36 extern int quit_on_intr; 37 extern long jump_sline_fraction; 38 39 /* 40 * Interrupt signal handler. 41 */ 42 /* ARGSUSED*/ 43 static RETSIGTYPE 44 u_interrupt(type) 45 int type; 46 { 47 bell(); 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 (reading) 63 intread(); /* May longjmp */ 64 } 65 66 #ifdef SIGTSTP 67 /* 68 * "Stop" (^Z) signal handler. 69 */ 70 /* ARGSUSED*/ 71 static RETSIGTYPE 72 stop(type) 73 int type; 74 { 75 LSIGNAL(SIGTSTP, stop); 76 sigs |= S_STOP; 77 if (reading) 78 intread(); 79 } 80 #endif 81 82 #ifdef SIGWINCH 83 /* 84 * "Window" change handler 85 */ 86 /* ARGSUSED*/ 87 public RETSIGTYPE 88 winch(type) 89 int type; 90 { 91 LSIGNAL(SIGWINCH, winch); 92 sigs |= S_WINCH; 93 if (reading) 94 intread(); 95 } 96 #else 97 #ifdef SIGWIND 98 /* 99 * "Window" change handler 100 */ 101 /* ARGSUSED*/ 102 public RETSIGTYPE 103 winch(type) 104 int type; 105 { 106 LSIGNAL(SIGWIND, winch); 107 sigs |= S_WINCH; 108 if (reading) 109 intread(); 110 } 111 #endif 112 #endif 113 114 #if MSDOS_COMPILER==WIN32C 115 /* 116 * Handle CTRL-C and CTRL-BREAK keys. 117 */ 118 #include "windows.h" 119 120 static BOOL WINAPI 121 wbreak_handler(dwCtrlType) 122 DWORD dwCtrlType; 123 { 124 switch (dwCtrlType) 125 { 126 case CTRL_C_EVENT: 127 case CTRL_BREAK_EVENT: 128 sigs |= S_INTERRUPT; 129 return (TRUE); 130 default: 131 break; 132 } 133 return (FALSE); 134 } 135 #endif 136 137 /* 138 * Set up the signal handlers. 139 */ 140 public void 141 init_signals(on) 142 int on; 143 { 144 if (on) 145 { 146 /* 147 * Set signal handlers. 148 */ 149 (void) LSIGNAL(SIGINT, u_interrupt); 150 #if MSDOS_COMPILER==WIN32C 151 SetConsoleCtrlHandler(wbreak_handler, TRUE); 152 #endif 153 #ifdef SIGTSTP 154 (void) LSIGNAL(SIGTSTP, stop); 155 #endif 156 #ifdef SIGWINCH 157 (void) LSIGNAL(SIGWINCH, winch); 158 #endif 159 #ifdef SIGWIND 160 (void) LSIGNAL(SIGWIND, winch); 161 #endif 162 #ifdef SIGQUIT 163 (void) LSIGNAL(SIGQUIT, SIG_IGN); 164 #endif 165 } else 166 { 167 /* 168 * Restore signals to defaults. 169 */ 170 (void) LSIGNAL(SIGINT, SIG_DFL); 171 #if MSDOS_COMPILER==WIN32C 172 SetConsoleCtrlHandler(wbreak_handler, FALSE); 173 #endif 174 #ifdef SIGTSTP 175 (void) LSIGNAL(SIGTSTP, SIG_DFL); 176 #endif 177 #ifdef SIGWINCH 178 (void) LSIGNAL(SIGWINCH, SIG_IGN); 179 #endif 180 #ifdef SIGWIND 181 (void) LSIGNAL(SIGWIND, SIG_IGN); 182 #endif 183 #ifdef SIGQUIT 184 (void) LSIGNAL(SIGQUIT, SIG_DFL); 185 #endif 186 } 187 } 188 189 /* 190 * Process any signals we have received. 191 * A received signal cause a bit to be set in "sigs". 192 */ 193 public void 194 psignals() 195 { 196 register int tsignals; 197 198 if ((tsignals = sigs) == 0) 199 return; 200 sigs = 0; 201 202 #ifdef SIGTSTP 203 if (tsignals & S_STOP) 204 { 205 /* 206 * Clean up the terminal. 207 */ 208 #ifdef SIGTTOU 209 LSIGNAL(SIGTTOU, SIG_IGN); 210 #endif 211 clear_bot(); 212 deinit(); 213 flush(); 214 raw_mode(0); 215 #ifdef SIGTTOU 216 LSIGNAL(SIGTTOU, SIG_DFL); 217 #endif 218 LSIGNAL(SIGTSTP, SIG_DFL); 219 kill(getpid(), SIGTSTP); 220 /* 221 * ... Bye bye. ... 222 * Hopefully we'll be back later and resume here... 223 * Reset the terminal and arrange to repaint the 224 * screen when we get back to the main command loop. 225 */ 226 LSIGNAL(SIGTSTP, stop); 227 raw_mode(1); 228 init(); 229 screen_trashed = 1; 230 tsignals |= S_WINCH; 231 } 232 #endif 233 #ifdef S_WINCH 234 if (tsignals & S_WINCH) 235 { 236 int old_width, old_height; 237 /* 238 * Re-execute scrsize() to read the new window size. 239 */ 240 old_width = sc_width; 241 old_height = sc_height; 242 get_term(); 243 if (sc_width != old_width || sc_height != old_height) 244 { 245 wscroll = (sc_height + 1) / 2; 246 calc_jump_sline(); 247 calc_shift_count(); 248 screen_trashed = 1; 249 } 250 } 251 #endif 252 if (tsignals & S_INTERRUPT) 253 { 254 if (quit_on_intr) 255 quit(QUIT_INTERRUPT); 256 } 257 } 258