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