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