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 } 388