1*84d9c625SLionel Sambuc /* $NetBSD: signal.c,v 1.4 2013/09/04 19:44:21 tron Exp $ */
2f7cf2976SLionel Sambuc
3f7cf2976SLionel Sambuc /*
4*84d9c625SLionel Sambuc * Copyright (C) 1984-2012 Mark Nudelman
5f7cf2976SLionel Sambuc *
6f7cf2976SLionel Sambuc * You may distribute under the terms of either the GNU General Public
7f7cf2976SLionel Sambuc * License or the Less License, as specified in the README file.
8f7cf2976SLionel Sambuc *
9*84d9c625SLionel Sambuc * For more information, see the README file.
10f7cf2976SLionel Sambuc */
11f7cf2976SLionel Sambuc
12f7cf2976SLionel Sambuc
13f7cf2976SLionel Sambuc /*
14f7cf2976SLionel Sambuc * Routines dealing with signals.
15f7cf2976SLionel Sambuc *
16f7cf2976SLionel Sambuc * A signal usually merely causes a bit to be set in the "signals" word.
17f7cf2976SLionel Sambuc * At some convenient time, the mainline code checks to see if any
18f7cf2976SLionel Sambuc * signals need processing by calling psignal().
19f7cf2976SLionel Sambuc * If we happen to be reading from a file [in iread()] at the time
20f7cf2976SLionel Sambuc * the signal is received, we call intread to interrupt the iread.
21f7cf2976SLionel Sambuc */
22f7cf2976SLionel Sambuc
23f7cf2976SLionel Sambuc #include "less.h"
24f7cf2976SLionel Sambuc #include <signal.h>
25f7cf2976SLionel Sambuc
26f7cf2976SLionel Sambuc /*
27f7cf2976SLionel Sambuc * "sigs" contains bits indicating signals which need to be processed.
28f7cf2976SLionel Sambuc */
29f7cf2976SLionel Sambuc public int sigs;
30f7cf2976SLionel Sambuc
31f7cf2976SLionel Sambuc static RETSIGTYPE u_interrupt __P((int));
32f7cf2976SLionel Sambuc static RETSIGTYPE stop __P((int));
33f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
34f7cf2976SLionel Sambuc static BOOL WINAPI wbreak_handler __P((DWORD));
35f7cf2976SLionel Sambuc #endif
36f7cf2976SLionel Sambuc
37f7cf2976SLionel Sambuc extern int sc_width, sc_height;
38f7cf2976SLionel Sambuc extern int screen_trashed;
39f7cf2976SLionel Sambuc extern int lnloop;
40f7cf2976SLionel Sambuc extern int linenums;
41f7cf2976SLionel Sambuc extern int wscroll;
42f7cf2976SLionel Sambuc extern int reading;
43f7cf2976SLionel Sambuc extern int quit_on_intr;
44f7cf2976SLionel Sambuc extern long jump_sline_fraction;
45f7cf2976SLionel Sambuc
46f7cf2976SLionel Sambuc /*
47f7cf2976SLionel Sambuc * Interrupt signal handler.
48f7cf2976SLionel Sambuc */
49f7cf2976SLionel Sambuc /* ARGSUSED*/
50f7cf2976SLionel Sambuc static RETSIGTYPE
u_interrupt(type)51f7cf2976SLionel Sambuc u_interrupt(type)
52f7cf2976SLionel Sambuc int type;
53f7cf2976SLionel Sambuc {
54f7cf2976SLionel Sambuc bell();
55f7cf2976SLionel Sambuc #if OS2
56f7cf2976SLionel Sambuc LSIGNAL(SIGINT, SIG_ACK);
57f7cf2976SLionel Sambuc #endif
58f7cf2976SLionel Sambuc LSIGNAL(SIGINT, u_interrupt);
59f7cf2976SLionel Sambuc sigs |= S_INTERRUPT;
60f7cf2976SLionel Sambuc #if MSDOS_COMPILER==DJGPPC
61f7cf2976SLionel Sambuc /*
62f7cf2976SLionel Sambuc * If a keyboard has been hit, it must be Ctrl-C
63f7cf2976SLionel Sambuc * (as opposed to Ctrl-Break), so consume it.
64f7cf2976SLionel Sambuc * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
65f7cf2976SLionel Sambuc */
66f7cf2976SLionel Sambuc if (kbhit())
67f7cf2976SLionel Sambuc getkey();
68f7cf2976SLionel Sambuc #endif
69f7cf2976SLionel Sambuc if (reading)
70f7cf2976SLionel Sambuc intread(); /* May longjmp */
71f7cf2976SLionel Sambuc }
72f7cf2976SLionel Sambuc
73f7cf2976SLionel Sambuc #ifdef SIGTSTP
74f7cf2976SLionel Sambuc /*
75f7cf2976SLionel Sambuc * "Stop" (^Z) signal handler.
76f7cf2976SLionel Sambuc */
77f7cf2976SLionel Sambuc /* ARGSUSED*/
78f7cf2976SLionel Sambuc static RETSIGTYPE
stop(type)79f7cf2976SLionel Sambuc stop(type)
80f7cf2976SLionel Sambuc int type;
81f7cf2976SLionel Sambuc {
82f7cf2976SLionel Sambuc LSIGNAL(SIGTSTP, stop);
83f7cf2976SLionel Sambuc sigs |= S_STOP;
84f7cf2976SLionel Sambuc if (reading)
85f7cf2976SLionel Sambuc intread();
86f7cf2976SLionel Sambuc }
87f7cf2976SLionel Sambuc #endif
88f7cf2976SLionel Sambuc
89f7cf2976SLionel Sambuc #ifdef SIGWINCH
90f7cf2976SLionel Sambuc /*
91f7cf2976SLionel Sambuc * "Window" change handler
92f7cf2976SLionel Sambuc */
93f7cf2976SLionel Sambuc /* ARGSUSED*/
94f7cf2976SLionel Sambuc public RETSIGTYPE
winch(type)95f7cf2976SLionel Sambuc winch(type)
96f7cf2976SLionel Sambuc int type;
97f7cf2976SLionel Sambuc {
98f7cf2976SLionel Sambuc LSIGNAL(SIGWINCH, winch);
99f7cf2976SLionel Sambuc sigs |= S_WINCH;
100f7cf2976SLionel Sambuc if (reading)
101f7cf2976SLionel Sambuc intread();
102f7cf2976SLionel Sambuc }
103f7cf2976SLionel Sambuc #else
104f7cf2976SLionel Sambuc #ifdef SIGWIND
105f7cf2976SLionel Sambuc /*
106f7cf2976SLionel Sambuc * "Window" change handler
107f7cf2976SLionel Sambuc */
108f7cf2976SLionel Sambuc /* ARGSUSED*/
109f7cf2976SLionel Sambuc public RETSIGTYPE
winch(type)110f7cf2976SLionel Sambuc winch(type)
111f7cf2976SLionel Sambuc int type;
112f7cf2976SLionel Sambuc {
113f7cf2976SLionel Sambuc LSIGNAL(SIGWIND, winch);
114f7cf2976SLionel Sambuc sigs |= S_WINCH;
115f7cf2976SLionel Sambuc if (reading)
116f7cf2976SLionel Sambuc intread();
117f7cf2976SLionel Sambuc }
118f7cf2976SLionel Sambuc #endif
119f7cf2976SLionel Sambuc #endif
120f7cf2976SLionel Sambuc
121f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
122f7cf2976SLionel Sambuc /*
123f7cf2976SLionel Sambuc * Handle CTRL-C and CTRL-BREAK keys.
124f7cf2976SLionel Sambuc */
125f7cf2976SLionel Sambuc #include "windows.h"
126f7cf2976SLionel Sambuc
127f7cf2976SLionel Sambuc static BOOL WINAPI
wbreak_handler(dwCtrlType)128f7cf2976SLionel Sambuc wbreak_handler(dwCtrlType)
129f7cf2976SLionel Sambuc DWORD dwCtrlType;
130f7cf2976SLionel Sambuc {
131f7cf2976SLionel Sambuc switch (dwCtrlType)
132f7cf2976SLionel Sambuc {
133f7cf2976SLionel Sambuc case CTRL_C_EVENT:
134f7cf2976SLionel Sambuc case CTRL_BREAK_EVENT:
135f7cf2976SLionel Sambuc sigs |= S_INTERRUPT;
136f7cf2976SLionel Sambuc return (TRUE);
137f7cf2976SLionel Sambuc default:
138f7cf2976SLionel Sambuc break;
139f7cf2976SLionel Sambuc }
140f7cf2976SLionel Sambuc return (FALSE);
141f7cf2976SLionel Sambuc }
142f7cf2976SLionel Sambuc #endif
143f7cf2976SLionel Sambuc
144f7cf2976SLionel Sambuc /*
145f7cf2976SLionel Sambuc * Set up the signal handlers.
146f7cf2976SLionel Sambuc */
147f7cf2976SLionel Sambuc public void
init_signals(on)148f7cf2976SLionel Sambuc init_signals(on)
149f7cf2976SLionel Sambuc int on;
150f7cf2976SLionel Sambuc {
151f7cf2976SLionel Sambuc if (on)
152f7cf2976SLionel Sambuc {
153f7cf2976SLionel Sambuc /*
154f7cf2976SLionel Sambuc * Set signal handlers.
155f7cf2976SLionel Sambuc */
156f7cf2976SLionel Sambuc (void) LSIGNAL(SIGINT, u_interrupt);
157f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
158f7cf2976SLionel Sambuc SetConsoleCtrlHandler(wbreak_handler, TRUE);
159f7cf2976SLionel Sambuc #endif
160f7cf2976SLionel Sambuc #ifdef SIGTSTP
161f7cf2976SLionel Sambuc (void) LSIGNAL(SIGTSTP, stop);
162f7cf2976SLionel Sambuc #endif
163f7cf2976SLionel Sambuc #ifdef SIGWINCH
164f7cf2976SLionel Sambuc (void) LSIGNAL(SIGWINCH, winch);
165f7cf2976SLionel Sambuc #endif
166f7cf2976SLionel Sambuc #ifdef SIGWIND
167f7cf2976SLionel Sambuc (void) LSIGNAL(SIGWIND, winch);
168f7cf2976SLionel Sambuc #endif
169f7cf2976SLionel Sambuc #ifdef SIGQUIT
170f7cf2976SLionel Sambuc (void) LSIGNAL(SIGQUIT, SIG_IGN);
171f7cf2976SLionel Sambuc #endif
172f7cf2976SLionel Sambuc } else
173f7cf2976SLionel Sambuc {
174f7cf2976SLionel Sambuc /*
175f7cf2976SLionel Sambuc * Restore signals to defaults.
176f7cf2976SLionel Sambuc */
177f7cf2976SLionel Sambuc (void) LSIGNAL(SIGINT, SIG_DFL);
178f7cf2976SLionel Sambuc #if MSDOS_COMPILER==WIN32C
179f7cf2976SLionel Sambuc SetConsoleCtrlHandler(wbreak_handler, FALSE);
180f7cf2976SLionel Sambuc #endif
181f7cf2976SLionel Sambuc #ifdef SIGTSTP
182f7cf2976SLionel Sambuc (void) LSIGNAL(SIGTSTP, SIG_DFL);
183f7cf2976SLionel Sambuc #endif
184f7cf2976SLionel Sambuc #ifdef SIGWINCH
185f7cf2976SLionel Sambuc (void) LSIGNAL(SIGWINCH, SIG_IGN);
186f7cf2976SLionel Sambuc #endif
187f7cf2976SLionel Sambuc #ifdef SIGWIND
188f7cf2976SLionel Sambuc (void) LSIGNAL(SIGWIND, SIG_IGN);
189f7cf2976SLionel Sambuc #endif
190f7cf2976SLionel Sambuc #ifdef SIGQUIT
191f7cf2976SLionel Sambuc (void) LSIGNAL(SIGQUIT, SIG_DFL);
192f7cf2976SLionel Sambuc #endif
193f7cf2976SLionel Sambuc }
194f7cf2976SLionel Sambuc }
195f7cf2976SLionel Sambuc
196f7cf2976SLionel Sambuc /*
197f7cf2976SLionel Sambuc * Process any signals we have received.
198f7cf2976SLionel Sambuc * A received signal cause a bit to be set in "sigs".
199f7cf2976SLionel Sambuc */
200f7cf2976SLionel Sambuc public void
psignals()201f7cf2976SLionel Sambuc psignals()
202f7cf2976SLionel Sambuc {
203f7cf2976SLionel Sambuc register int tsignals;
204f7cf2976SLionel Sambuc
205f7cf2976SLionel Sambuc if ((tsignals = sigs) == 0)
206f7cf2976SLionel Sambuc return;
207f7cf2976SLionel Sambuc sigs = 0;
208f7cf2976SLionel Sambuc
209f7cf2976SLionel Sambuc #ifdef SIGTSTP
210f7cf2976SLionel Sambuc if (tsignals & S_STOP)
211f7cf2976SLionel Sambuc {
212f7cf2976SLionel Sambuc /*
213f7cf2976SLionel Sambuc * Clean up the terminal.
214f7cf2976SLionel Sambuc */
215f7cf2976SLionel Sambuc #ifdef SIGTTOU
216f7cf2976SLionel Sambuc LSIGNAL(SIGTTOU, SIG_IGN);
217f7cf2976SLionel Sambuc #endif
218f7cf2976SLionel Sambuc clear_bot();
219f7cf2976SLionel Sambuc deinit();
220f7cf2976SLionel Sambuc flush();
221f7cf2976SLionel Sambuc raw_mode(0);
222f7cf2976SLionel Sambuc #ifdef SIGTTOU
223f7cf2976SLionel Sambuc LSIGNAL(SIGTTOU, SIG_DFL);
224f7cf2976SLionel Sambuc #endif
225f7cf2976SLionel Sambuc LSIGNAL(SIGTSTP, SIG_DFL);
226f7cf2976SLionel Sambuc kill(getpid(), SIGTSTP);
227f7cf2976SLionel Sambuc /*
228f7cf2976SLionel Sambuc * ... Bye bye. ...
229f7cf2976SLionel Sambuc * Hopefully we'll be back later and resume here...
230f7cf2976SLionel Sambuc * Reset the terminal and arrange to repaint the
231f7cf2976SLionel Sambuc * screen when we get back to the main command loop.
232f7cf2976SLionel Sambuc */
233f7cf2976SLionel Sambuc LSIGNAL(SIGTSTP, stop);
234f7cf2976SLionel Sambuc raw_mode(1);
235f7cf2976SLionel Sambuc init();
236f7cf2976SLionel Sambuc screen_trashed = 1;
237f7cf2976SLionel Sambuc tsignals |= S_WINCH;
238f7cf2976SLionel Sambuc }
239f7cf2976SLionel Sambuc #endif
240f7cf2976SLionel Sambuc #ifdef S_WINCH
241f7cf2976SLionel Sambuc if (tsignals & S_WINCH)
242f7cf2976SLionel Sambuc {
243f7cf2976SLionel Sambuc int old_width, old_height;
244f7cf2976SLionel Sambuc /*
245f7cf2976SLionel Sambuc * Re-execute scrsize() to read the new window size.
246f7cf2976SLionel Sambuc */
247f7cf2976SLionel Sambuc old_width = sc_width;
248f7cf2976SLionel Sambuc old_height = sc_height;
249f7cf2976SLionel Sambuc get_term();
250f7cf2976SLionel Sambuc if (sc_width != old_width || sc_height != old_height)
251f7cf2976SLionel Sambuc {
252f7cf2976SLionel Sambuc wscroll = (sc_height + 1) / 2;
253f7cf2976SLionel Sambuc calc_jump_sline();
254f7cf2976SLionel Sambuc calc_shift_count();
255f7cf2976SLionel Sambuc screen_trashed = 1;
256f7cf2976SLionel Sambuc }
257f7cf2976SLionel Sambuc }
258f7cf2976SLionel Sambuc #endif
259f7cf2976SLionel Sambuc if (tsignals & S_INTERRUPT)
260f7cf2976SLionel Sambuc {
261f7cf2976SLionel Sambuc if (quit_on_intr)
262f7cf2976SLionel Sambuc quit(QUIT_INTERRUPT);
263f7cf2976SLionel Sambuc }
264f7cf2976SLionel Sambuc }
265