1 /*
2 * Copyright (c) 1988 Mark Nudleman
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * %sccs.include.redist.c%
7 */
8
9 #ifndef lint
10 static char sccsid[] = "@(#)signal.c 8.1 (Berkeley) 06/06/93";
11 #endif /* not lint */
12
13 /*
14 * Routines dealing with signals.
15 *
16 * A signal usually merely causes a bit to be set in the "signals" word.
17 * At some convenient time, the mainline code checks to see if any
18 * signals need processing by calling psignal().
19 * If we happen to be reading from a file [in iread()] at the time
20 * the signal is received, we call intread to interrupt the iread.
21 */
22
23 #include <less.h>
24 #include <signal.h>
25
26 /*
27 * "sigs" contains bits indicating signals which need to be processed.
28 */
29 int sigs;
30
31 #ifdef SIGTSTP
32 #define S_STOP 02
33 #endif
34 #if defined(SIGWINCH) || defined(SIGWIND)
35 #define S_WINCH 04
36 #endif
37
38 extern int sc_width, sc_height;
39 extern int screen_trashed;
40 extern int lnloop;
41 extern int linenums;
42 extern int scroll;
43 extern int reading;
44
45 #ifdef SIGTSTP
46 /*
47 * "Stop" (^Z) signal handler.
48 */
49 static void
stop()50 stop()
51 {
52 (void)signal(SIGTSTP, stop);
53 sigs |= S_STOP;
54 if (reading)
55 intread();
56 }
57 #endif
58
59 #ifdef SIGWINCH
60 /*
61 * "Window" change handler
62 */
63 void
winch()64 winch()
65 {
66 (void)signal(SIGWINCH, winch);
67 sigs |= S_WINCH;
68 if (reading)
69 intread();
70 }
71 #else
72 #ifdef SIGWIND
73 /*
74 * "Window" change handler
75 */
winch()76 winch()
77 {
78 (void)signal(SIGWIND, winch);
79 sigs |= S_WINCH;
80 if (reading)
81 intread();
82 }
83 #endif
84 #endif
85
86 static void
purgeandquit()87 purgeandquit()
88 {
89
90 purge(); /* purge buffered output */
91 quit();
92 }
93
94 /*
95 * Set up the signal handlers.
96 */
init_signals(on)97 init_signals(on)
98 int on;
99 {
100 if (on)
101 {
102 /*
103 * Set signal handlers.
104 */
105 (void)signal(SIGINT, purgeandquit);
106 #ifdef SIGTSTP
107 (void)signal(SIGTSTP, stop);
108 #endif
109 #ifdef SIGWINCH
110 (void)signal(SIGWINCH, winch);
111 #else
112 #ifdef SIGWIND
113 (void)signal(SIGWIND, winch);
114 #endif
115 #endif
116 } else
117 {
118 /*
119 * Restore signals to defaults.
120 */
121 (void)signal(SIGINT, SIG_DFL);
122 #ifdef SIGTSTP
123 (void)signal(SIGTSTP, SIG_DFL);
124 #endif
125 #ifdef SIGWINCH
126 (void)signal(SIGWINCH, SIG_IGN);
127 #endif
128 #ifdef SIGWIND
129 (void)signal(SIGWIND, SIG_IGN);
130 #endif
131 }
132 }
133
134 /*
135 * Process any signals we have received.
136 * A received signal cause a bit to be set in "sigs".
137 */
psignals()138 psignals()
139 {
140 register int tsignals;
141
142 if ((tsignals = sigs) == 0)
143 return;
144 sigs = 0;
145
146 #ifdef S_WINCH
147 if (tsignals & S_WINCH)
148 {
149 int old_width, old_height;
150 /*
151 * Re-execute get_term() to read the new window size.
152 */
153 old_width = sc_width;
154 old_height = sc_height;
155 get_term();
156 if (sc_width != old_width || sc_height != old_height)
157 {
158 scroll = (sc_height + 1) / 2;
159 screen_trashed = 1;
160 }
161 }
162 #endif
163 #ifdef SIGTSTP
164 if (tsignals & S_STOP)
165 {
166 /*
167 * Clean up the terminal.
168 */
169 #ifdef SIGTTOU
170 (void)signal(SIGTTOU, SIG_IGN);
171 #endif
172 lower_left();
173 clear_eol();
174 deinit();
175 (void)flush();
176 raw_mode(0);
177 #ifdef SIGTTOU
178 (void)signal(SIGTTOU, SIG_DFL);
179 #endif
180 (void)signal(SIGTSTP, SIG_DFL);
181 (void)kill(getpid(), SIGTSTP);
182 /*
183 * ... Bye bye. ...
184 * Hopefully we'll be back later and resume here...
185 * Reset the terminal and arrange to repaint the
186 * screen when we get back to the main command loop.
187 */
188 (void)signal(SIGTSTP, stop);
189 raw_mode(1);
190 init();
191 screen_trashed = 1;
192 }
193 #endif
194 }
195