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