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