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