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