hack.tty.c revision 1.12
1/*	$OpenBSD: hack.tty.c,v 1.12 2015/01/15 17:13:37 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	"hack.h"
98#include	<stdio.h>
99#include	<stdarg.h>
100#include	<stdlib.h>
101#include	<termios.h>
102
103static char erase_char, kill_char;
104static boolean settty_needed = FALSE;
105struct termios inittyb, curttyb;
106
107static void setctty();
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 */
114void
115gettty()
116{
117	if(tcgetattr(0, &inittyb) < 0)
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 */
133void
134settty(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) < 0)
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
147static void
148setctty()
149{
150	if(tcsetattr(0, TCSADRAIN, &curttyb) < 0)
151		perror("Hack (setctty)");
152}
153
154void
155setftty()
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		change++;
171	}
172	if(change){
173		setctty();
174	}
175	start_screen();
176}
177
178
179/* fatal error */
180void
181error(char *s, ...)
182{
183	va_list ap;
184
185	if(settty_needed)
186		settty((char *) 0);
187	va_start(ap, s);
188	vprintf(s, ap);
189	va_end(ap);
190	putchar('\n');
191	exit(1);
192}
193
194/*
195 * Read a line closed with '\n' into the array char bufp[BUFSZ].
196 * (The '\n' is not stored. The string is closed with a '\0'.)
197 * Reading can be interrupted by an escape ('\033') - now the
198 * resulting string is "\033".
199 */
200void
201getlin(char *bufp)
202{
203	char *obufp = bufp;
204	int c;
205
206	flags.toplin = 2;		/* nonempty, no --More-- required */
207	for(;;) {
208		(void) fflush(stdout);
209		if((c = getchar()) == EOF) {
210			*bufp = 0;
211			return;
212		}
213		if(c == '\033') {
214			*obufp = c;
215			obufp[1] = 0;
216			return;
217		}
218		if(c == erase_char || c == '\b') {
219			if(bufp != obufp) {
220				bufp--;
221				putstr("\b \b"); /* putsym converts \b */
222			} else	hackbell();
223		} else if(c == '\n') {
224			*bufp = 0;
225			return;
226		} else if(' ' <= c && c < '\177') {
227				/* avoid isprint() - some people don't have it
228				   ' ' is not always a printing char */
229			*bufp = c;
230			bufp[1] = 0;
231			putstr(bufp);
232			if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
233				bufp++;
234		} else if(c == kill_char || c == '\177') { /* Robert Viduya */
235				/* this test last - @ might be the kill_char */
236			while(bufp != obufp) {
237				bufp--;
238				putstr("\b \b");
239			}
240		} else
241			hackbell();
242	}
243}
244
245void
246getret()
247{
248	cgetret("");
249}
250
251void
252cgetret(char *s)
253{
254	putsym('\n');
255	if(flags.standout)
256		standoutbeg();
257	putstr("Hit ");
258	putstr(flags.cbreak ? "space" : "return");
259	putstr(" to continue: ");
260	if(flags.standout)
261		standoutend();
262	xwaitforspace(s);
263}
264
265char morc;	/* tell the outside world what char he used */
266
267/* s: chars allowed besides space or return */
268void
269xwaitforspace(char *s)
270{
271	int c;
272
273	morc = 0;
274
275	while((c = readchar()) != '\n') {
276	    if(flags.cbreak) {
277		if(c == ' ') break;
278		if(s && strchr(s,c)) {
279			morc = c;
280			break;
281		}
282		hackbell();
283	    }
284	}
285}
286
287char *
288parse()
289{
290	static char inputline[COLNO];
291	int foo;
292
293	flags.move = 1;
294	if(!Invisible) curs_on_u(); else home();
295	while((foo = readchar()) >= '0' && foo <= '9')
296		multi = 10*multi+foo-'0';
297	if(multi) {
298		multi--;
299		save_cm = inputline;
300	}
301	inputline[0] = foo;
302	inputline[1] = 0;
303	if(foo == 'f' || foo == 'F'){
304		inputline[1] = getchar();
305#ifdef QUEST
306		if(inputline[1] == foo) inputline[2] = getchar(); else
307#endif /* QUEST */
308		inputline[2] = 0;
309	}
310	if(foo == 'm' || foo == 'M'){
311		inputline[1] = getchar();
312		inputline[2] = 0;
313	}
314	clrlin();
315	return(inputline);
316}
317
318char
319readchar()
320{
321	int sym;
322
323	(void) fflush(stdout);
324	if((sym = getchar()) == EOF)
325		end_of_input();
326	if(flags.toplin == 1)
327		flags.toplin = 2;
328	return((char) sym);
329}
330
331void
332end_of_input()
333{
334	settty("End of input?\n");
335	clearlocks();
336	exit(0);
337}
338