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