Annotation of src/usr.bin/less/signal.c, Revision 1.6
1.1 etheisen 1: /*
1.4 millert 2: * Copyright (C) 1984-2002 Mark Nudelman
1.1 etheisen 3: *
1.4 millert 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.
1.1 etheisen 6: *
1.4 millert 7: * For more information about less, or for information on how to
8: * contact the author, see the README file.
1.1 etheisen 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: */
19:
20: #include "less.h"
21: #include <signal.h>
22:
23: /*
24: * "sigs" contains bits indicating signals which need to be processed.
25: */
26: public int sigs;
27:
28: extern int sc_width, sc_height;
29: extern int screen_trashed;
30: extern int lnloop;
31: extern int linenums;
32: extern int wscroll;
33:
34: /*
35: * Interrupt signal handler.
36: */
37: /* ARGSUSED*/
38: static RETSIGTYPE
39: u_interrupt(type)
40: int type;
41: {
42: #if OS2
1.4 millert 43: LSIGNAL(SIGINT, SIG_ACK);
1.1 etheisen 44: #endif
45: sigs |= S_INTERRUPT;
1.4 millert 46: #if MSDOS_COMPILER==DJGPPC
47: /*
48: * If a keyboard has been hit, it must be Ctrl-C
49: * (as opposed to Ctrl-Break), so consume it.
50: * (Otherwise, Less will beep when it sees Ctrl-C from keyboard.)
51: */
52: if (kbhit())
53: getkey();
54: #endif
1.1 etheisen 55: }
56:
57: #ifdef SIGTSTP
58: /*
59: * "Stop" (^Z) signal handler.
60: */
61: /* ARGSUSED*/
62: static RETSIGTYPE
63: stop(type)
64: int type;
65: {
66: sigs |= S_STOP;
67: }
68: #endif
69:
70: #ifdef SIGWINCH
71: /*
72: * "Window" change handler
73: */
74: /* ARGSUSED*/
75: public RETSIGTYPE
76: winch(type)
77: int type;
78: {
79: sigs |= S_WINCH;
80: }
81: #else
82: #ifdef SIGWIND
83: /*
84: * "Window" change handler
85: */
86: /* ARGSUSED*/
87: public RETSIGTYPE
88: winch(type)
89: int type;
90: {
91: sigs |= S_WINCH;
92: }
93: #endif
94: #endif
95:
1.4 millert 96: #if MSDOS_COMPILER==WIN32C
97: /*
98: * Handle CTRL-C and CTRL-BREAK keys.
99: */
100: #include "windows.h"
101:
102: static BOOL WINAPI
103: wbreak_handler(dwCtrlType)
104: DWORD dwCtrlType;
105: {
106: switch (dwCtrlType)
107: {
108: case CTRL_C_EVENT:
109: case CTRL_BREAK_EVENT:
110: sigs |= S_INTERRUPT;
111: return (TRUE);
112: default:
113: break;
114: }
115: return (FALSE);
116: }
117: #endif
118:
1.1 etheisen 119: /*
120: * Set up the signal handlers.
121: */
122: public void
123: init_signals(on)
124: int on;
125: {
126: if (on)
127: {
128: /*
129: * Set signal handlers.
130: */
1.4 millert 131: (void) LSIGNAL(SIGINT, u_interrupt);
132: #if MSDOS_COMPILER==WIN32C
133: SetConsoleCtrlHandler(wbreak_handler, TRUE);
134: #endif
1.1 etheisen 135: #ifdef SIGTSTP
1.4 millert 136: (void) LSIGNAL(SIGTSTP, stop);
1.1 etheisen 137: #endif
138: #ifdef SIGWINCH
1.4 millert 139: (void) LSIGNAL(SIGWINCH, winch);
1.1 etheisen 140: #else
141: #ifdef SIGWIND
1.4 millert 142: (void) LSIGNAL(SIGWIND, winch);
143: #endif
144: #ifdef SIGQUIT
145: (void) LSIGNAL(SIGQUIT, SIG_IGN);
1.1 etheisen 146: #endif
147: #endif
148: } else
149: {
150: /*
151: * Restore signals to defaults.
152: */
1.4 millert 153: (void) LSIGNAL(SIGINT, SIG_DFL);
154: #if MSDOS_COMPILER==WIN32C
155: SetConsoleCtrlHandler(wbreak_handler, FALSE);
156: #endif
1.1 etheisen 157: #ifdef SIGTSTP
1.4 millert 158: (void) LSIGNAL(SIGTSTP, SIG_DFL);
1.1 etheisen 159: #endif
160: #ifdef SIGWINCH
1.4 millert 161: (void) LSIGNAL(SIGWINCH, SIG_IGN);
1.1 etheisen 162: #endif
163: #ifdef SIGWIND
1.4 millert 164: (void) LSIGNAL(SIGWIND, SIG_IGN);
165: #endif
166: #ifdef SIGQUIT
167: (void) LSIGNAL(SIGQUIT, SIG_DFL);
1.1 etheisen 168: #endif
169: }
170: }
171:
172: /*
173: * Process any signals we have received.
174: * A received signal cause a bit to be set in "sigs".
175: */
176: public void
177: psignals()
178: {
1.4 millert 179: register int tsignals;
1.1 etheisen 180:
181: if ((tsignals = sigs) == 0)
182: return;
183: sigs = 0;
184:
185: #ifdef SIGTSTP
186: if (tsignals & S_STOP)
187: {
188: /*
189: * Clean up the terminal.
190: */
191: #ifdef SIGTTOU
1.4 millert 192: LSIGNAL(SIGTTOU, SIG_IGN);
1.1 etheisen 193: #endif
194: clear_bot();
195: deinit();
196: flush();
197: raw_mode(0);
198: #ifdef SIGTTOU
1.4 millert 199: LSIGNAL(SIGTTOU, SIG_DFL);
1.1 etheisen 200: #endif
1.4 millert 201: LSIGNAL(SIGTSTP, SIG_DFL);
1.1 etheisen 202: kill(getpid(), SIGTSTP);
203: /*
204: * ... Bye bye. ...
205: * Hopefully we'll be back later and resume here...
206: * Reset the terminal and arrange to repaint the
207: * screen when we get back to the main command loop.
208: */
1.4 millert 209: LSIGNAL(SIGTSTP, stop);
1.1 etheisen 210: raw_mode(1);
211: init();
212: screen_trashed = 1;
213: tsignals |= S_WINCH;
214: }
215: #endif
216: #ifdef S_WINCH
217: if (tsignals & S_WINCH)
218: {
219: int old_width, old_height;
220: /*
221: * Re-execute scrsize() to read the new window size.
222: */
223: old_width = sc_width;
224: old_height = sc_height;
225: get_term();
226: if (sc_width != old_width || sc_height != old_height)
227: {
228: wscroll = (sc_height + 1) / 2;
229: screen_trashed = 1;
230: }
231: }
232: #endif
233: if (tsignals & S_INTERRUPT)
234: {
235: bell();
236: /*
237: * {{ You may wish to replace the bell() with
238: * error("Interrupt", NULL_PARG); }}
239: */
240:
241: /*
242: * If we were interrupted while in the "calculating
243: * line numbers" loop, turn off line numbers.
244: */
245: if (lnloop)
246: {
247: lnloop = 0;
1.6 ! millert 248: if (linenums == OPT_ONPLUS)
1.1 etheisen 249: screen_trashed = 1;
250: linenums = 0;
251: error("Line numbers turned off", NULL_PARG);
252: }
253:
254: }
1.5 millert 255: }
256:
257: /*
258: * Custom version of signal() that causes syscalls to be interrupted.
259: */
260: public void
261: (*lsignal(s, a))()
262: int s;
263: void (*a) ();
264: {
265: struct sigaction sa, osa;
266:
267: sa.sa_handler = a;
268: sigemptyset(&sa.sa_mask);
269: sa.sa_flags = 0; /* don't restart system calls */
270: if (sigaction(s, &sa, &osa) != 0)
271: return (SIG_ERR);
272: return (osa.sa_handler);
1.1 etheisen 273: }