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