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