local@ihopb.UUCP (Steven Spearman) (07/18/85)
Here is yet another rendition of hack.tty.c for System V unix. This attempts a fix of the 'End of Input?' error caused by hitting the old BREAK at the wrong time. The problem appears to be casued by the interrupt normally occuring while waiting for input in getchar() which in system V causes a return of -1 which looks like an EOF. The solution is to do a clearerr(stdin) and try again. I don't have any idea if this is now still compatible with BSD. Steve Spearman ihnp4!ihopb!spear -----cut here------- /* * Here is hack.tty.c, modified to work on System V Release 2. * I haven't checked to see if it will still work on BSD, but it should. * Bill */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* hack.tty.c - version 1.0.2 */ /* hacked by bill stewart at att-bl because the CBREAK flag doesn't work */ /* on System V - so I hacked it to use termio instead */ /* * re-hacked to eliminate 'End of Input?' error upon signal * -Steve Spearman ihnp4!ihopb!spear */ #include "hack.h" #include <stdio.h> #include <ctype.h> /* for isprint() */ #ifdef BSD #include <sgtty.h> #else #include <termio.h> #define sgttyb termio #define sg_flags c_lflag /* Well, most of the time it's used for c_lflag */ /* Yes, I admit it's crude */ #define CBREAK ICANON /* Usually you just care about the bitmask */ #endif BSD struct sgttyb inittyb, curttyb; short ospeed; char erase_char, kill_char; static boolean settty_needed = FALSE; #ifndef BSD unsigned char c_cc_VMIN, c_cc_VTIME; /* = c_cc[EOF] and c_cc[EOL] */ #endif /* * Get initial state of terminal, set ospeed (for termcap routines) * and switch off tab expansion if necessary. * Called by startup() in termcap.c and after returning from ! or ^Z */ gettty(){ #ifdef BSD (void) gtty(0, &inittyb); (void) gtty(0, &curttyb); ospeed = inittyb.sg_ospeed; erase_char = inittyb.sg_erase; kill_char = inittyb.sg_kill; getioctls(); #else (void) ioctl(0, TCGETA, &inittyb); (void) ioctl(0, TCGETA, &curttyb); ospeed = inittyb.c_cflag & CBAUD; erase_char = inittyb.c_cc[VERASE]; kill_char = inittyb.c_cc[VKILL]; getioctls(); #endif /* do not expand tabs - they might be needed inside a cm sequence */ #ifdef BSD if(curttyb.sg_flags & XTABS) { curttyb.sg_flags &= ~XTABS; #else if(curttyb.c_oflag & TAB3) { curttyb.c_oflag &= ~TAB3; #endif BSD setctty(); } settty_needed = TRUE; } /* fatal error */ /*VARARGS1*/ error(s,x,y) char *s; { if(settty_needed) settty((char *) 0); printf(s,x,y); putchar('\n'); exit(1); } /* reset terminal to original state */ settty(s) char *s; { clear_screen(); end_screen(); if(s) printf(s); (void) fflush(stdout); #ifdef BSD if(stty(0, &inittyb) == -1) #else if(ioctl(0, TCSETA, &inittyb) == -1) #endif BSD puts("Cannot change tty"); flags.echo = (inittyb.sg_flags & ECHO) ? ON : OFF; #ifdef BSD flags.cbreak = (inittyb.sg_flags & CBREAK) ? ON : OFF; #else flags.cbreak = (inittyb.c_lflag & ICANON) ? OFF : ON; #endif setioctls(); } setctty(){ #ifdef BSD if(stty(0, &curttyb) == -1) puts("Cannot change tty"); #else if(ioctl(0, TCSETA, &curttyb) == -1) puts("Cannot change tty"); #endif BSD } setftty(){ flags.cbreak = ON; flags.echo = OFF; setxtty(); } setxtty(){ register int ef = (flags.echo == ON) ? ECHO : 0; #ifdef BSD register int cf = (flags.cbreak == ON) ? CBREAK : 0; #else register int cf = (flags.cbreak == ON) ? 0 : ICANON; #endif register int change = 0; /* Should use (ECHO|CRMOD) here instead of ECHO */ if((curttyb.sg_flags & ECHO) != ef){ curttyb.sg_flags &= ~ECHO; curttyb.sg_flags |= ef; change++; } #ifdef BSD if((curttyb.sg_flags & CBREAK) != cf){ curttyb.sg_flags &= ~CBREAK; #else if((curttyb.sg_flags & ICANON || curttyb.c_cc[VMIN] > 1 ) != cf){ curttyb.sg_flags &= ~ICANON; curttyb.c_cc[VMIN] = (char) 1; /* Characters in a read() */ curttyb.c_cc[VTIME] = (char) 0; /* No timeout on a read() */ #endif BSD curttyb.sg_flags |= cf; change++; } if(change){ setctty(); } start_screen(); } /* * Read a line closed with '\n' into the array char bufp[BUFSZ]. * (The '\n' is not stored. The string is closed with a '\0'.) * Reading can be interrupted by an escape ('\033') - now the * resulting string is "\033". */ getlin(bufp) register char *bufp; { register char *obufp = bufp; register int c; flags.toplin = 2; /* nonempty, no --More-- required */ for(;;) { (void) fflush(stdout); if((c = getchar()) == EOF) { *bufp = 0; return; } if(c == '\033') { *obufp = c; obufp[1] = 0; return; } if(c == erase_char || c == '\b') { if(bufp != obufp) { bufp--; putstr("\b \b"); /* putsym converts \b */ } else bell(); } else if(c == '\n') { *bufp = 0; return; } else if(c == kill_char || c == '\177') { /* Robert Viduya */ while(bufp != obufp) { bufp--; putstr("\b \b"); } } else if(isprint(c) || c == ' ') { *bufp = c; bufp[1] = 0; putstr(bufp); if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) bufp++; } else bell(); } } getret() { xgetret(""); } cgetret(s) register char *s; { xgetret(s); } xgetret(s) register char *s; { putsym('\n'); if(flags.standout) standoutbeg(); putstr("Hit "); putstr(flags.cbreak ? "space" : "return"); putstr(" to continue: "); if(flags.standout) standoutend(); xwaitforspace(s); } char morc; /* tell the outside world what char he used */ xwaitforspace(s) register char *s; /* chars allowed besides space or return */ { register int c; (void) fflush(stdout); morc = 0; while((c = getchar()) != '\n') { if(c == EOF) { clearerr(stdin); if((c = getchar()) == EOF) end_of_input(); } if(flags.cbreak) { if(c == ' ') break; if(s && index(s,c)) { morc = c; break; } bell(); /* useless if !cbreak */ } } } char * parse() { static char inline[COLNO]; register foo; int footry; flags.move = 1; if(!Invis) curs_on_u(); else home(); (void) fflush(stdout); footry= 0; retry: while((foo = getchar()) >= '0' && foo <= '9') multi += 10*multi+foo-'0'; if(multi) { multi--; save_cm = inline; } inline[0] = foo; inline[1] = 0; if(foo == EOF) { clearerr(stdin); if (footry++ > 0) end_of_input(); goto retry; } if(foo == 'f' || foo == 'F'){ inline[1] = getchar(); #ifdef QUEST if(inline[1] == foo) inline[2] = getchar(); else #endif QUEST inline[2] = 0; } if(foo == 'm' || foo == 'M'){ inline[1] = getchar(); inline[2] = 0; } clrlin(); return(inline); } char readchar() { register int sym; (void) fflush(stdout); if((sym = getchar()) == EOF) { /* try to fix error */ clearerr(stdin); if((sym = getchar()) == EOF) end_of_input(); } if(flags.toplin == 1) flags.toplin = 2; return((char) sym); } end_of_input() { settty("End of input?\n"); clearlocks(); exit(0); }