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 /* $FreeBSD$ */ 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 int less_is_more; 38 extern long jump_sline_fraction; 39 40 /* 41 * Interrupt signal handler. 42 */ 43 /* ARGSUSED*/ 44 static RETSIGTYPE 45 u_interrupt(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 (less_is_more) 63 quit(0); 64 if (reading) 65 intread(); /* May longjmp */ 66 } 67 68 #ifdef SIGTSTP 69 /* 70 * "Stop" (^Z) signal handler. 71 */ 72 /* ARGSUSED*/ 73 static RETSIGTYPE 74 stop(int type) 75 { 76 LSIGNAL(SIGTSTP, stop); 77 sigs |= S_STOP; 78 if (reading) 79 intread(); 80 } 81 #endif 82 83 #ifdef SIGWINCH 84 /* 85 * "Window" change handler 86 */ 87 /* ARGSUSED*/ 88 public RETSIGTYPE 89 winch(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(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(DWORD dwCtrlType) 121 { 122 switch (dwCtrlType) 123 { 124 case CTRL_C_EVENT: 125 case CTRL_BREAK_EVENT: 126 sigs |= S_INTERRUPT; 127 return (TRUE); 128 default: 129 break; 130 } 131 return (FALSE); 132 } 133 #endif 134 135 /* 136 * Set up the signal handlers. 137 */ 138 public void 139 init_signals(int on) 140 { 141 if (on) 142 { 143 /* 144 * Set signal handlers. 145 */ 146 (void) LSIGNAL(SIGINT, u_interrupt); 147 #if MSDOS_COMPILER==WIN32C 148 SetConsoleCtrlHandler(wbreak_handler, TRUE); 149 #endif 150 #ifdef SIGTSTP 151 (void) LSIGNAL(SIGTSTP, stop); 152 #endif 153 #ifdef SIGWINCH 154 (void) LSIGNAL(SIGWINCH, winch); 155 #endif 156 #ifdef SIGWIND 157 (void) LSIGNAL(SIGWIND, winch); 158 #endif 159 #ifdef SIGQUIT 160 (void) LSIGNAL(SIGQUIT, SIG_IGN); 161 #endif 162 } else 163 { 164 /* 165 * Restore signals to defaults. 166 */ 167 (void) LSIGNAL(SIGINT, SIG_DFL); 168 #if MSDOS_COMPILER==WIN32C 169 SetConsoleCtrlHandler(wbreak_handler, FALSE); 170 #endif 171 #ifdef SIGTSTP 172 (void) LSIGNAL(SIGTSTP, SIG_DFL); 173 #endif 174 #ifdef SIGWINCH 175 (void) LSIGNAL(SIGWINCH, SIG_IGN); 176 #endif 177 #ifdef SIGWIND 178 (void) LSIGNAL(SIGWIND, SIG_IGN); 179 #endif 180 #ifdef SIGQUIT 181 (void) LSIGNAL(SIGQUIT, SIG_DFL); 182 #endif 183 } 184 } 185 186 /* 187 * Process any signals we have received. 188 * A received signal cause a bit to be set in "sigs". 189 */ 190 public void 191 psignals(void) 192 { 193 int tsignals; 194 195 if ((tsignals = sigs) == 0) 196 return; 197 sigs = 0; 198 199 #ifdef SIGTSTP 200 if (tsignals & S_STOP) 201 { 202 /* 203 * Clean up the terminal. 204 */ 205 #ifdef SIGTTOU 206 LSIGNAL(SIGTTOU, SIG_IGN); 207 #endif 208 clear_bot(); 209 deinit(); 210 flush(); 211 raw_mode(0); 212 #ifdef SIGTTOU 213 LSIGNAL(SIGTTOU, SIG_DFL); 214 #endif 215 LSIGNAL(SIGTSTP, SIG_DFL); 216 kill(getpid(), SIGTSTP); 217 /* 218 * ... Bye bye. ... 219 * Hopefully we'll be back later and resume here... 220 * Reset the terminal and arrange to repaint the 221 * screen when we get back to the main command loop. 222 */ 223 LSIGNAL(SIGTSTP, stop); 224 raw_mode(1); 225 init(); 226 screen_trashed = 1; 227 tsignals |= S_WINCH; 228 } 229 #endif 230 #ifdef S_WINCH 231 if (tsignals & S_WINCH) 232 { 233 int old_width, old_height; 234 /* 235 * Re-execute scrsize() to read the new window size. 236 */ 237 old_width = sc_width; 238 old_height = sc_height; 239 get_term(); 240 if (sc_width != old_width || sc_height != old_height) 241 { 242 wscroll = (sc_height + 1) / 2; 243 calc_jump_sline(); 244 calc_shift_count(); 245 screen_trashed = 1; 246 } 247 } 248 #endif 249 if (tsignals & S_INTERRUPT) 250 { 251 if (quit_on_intr) 252 quit(QUIT_INTERRUPT); 253 } 254 } 255