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