11590Srgrimes/* 21590Srgrimes * Copyright (C) 1984-2023 Mark Nudelman 31590Srgrimes * 41590Srgrimes * You may distribute under the terms of either the GNU General Public 51590Srgrimes * License or the Less License, as specified in the README file. 61590Srgrimes * 71590Srgrimes * For more information, see the README file. 81590Srgrimes */ 91590Srgrimes 101590Srgrimes/* $FreeBSD$ */ 111590Srgrimes 121590Srgrimes/* 131590Srgrimes * Routines dealing with signals. 141590Srgrimes * 151590Srgrimes * A signal usually merely causes a bit to be set in the "signals" word. 161590Srgrimes * At some convenient time, the mainline code checks to see if any 171590Srgrimes * signals need processing by calling psignal(). 181590Srgrimes * If we happen to be reading from a file [in iread()] at the time 191590Srgrimes * the signal is received, we call intread to interrupt the iread. 201590Srgrimes */ 211590Srgrimes 221590Srgrimes#include "less.h" 231590Srgrimes#include <signal.h> 241590Srgrimes 251590Srgrimes/* 261590Srgrimes * "sigs" contains bits indicating signals which need to be processed. 271590Srgrimes */ 281590Srgrimespublic int sigs; 291590Srgrimes 301590Srgrimesextern int sc_width, sc_height; 3129207Sjoergextern int screen_trashed; 3250477Speterextern int lnloop; 331590Srgrimesextern int linenums; 34200632Sjhextern int wscroll; 351590Srgrimesextern int reading; 361590Srgrimesextern int quit_on_intr; 371590Srgrimesextern int secure; 381590Srgrimesextern long jump_sline_fraction; 391590Srgrimes 401590Srgrimesextern int less_is_more; 4128503Scharnier 421590Srgrimes/* 4329207Sjoerg * Interrupt signal handler. 4497257Strhodes */ 451590Srgrimes#if MSDOS_COMPILER!=WIN32C 461590Srgrimes /* ARGSUSED*/ 471590Srgrimesstatic RETSIGTYPE u_interrupt(int type) 481590Srgrimes{ 491590Srgrimes bell(); 501590Srgrimes#if OS2 511590Srgrimes LSIGNAL(SIGINT, SIG_ACK); 5228503Scharnier#endif 5397529Stjr LSIGNAL(SIGINT, u_interrupt); 5497529Stjr sigs |= S_INTERRUPT; 5597529Stjr#if MSDOS_COMPILER==DJGPPC 5697529Stjr /* 5797529Stjr * If a keyboard has been hit, it must be Ctrl-C 5897529Stjr * (as opposed to Ctrl-Break), so consume it. 5997529Stjr * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 6097529Stjr */ 61107276Sru if (kbhit()) 6297529Stjr getkey(); 6397529Stjr#endif 6497529Stjr if (less_is_more) 6597529Stjr quit(0); 661590Srgrimes#if HILITE_SEARCH 671590Srgrimes set_filter_pattern(NULL, 0); 681590Srgrimes#endif 691590Srgrimes if (reading) 701590Srgrimes intread(); /* May longjmp */ 711590Srgrimes} 721590Srgrimes#endif 731590Srgrimes 741590Srgrimes#ifdef SIGTSTP 751590Srgrimes/* 761590Srgrimes * "Stop" (^Z) signal handler. 7744769Sbillf */ 7897070Strhodes /* ARGSUSED*/ 791590Srgrimesstatic RETSIGTYPE stop(int type) 8097070Strhodes{ 8197257Strhodes LSIGNAL(SIGTSTP, stop); 821590Srgrimes sigs |= S_STOP; 831590Srgrimes if (reading) 84131491Sru intread(); 851590Srgrimes} 861590Srgrimes#endif 871590Srgrimes 881590Srgrimes#undef SIG_LESSWINDOW 891590Srgrimes#ifdef SIGWINCH 901590Srgrimes#define SIG_LESSWINDOW SIGWINCH 911590Srgrimes#else 921590Srgrimes#ifdef SIGWIND 931590Srgrimes#define SIG_LESSWINDOW SIGWIND 9497070Strhodes#endif 951590Srgrimes#endif 96131491Sru 971590Srgrimes#ifdef SIG_LESSWINDOW 9844769Sbillf/* 9929207Sjoerg * "Window" change handler 10029207Sjoerg */ 1011590Srgrimes /* ARGSUSED*/ 1021590Srgrimespublic RETSIGTYPE winch(int type) 1031590Srgrimes{ 1041590Srgrimes LSIGNAL(SIG_LESSWINDOW, winch); 1051590Srgrimes sigs |= S_WINCH; 1061590Srgrimes if (reading) 1071590Srgrimes intread(); 1081590Srgrimes} 1091590Srgrimes#endif 1101590Srgrimes 1111590Srgrimes#if MSDOS_COMPILER==WIN32C 1121590Srgrimes/* 1131590Srgrimes * Handle CTRL-C and CTRL-BREAK keys. 1141590Srgrimes */ 1151590Srgrimes#define WIN32_LEAN_AND_MEAN 1161590Srgrimes#include <windows.h> 1171590Srgrimes 1181590Srgrimesstatic BOOL WINAPI wbreak_handler(DWORD dwCtrlType) 1191590Srgrimes{ 120113382Stjr switch (dwCtrlType) 121113382Stjr { 122113382Stjr case CTRL_C_EVENT: 123113382Stjr case CTRL_BREAK_EVENT: 124113382Stjr sigs |= S_INTERRUPT; 125113382Stjr#if HILITE_SEARCH 126113382Stjr set_filter_pattern(NULL, 0); 127113382Stjr#endif 128113382Stjr return (TRUE); 129113382Stjr default: 130113382Stjr break; 131140368Sru } 13281687Sru return (FALSE); 1331590Srgrimes} 1341590Srgrimes#endif 1351590Srgrimes 1361590Srgrimesstatic RETSIGTYPE terminate(int type) 1371590Srgrimes{ 1381590Srgrimes quit(15); 1391590Srgrimes} 1401590Srgrimes 1411590Srgrimes/* 1421590Srgrimes * Set up the signal handlers. 14328503Scharnier */ 144113382Stjrpublic void init_signals(int on) 145113382Stjr{ 146131491Sru if (on) 14799435Stjr { 14899435Stjr /* 14999435Stjr * Set signal handlers. 15099435Stjr */ 15199435Stjr#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 */ 203public 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