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