1 /* $OpenBSD: hack.tty.c,v 1.16 2019/06/28 13:32:52 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 <stdio.h> 98 #include <stdlib.h> 99 #include <termios.h> 100 101 #include "hack.h" 102 103 static char erase_char, kill_char; 104 static boolean settty_needed = FALSE; 105 struct termios inittyb, curttyb; 106 107 static void setctty(void); 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 */ 114 void 115 gettty(void) 116 { 117 if(tcgetattr(0, &inittyb) == -1) 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 */ 133 void 134 settty(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) == -1) 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 147 static void 148 setctty(void) 149 { 150 if(tcsetattr(0, TCSADRAIN, &curttyb) == -1) 151 perror("Hack (setctty)"); 152 } 153 154 void 155 setftty(void) 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 /* we need to be able to read ^Z */ 171 curttyb.c_cc[VSUSP] = _POSIX_VDISABLE; 172 change++; 173 } 174 if(change){ 175 setctty(); 176 } 177 start_screen(); 178 } 179 180 181 /* fatal error */ 182 void 183 error(const char *s, ...) 184 { 185 va_list ap; 186 187 if(settty_needed) 188 settty(NULL); 189 va_start(ap, s); 190 vprintf(s, ap); 191 va_end(ap); 192 putchar('\n'); 193 exit(1); 194 } 195 196 /* 197 * Read a line closed with '\n' into the array char bufp[BUFSZ]. 198 * (The '\n' is not stored. The string is closed with a '\0'.) 199 * Reading can be interrupted by an escape ('\033') - now the 200 * resulting string is "\033". 201 */ 202 void 203 getlin(char *bufp) 204 { 205 char *obufp = bufp; 206 int c; 207 208 flags.toplin = 2; /* nonempty, no --More-- required */ 209 for(;;) { 210 (void) fflush(stdout); 211 if((c = getchar()) == EOF) { 212 *bufp = 0; 213 return; 214 } 215 if(c == '\033') { 216 *obufp = c; 217 obufp[1] = 0; 218 return; 219 } 220 if(c == erase_char || c == '\b') { 221 if(bufp != obufp) { 222 bufp--; 223 putstr("\b \b"); /* putsym converts \b */ 224 } else hackbell(); 225 } else if(c == '\n') { 226 *bufp = 0; 227 return; 228 } else if(' ' <= c && c < '\177') { 229 /* avoid isprint() - some people don't have it 230 ' ' is not always a printing char */ 231 *bufp = c; 232 bufp[1] = 0; 233 putstr(bufp); 234 if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) 235 bufp++; 236 } else if(c == kill_char || c == '\177') { /* Robert Viduya */ 237 /* this test last - @ might be the kill_char */ 238 while(bufp != obufp) { 239 bufp--; 240 putstr("\b \b"); 241 } 242 } else 243 hackbell(); 244 } 245 } 246 247 void 248 getret(void) 249 { 250 cgetret(""); 251 } 252 253 void 254 cgetret(char *s) 255 { 256 putsym('\n'); 257 if(flags.standout) 258 standoutbeg(); 259 putstr("Hit "); 260 putstr(flags.cbreak ? "space" : "return"); 261 putstr(" to continue: "); 262 if(flags.standout) 263 standoutend(); 264 xwaitforspace(s); 265 } 266 267 char morc; /* tell the outside world what char he used */ 268 269 /* s: chars allowed besides space or return */ 270 void 271 xwaitforspace(char *s) 272 { 273 int c; 274 275 morc = 0; 276 277 while((c = readchar()) != '\n') { 278 if(flags.cbreak) { 279 if(c == ' ') break; 280 if(s && strchr(s,c)) { 281 morc = c; 282 break; 283 } 284 hackbell(); 285 } 286 } 287 } 288 289 char * 290 parse(void) 291 { 292 static char inputline[COLNO]; 293 int foo; 294 295 flags.move = 1; 296 if(!Invisible) curs_on_u(); else home(); 297 while((foo = readchar()) >= '0' && foo <= '9') 298 multi = 10*multi+foo-'0'; 299 if(multi) { 300 multi--; 301 save_cm = inputline; 302 } 303 inputline[0] = foo; 304 inputline[1] = 0; 305 if(foo == 'f' || foo == 'F'){ 306 inputline[1] = getchar(); 307 #ifdef QUEST 308 if(inputline[1] == foo) inputline[2] = getchar(); else 309 #endif /* QUEST */ 310 inputline[2] = 0; 311 } 312 if(foo == 'm' || foo == 'M'){ 313 inputline[1] = getchar(); 314 inputline[2] = 0; 315 } 316 clrlin(); 317 return(inputline); 318 } 319 320 char 321 readchar(void) 322 { 323 int sym; 324 325 (void) fflush(stdout); 326 if((sym = getchar()) == EOF) 327 end_of_input(); 328 if(flags.toplin == 1) 329 flags.toplin = 2; 330 return((char) sym); 331 } 332 333 void 334 end_of_input(void) 335 { 336 settty("End of input?\n"); 337 clearlocks(); 338 exit(0); 339 } 340