xref: /freebsd/contrib/less/signal.c (revision 51525cb0209d650ec6d5b1ec8662aa812bdbb2c6)
1a5f0fb15SPaul Saab /*
2a5f0fb15SPaul Saab  * Copyright (C) 1984-2000  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;
3751525cb0SPaul Saab extern int more_mode;
38a5f0fb15SPaul Saab 
39a5f0fb15SPaul Saab /*
40a5f0fb15SPaul Saab  * Interrupt signal handler.
41a5f0fb15SPaul Saab  */
42a5f0fb15SPaul Saab 	/* ARGSUSED*/
43a5f0fb15SPaul Saab 	static RETSIGTYPE
44a5f0fb15SPaul Saab u_interrupt(type)
45a5f0fb15SPaul Saab 	int type;
46a5f0fb15SPaul Saab {
47a5f0fb15SPaul Saab #if OS2
48a5f0fb15SPaul Saab 	LSIGNAL(SIGINT, SIG_ACK);
49a5f0fb15SPaul Saab #endif
50a5f0fb15SPaul Saab 	LSIGNAL(SIGINT, u_interrupt);
51a5f0fb15SPaul Saab 	sigs |= S_INTERRUPT;
52a5f0fb15SPaul Saab #if MSDOS_COMPILER==DJGPPC
53a5f0fb15SPaul Saab 	/*
54a5f0fb15SPaul Saab 	 * If a keyboard has been hit, it must be Ctrl-C
55a5f0fb15SPaul Saab 	 * (as opposed to Ctrl-Break), so consume it.
56a5f0fb15SPaul Saab 	 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
57a5f0fb15SPaul Saab 	 */
58a5f0fb15SPaul Saab 	if (kbhit())
59a5f0fb15SPaul Saab 		getkey();
60a5f0fb15SPaul Saab #endif
6151525cb0SPaul Saab 	if (more_mode)
6251525cb0SPaul Saab 		quit(0);
63a5f0fb15SPaul Saab 	if (reading)
64a5f0fb15SPaul Saab 		intread();
65a5f0fb15SPaul Saab }
66a5f0fb15SPaul Saab 
67a5f0fb15SPaul Saab #ifdef SIGTSTP
68a5f0fb15SPaul Saab /*
69a5f0fb15SPaul Saab  * "Stop" (^Z) signal handler.
70a5f0fb15SPaul Saab  */
71a5f0fb15SPaul Saab 	/* ARGSUSED*/
72a5f0fb15SPaul Saab 	static RETSIGTYPE
73a5f0fb15SPaul Saab stop(type)
74a5f0fb15SPaul Saab 	int type;
75a5f0fb15SPaul Saab {
76a5f0fb15SPaul Saab 	LSIGNAL(SIGTSTP, stop);
77a5f0fb15SPaul Saab 	sigs |= S_STOP;
78a5f0fb15SPaul Saab 	if (reading)
79a5f0fb15SPaul Saab 		intread();
80a5f0fb15SPaul Saab }
81a5f0fb15SPaul Saab #endif
82a5f0fb15SPaul Saab 
83a5f0fb15SPaul Saab #ifdef SIGWINCH
84a5f0fb15SPaul Saab /*
85a5f0fb15SPaul Saab  * "Window" change handler
86a5f0fb15SPaul Saab  */
87a5f0fb15SPaul Saab 	/* ARGSUSED*/
88a5f0fb15SPaul Saab 	public RETSIGTYPE
89a5f0fb15SPaul Saab winch(type)
90a5f0fb15SPaul Saab 	int type;
91a5f0fb15SPaul Saab {
92a5f0fb15SPaul Saab 	LSIGNAL(SIGWINCH, winch);
93a5f0fb15SPaul Saab 	sigs |= S_WINCH;
94a5f0fb15SPaul Saab 	if (reading)
95a5f0fb15SPaul Saab 		intread();
96a5f0fb15SPaul Saab }
97a5f0fb15SPaul Saab #else
98a5f0fb15SPaul Saab #ifdef SIGWIND
99a5f0fb15SPaul Saab /*
100a5f0fb15SPaul Saab  * "Window" change handler
101a5f0fb15SPaul Saab  */
102a5f0fb15SPaul Saab 	/* ARGSUSED*/
103a5f0fb15SPaul Saab 	public RETSIGTYPE
104a5f0fb15SPaul Saab winch(type)
105a5f0fb15SPaul Saab 	int type;
106a5f0fb15SPaul Saab {
107a5f0fb15SPaul Saab 	LSIGNAL(SIGWIND, winch);
108a5f0fb15SPaul Saab 	sigs |= S_WINCH;
109a5f0fb15SPaul Saab 	if (reading)
110a5f0fb15SPaul Saab 		intread();
111a5f0fb15SPaul Saab }
112a5f0fb15SPaul Saab #endif
113a5f0fb15SPaul Saab #endif
114a5f0fb15SPaul Saab 
115a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
116a5f0fb15SPaul Saab /*
117a5f0fb15SPaul Saab  * Handle CTRL-C and CTRL-BREAK keys.
118a5f0fb15SPaul Saab  */
119a5f0fb15SPaul Saab #include "windows.h"
120a5f0fb15SPaul Saab 
121a5f0fb15SPaul Saab 	static BOOL WINAPI
122a5f0fb15SPaul Saab wbreak_handler(dwCtrlType)
123a5f0fb15SPaul Saab 	DWORD dwCtrlType;
124a5f0fb15SPaul Saab {
125a5f0fb15SPaul Saab 	switch (dwCtrlType)
126a5f0fb15SPaul Saab 	{
127a5f0fb15SPaul Saab 	case CTRL_C_EVENT:
128a5f0fb15SPaul Saab 	case CTRL_BREAK_EVENT:
129a5f0fb15SPaul Saab 		sigs |= S_INTERRUPT;
130a5f0fb15SPaul Saab 		return (TRUE);
131a5f0fb15SPaul Saab 	default:
132a5f0fb15SPaul Saab 		break;
133a5f0fb15SPaul Saab 	}
134a5f0fb15SPaul Saab 	return (FALSE);
135a5f0fb15SPaul Saab }
136a5f0fb15SPaul Saab #endif
137a5f0fb15SPaul Saab 
138a5f0fb15SPaul Saab /*
139a5f0fb15SPaul Saab  * Set up the signal handlers.
140a5f0fb15SPaul Saab  */
141a5f0fb15SPaul Saab 	public void
142a5f0fb15SPaul Saab init_signals(on)
143a5f0fb15SPaul Saab 	int on;
144a5f0fb15SPaul Saab {
145a5f0fb15SPaul Saab 	if (on)
146a5f0fb15SPaul Saab 	{
147a5f0fb15SPaul Saab 		/*
148a5f0fb15SPaul Saab 		 * Set signal handlers.
149a5f0fb15SPaul Saab 		 */
150a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGINT, u_interrupt);
151a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
152a5f0fb15SPaul Saab 		SetConsoleCtrlHandler(wbreak_handler, TRUE);
153a5f0fb15SPaul Saab #endif
154a5f0fb15SPaul Saab #ifdef SIGTSTP
155a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGTSTP, stop);
156a5f0fb15SPaul Saab #endif
157a5f0fb15SPaul Saab #ifdef SIGWINCH
158a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGWINCH, winch);
159a5f0fb15SPaul Saab #else
160a5f0fb15SPaul Saab #ifdef SIGWIND
161a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGWIND, winch);
162a5f0fb15SPaul Saab #endif
163a5f0fb15SPaul Saab #ifdef SIGQUIT
164a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGQUIT, SIG_IGN);
165a5f0fb15SPaul Saab #endif
166a5f0fb15SPaul Saab #endif
167a5f0fb15SPaul Saab 	} else
168a5f0fb15SPaul Saab 	{
169a5f0fb15SPaul Saab 		/*
170a5f0fb15SPaul Saab 		 * Restore signals to defaults.
171a5f0fb15SPaul Saab 		 */
172a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGINT, SIG_DFL);
173a5f0fb15SPaul Saab #if MSDOS_COMPILER==WIN32C
174a5f0fb15SPaul Saab 		SetConsoleCtrlHandler(wbreak_handler, FALSE);
175a5f0fb15SPaul Saab #endif
176a5f0fb15SPaul Saab #ifdef SIGTSTP
177a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGTSTP, SIG_DFL);
178a5f0fb15SPaul Saab #endif
179a5f0fb15SPaul Saab #ifdef SIGWINCH
180a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGWINCH, SIG_IGN);
181a5f0fb15SPaul Saab #endif
182a5f0fb15SPaul Saab #ifdef SIGWIND
183a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGWIND, SIG_IGN);
184a5f0fb15SPaul Saab #endif
185a5f0fb15SPaul Saab #ifdef SIGQUIT
186a5f0fb15SPaul Saab 		(void) LSIGNAL(SIGQUIT, SIG_DFL);
187a5f0fb15SPaul Saab #endif
188a5f0fb15SPaul Saab 	}
189a5f0fb15SPaul Saab }
190a5f0fb15SPaul Saab 
191a5f0fb15SPaul Saab /*
192a5f0fb15SPaul Saab  * Process any signals we have received.
193a5f0fb15SPaul Saab  * A received signal cause a bit to be set in "sigs".
194a5f0fb15SPaul Saab  */
195a5f0fb15SPaul Saab 	public void
196a5f0fb15SPaul Saab psignals()
197a5f0fb15SPaul Saab {
198a5f0fb15SPaul Saab 	register int tsignals;
199a5f0fb15SPaul Saab 
200a5f0fb15SPaul Saab 	if ((tsignals = sigs) == 0)
201a5f0fb15SPaul Saab 		return;
202a5f0fb15SPaul Saab 	sigs = 0;
203a5f0fb15SPaul Saab 
204a5f0fb15SPaul Saab #ifdef SIGTSTP
205a5f0fb15SPaul Saab 	if (tsignals & S_STOP)
206a5f0fb15SPaul Saab 	{
207a5f0fb15SPaul Saab 		/*
208a5f0fb15SPaul Saab 		 * Clean up the terminal.
209a5f0fb15SPaul Saab 		 */
210a5f0fb15SPaul Saab #ifdef SIGTTOU
211a5f0fb15SPaul Saab 		LSIGNAL(SIGTTOU, SIG_IGN);
212a5f0fb15SPaul Saab #endif
213a5f0fb15SPaul Saab 		clear_bot();
214a5f0fb15SPaul Saab 		deinit();
215a5f0fb15SPaul Saab 		flush();
216a5f0fb15SPaul Saab 		raw_mode(0);
217a5f0fb15SPaul Saab #ifdef SIGTTOU
218a5f0fb15SPaul Saab 		LSIGNAL(SIGTTOU, SIG_DFL);
219a5f0fb15SPaul Saab #endif
220a5f0fb15SPaul Saab 		LSIGNAL(SIGTSTP, SIG_DFL);
221a5f0fb15SPaul Saab 		kill(getpid(), SIGTSTP);
222a5f0fb15SPaul Saab 		/*
223a5f0fb15SPaul Saab 		 * ... Bye bye. ...
224a5f0fb15SPaul Saab 		 * Hopefully we'll be back later and resume here...
225a5f0fb15SPaul Saab 		 * Reset the terminal and arrange to repaint the
226a5f0fb15SPaul Saab 		 * screen when we get back to the main command loop.
227a5f0fb15SPaul Saab 		 */
228a5f0fb15SPaul Saab 		LSIGNAL(SIGTSTP, stop);
229a5f0fb15SPaul Saab 		raw_mode(1);
230a5f0fb15SPaul Saab 		init();
231a5f0fb15SPaul Saab 		screen_trashed = 1;
232a5f0fb15SPaul Saab 		tsignals |= S_WINCH;
233a5f0fb15SPaul Saab 	}
234a5f0fb15SPaul Saab #endif
235a5f0fb15SPaul Saab #ifdef S_WINCH
236a5f0fb15SPaul Saab 	if (tsignals & S_WINCH)
237a5f0fb15SPaul Saab 	{
238a5f0fb15SPaul Saab 		int old_width, old_height;
239a5f0fb15SPaul Saab 		/*
240a5f0fb15SPaul Saab 		 * Re-execute scrsize() to read the new window size.
241a5f0fb15SPaul Saab 		 */
242a5f0fb15SPaul Saab 		old_width = sc_width;
243a5f0fb15SPaul Saab 		old_height = sc_height;
244a5f0fb15SPaul Saab 		get_term();
245a5f0fb15SPaul Saab 		if (sc_width != old_width || sc_height != old_height)
246a5f0fb15SPaul Saab 		{
247a5f0fb15SPaul Saab 			wscroll = (sc_height + 1) / 2;
248a5f0fb15SPaul Saab 			screen_trashed = 1;
249a5f0fb15SPaul Saab 		}
250a5f0fb15SPaul Saab 	}
251a5f0fb15SPaul Saab #endif
252a5f0fb15SPaul Saab 	if (tsignals & S_INTERRUPT)
253a5f0fb15SPaul Saab 	{
254a5f0fb15SPaul Saab 		bell();
255a5f0fb15SPaul Saab 		/*
256a5f0fb15SPaul Saab 		 * {{ You may wish to replace the bell() with
257a5f0fb15SPaul Saab 		 *    error("Interrupt", NULL_PARG); }}
258a5f0fb15SPaul Saab 		 */
259a5f0fb15SPaul Saab 
260a5f0fb15SPaul Saab 		/*
261a5f0fb15SPaul Saab 		 * If we were interrupted while in the "calculating
262a5f0fb15SPaul Saab 		 * line numbers" loop, turn off line numbers.
263a5f0fb15SPaul Saab 		 */
264a5f0fb15SPaul Saab 		if (lnloop)
265a5f0fb15SPaul Saab 		{
266a5f0fb15SPaul Saab 			lnloop = 0;
267a5f0fb15SPaul Saab 			if (linenums == 2)
268a5f0fb15SPaul Saab 				screen_trashed = 1;
269a5f0fb15SPaul Saab 			linenums = 0;
270a5f0fb15SPaul Saab 			error("Line numbers turned off", NULL_PARG);
271a5f0fb15SPaul Saab 		}
272a5f0fb15SPaul Saab 
273a5f0fb15SPaul Saab 	}
274a5f0fb15SPaul Saab }
275