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