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