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