xref: /dflybsd-src/contrib/less/signal.c (revision e0f238eda64c20d98364903e0c003825fd0b66dd)
11133e27eSPeter Avalos /*
2*e433da38SAaron LI  * Copyright (C) 1984-2024  Mark Nudelman
31133e27eSPeter Avalos  *
41133e27eSPeter Avalos  * You may distribute under the terms of either the GNU General Public
51133e27eSPeter Avalos  * License or the Less License, as specified in the README file.
61133e27eSPeter Avalos  *
7e639dc31SJohn Marino  * For more information, see the README file.
81133e27eSPeter Avalos  */
91133e27eSPeter Avalos 
101133e27eSPeter Avalos 
111133e27eSPeter Avalos /*
121133e27eSPeter Avalos  * Routines dealing with signals.
131133e27eSPeter Avalos  *
141133e27eSPeter Avalos  * A signal usually merely causes a bit to be set in the "signals" word.
151133e27eSPeter Avalos  * At some convenient time, the mainline code checks to see if any
161133e27eSPeter Avalos  * signals need processing by calling psignal().
171133e27eSPeter Avalos  * If we happen to be reading from a file [in iread()] at the time
181133e27eSPeter Avalos  * the signal is received, we call intread to interrupt the iread.
191133e27eSPeter Avalos  */
201133e27eSPeter Avalos 
211133e27eSPeter Avalos #include "less.h"
221133e27eSPeter Avalos #include <signal.h>
231133e27eSPeter Avalos 
241133e27eSPeter Avalos /*
251133e27eSPeter Avalos  * "sigs" contains bits indicating signals which need to be processed.
261133e27eSPeter Avalos  */
271133e27eSPeter Avalos public int sigs;
281133e27eSPeter Avalos 
291133e27eSPeter Avalos extern int sc_width, sc_height;
301133e27eSPeter Avalos extern int linenums;
311133e27eSPeter Avalos extern int wscroll;
321133e27eSPeter Avalos extern int reading;
331133e27eSPeter Avalos extern int quit_on_intr;
341133e27eSPeter Avalos extern long jump_sline_fraction;
351133e27eSPeter Avalos 
361133e27eSPeter Avalos /*
371133e27eSPeter Avalos  * Interrupt signal handler.
381133e27eSPeter Avalos  */
3902d62a0fSDaniel Fojt #if MSDOS_COMPILER!=WIN32C
401133e27eSPeter Avalos 	/* ARGSUSED*/
u_interrupt(int type)41320d7c8aSAaron LI static RETSIGTYPE u_interrupt(int type)
421133e27eSPeter Avalos {
43*e433da38SAaron LI 	(void) type;
448be36e5bSPeter Avalos 	bell();
451133e27eSPeter Avalos #if OS2
461133e27eSPeter Avalos 	LSIGNAL(SIGINT, SIG_ACK);
471133e27eSPeter Avalos #endif
481133e27eSPeter Avalos 	LSIGNAL(SIGINT, u_interrupt);
491133e27eSPeter Avalos 	sigs |= S_INTERRUPT;
501133e27eSPeter Avalos #if MSDOS_COMPILER==DJGPPC
511133e27eSPeter Avalos 	/*
521133e27eSPeter Avalos 	 * If a keyboard has been hit, it must be Ctrl-C
531133e27eSPeter Avalos 	 * (as opposed to Ctrl-Break), so consume it.
541133e27eSPeter Avalos 	 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
551133e27eSPeter Avalos 	 */
561133e27eSPeter Avalos 	if (kbhit())
571133e27eSPeter Avalos 		getkey();
581133e27eSPeter Avalos #endif
590c7ad07eSAntonio Huete Jimenez #if HILITE_SEARCH
600c7ad07eSAntonio Huete Jimenez 	set_filter_pattern(NULL, 0);
610c7ad07eSAntonio Huete Jimenez #endif
621133e27eSPeter Avalos 	if (reading)
638be36e5bSPeter Avalos 		intread(); /* May longjmp */
641133e27eSPeter Avalos }
6502d62a0fSDaniel Fojt #endif
661133e27eSPeter Avalos 
671133e27eSPeter Avalos #ifdef SIGTSTP
681133e27eSPeter Avalos /*
691133e27eSPeter Avalos  * "Stop" (^Z) signal handler.
701133e27eSPeter Avalos  */
711133e27eSPeter Avalos 	/* ARGSUSED*/
stop(int type)72320d7c8aSAaron LI static RETSIGTYPE stop(int type)
731133e27eSPeter Avalos {
74*e433da38SAaron LI 	(void) type;
751133e27eSPeter Avalos 	LSIGNAL(SIGTSTP, stop);
761133e27eSPeter Avalos 	sigs |= S_STOP;
771133e27eSPeter Avalos 	if (reading)
781133e27eSPeter Avalos 		intread();
791133e27eSPeter Avalos }
801133e27eSPeter Avalos #endif
811133e27eSPeter Avalos 
8202d62a0fSDaniel Fojt #undef SIG_LESSWINDOW
831133e27eSPeter Avalos #ifdef SIGWINCH
8402d62a0fSDaniel Fojt #define SIG_LESSWINDOW SIGWINCH
851133e27eSPeter Avalos #else
861133e27eSPeter Avalos #ifdef SIGWIND
8702d62a0fSDaniel Fojt #define SIG_LESSWINDOW SIGWIND
8802d62a0fSDaniel Fojt #endif
8902d62a0fSDaniel Fojt #endif
9002d62a0fSDaniel Fojt 
9102d62a0fSDaniel Fojt #ifdef SIG_LESSWINDOW
921133e27eSPeter Avalos /*
931133e27eSPeter Avalos  * "Window" change handler
941133e27eSPeter Avalos  */
951133e27eSPeter Avalos 	/* ARGSUSED*/
winch(int type)96320d7c8aSAaron LI public RETSIGTYPE winch(int type)
971133e27eSPeter Avalos {
98*e433da38SAaron LI 	(void) type;
9902d62a0fSDaniel Fojt 	LSIGNAL(SIG_LESSWINDOW, winch);
1001133e27eSPeter Avalos 	sigs |= S_WINCH;
1011133e27eSPeter Avalos 	if (reading)
1021133e27eSPeter Avalos 		intread();
1031133e27eSPeter Avalos }
1041133e27eSPeter Avalos #endif
1051133e27eSPeter Avalos 
1061133e27eSPeter Avalos #if MSDOS_COMPILER==WIN32C
1071133e27eSPeter Avalos /*
1081133e27eSPeter Avalos  * Handle CTRL-C and CTRL-BREAK keys.
1091133e27eSPeter Avalos  */
11002d62a0fSDaniel Fojt #define WIN32_LEAN_AND_MEAN
11102d62a0fSDaniel Fojt #include <windows.h>
1121133e27eSPeter Avalos 
wbreak_handler(DWORD dwCtrlType)113320d7c8aSAaron LI static BOOL WINAPI wbreak_handler(DWORD dwCtrlType)
1141133e27eSPeter Avalos {
1151133e27eSPeter Avalos 	switch (dwCtrlType)
1161133e27eSPeter Avalos 	{
1171133e27eSPeter Avalos 	case CTRL_C_EVENT:
1181133e27eSPeter Avalos 	case CTRL_BREAK_EVENT:
1191133e27eSPeter Avalos 		sigs |= S_INTERRUPT;
1200c7ad07eSAntonio Huete Jimenez #if HILITE_SEARCH
1210c7ad07eSAntonio Huete Jimenez 		set_filter_pattern(NULL, 0);
1220c7ad07eSAntonio Huete Jimenez #endif
1231133e27eSPeter Avalos 		return (TRUE);
1241133e27eSPeter Avalos 	default:
1251133e27eSPeter Avalos 		break;
1261133e27eSPeter Avalos 	}
1271133e27eSPeter Avalos 	return (FALSE);
1281133e27eSPeter Avalos }
1291133e27eSPeter Avalos #endif
1301133e27eSPeter Avalos 
terminate(int type)131320d7c8aSAaron LI static RETSIGTYPE terminate(int type)
13202d62a0fSDaniel Fojt {
133*e433da38SAaron LI 	(void) type;
13402d62a0fSDaniel Fojt 	quit(15);
13502d62a0fSDaniel Fojt }
13602d62a0fSDaniel Fojt 
1371133e27eSPeter Avalos /*
1381133e27eSPeter Avalos  * Set up the signal handlers.
1391133e27eSPeter Avalos  */
init_signals(int on)140320d7c8aSAaron LI public void init_signals(int on)
1411133e27eSPeter Avalos {
1421133e27eSPeter Avalos 	if (on)
1431133e27eSPeter Avalos 	{
1441133e27eSPeter Avalos 		/*
1451133e27eSPeter Avalos 		 * Set signal handlers.
1461133e27eSPeter Avalos 		 */
1471133e27eSPeter Avalos #if MSDOS_COMPILER==WIN32C
1481133e27eSPeter Avalos 		SetConsoleCtrlHandler(wbreak_handler, TRUE);
14902d62a0fSDaniel Fojt #else
15002d62a0fSDaniel Fojt 		(void) LSIGNAL(SIGINT, u_interrupt);
1511133e27eSPeter Avalos #endif
1521133e27eSPeter Avalos #ifdef SIGTSTP
153*e433da38SAaron LI 		(void) LSIGNAL(SIGTSTP, !secure_allow(SF_STOP) ? SIG_IGN : stop);
1541133e27eSPeter Avalos #endif
1551133e27eSPeter Avalos #ifdef SIGWINCH
1561133e27eSPeter Avalos 		(void) LSIGNAL(SIGWINCH, winch);
1571133e27eSPeter Avalos #endif
1581133e27eSPeter Avalos #ifdef SIGWIND
1591133e27eSPeter Avalos 		(void) LSIGNAL(SIGWIND, winch);
1601133e27eSPeter Avalos #endif
1611133e27eSPeter Avalos #ifdef SIGQUIT
1621133e27eSPeter Avalos 		(void) LSIGNAL(SIGQUIT, SIG_IGN);
1631133e27eSPeter Avalos #endif
16402d62a0fSDaniel Fojt #ifdef SIGTERM
16502d62a0fSDaniel Fojt 		(void) LSIGNAL(SIGTERM, terminate);
16602d62a0fSDaniel Fojt #endif
1671133e27eSPeter Avalos 	} else
1681133e27eSPeter Avalos 	{
1691133e27eSPeter Avalos 		/*
1701133e27eSPeter Avalos 		 * Restore signals to defaults.
1711133e27eSPeter Avalos 		 */
1721133e27eSPeter Avalos #if MSDOS_COMPILER==WIN32C
1731133e27eSPeter Avalos 		SetConsoleCtrlHandler(wbreak_handler, FALSE);
17402d62a0fSDaniel Fojt #else
17502d62a0fSDaniel Fojt 		(void) LSIGNAL(SIGINT, SIG_DFL);
1761133e27eSPeter Avalos #endif
1771133e27eSPeter Avalos #ifdef SIGTSTP
1781133e27eSPeter Avalos 		(void) LSIGNAL(SIGTSTP, SIG_DFL);
1791133e27eSPeter Avalos #endif
1801133e27eSPeter Avalos #ifdef SIGWINCH
1811133e27eSPeter Avalos 		(void) LSIGNAL(SIGWINCH, SIG_IGN);
1821133e27eSPeter Avalos #endif
1831133e27eSPeter Avalos #ifdef SIGWIND
1841133e27eSPeter Avalos 		(void) LSIGNAL(SIGWIND, SIG_IGN);
1851133e27eSPeter Avalos #endif
1861133e27eSPeter Avalos #ifdef SIGQUIT
1871133e27eSPeter Avalos 		(void) LSIGNAL(SIGQUIT, SIG_DFL);
1881133e27eSPeter Avalos #endif
18902d62a0fSDaniel Fojt #ifdef SIGTERM
19002d62a0fSDaniel Fojt 		(void) LSIGNAL(SIGTERM, SIG_DFL);
19102d62a0fSDaniel Fojt #endif
1921133e27eSPeter Avalos 	}
1931133e27eSPeter Avalos }
1941133e27eSPeter Avalos 
1951133e27eSPeter Avalos /*
1961133e27eSPeter Avalos  * Process any signals we have received.
1971133e27eSPeter Avalos  * A received signal cause a bit to be set in "sigs".
1981133e27eSPeter Avalos  */
psignals(void)199320d7c8aSAaron LI public void psignals(void)
2001133e27eSPeter Avalos {
20102d62a0fSDaniel Fojt 	int tsignals;
2021133e27eSPeter Avalos 
2031133e27eSPeter Avalos 	if ((tsignals = sigs) == 0)
2041133e27eSPeter Avalos 		return;
2051133e27eSPeter Avalos 	sigs = 0;
2061133e27eSPeter Avalos 
2071133e27eSPeter Avalos #ifdef SIGTSTP
2081133e27eSPeter Avalos 	if (tsignals & S_STOP)
2091133e27eSPeter Avalos 	{
2101133e27eSPeter Avalos 		/*
2111133e27eSPeter Avalos 		 * Clean up the terminal.
2121133e27eSPeter Avalos 		 */
2131133e27eSPeter Avalos #ifdef SIGTTOU
2141133e27eSPeter Avalos 		LSIGNAL(SIGTTOU, SIG_IGN);
2151133e27eSPeter Avalos #endif
2161133e27eSPeter Avalos 		clear_bot();
2171133e27eSPeter Avalos 		deinit();
2181133e27eSPeter Avalos 		flush();
2191133e27eSPeter Avalos 		raw_mode(0);
2201133e27eSPeter Avalos #ifdef SIGTTOU
2211133e27eSPeter Avalos 		LSIGNAL(SIGTTOU, SIG_DFL);
2221133e27eSPeter Avalos #endif
2231133e27eSPeter Avalos 		LSIGNAL(SIGTSTP, SIG_DFL);
2241133e27eSPeter Avalos 		kill(getpid(), SIGTSTP);
2251133e27eSPeter Avalos 		/*
2261133e27eSPeter Avalos 		 * ... Bye bye. ...
2271133e27eSPeter Avalos 		 * Hopefully we'll be back later and resume here...
2281133e27eSPeter Avalos 		 * Reset the terminal and arrange to repaint the
2291133e27eSPeter Avalos 		 * screen when we get back to the main command loop.
2301133e27eSPeter Avalos 		 */
2311133e27eSPeter Avalos 		LSIGNAL(SIGTSTP, stop);
2321133e27eSPeter Avalos 		raw_mode(1);
2331133e27eSPeter Avalos 		init();
234*e433da38SAaron LI 		screen_trashed();
2351133e27eSPeter Avalos 		tsignals |= S_WINCH;
2361133e27eSPeter Avalos 	}
2371133e27eSPeter Avalos #endif
2381133e27eSPeter Avalos #ifdef S_WINCH
2391133e27eSPeter Avalos 	if (tsignals & S_WINCH)
2401133e27eSPeter Avalos 	{
2411133e27eSPeter Avalos 		int old_width, old_height;
2421133e27eSPeter Avalos 		/*
2431133e27eSPeter Avalos 		 * Re-execute scrsize() to read the new window size.
2441133e27eSPeter Avalos 		 */
2451133e27eSPeter Avalos 		old_width = sc_width;
2461133e27eSPeter Avalos 		old_height = sc_height;
2471133e27eSPeter Avalos 		get_term();
2481133e27eSPeter Avalos 		if (sc_width != old_width || sc_height != old_height)
2491133e27eSPeter Avalos 		{
2501133e27eSPeter Avalos 			wscroll = (sc_height + 1) / 2;
2511133e27eSPeter Avalos 			calc_jump_sline();
252a9adbba3SJan Lentfer 			calc_shift_count();
253*e433da38SAaron LI 			calc_match_shift();
2541133e27eSPeter Avalos 		}
255*e433da38SAaron LI 		screen_trashed();
2561133e27eSPeter Avalos 	}
2571133e27eSPeter Avalos #endif
2581133e27eSPeter Avalos 	if (tsignals & S_INTERRUPT)
2591133e27eSPeter Avalos 	{
2601133e27eSPeter Avalos 		if (quit_on_intr)
26125ce721eSPeter Avalos 			quit(QUIT_INTERRUPT);
262*e433da38SAaron LI 		getcc_clear();
263*e433da38SAaron LI #if MSDOS_COMPILER==WIN32C
264*e433da38SAaron LI 		win32_getch_clear();
265*e433da38SAaron LI #endif
2661133e27eSPeter Avalos 	}
2671133e27eSPeter Avalos }
268