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