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