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