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