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