xref: /netbsd-src/distrib/utils/more/signal.c (revision c2472e10b24b4fff355b4a0aa2e5e52e121ba74c)
1 /*	$NetBSD: signal.c,v 1.6 2004/09/01 01:46:56 chs 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
36 static char sccsid[] = "@(#)signal.c	8.1 (Berkeley) 6/6/93";
37 #else
38 __RCSID("$NetBSD: signal.c,v 1.6 2004/09/01 01:46:56 chs 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  */
61 int 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 
71 static void purgeandquit __P((int));
72 
73 #ifdef SIGTSTP
74 static void stop __P((int));
75 /*
76  * "Stop" (^Z) signal handler.
77  */
78 static void
stop(n)79 stop(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  */
93 void
winch(n)94 winch(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  */
winch()107 winch()
108 {
109 	(void)signal(SIGWIND, winch);
110 	sigs |= S_WINCH;
111 	if (reading)
112 		intread();
113 }
114 #endif
115 #endif
116 
117 static void
purgeandquit(n)118 purgeandquit(n)
119 	int n;
120 {
121 
122 	purge();	/* purge buffered output */
123 	quit();
124 }
125 
126 /*
127  * Set up the signal handlers.
128  */
129 void
init_signals(on)130 init_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  */
171 void
psignals()172 psignals()
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