hack.tty.c revision 1.7
1/* $OpenBSD: hack.tty.c,v 1.7 2003/05/19 06:30:56 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.7 2003/05/19 06:30:56 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 <termios.h> 113 114/* 115 * Some systems may have getchar() return EOF for various reasons, and 116 * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs. 117 */ 118#ifndef BSD 119#define NR_OF_EOFS 20 120#endif /* BSD */ 121 122static char erase_char, kill_char; 123static boolean settty_needed = FALSE; 124struct termios inittyb, curttyb; 125 126static void setctty(); 127 128/* 129 * Get initial state of terminal, 130 * and switch off tab expansion if necessary. 131 * Called by startup() in termcap.c and after returning from ! or ^Z 132 */ 133void 134gettty() 135{ 136 if(tcgetattr(0, &inittyb) < 0) 137 perror("Hack (gettty)"); 138 curttyb = inittyb; 139 erase_char = inittyb.c_cc[VERASE]; 140 kill_char = inittyb.c_cc[VKILL]; 141 getioctls(); 142 143 /* do not expand tabs - they might be needed inside a cm sequence */ 144 if(curttyb.c_oflag & OXTABS) { 145 curttyb.c_oflag &= ~OXTABS; 146 setctty(); 147 } 148 settty_needed = TRUE; 149} 150 151/* reset terminal to original state */ 152void 153settty(char *s) 154{ 155 clr_screen(); 156 end_screen(); 157 if(s) 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 166static void 167setctty() 168{ 169 if(tcsetattr(0, TCSADRAIN, &curttyb) < 0) 170 perror("Hack (setctty)"); 171} 172 173void 174setftty() 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 */ 199void 200error(char *s, ...) 201{ 202 va_list ap; 203 204 if(settty_needed) 205 settty((char *) 0); 206 va_start(ap, s); 207 printf(s, ap); 208 va_end(ap); 209 putchar('\n'); 210 exit(1); 211} 212 213/* 214 * Read a line closed with '\n' into the array char bufp[BUFSZ]. 215 * (The '\n' is not stored. The string is closed with a '\0'.) 216 * Reading can be interrupted by an escape ('\033') - now the 217 * resulting string is "\033". 218 */ 219void 220getlin(char *bufp) 221{ 222 char *obufp = bufp; 223 int c; 224 225 flags.toplin = 2; /* nonempty, no --More-- required */ 226 for(;;) { 227 (void) fflush(stdout); 228 if((c = getchar()) == EOF) { 229 *bufp = 0; 230 return; 231 } 232 if(c == '\033') { 233 *obufp = c; 234 obufp[1] = 0; 235 return; 236 } 237 if(c == erase_char || c == '\b') { 238 if(bufp != obufp) { 239 bufp--; 240 putstr("\b \b"); /* putsym converts \b */ 241 } else hackbell(); 242 } else if(c == '\n') { 243 *bufp = 0; 244 return; 245 } else if(' ' <= c && c < '\177') { 246 /* avoid isprint() - some people don't have it 247 ' ' is not always a printing char */ 248 *bufp = c; 249 bufp[1] = 0; 250 putstr(bufp); 251 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) 252 bufp++; 253 } else if(c == kill_char || c == '\177') { /* Robert Viduya */ 254 /* this test last - @ might be the kill_char */ 255 while(bufp != obufp) { 256 bufp--; 257 putstr("\b \b"); 258 } 259 } else 260 hackbell(); 261 } 262} 263 264void 265getret() 266{ 267 cgetret(""); 268} 269 270void 271cgetret(char *s) 272{ 273 putsym('\n'); 274 if(flags.standout) 275 standoutbeg(); 276 putstr("Hit "); 277 putstr(flags.cbreak ? "space" : "return"); 278 putstr(" to continue: "); 279 if(flags.standout) 280 standoutend(); 281 xwaitforspace(s); 282} 283 284char morc; /* tell the outside world what char he used */ 285 286/* s: chars allowed besides space or return */ 287void 288xwaitforspace(char *s) 289{ 290 int c; 291 292 morc = 0; 293 294 while((c = readchar()) != '\n') { 295 if(flags.cbreak) { 296 if(c == ' ') break; 297 if(s && strchr(s,c)) { 298 morc = c; 299 break; 300 } 301 hackbell(); 302 } 303 } 304} 305 306char * 307parse() 308{ 309 static char inputline[COLNO]; 310 int foo; 311 312 flags.move = 1; 313 if(!Invisible) curs_on_u(); else home(); 314 while((foo = readchar()) >= '0' && foo <= '9') 315 multi = 10*multi+foo-'0'; 316 if(multi) { 317 multi--; 318 save_cm = inputline; 319 } 320 inputline[0] = foo; 321 inputline[1] = 0; 322 if(foo == 'f' || foo == 'F'){ 323 inputline[1] = getchar(); 324#ifdef QUEST 325 if(inputline[1] == foo) inputline[2] = getchar(); else 326#endif /* QUEST */ 327 inputline[2] = 0; 328 } 329 if(foo == 'm' || foo == 'M'){ 330 inputline[1] = getchar(); 331 inputline[2] = 0; 332 } 333 clrlin(); 334 return(inputline); 335} 336 337char 338readchar() 339{ 340 int sym; 341 342 (void) fflush(stdout); 343 if((sym = getchar()) == EOF) 344#ifdef NR_OF_EOFS 345 { /* 346 * Some SYSV systems seem to return EOFs for various reasons 347 * (?like when one hits break or for interrupted systemcalls?), 348 * and we must see several before we quit. 349 */ 350 int cnt = NR_OF_EOFS; 351 while (cnt--) { 352 clearerr(stdin); /* omit if clearerr is undefined */ 353 if((sym = getchar()) != EOF) goto noteof; 354 } 355 end_of_input(); 356 noteof: ; 357 } 358#else 359 end_of_input(); 360#endif /* NR_OF_EOFS */ 361 if(flags.toplin == 1) 362 flags.toplin = 2; 363 return((char) sym); 364} 365 366void 367end_of_input() 368{ 369 settty("End of input?\n"); 370 clearlocks(); 371 exit(0); 372} 373