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