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