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