1 /* $OpenBSD: hack.tty.c,v 1.16 2019/06/28 13:32:52 deraadt Exp $ */
2
3 /*-
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
34 * Amsterdam
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions are
39 * met:
40 *
41 * - Redistributions of source code must retain the above copyright notice,
42 * this list of conditions and the following disclaimer.
43 *
44 * - Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 *
48 * - Neither the name of the Stichting Centrum voor Wiskunde en
49 * Informatica, nor the names of its contributors may be used to endorse or
50 * promote products derived from this software without specific prior
51 * written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
54 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
56 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
57 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 */
65
66 /*
67 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
68 * All rights reserved.
69 *
70 * Redistribution and use in source and binary forms, with or without
71 * modification, are permitted provided that the following conditions
72 * are met:
73 * 1. Redistributions of source code must retain the above copyright
74 * notice, this list of conditions and the following disclaimer.
75 * 2. Redistributions in binary form must reproduce the above copyright
76 * notice, this list of conditions and the following disclaimer in the
77 * documentation and/or other materials provided with the distribution.
78 * 3. The name of the author may not be used to endorse or promote products
79 * derived from this software without specific prior written permission.
80 *
81 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
82 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
83 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
84 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
85 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
86 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
87 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
88 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
89 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
90 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
91 */
92
93 /* hack.tty.c - version 1.0.3 */
94 /* With thanks to the people who sent code for SYSV - hpscdi!jon,
95 arnold@ucsf-cgl, wcs@bo95b, cbcephus!pds and others. */
96
97 #include <stdio.h>
98 #include <stdlib.h>
99 #include <termios.h>
100
101 #include "hack.h"
102
103 static char erase_char, kill_char;
104 static boolean settty_needed = FALSE;
105 struct termios inittyb, curttyb;
106
107 static void setctty(void);
108
109 /*
110 * Get initial state of terminal,
111 * and switch off tab expansion if necessary.
112 * Called by startup() in termcap.c and after returning from ! or ^Z
113 */
114 void
gettty(void)115 gettty(void)
116 {
117 if(tcgetattr(0, &inittyb) == -1)
118 perror("Hack (gettty)");
119 curttyb = inittyb;
120 erase_char = inittyb.c_cc[VERASE];
121 kill_char = inittyb.c_cc[VKILL];
122 getioctls();
123
124 /* do not expand tabs - they might be needed inside a cm sequence */
125 if(curttyb.c_oflag & OXTABS) {
126 curttyb.c_oflag &= ~OXTABS;
127 setctty();
128 }
129 settty_needed = TRUE;
130 }
131
132 /* reset terminal to original state */
133 void
settty(char * s)134 settty(char *s)
135 {
136 clr_screen();
137 end_screen();
138 if(s) printf("%s", s);
139 (void) fflush(stdout);
140 if(tcsetattr(0, TCSADRAIN, &inittyb) == -1)
141 perror("Hack (settty)");
142 flags.echo = (inittyb.c_lflag & ECHO) ? ON : OFF;
143 flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON;
144 setioctls();
145 }
146
147 static void
setctty(void)148 setctty(void)
149 {
150 if(tcsetattr(0, TCSADRAIN, &curttyb) == -1)
151 perror("Hack (setctty)");
152 }
153
154 void
setftty(void)155 setftty(void)
156 {
157 int change = 0;
158 flags.cbreak = ON;
159 flags.echo = OFF;
160 /* Should use (ECHO|CRMOD) here instead of ECHO */
161 if(curttyb.c_lflag & ECHO){
162 curttyb.c_lflag &= ~ECHO;
163 change++;
164 }
165 if(curttyb.c_lflag & ICANON){
166 curttyb.c_lflag &= ~ICANON;
167 /* be satisfied with one character; no timeout */
168 curttyb.c_cc[VMIN] = 1;
169 curttyb.c_cc[VTIME] = 0;
170 /* we need to be able to read ^Z */
171 curttyb.c_cc[VSUSP] = _POSIX_VDISABLE;
172 change++;
173 }
174 if(change){
175 setctty();
176 }
177 start_screen();
178 }
179
180
181 /* fatal error */
182 void
error(const char * s,...)183 error(const char *s, ...)
184 {
185 va_list ap;
186
187 if(settty_needed)
188 settty(NULL);
189 va_start(ap, s);
190 vprintf(s, ap);
191 va_end(ap);
192 putchar('\n');
193 exit(1);
194 }
195
196 /*
197 * Read a line closed with '\n' into the array char bufp[BUFSZ].
198 * (The '\n' is not stored. The string is closed with a '\0'.)
199 * Reading can be interrupted by an escape ('\033') - now the
200 * resulting string is "\033".
201 */
202 void
getlin(char * bufp)203 getlin(char *bufp)
204 {
205 char *obufp = bufp;
206 int c;
207
208 flags.toplin = 2; /* nonempty, no --More-- required */
209 for(;;) {
210 (void) fflush(stdout);
211 if((c = getchar()) == EOF) {
212 *bufp = 0;
213 return;
214 }
215 if(c == '\033') {
216 *obufp = c;
217 obufp[1] = 0;
218 return;
219 }
220 if(c == erase_char || c == '\b') {
221 if(bufp != obufp) {
222 bufp--;
223 putstr("\b \b"); /* putsym converts \b */
224 } else hackbell();
225 } else if(c == '\n') {
226 *bufp = 0;
227 return;
228 } else if(' ' <= c && c < '\177') {
229 /* avoid isprint() - some people don't have it
230 ' ' is not always a printing char */
231 *bufp = c;
232 bufp[1] = 0;
233 putstr(bufp);
234 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
235 bufp++;
236 } else if(c == kill_char || c == '\177') { /* Robert Viduya */
237 /* this test last - @ might be the kill_char */
238 while(bufp != obufp) {
239 bufp--;
240 putstr("\b \b");
241 }
242 } else
243 hackbell();
244 }
245 }
246
247 void
getret(void)248 getret(void)
249 {
250 cgetret("");
251 }
252
253 void
cgetret(char * s)254 cgetret(char *s)
255 {
256 putsym('\n');
257 if(flags.standout)
258 standoutbeg();
259 putstr("Hit ");
260 putstr(flags.cbreak ? "space" : "return");
261 putstr(" to continue: ");
262 if(flags.standout)
263 standoutend();
264 xwaitforspace(s);
265 }
266
267 char morc; /* tell the outside world what char he used */
268
269 /* s: chars allowed besides space or return */
270 void
xwaitforspace(char * s)271 xwaitforspace(char *s)
272 {
273 int c;
274
275 morc = 0;
276
277 while((c = readchar()) != '\n') {
278 if(flags.cbreak) {
279 if(c == ' ') break;
280 if(s && strchr(s,c)) {
281 morc = c;
282 break;
283 }
284 hackbell();
285 }
286 }
287 }
288
289 char *
parse(void)290 parse(void)
291 {
292 static char inputline[COLNO];
293 int foo;
294
295 flags.move = 1;
296 if(!Invisible) curs_on_u(); else home();
297 while((foo = readchar()) >= '0' && foo <= '9')
298 multi = 10*multi+foo-'0';
299 if(multi) {
300 multi--;
301 save_cm = inputline;
302 }
303 inputline[0] = foo;
304 inputline[1] = 0;
305 if(foo == 'f' || foo == 'F'){
306 inputline[1] = getchar();
307 #ifdef QUEST
308 if(inputline[1] == foo) inputline[2] = getchar(); else
309 #endif /* QUEST */
310 inputline[2] = 0;
311 }
312 if(foo == 'm' || foo == 'M'){
313 inputline[1] = getchar();
314 inputline[2] = 0;
315 }
316 clrlin();
317 return(inputline);
318 }
319
320 char
readchar(void)321 readchar(void)
322 {
323 int sym;
324
325 (void) fflush(stdout);
326 if((sym = getchar()) == EOF)
327 end_of_input();
328 if(flags.toplin == 1)
329 flags.toplin = 2;
330 return((char) sym);
331 }
332
333 void
end_of_input(void)334 end_of_input(void)
335 {
336 settty("End of input?\n");
337 clearlocks();
338 exit(0);
339 }
340