1 /* 2 * Copyright (C) 1984-2023 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 u_interrupt(int type) 48 { 49 bell(); 50 #if OS2 51 LSIGNAL(SIGINT, SIG_ACK); 52 #endif 53 LSIGNAL(SIGINT, u_interrupt); 54 sigs |= S_INTERRUPT; 55 #if MSDOS_COMPILER==DJGPPC 56 /* 57 * If a keyboard has been hit, it must be Ctrl-C 58 * (as opposed to Ctrl-Break), so consume it. 59 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 60 */ 61 if (kbhit()) 62 getkey(); 63 #endif 64 if (less_is_more) 65 quit(0); 66 #if HILITE_SEARCH 67 set_filter_pattern(NULL, 0); 68 #endif 69 if (reading) 70 intread(); /* May longjmp */ 71 } 72 #endif 73 74 #ifdef SIGTSTP 75 /* 76 * "Stop" (^Z) signal handler. 77 */ 78 /* ARGSUSED*/ 79 static RETSIGTYPE stop(int type) 80 { 81 LSIGNAL(SIGTSTP, stop); 82 sigs |= S_STOP; 83 if (reading) 84 intread(); 85 } 86 #endif 87 88 #undef SIG_LESSWINDOW 89 #ifdef SIGWINCH 90 #define SIG_LESSWINDOW SIGWINCH 91 #else 92 #ifdef SIGWIND 93 #define SIG_LESSWINDOW SIGWIND 94 #endif 95 #endif 96 97 #ifdef SIG_LESSWINDOW 98 /* 99 * "Window" change handler 100 */ 101 /* ARGSUSED*/ 102 public RETSIGTYPE winch(int type) 103 { 104 LSIGNAL(SIG_LESSWINDOW, winch); 105 sigs |= S_WINCH; 106 if (reading) 107 intread(); 108 } 109 #endif 110 111 #if MSDOS_COMPILER==WIN32C 112 /* 113 * Handle CTRL-C and CTRL-BREAK keys. 114 */ 115 #define WIN32_LEAN_AND_MEAN 116 #include <windows.h> 117 118 static BOOL WINAPI wbreak_handler(DWORD dwCtrlType) 119 { 120 switch (dwCtrlType) 121 { 122 case CTRL_C_EVENT: 123 case CTRL_BREAK_EVENT: 124 sigs |= S_INTERRUPT; 125 #if HILITE_SEARCH 126 set_filter_pattern(NULL, 0); 127 #endif 128 return (TRUE); 129 default: 130 break; 131 } 132 return (FALSE); 133 } 134 #endif 135 136 static RETSIGTYPE terminate(int type) 137 { 138 quit(15); 139 } 140 141 /* 142 * Set up the signal handlers. 143 */ 144 public void init_signals(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, secure ? SIG_IGN : 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 psignals(void) 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 } 258 screen_trashed = 1; 259 } 260 #endif 261 if (tsignals & S_INTERRUPT) 262 { 263 if (quit_on_intr) 264 quit(QUIT_INTERRUPT); 265 } 266 } 267