1/*	$NetBSD: signal.c,v 1.5 2003/10/13 14:34:25 agc Exp $	*/
2
3/*
4 * Copyright (c) 1988 Mark Nudelman
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34#ifndef lint
35#if 0
36static char sccsid[] = "@(#)signal.c	8.1 (Berkeley) 6/6/93";
37#else
38__RCSID("$NetBSD: signal.c,v 1.5 2003/10/13 14:34:25 agc Exp $");
39#endif
40#endif /* not lint */
41
42/*
43 * Routines dealing with signals.
44 *
45 * A signal usually merely causes a bit to be set in the "signals" word.
46 * At some convenient time, the mainline code checks to see if any
47 * signals need processing by calling psignal().
48 * If we happen to be reading from a file [in iread()] at the time
49 * the signal is received, we call intread to interrupt the iread.
50 */
51
52#include <signal.h>
53#include <unistd.h>
54
55#include "less.h"
56#include "extern.h"
57
58/*
59 * "sigs" contains bits indicating signals which need to be processed.
60 */
61int sigs;
62
63#ifdef SIGTSTP
64#define	S_STOP		02
65#endif
66#if defined(SIGWINCH) || defined(SIGWIND)
67#define S_WINCH		04
68#endif
69
70
71static void purgeandquit __P((int));
72
73#ifdef SIGTSTP
74static void stop __P((int));
75/*
76 * "Stop" (^Z) signal handler.
77 */
78static void
79stop(n)
80	int n;
81{
82	(void)signal(SIGTSTP, stop);
83	sigs |= S_STOP;
84	if (reading)
85		intread();
86}
87#endif
88
89#ifdef SIGWINCH
90/*
91 * "Window" change handler
92 */
93void
94winch(n)
95	int n;
96{
97	(void)signal(SIGWINCH, winch);
98	sigs |= S_WINCH;
99	if (reading)
100		intread();
101}
102#else
103#ifdef SIGWIND
104/*
105 * "Window" change handler
106 */
107winch()
108{
109	(void)signal(SIGWIND, winch);
110	sigs |= S_WINCH;
111	if (reading)
112		intread();
113}
114#endif
115#endif
116
117static void
118purgeandquit(n)
119	int n;
120{
121
122	purge();	/* purge buffered output */
123	quit();
124}
125
126/*
127 * Set up the signal handlers.
128 */
129void
130init_signals(on)
131	int on;
132{
133	if (on)
134	{
135		/*
136		 * Set signal handlers.
137		 */
138		(void)signal(SIGINT, purgeandquit);
139#ifdef SIGTSTP
140		(void)signal(SIGTSTP, stop);
141#endif
142#ifdef SIGWINCH
143		(void)signal(SIGWINCH, winch);
144#else
145#ifdef SIGWIND
146		(void)signal(SIGWIND, winch);
147#endif
148#endif
149	} else
150	{
151		/*
152		 * Restore signals to defaults.
153		 */
154		(void)signal(SIGINT, SIG_DFL);
155#ifdef SIGTSTP
156		(void)signal(SIGTSTP, SIG_DFL);
157#endif
158#ifdef SIGWINCH
159		(void)signal(SIGWINCH, SIG_IGN);
160#endif
161#ifdef SIGWIND
162		(void)signal(SIGWIND, SIG_IGN);
163#endif
164	}
165}
166
167/*
168 * Process any signals we have received.
169 * A received signal cause a bit to be set in "sigs".
170 */
171void
172psignals()
173{
174	int tsignals;
175
176	if ((tsignals = sigs) == 0)
177		return;
178	sigs = 0;
179
180#ifdef S_WINCH
181	if (tsignals & S_WINCH)
182	{
183		int old_width, old_height;
184		/*
185		 * Re-execute get_term() to read the new window size.
186		 */
187		old_width = sc_width;
188		old_height = sc_height;
189		get_term();
190		if (sc_width != old_width || sc_height != old_height)
191		{
192			scroll_lines = (sc_height + 1) / 2;
193			screen_trashed = 1;
194		}
195	}
196#endif
197#ifdef SIGTSTP
198	if (tsignals & S_STOP)
199	{
200		/*
201		 * Clean up the terminal.
202		 */
203#ifdef SIGTTOU
204		(void)signal(SIGTTOU, SIG_IGN);
205#endif
206		lower_left();
207		clear_eol();
208		deinit();
209		(void)flush();
210		raw_mode(0);
211#ifdef SIGTTOU
212		(void)signal(SIGTTOU, SIG_DFL);
213#endif
214		(void)signal(SIGTSTP, SIG_DFL);
215		(void)kill(getpid(), SIGTSTP);
216		/*
217		 * ... Bye bye. ...
218		 * Hopefully we'll be back later and resume here...
219		 * Reset the terminal and arrange to repaint the
220		 * screen when we get back to the main command loop.
221		 */
222		(void)signal(SIGTSTP, stop);
223		raw_mode(1);
224		init();
225		screen_trashed = 1;
226	}
227#endif
228}
229