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 /* $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 #if MSDOS_COMPILER!=WIN32C 44 /* ARGSUSED*/ 45 static RETSIGTYPE 46 u_interrupt(type) 47 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 (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 return (TRUE); 129 default: 130 break; 131 } 132 return (FALSE); 133 } 134 #endif 135 136 static RETSIGTYPE 137 terminate(type) 138 int type; 139 { 140 quit(15); 141 } 142 143 /* 144 * Set up the signal handlers. 145 */ 146 public void 147 init_signals(on) 148 int on; 149 { 150 if (on) 151 { 152 /* 153 * Set signal handlers. 154 */ 155 #if MSDOS_COMPILER==WIN32C 156 SetConsoleCtrlHandler(wbreak_handler, TRUE); 157 #else 158 (void) LSIGNAL(SIGINT, u_interrupt); 159 #endif 160 #ifdef SIGTSTP 161 (void) LSIGNAL(SIGTSTP, stop); 162 #endif 163 #ifdef SIGWINCH 164 (void) LSIGNAL(SIGWINCH, winch); 165 #endif 166 #ifdef SIGWIND 167 (void) LSIGNAL(SIGWIND, winch); 168 #endif 169 #ifdef SIGQUIT 170 (void) LSIGNAL(SIGQUIT, SIG_IGN); 171 #endif 172 #ifdef SIGTERM 173 (void) LSIGNAL(SIGTERM, terminate); 174 #endif 175 } else 176 { 177 /* 178 * Restore signals to defaults. 179 */ 180 #if MSDOS_COMPILER==WIN32C 181 SetConsoleCtrlHandler(wbreak_handler, FALSE); 182 #else 183 (void) LSIGNAL(SIGINT, SIG_DFL); 184 #endif 185 #ifdef SIGTSTP 186 (void) LSIGNAL(SIGTSTP, SIG_DFL); 187 #endif 188 #ifdef SIGWINCH 189 (void) LSIGNAL(SIGWINCH, SIG_IGN); 190 #endif 191 #ifdef SIGWIND 192 (void) LSIGNAL(SIGWIND, SIG_IGN); 193 #endif 194 #ifdef SIGQUIT 195 (void) LSIGNAL(SIGQUIT, SIG_DFL); 196 #endif 197 #ifdef SIGTERM 198 (void) LSIGNAL(SIGTERM, SIG_DFL); 199 #endif 200 } 201 } 202 203 /* 204 * Process any signals we have received. 205 * A received signal cause a bit to be set in "sigs". 206 */ 207 public void 208 psignals(VOID_PARAM) 209 { 210 int tsignals; 211 212 if ((tsignals = sigs) == 0) 213 return; 214 sigs = 0; 215 216 #ifdef SIGTSTP 217 if (tsignals & S_STOP) 218 { 219 /* 220 * Clean up the terminal. 221 */ 222 #ifdef SIGTTOU 223 LSIGNAL(SIGTTOU, SIG_IGN); 224 #endif 225 clear_bot(); 226 deinit(); 227 flush(); 228 raw_mode(0); 229 #ifdef SIGTTOU 230 LSIGNAL(SIGTTOU, SIG_DFL); 231 #endif 232 LSIGNAL(SIGTSTP, SIG_DFL); 233 kill(getpid(), SIGTSTP); 234 /* 235 * ... Bye bye. ... 236 * Hopefully we'll be back later and resume here... 237 * Reset the terminal and arrange to repaint the 238 * screen when we get back to the main command loop. 239 */ 240 LSIGNAL(SIGTSTP, stop); 241 raw_mode(1); 242 init(); 243 screen_trashed = 1; 244 tsignals |= S_WINCH; 245 } 246 #endif 247 #ifdef S_WINCH 248 if (tsignals & S_WINCH) 249 { 250 int old_width, old_height; 251 /* 252 * Re-execute scrsize() to read the new window size. 253 */ 254 old_width = sc_width; 255 old_height = sc_height; 256 get_term(); 257 if (sc_width != old_width || sc_height != old_height) 258 { 259 wscroll = (sc_height + 1) / 2; 260 calc_jump_sline(); 261 calc_shift_count(); 262 } 263 screen_trashed = 1; 264 } 265 #endif 266 if (tsignals & S_INTERRUPT) 267 { 268 if (quit_on_intr) 269 quit(QUIT_INTERRUPT); 270 } 271 } 272