xref: /freebsd/contrib/less/signal.c (revision 7374caaaed222af059fc66cb7fade7074ab391f4)
1a5f0fb15SPaul Saab /*
27374caaaSXin LI  * Copyright (C) 1984-2008  Mark Nudelman
3a5f0fb15SPaul Saab  *
4a5f0fb15SPaul Saab  * You may distribute under the terms of either the GNU General Public
5a5f0fb15SPaul Saab  * License or the Less License, as specified in the README file.
6a5f0fb15SPaul Saab  *
7a5f0fb15SPaul Saab  * For more information about less, or for information on how to
8a5f0fb15SPaul Saab  * contact the author, see the README file.
9a5f0fb15SPaul Saab  */
10a5f0fb15SPaul Saab 
1151525cb0SPaul Saab /* $FreeBSD$ */
12a5f0fb15SPaul Saab 
13a5f0fb15SPaul Saab /*
14a5f0fb15SPaul Saab  * Routines dealing with signals.
15a5f0fb15SPaul Saab  *
16a5f0fb15SPaul Saab  * A signal usually merely causes a bit to be set in the "signals" word.
17a5f0fb15SPaul Saab  * At some convenient time, the mainline code checks to see if any
18a5f0fb15SPaul Saab  * signals need processing by calling psignal().
19a5f0fb15SPaul Saab  * If we happen to be reading from a file [in iread()] at the time
20a5f0fb15SPaul Saab  * the signal is received, we call intread to interrupt the iread.
21a5f0fb15SPaul Saab  */
22a5f0fb15SPaul Saab 
23a5f0fb15SPaul Saab #include "less.h"
24a5f0fb15SPaul Saab #include <signal.h>
25a5f0fb15SPaul Saab 
26a5f0fb15SPaul Saab /*
27a5f0fb15SPaul Saab  * "sigs" contains bits indicating signals which need to be processed.
28a5f0fb15SPaul Saab  */
29a5f0fb15SPaul Saab public int sigs;
30a5f0fb15SPaul Saab 
31a5f0fb15SPaul Saab extern int sc_width, sc_height;
32a5f0fb15SPaul Saab extern int screen_trashed;
33a5f0fb15SPaul Saab extern int lnloop;
34a5f0fb15SPaul Saab extern int linenums;
35a5f0fb15SPaul Saab extern int wscroll;
36a5f0fb15SPaul Saab extern int reading;
3789dd99dcSXin LI extern int quit_on_intr;
38720c436cSXin LI extern int less_is_more;
39720c436cSXin LI extern long jump_sline_fraction;
40a5f0fb15SPaul Saab 
41a5f0fb15SPaul Saab /*
42a5f0fb15SPaul Saab  * Interrupt signal handler.
43a5f0fb15SPaul Saab  */
44a5f0fb15SPaul Saab 	/* ARGSUSED*/
45a5f0fb15SPaul Saab 	static RETSIGTYPE
46a5f0fb15SPaul Saab u_interrupt(type)
47a5f0fb15SPaul Saab 	int type;
48a5f0fb15SPaul Saab {
497374caaaSXin LI 	bell();
50a5f0fb15SPaul Saab #if OS2
51a5f0fb15SPaul Saab 	LSIGNAL(SIGINT, SIG_ACK);
52a5f0fb15SPaul Saab #endif
53a5f0fb15SPaul Saab 	LSIGNAL(SIGINT, u_interrupt);
54a5f0fb15SPaul Saab 	sigs |= S_INTERRUPT;
55a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC
56a5f0fb15SPaul Saab 	/*
57a5f0fb15SPaul Saab 	 * If a keyboard has been hit, it must be Ctrl-C
58a5f0fb15SPaul Saab 	 * (as opposed to Ctrl-Break), so consume it.
59a5f0fb15SPaul Saab 	 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
60a5f0fb15SPaul Saab 	 */
61a5f0fb15SPaul Saab 	if (kbhit())
62a5f0fb15SPaul Saab 		getkey();
63a5f0fb15SPaul Saab #endif
64720c436cSXin LI 	if (less_is_more)
6551525cb0SPaul Saab 		quit(0);
66a5f0fb15SPaul Saab 	if (reading)
677374caaaSXin LI 		intread(); /* May longjmp */
68a5f0fb15SPaul Saab }
69a5f0fb15SPaul Saab 
70a5f0fb15SPaul Saab #ifdef SIGTSTP
71a5f0fb15SPaul Saab /*
72a5f0fb15SPaul Saab  * "Stop" (^Z) signal handler.
73a5f0fb15SPaul Saab  */
74a5f0fb15SPaul Saab 	/* ARGSUSED*/
75a5f0fb15SPaul Saab 	static RETSIGTYPE
76a5f0fb15SPaul Saab stop(type)
77a5f0fb15SPaul Saab 	int type;
78a5f0fb15SPaul Saab {
79a5f0fb15SPaul Saab 	LSIGNAL(SIGTSTP, stop);
80a5f0fb15SPaul Saab 	sigs |= S_STOP;
81a5f0fb15SPaul Saab 	if (reading)
82a5f0fb15SPaul Saab 		intread();
83a5f0fb15SPaul Saab }
84a5f0fb15SPaul Saab #endif
85a5f0fb15SPaul Saab 
86a5f0fb15SPaul Saab #ifdef SIGWINCH
87a5f0fb15SPaul Saab /*
88a5f0fb15SPaul Saab  * "Window" change handler
89a5f0fb15SPaul Saab  */
90a5f0fb15SPaul Saab 	/* ARGSUSED*/
91a5f0fb15SPaul Saab 	public RETSIGTYPE
92a5f0fb15SPaul Saab winch(type)
93a5f0fb15SPaul Saab 	int type;
94a5f0fb15SPaul Saab {
95a5f0fb15SPaul Saab 	LSIGNAL(SIGWINCH, winch);
96a5f0fb15SPaul Saab 	sigs |= S_WINCH;
9759a2d077SXin LI 	if (reading)
9859a2d077SXin LI 		intread();
99a5f0fb15SPaul Saab }
100a5f0fb15SPaul Saab #else
101a5f0fb15SPaul Saab #ifdef SIGWIND
102a5f0fb15SPaul Saab /*
103a5f0fb15SPaul Saab  * "Window" change handler
104a5f0fb15SPaul Saab  */
105a5f0fb15SPaul Saab 	/* ARGSUSED*/
106a5f0fb15SPaul Saab 	public RETSIGTYPE
107a5f0fb15SPaul Saab winch(type)
108a5f0fb15SPaul Saab 	int type;
109a5f0fb15SPaul Saab {
110a5f0fb15SPaul Saab 	LSIGNAL(SIGWIND, winch);
111a5f0fb15SPaul Saab 	sigs |= S_WINCH;
112a5f0fb15SPaul Saab 	if (reading)
113a5f0fb15SPaul Saab 		intread();
114a5f0fb15SPaul Saab }
115a5f0fb15SPaul Saab #endif
116a5f0fb15SPaul Saab #endif
117a5f0fb15SPaul Saab 
118a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
119a5f0fb15SPaul Saab /*
120a5f0fb15SPaul Saab  * Handle CTRL-C and CTRL-BREAK keys.
121a5f0fb15SPaul Saab  */
122a5f0fb15SPaul Saab #include "windows.h"
123a5f0fb15SPaul Saab 
124a5f0fb15SPaul Saab 	static BOOL WINAPI
125a5f0fb15SPaul Saab wbreak_handler(dwCtrlType)
126a5f0fb15SPaul Saab 	DWORD dwCtrlType;
127a5f0fb15SPaul Saab {
128a5f0fb15SPaul Saab 	switch (dwCtrlType)
129a5f0fb15SPaul Saab 	{
130a5f0fb15SPaul Saab 	case CTRL_C_EVENT:
131a5f0fb15SPaul Saab 	case CTRL_BREAK_EVENT:
132a5f0fb15SPaul Saab 		sigs |= S_INTERRUPT;
133a5f0fb15SPaul Saab 		return (TRUE);
134a5f0fb15SPaul Saab 	default:
135a5f0fb15SPaul Saab 		break;
136a5f0fb15SPaul Saab 	}
137a5f0fb15SPaul Saab 	return (FALSE);
138a5f0fb15SPaul Saab }
139a5f0fb15SPaul Saab #endif
140a5f0fb15SPaul Saab 
141a5f0fb15SPaul Saab /*
142a5f0fb15SPaul Saab  * Set up the signal handlers.
143a5f0fb15SPaul Saab  */
144a5f0fb15SPaul Saab 	public void
145a5f0fb15SPaul Saab init_signals(on)
146a5f0fb15SPaul Saab 	int on;
147a5f0fb15SPaul Saab {
148a5f0fb15SPaul Saab 	if (on)
149a5f0fb15SPaul Saab 	{
150a5f0fb15SPaul Saab 		/*
151a5f0fb15SPaul Saab 		 * Set signal handlers.
152a5f0fb15SPaul Saab 		 */
153a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGINT, u_interrupt);
154a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
155a5f0fb15SPaul Saab 		SetConsoleCtrlHandler(wbreak_handler, TRUE);
156a5f0fb15SPaul Saab #endif
157a5f0fb15SPaul Saab #ifdef SIGTSTP
158a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGTSTP, stop);
159a5f0fb15SPaul Saab #endif
160a5f0fb15SPaul Saab #ifdef SIGWINCH
161a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGWINCH, winch);
162720c436cSXin LI #endif
163a5f0fb15SPaul Saab #ifdef SIGWIND
164a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGWIND, winch);
165a5f0fb15SPaul Saab #endif
166a5f0fb15SPaul Saab #ifdef SIGQUIT
167a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGQUIT, SIG_IGN);
168a5f0fb15SPaul Saab #endif
169a5f0fb15SPaul Saab 	} else
170a5f0fb15SPaul Saab 	{
171a5f0fb15SPaul Saab 		/*
172a5f0fb15SPaul Saab 		 * Restore signals to defaults.
173a5f0fb15SPaul Saab 		 */
174a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGINT, SIG_DFL);
175a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
176a5f0fb15SPaul Saab 		SetConsoleCtrlHandler(wbreak_handler, FALSE);
177a5f0fb15SPaul Saab #endif
178a5f0fb15SPaul Saab #ifdef SIGTSTP
179a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGTSTP, SIG_DFL);
180a5f0fb15SPaul Saab #endif
181a5f0fb15SPaul Saab #ifdef SIGWINCH
182a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGWINCH, SIG_IGN);
183a5f0fb15SPaul Saab #endif
184a5f0fb15SPaul Saab #ifdef SIGWIND
185a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGWIND, SIG_IGN);
186a5f0fb15SPaul Saab #endif
187a5f0fb15SPaul Saab #ifdef SIGQUIT
188a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGQUIT, SIG_DFL);
189a5f0fb15SPaul Saab #endif
190a5f0fb15SPaul Saab 	}
191a5f0fb15SPaul Saab }
192a5f0fb15SPaul Saab 
193a5f0fb15SPaul Saab /*
194a5f0fb15SPaul Saab  * Process any signals we have received.
195a5f0fb15SPaul Saab  * A received signal cause a bit to be set in "sigs".
196a5f0fb15SPaul Saab  */
197a5f0fb15SPaul Saab 	public void
198a5f0fb15SPaul Saab psignals()
199a5f0fb15SPaul Saab {
200a5f0fb15SPaul Saab 	register int tsignals;
201a5f0fb15SPaul Saab 
202a5f0fb15SPaul Saab 	if ((tsignals = sigs) == 0)
203a5f0fb15SPaul Saab 		return;
204a5f0fb15SPaul Saab 	sigs = 0;
205a5f0fb15SPaul Saab 
206a5f0fb15SPaul Saab #ifdef SIGTSTP
207a5f0fb15SPaul Saab 	if (tsignals & S_STOP)
208a5f0fb15SPaul Saab 	{
209a5f0fb15SPaul Saab 		/*
210a5f0fb15SPaul Saab 		 * Clean up the terminal.
211a5f0fb15SPaul Saab 		 */
212a5f0fb15SPaul Saab #ifdef SIGTTOU
213a5f0fb15SPaul Saab 		LSIGNAL(SIGTTOU, SIG_IGN);
214a5f0fb15SPaul Saab #endif
215a5f0fb15SPaul Saab 		clear_bot();
216a5f0fb15SPaul Saab 		deinit();
217a5f0fb15SPaul Saab 		flush();
218a5f0fb15SPaul Saab 		raw_mode(0);
219a5f0fb15SPaul Saab #ifdef SIGTTOU
220a5f0fb15SPaul Saab 		LSIGNAL(SIGTTOU, SIG_DFL);
221a5f0fb15SPaul Saab #endif
222a5f0fb15SPaul Saab 		LSIGNAL(SIGTSTP, SIG_DFL);
223a5f0fb15SPaul Saab 		kill(getpid(), SIGTSTP);
224a5f0fb15SPaul Saab 		/*
225a5f0fb15SPaul Saab 		 * ... Bye bye. ...
226a5f0fb15SPaul Saab 		 * Hopefully we'll be back later and resume here...
227a5f0fb15SPaul Saab 		 * Reset the terminal and arrange to repaint the
228a5f0fb15SPaul Saab 		 * screen when we get back to the main command loop.
229a5f0fb15SPaul Saab 		 */
230a5f0fb15SPaul Saab 		LSIGNAL(SIGTSTP, stop);
231a5f0fb15SPaul Saab 		raw_mode(1);
232a5f0fb15SPaul Saab 		init();
233a5f0fb15SPaul Saab 		screen_trashed = 1;
234a5f0fb15SPaul Saab 		tsignals |= S_WINCH;
235a5f0fb15SPaul Saab 	}
236a5f0fb15SPaul Saab #endif
237a5f0fb15SPaul Saab #ifdef S_WINCH
238a5f0fb15SPaul Saab 	if (tsignals & S_WINCH)
239a5f0fb15SPaul Saab 	{
240a5f0fb15SPaul Saab 		int old_width, old_height;
241a5f0fb15SPaul Saab 		/*
242a5f0fb15SPaul Saab 		 * Re-execute scrsize() to read the new window size.
243a5f0fb15SPaul Saab 		 */
244a5f0fb15SPaul Saab 		old_width = sc_width;
245a5f0fb15SPaul Saab 		old_height = sc_height;
246a5f0fb15SPaul Saab 		get_term();
247a5f0fb15SPaul Saab 		if (sc_width != old_width || sc_height != old_height)
248a5f0fb15SPaul Saab 		{
249a5f0fb15SPaul Saab 			wscroll = (sc_height + 1) / 2;
250720c436cSXin LI 			calc_jump_sline();
251a5f0fb15SPaul Saab 			screen_trashed = 1;
252a5f0fb15SPaul Saab 		}
253a5f0fb15SPaul Saab 	}
254a5f0fb15SPaul Saab #endif
255a5f0fb15SPaul Saab 	if (tsignals & S_INTERRUPT)
256a5f0fb15SPaul Saab 	{
25789dd99dcSXin LI 		if (quit_on_intr)
25889dd99dcSXin LI 			quit(QUIT_OK);
259a5f0fb15SPaul Saab 	}
260a5f0fb15SPaul Saab }
261