xref: /original-bsd/usr.bin/more/signal.c (revision 4b05c5c5)
1 /*
2  * Copyright (c) 1988 Mark Nudleman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)signal.c	5.7 (Berkeley) 06/01/90";
11 #endif /* not lint */
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 int sigs;
30 
31 #ifdef SIGTSTP
32 #define	S_STOP		02
33 #endif
34 #if defined(SIGWINCH) || defined(SIGWIND)
35 #define S_WINCH		04
36 #endif
37 
38 extern int sc_width, sc_height;
39 extern int screen_trashed;
40 extern int lnloop;
41 extern int linenums;
42 extern int scroll;
43 extern int reading;
44 
45 #ifdef SIGTSTP
46 /*
47  * "Stop" (^Z) signal handler.
48  */
49 static
50 stop()
51 {
52 	(void)signal(SIGTSTP, stop);
53 	sigs |= S_STOP;
54 	if (reading)
55 		intread();
56 }
57 #endif
58 
59 #ifdef SIGWINCH
60 /*
61  * "Window" change handler
62  */
63 winch()
64 {
65 	(void)signal(SIGWINCH, winch);
66 	sigs |= S_WINCH;
67 	if (reading)
68 		intread();
69 }
70 #else
71 #ifdef SIGWIND
72 /*
73  * "Window" change handler
74  */
75 winch()
76 {
77 	(void)signal(SIGWIND, winch);
78 	sigs |= S_WINCH;
79 	if (reading)
80 		intread();
81 }
82 #endif
83 #endif
84 
85 static int
86 purgeandquit()
87 {
88 
89 	purge();	/* purge buffered output */
90 	quit();
91 }
92 
93 /*
94  * Set up the signal handlers.
95  */
96 init_signals(on)
97 	int on;
98 {
99 	int quit();
100 
101 	if (on)
102 	{
103 		/*
104 		 * Set signal handlers.
105 		 */
106 		(void)signal(SIGINT, purgeandquit);
107 #ifdef SIGTSTP
108 		(void)signal(SIGTSTP, stop);
109 #endif
110 #ifdef SIGWINCH
111 		(void)signal(SIGWINCH, winch);
112 #else
113 #ifdef SIGWIND
114 		(void)signal(SIGWIND, winch);
115 #endif
116 #endif
117 	} else
118 	{
119 		/*
120 		 * Restore signals to defaults.
121 		 */
122 		(void)signal(SIGINT, SIG_DFL);
123 #ifdef SIGTSTP
124 		(void)signal(SIGTSTP, SIG_DFL);
125 #endif
126 #ifdef SIGWINCH
127 		(void)signal(SIGWINCH, SIG_IGN);
128 #endif
129 #ifdef SIGWIND
130 		(void)signal(SIGWIND, SIG_IGN);
131 #endif
132 	}
133 }
134 
135 /*
136  * Process any signals we have received.
137  * A received signal cause a bit to be set in "sigs".
138  */
139 psignals()
140 {
141 	register int tsignals;
142 
143 	if ((tsignals = sigs) == 0)
144 		return;
145 	sigs = 0;
146 
147 #ifdef S_WINCH
148 	if (tsignals & S_WINCH)
149 	{
150 		int old_width, old_height;
151 		/*
152 		 * Re-execute get_term() to read the new window size.
153 		 */
154 		old_width = sc_width;
155 		old_height = sc_height;
156 		get_term();
157 		if (sc_width != old_width || sc_height != old_height)
158 		{
159 			scroll = (sc_height + 1) / 2;
160 			screen_trashed = 1;
161 		}
162 	}
163 #endif
164 #ifdef SIGTSTP
165 	if (tsignals & S_STOP)
166 	{
167 		/*
168 		 * Clean up the terminal.
169 		 */
170 #ifdef SIGTTOU
171 		(void)signal(SIGTTOU, SIG_IGN);
172 #endif
173 		lower_left();
174 		clear_eol();
175 		deinit();
176 		(void)flush();
177 		raw_mode(0);
178 #ifdef SIGTTOU
179 		(void)signal(SIGTTOU, SIG_DFL);
180 #endif
181 		(void)signal(SIGTSTP, SIG_DFL);
182 		(void)kill(getpid(), SIGTSTP);
183 		/*
184 		 * ... Bye bye. ...
185 		 * Hopefully we'll be back later and resume here...
186 		 * Reset the terminal and arrange to repaint the
187 		 * screen when we get back to the main command loop.
188 		 */
189 		(void)signal(SIGTSTP, stop);
190 		raw_mode(1);
191 		init();
192 		screen_trashed = 1;
193 	}
194 #endif
195 }
196