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