Bump to 608
[platform/upstream/less.git] / signal.c
1 /*
2  * Copyright (C) 1984-2022  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
11 /*
12  * Routines dealing with signals.
13  *
14  * A signal usually merely causes a bit to be set in the "signals" word.
15  * At some convenient time, the mainline code checks to see if any
16  * signals need processing by calling psignal().
17  * If we happen to be reading from a file [in iread()] at the time
18  * the signal is received, we call intread to interrupt the iread.
19  */
20
21 #include "less.h"
22 #include <signal.h>
23
24 /*
25  * "sigs" contains bits indicating signals which need to be processed.
26  */
27 public int sigs;
28
29 extern int sc_width, sc_height;
30 extern int screen_trashed;
31 extern int lnloop;
32 extern int linenums;
33 extern int wscroll;
34 extern int reading;
35 extern int quit_on_intr;
36 extern int secure;
37 extern long jump_sline_fraction;
38
39 /*
40  * Interrupt signal handler.
41  */
42 #if MSDOS_COMPILER!=WIN32C
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 HILITE_SEARCH
64         set_filter_pattern(NULL, 0);
65 #endif
66         if (reading)
67                 intread(); /* May longjmp */
68 }
69 #endif
70
71 #ifdef SIGTSTP
72 /*
73  * "Stop" (^Z) signal handler.
74  */
75         /* ARGSUSED*/
76         static RETSIGTYPE
77 stop(type)
78         int type;
79 {
80         LSIGNAL(SIGTSTP, stop);
81         sigs |= S_STOP;
82         if (reading)
83                 intread();
84 }
85 #endif
86
87 #undef SIG_LESSWINDOW
88 #ifdef SIGWINCH
89 #define SIG_LESSWINDOW SIGWINCH
90 #else
91 #ifdef SIGWIND
92 #define SIG_LESSWINDOW SIGWIND
93 #endif
94 #endif
95
96 #ifdef SIG_LESSWINDOW
97 /*
98  * "Window" change handler
99  */
100         /* ARGSUSED*/
101         public RETSIGTYPE
102 winch(type)
103         int type;
104 {
105         LSIGNAL(SIG_LESSWINDOW, winch);
106         sigs |= S_WINCH;
107         if (reading)
108                 intread();
109 }
110 #endif
111
112 #if MSDOS_COMPILER==WIN32C
113 /*
114  * Handle CTRL-C and CTRL-BREAK keys.
115  */
116 #define WIN32_LEAN_AND_MEAN
117 #include <windows.h>
118
119         static BOOL WINAPI 
120 wbreak_handler(dwCtrlType)
121         DWORD dwCtrlType;
122 {
123         switch (dwCtrlType)
124         {
125         case CTRL_C_EVENT:
126         case CTRL_BREAK_EVENT:
127                 sigs |= S_INTERRUPT;
128 #if HILITE_SEARCH
129                 set_filter_pattern(NULL, 0);
130 #endif
131                 return (TRUE);
132         default:
133                 break;
134         }
135         return (FALSE);
136 }
137 #endif
138
139         static RETSIGTYPE
140 terminate(type)
141         int type;
142 {
143         quit(15);
144 }
145
146 /*
147  * Set up the signal handlers.
148  */
149         public void
150 init_signals(on)
151         int on;
152 {
153         if (on)
154         {
155                 /*
156                  * Set signal handlers.
157                  */
158 #if MSDOS_COMPILER==WIN32C
159                 SetConsoleCtrlHandler(wbreak_handler, TRUE);
160 #else
161                 (void) LSIGNAL(SIGINT, u_interrupt);
162 #endif
163 #ifdef SIGTSTP
164                 (void) LSIGNAL(SIGTSTP, secure ? SIG_IGN : stop);
165 #endif
166 #ifdef SIGWINCH
167                 (void) LSIGNAL(SIGWINCH, winch);
168 #endif
169 #ifdef SIGWIND
170                 (void) LSIGNAL(SIGWIND, winch);
171 #endif
172 #ifdef SIGQUIT
173                 (void) LSIGNAL(SIGQUIT, SIG_IGN);
174 #endif
175 #ifdef SIGTERM
176                 (void) LSIGNAL(SIGTERM, terminate);
177 #endif
178         } else
179         {
180                 /*
181                  * Restore signals to defaults.
182                  */
183 #if MSDOS_COMPILER==WIN32C
184                 SetConsoleCtrlHandler(wbreak_handler, FALSE);
185 #else
186                 (void) LSIGNAL(SIGINT, SIG_DFL);
187 #endif
188 #ifdef SIGTSTP
189                 (void) LSIGNAL(SIGTSTP, SIG_DFL);
190 #endif
191 #ifdef SIGWINCH
192                 (void) LSIGNAL(SIGWINCH, SIG_IGN);
193 #endif
194 #ifdef SIGWIND
195                 (void) LSIGNAL(SIGWIND, SIG_IGN);
196 #endif
197 #ifdef SIGQUIT
198                 (void) LSIGNAL(SIGQUIT, SIG_DFL);
199 #endif
200 #ifdef SIGTERM
201                 (void) LSIGNAL(SIGTERM, SIG_DFL);
202 #endif
203         }
204 }
205
206 /*
207  * Process any signals we have received.
208  * A received signal cause a bit to be set in "sigs".
209  */
210         public void
211 psignals(VOID_PARAM)
212 {
213         int tsignals;
214
215         if ((tsignals = sigs) == 0)
216                 return;
217         sigs = 0;
218
219 #ifdef SIGTSTP
220         if (tsignals & S_STOP)
221         {
222                 /*
223                  * Clean up the terminal.
224                  */
225 #ifdef SIGTTOU
226                 LSIGNAL(SIGTTOU, SIG_IGN);
227 #endif
228                 clear_bot();
229                 deinit();
230                 flush();
231                 raw_mode(0);
232 #ifdef SIGTTOU
233                 LSIGNAL(SIGTTOU, SIG_DFL);
234 #endif
235                 LSIGNAL(SIGTSTP, SIG_DFL);
236                 kill(getpid(), SIGTSTP);
237                 /*
238                  * ... Bye bye. ...
239                  * Hopefully we'll be back later and resume here...
240                  * Reset the terminal and arrange to repaint the
241                  * screen when we get back to the main command loop.
242                  */
243                 LSIGNAL(SIGTSTP, stop);
244                 raw_mode(1);
245                 init();
246                 screen_trashed = 1;
247                 tsignals |= S_WINCH;
248         }
249 #endif
250 #ifdef S_WINCH
251         if (tsignals & S_WINCH)
252         {
253                 int old_width, old_height;
254                 /*
255                  * Re-execute scrsize() to read the new window size.
256                  */
257                 old_width = sc_width;
258                 old_height = sc_height;
259                 get_term();
260                 if (sc_width != old_width || sc_height != old_height)
261                 {
262                         wscroll = (sc_height + 1) / 2;
263                         calc_jump_sline();
264                         calc_shift_count();
265                 }
266                 screen_trashed = 1;
267         }
268 #endif
269         if (tsignals & S_INTERRUPT)
270         {
271                 if (quit_on_intr)
272                         quit(QUIT_INTERRUPT);
273         }
274 }