Add precautions so that threads won't race to exit1() and get stuck there.
[dragonfly.git] / contrib / less-394 / signal.c
blobd09747884f1aaa7a543d1e7d607fca9bb37c74eb
1 /*
2 * Copyright (C) 1984-2004 Mark Nudelman
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
7 * For more information about less, or for information on how to
8 * contact the author, see the README file.
9 */
13 * Routines dealing with signals.
15 * A signal usually merely causes a bit to be set in the "signals" word.
16 * At some convenient time, the mainline code checks to see if any
17 * signals need processing by calling psignal().
18 * If we happen to be reading from a file [in iread()] at the time
19 * the signal is received, we call intread to interrupt the iread.
22 #include "less.h"
23 #include <signal.h>
26 * "sigs" contains bits indicating signals which need to be processed.
28 public int sigs;
30 extern int sc_width, sc_height;
31 extern int screen_trashed;
32 extern int lnloop;
33 extern int linenums;
34 extern int wscroll;
35 extern int reading;
36 extern int quit_on_intr;
39 * Interrupt signal handler.
41 /* ARGSUSED*/
42 static RETSIGTYPE
43 u_interrupt(type)
44 int type;
46 #if OS2
47 LSIGNAL(SIGINT, SIG_ACK);
48 #endif
49 LSIGNAL(SIGINT, u_interrupt);
50 sigs |= S_INTERRUPT;
51 #if MSDOS_COMPILER==DJGPPC
53 * If a keyboard has been hit, it must be Ctrl-C
54 * (as opposed to Ctrl-Break), so consume it.
55 * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
57 if (kbhit())
58 getkey();
59 #endif
60 if (reading)
61 intread();
64 #ifdef SIGTSTP
66 * "Stop" (^Z) signal handler.
68 /* ARGSUSED*/
69 static RETSIGTYPE
70 stop(type)
71 int type;
73 LSIGNAL(SIGTSTP, stop);
74 sigs |= S_STOP;
75 if (reading)
76 intread();
78 #endif
80 #ifdef SIGWINCH
82 * "Window" change handler
84 /* ARGSUSED*/
85 public RETSIGTYPE
86 winch(type)
87 int type;
89 LSIGNAL(SIGWINCH, winch);
90 sigs |= S_WINCH;
91 if (reading)
92 intread();
94 #else
95 #ifdef SIGWIND
97 * "Window" change handler
99 /* ARGSUSED*/
100 public RETSIGTYPE
101 winch(type)
102 int type;
104 LSIGNAL(SIGWIND, winch);
105 sigs |= S_WINCH;
106 if (reading)
107 intread();
109 #endif
110 #endif
112 #if MSDOS_COMPILER==WIN32C
114 * Handle CTRL-C and CTRL-BREAK keys.
116 #include "windows.h"
118 static BOOL WINAPI
119 wbreak_handler(dwCtrlType)
120 DWORD dwCtrlType;
122 switch (dwCtrlType)
124 case CTRL_C_EVENT:
125 case CTRL_BREAK_EVENT:
126 sigs |= S_INTERRUPT;
127 return (TRUE);
128 default:
129 break;
131 return (FALSE);
133 #endif
136 * Set up the signal handlers.
138 public void
139 init_signals(on)
140 int on;
142 if (on)
145 * Set signal handlers.
147 (void) LSIGNAL(SIGINT, u_interrupt);
148 #if MSDOS_COMPILER==WIN32C
149 SetConsoleCtrlHandler(wbreak_handler, TRUE);
150 #endif
151 #ifdef SIGTSTP
152 (void) LSIGNAL(SIGTSTP, stop);
153 #endif
154 #ifdef SIGWINCH
155 (void) LSIGNAL(SIGWINCH, winch);
156 #else
157 #ifdef SIGWIND
158 (void) LSIGNAL(SIGWIND, winch);
159 #endif
160 #ifdef SIGQUIT
161 (void) LSIGNAL(SIGQUIT, SIG_IGN);
162 #endif
163 #endif
164 } else
167 * Restore signals to defaults.
169 (void) LSIGNAL(SIGINT, SIG_DFL);
170 #if MSDOS_COMPILER==WIN32C
171 SetConsoleCtrlHandler(wbreak_handler, FALSE);
172 #endif
173 #ifdef SIGTSTP
174 (void) LSIGNAL(SIGTSTP, SIG_DFL);
175 #endif
176 #ifdef SIGWINCH
177 (void) LSIGNAL(SIGWINCH, SIG_IGN);
178 #endif
179 #ifdef SIGWIND
180 (void) LSIGNAL(SIGWIND, SIG_IGN);
181 #endif
182 #ifdef SIGQUIT
183 (void) LSIGNAL(SIGQUIT, SIG_DFL);
184 #endif
189 * Process any signals we have received.
190 * A received signal cause a bit to be set in "sigs".
192 public void
193 psignals()
195 register int tsignals;
197 if ((tsignals = sigs) == 0)
198 return;
199 sigs = 0;
201 #ifdef SIGTSTP
202 if (tsignals & S_STOP)
205 * Clean up the terminal.
207 #ifdef SIGTTOU
208 LSIGNAL(SIGTTOU, SIG_IGN);
209 #endif
210 clear_bot();
211 deinit();
212 flush();
213 raw_mode(0);
214 #ifdef SIGTTOU
215 LSIGNAL(SIGTTOU, SIG_DFL);
216 #endif
217 LSIGNAL(SIGTSTP, SIG_DFL);
218 kill(getpid(), SIGTSTP);
220 * ... Bye bye. ...
221 * Hopefully we'll be back later and resume here...
222 * Reset the terminal and arrange to repaint the
223 * screen when we get back to the main command loop.
225 LSIGNAL(SIGTSTP, stop);
226 raw_mode(1);
227 init();
228 screen_trashed = 1;
229 tsignals |= S_WINCH;
231 #endif
232 #ifdef S_WINCH
233 if (tsignals & S_WINCH)
235 int old_width, old_height;
237 * Re-execute scrsize() to read the new window size.
239 old_width = sc_width;
240 old_height = sc_height;
241 get_term();
242 if (sc_width != old_width || sc_height != old_height)
244 wscroll = (sc_height + 1) / 2;
245 screen_trashed = 1;
248 #endif
249 if (tsignals & S_INTERRUPT)
251 if (quit_on_intr)
252 quit(QUIT_OK);
253 bell();
255 * {{ You may wish to replace the bell() with
256 * error("Interrupt", NULL_PARG); }}
260 * If we were interrupted while in the "calculating
261 * line numbers" loop, turn off line numbers.
263 if (lnloop)
265 lnloop = 0;
266 if (linenums == 2)
267 screen_trashed = 1;
268 linenums = 0;
269 error("Line numbers turned off", NULL_PARG);