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