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