1238730Sdelphij/* 2330571Sdelphij * Copyright (C) 1984-2017 Mark Nudelman 3238730Sdelphij * 4238730Sdelphij * You may distribute under the terms of either the GNU General Public 5238730Sdelphij * License or the Less License, as specified in the README file. 6238730Sdelphij * 7238730Sdelphij * For more information, see the README file. 8238730Sdelphij */ 960786Sps 1063120Sps/* $FreeBSD: stable/10/contrib/less/signal.c 330571 2018-03-07 06:39:00Z delphij $ */ 1160786Sps 1260786Sps/* 1360786Sps * Routines dealing with signals. 1460786Sps * 1560786Sps * A signal usually merely causes a bit to be set in the "signals" word. 1660786Sps * At some convenient time, the mainline code checks to see if any 1760786Sps * signals need processing by calling psignal(). 1860786Sps * If we happen to be reading from a file [in iread()] at the time 1960786Sps * the signal is received, we call intread to interrupt the iread. 2060786Sps */ 2160786Sps 2260786Sps#include "less.h" 2360786Sps#include <signal.h> 2460786Sps 2560786Sps/* 2660786Sps * "sigs" contains bits indicating signals which need to be processed. 2760786Sps */ 2860786Spspublic int sigs; 2960786Sps 3060786Spsextern int sc_width, sc_height; 3160786Spsextern int screen_trashed; 3260786Spsextern int lnloop; 3360786Spsextern int linenums; 3460786Spsextern int wscroll; 3560786Spsextern int reading; 36161478Sdelphijextern int quit_on_intr; 37170259Sdelphijextern int less_is_more; 38170259Sdelphijextern long jump_sline_fraction; 3960786Sps 4060786Sps/* 4160786Sps * Interrupt signal handler. 4260786Sps */ 4360786Sps /* ARGSUSED*/ 4460786Sps static RETSIGTYPE 4560786Spsu_interrupt(type) 4660786Sps int type; 4760786Sps{ 48191930Sdelphij bell(); 4960786Sps#if OS2 5060786Sps LSIGNAL(SIGINT, SIG_ACK); 5160786Sps#endif 5260786Sps LSIGNAL(SIGINT, u_interrupt); 5360786Sps sigs |= S_INTERRUPT; 5460786Sps#if MSDOS_COMPILER==DJGPPC 5560786Sps /* 5660786Sps * If a keyboard has been hit, it must be Ctrl-C 5760786Sps * (as opposed to Ctrl-Break), so consume it. 5860786Sps * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.) 5960786Sps */ 6060786Sps if (kbhit()) 6160786Sps getkey(); 6260786Sps#endif 63170259Sdelphij if (less_is_more) 6463120Sps quit(0); 6560786Sps if (reading) 66191930Sdelphij intread(); /* May longjmp */ 6760786Sps} 6860786Sps 6960786Sps#ifdef SIGTSTP 7060786Sps/* 7160786Sps * "Stop" (^Z) signal handler. 7260786Sps */ 7360786Sps /* ARGSUSED*/ 7460786Sps static RETSIGTYPE 7560786Spsstop(type) 7660786Sps int type; 7760786Sps{ 7860786Sps LSIGNAL(SIGTSTP, stop); 7960786Sps sigs |= S_STOP; 8060786Sps if (reading) 8160786Sps intread(); 8260786Sps} 8360786Sps#endif 8460786Sps 85330571Sdelphij#undef SIG_LESSWINDOW 8660786Sps#ifdef SIGWINCH 87330571Sdelphij#define SIG_LESSWINDOW SIGWINCH 8860786Sps#else 8960786Sps#ifdef SIGWIND 90330571Sdelphij#define SIG_LESSWINDOW SIGWIND 91330571Sdelphij#endif 92330571Sdelphij#endif 93330571Sdelphij 94330571Sdelphij#ifdef SIG_LESSWINDOW 9560786Sps/* 9660786Sps * "Window" change handler 9760786Sps */ 9860786Sps /* ARGSUSED*/ 9960786Sps public RETSIGTYPE 10060786Spswinch(type) 10160786Sps int type; 10260786Sps{ 103330571Sdelphij LSIGNAL(SIG_LESSWINDOW, winch); 10460786Sps sigs |= S_WINCH; 10560786Sps if (reading) 10660786Sps intread(); 10760786Sps} 10860786Sps#endif 10960786Sps 11060786Sps#if MSDOS_COMPILER==WIN32C 11160786Sps/* 11260786Sps * Handle CTRL-C and CTRL-BREAK keys. 11360786Sps */ 11460786Sps#include "windows.h" 11560786Sps 11660786Sps static BOOL WINAPI 11760786Spswbreak_handler(dwCtrlType) 11860786Sps DWORD dwCtrlType; 11960786Sps{ 12060786Sps switch (dwCtrlType) 12160786Sps { 12260786Sps case CTRL_C_EVENT: 12360786Sps case CTRL_BREAK_EVENT: 12460786Sps sigs |= S_INTERRUPT; 12560786Sps return (TRUE); 12660786Sps default: 12760786Sps break; 12860786Sps } 12960786Sps return (FALSE); 13060786Sps} 13160786Sps#endif 13260786Sps 133330571Sdelphij static RETSIGTYPE 134330571Sdelphijterminate(type) 135330571Sdelphij int type; 136330571Sdelphij{ 137330571Sdelphij quit(15); 138330571Sdelphij} 139330571Sdelphij 14060786Sps/* 14160786Sps * Set up the signal handlers. 14260786Sps */ 14360786Sps public void 14460786Spsinit_signals(on) 14560786Sps int on; 14660786Sps{ 14760786Sps if (on) 14860786Sps { 14960786Sps /* 15060786Sps * Set signal handlers. 15160786Sps */ 15260786Sps (void) LSIGNAL(SIGINT, u_interrupt); 15360786Sps#if MSDOS_COMPILER==WIN32C 15460786Sps SetConsoleCtrlHandler(wbreak_handler, TRUE); 15560786Sps#endif 15660786Sps#ifdef SIGTSTP 15760786Sps (void) LSIGNAL(SIGTSTP, stop); 15860786Sps#endif 15960786Sps#ifdef SIGWINCH 16060786Sps (void) LSIGNAL(SIGWINCH, winch); 161170259Sdelphij#endif 16260786Sps#ifdef SIGWIND 16360786Sps (void) LSIGNAL(SIGWIND, winch); 16460786Sps#endif 16560786Sps#ifdef SIGQUIT 16660786Sps (void) LSIGNAL(SIGQUIT, SIG_IGN); 16760786Sps#endif 168330571Sdelphij#ifdef SIGTERM 169330571Sdelphij (void) LSIGNAL(SIGTERM, terminate); 170330571Sdelphij#endif 17160786Sps } else 17260786Sps { 17360786Sps /* 17460786Sps * Restore signals to defaults. 17560786Sps */ 17660786Sps (void) LSIGNAL(SIGINT, SIG_DFL); 17760786Sps#if MSDOS_COMPILER==WIN32C 17860786Sps SetConsoleCtrlHandler(wbreak_handler, FALSE); 17960786Sps#endif 18060786Sps#ifdef SIGTSTP 18160786Sps (void) LSIGNAL(SIGTSTP, SIG_DFL); 18260786Sps#endif 18360786Sps#ifdef SIGWINCH 18460786Sps (void) LSIGNAL(SIGWINCH, SIG_IGN); 18560786Sps#endif 18660786Sps#ifdef SIGWIND 18760786Sps (void) LSIGNAL(SIGWIND, SIG_IGN); 18860786Sps#endif 18960786Sps#ifdef SIGQUIT 19060786Sps (void) LSIGNAL(SIGQUIT, SIG_DFL); 19160786Sps#endif 192330571Sdelphij#ifdef SIGTERM 193330571Sdelphij (void) LSIGNAL(SIGTERM, SIG_DFL); 194330571Sdelphij#endif 19560786Sps } 19660786Sps} 19760786Sps 19860786Sps/* 19960786Sps * Process any signals we have received. 20060786Sps * A received signal cause a bit to be set in "sigs". 20160786Sps */ 20260786Sps public void 20360786Spspsignals() 20460786Sps{ 205330571Sdelphij int tsignals; 20660786Sps 20760786Sps if ((tsignals = sigs) == 0) 20860786Sps return; 20960786Sps sigs = 0; 21060786Sps 21160786Sps#ifdef SIGTSTP 21260786Sps if (tsignals & S_STOP) 21360786Sps { 21460786Sps /* 21560786Sps * Clean up the terminal. 21660786Sps */ 21760786Sps#ifdef SIGTTOU 21860786Sps LSIGNAL(SIGTTOU, SIG_IGN); 21960786Sps#endif 22060786Sps clear_bot(); 22160786Sps deinit(); 22260786Sps flush(); 22360786Sps raw_mode(0); 22460786Sps#ifdef SIGTTOU 22560786Sps LSIGNAL(SIGTTOU, SIG_DFL); 22660786Sps#endif 22760786Sps LSIGNAL(SIGTSTP, SIG_DFL); 22860786Sps kill(getpid(), SIGTSTP); 22960786Sps /* 23060786Sps * ... Bye bye. ... 23160786Sps * Hopefully we'll be back later and resume here... 23260786Sps * Reset the terminal and arrange to repaint the 23360786Sps * screen when we get back to the main command loop. 23460786Sps */ 23560786Sps LSIGNAL(SIGTSTP, stop); 23660786Sps raw_mode(1); 23760786Sps init(); 23860786Sps screen_trashed = 1; 23960786Sps tsignals |= S_WINCH; 24060786Sps } 24160786Sps#endif 24260786Sps#ifdef S_WINCH 24360786Sps if (tsignals & S_WINCH) 24460786Sps { 24560786Sps int old_width, old_height; 24660786Sps /* 24760786Sps * Re-execute scrsize() to read the new window size. 24860786Sps */ 24960786Sps old_width = sc_width; 25060786Sps old_height = sc_height; 25160786Sps get_term(); 25260786Sps if (sc_width != old_width || sc_height != old_height) 25360786Sps { 25460786Sps wscroll = (sc_height + 1) / 2; 255170259Sdelphij calc_jump_sline(); 256195941Sdelphij calc_shift_count(); 25760786Sps screen_trashed = 1; 25860786Sps } 25960786Sps } 26060786Sps#endif 26160786Sps if (tsignals & S_INTERRUPT) 26260786Sps { 263161478Sdelphij if (quit_on_intr) 264221715Sdelphij quit(QUIT_INTERRUPT); 26560786Sps } 26660786Sps} 267