
1: /* $NetBSD: hack.tty.c,v 1.12 2003/08/07 09:37:19 agc 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.12 2003/08/07 09:37:19 agc 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@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() 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(s) 152: const char *s; 153: { 154: clear_screen(); 155: end_screen(); 156: if (s) 157: printf("%s", s); 158: (void) fflush(stdout); 159: if (tcsetattr(0, TCSADRAIN, &inittyb) < 0) 160: perror("Hack (settty)"); 161: flags.echo = (inittyb.c_lflag & ECHO) ? ON : OFF; 162: flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON; 163: setioctls(); 164: } 165: 166: void 167: setctty() 168: { 169: if (tcsetattr(0, TCSADRAIN, &curttyb) < 0) 170: perror("Hack (setctty)"); 171: } 172: 173: 174: void 175: setftty() 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 */ 200: /* VARARGS1 */ 201: void 202: error(const char *fmt, ...) 203: { 204: va_list ap; 205: 206: va_start(ap, fmt); 207: if (settty_needed) 208: settty((char *) 0); 209: vprintf(fmt, ap); 210: va_end(ap); 211: putchar('\n'); 212: exit(1); 213: } 214: 215: /* 216: * Read a line closed with '\n' into the array char bufp[BUFSZ]. 217: * (The '\n' is not stored. The string is closed with a '\0'.) 218: * Reading can be interrupted by an escape ('\033') - now the 219: * resulting string is "\033". 220: */ 221: void 222: getlin(bufp) 223: char *bufp; 224: { 225: char *obufp = bufp; 226: int c; 227: 228: flags.toplin = 2; /* nonempty, no --More-- required */ 229: for (;;) { 230: (void) fflush(stdout); 231: if ((c = getchar()) == EOF) { 232: *bufp = 0; 233: return; 234: } 235: if (c == '\033') { 236: *obufp = c; 237: obufp[1] = 0; 238: return; 239: } 240: if (c == erase_char || c == '\b') { 241: if (bufp != obufp) { 242: bufp--; 243: putstr("\b \b"); /* putsym converts \b */ 244: } else 245: bell(); 246: } else if (c == '\n') { 247: *bufp = 0; 248: return; 249: } else if (' ' <= c && c < '\177') { 250: /* 251: * avoid isprint() - some people don't have it ' ' is 252: * not always a printing char 253: */ 254: *bufp = c; 255: bufp[1] = 0; 256: putstr(bufp); 257: if (bufp - obufp < BUFSZ - 1 && bufp - obufp < COLNO) 258: bufp++; 259: } else if (c == kill_char || c == '\177') { /* Robert Viduya */ 260: /* this test last - @ might be the kill_char */ 261: while (bufp != obufp) { 262: bufp--; 263: putstr("\b \b"); 264: } 265: } else 266: bell(); 267: } 268: } 269: 270: void 271: getret() 272: { 273: cgetret(""); 274: } 275: 276: void 277: cgetret(s) 278: const char *s; 279: { 280: putsym('\n'); 281: if (flags.standout) 282: standoutbeg(); 283: putstr("Hit "); 284: putstr(flags.cbreak ? "space" : "return"); 285: putstr(" to continue: "); 286: if (flags.standout) 287: standoutend(); 288: xwaitforspace(s); 289: } 290: 291: char morc; /* tell the outside world what char he used */ 292: 293: void 294: xwaitforspace(s) 295: const char *s; /* chars allowed besides space or return */ 296: { 297: int c; 298: 299: morc = 0; 300: 301: while ((c = readchar()) != '\n') { 302: if (flags.cbreak) { 303: if (c == ' ') 304: break; 305: if (s && strchr(s, c)) { 306: morc = c; 307: break; 308: } 309: bell(); 310: } 311: } 312: } 313: 314: char * 315: parse() 316: { 317: static char inputline[COLNO]; 318: int foo; 319: 320: flags.move = 1; 321: if (!Invisible) 322: curs_on_u(); 323: else 324: home(); 325: while ((foo = readchar()) >= '0' && foo <= '9') 326: multi = 10 * multi + foo - '0'; 327: if (multi) { 328: multi--; 329: save_cm = inputline; 330: } 331: inputline[0] = foo; 332: inputline[1] = 0; 333: if (foo == 'f' || foo == 'F') { 334: inputline[1] = getchar(); 335: #ifdef QUEST 336: if (inputline[1] == foo) 337: inputline[2] = getchar(); 338: else 339: #endif /* QUEST */ 340: inputline[2] = 0; 341: } 342: if (foo == 'm' || foo == 'M') { 343: inputline[1] = getchar(); 344: inputline[2] = 0; 345: } 346: clrlin(); 347: return (inputline); 348: } 349: 350: char 351: readchar() 352: { 353: int sym; 354: 355: (void) fflush(stdout); 356: if ((sym = getchar()) == EOF) 357: #ifdef NR_OF_EOFS 358: { /* 359: * Some SYSV systems seem to return EOFs for various reasons 360: * (?like when one hits break or for interrupted systemcalls?), 361: * and we must see several before we quit. 362: */ 363: int cnt = NR_OF_EOFS; 364: while (cnt--) { 365: clearerr(stdin); /* omit if clearerr is 366: * undefined */ 367: if ((sym = getchar()) != EOF) 368: goto noteof; 369: } 370: end_of_input(); 371: noteof: ; 372: } 373: #else 374: end_of_input(); 375: #endif /* NR_OF_EOFS */ 376: if (flags.toplin == 1) 377: flags.toplin = 2; 378: return ((char) sym); 379: } 380: 381: void 382: end_of_input() 383: { 384: settty("End of input?\n"); 385: clearlocks(); 386: exit(0); 387: }