stevesu@azure.UUCP (Steve Summit) (08/22/85)
The other day I was wishing that typing control-C wouldn't flush the output queue. In desperation, I took a look at the tty driver code, and lo and behold, I found /* * Look for interrupt/quit chars. */ if (c == tp->t_intrc || c == tp->t_quitc) { if ((tp->t_flags&NOFLSH) == 0) ttyflush(tp, FREAD|FWRITE); ttyecho(c, tp); gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT); goto endcase; } (This is from the vicinity of line 720, routine ttyinput(), file tty.c .) Yup, the NOFLSH bit says, "don't flush the input and output queues on the interrupt and quit characters." There's a #definition for LNOFLSH in <sys/ioctl.h>, so your programs can set it, but it turns out that stty knows about it, too! Try stty noflsh cat /usr/dict/words date ^C where you type "date" and hit control-C while /usr/dict/words is still flying past. First you'll notice that it keeps flying for a bit after you hit control-C (because the output wasn't flushed) and then you'll notice the date get printed (because the input wasn't flushed, either). (Disclaimer: this test, for some reason, doesn't work under the Korn shell, but it works fine under sh and csh.) While searching for the ttyflush() routine, I came across a call to it in the TIOCFLUSH ioctl: case TIOCFLUSH: { register int flags = *(int *)data; if (flags == 0) flags = FREAD|FWRITE; else flags &= FREAD|FWRITE; ttyflush(tp, flags); break; } (circa line 334, routine ttioctl(), same file.) And, it turns out that ttyflush() (a bizarre little routine that I won't reprint here) uses the FREAD and FWRITE bits in its second argument to decide which queues to flush. So, the third argument to a TIOCFLUSH ioctl, which I always thought was garbage, or a pointer to some garbage, anyway, is actually used for something, and if you pass the address of something that isn't zero, you're liable to get less flushed than you wanted. In fact, though, this is useful, too, since if I want control-C to flush input but not output, all I have to do is something like #include <signal.h> #include <sgtty.h> #include <sys/file.h> /* for FREAD */ int sigint(); main() { int noflsh = LNOFLSH; ioctl(0, TIOCLBIS, &noflsh); signal(SIGINT, sigint); pause(); } sigint() { int fread = FREAD; ioctl(0, TIOCFLUSH, &fread); } Now, the $64,000 question is, even though they do _j_u_s_t what I want, can I use these things? I really don't like to use undocumented features. What I've described exists in several 4.2 ports I've looked at. But how many? Steve Summit tektronix!bronze!stevesu
trt@rti-sel.UUCP (Tom Truscott) (08/23/85)
As you point out, the FREAD/FWRITE parameter to the TIOCFLUSH ioctl is not merely undocumented, it is required! That is: ioctl(fd, TIOCFLUSH, (char *)0); is a NOP on 4.2 BSD/VAX. I suppose this feature is widely known, but I have noticed some programs that have these NOPs in them. For example, the 'flushinp()' routine in Pavel Curtis' terminfo. The correct way to flush input is, of course: #include <file.h> int flushread = FREAD; ... ioctl(fd, TIOCFLUSH, (char *)&flushread); It would be nice if a third parameter of '(char *)0' had the effect of flushing both input and output. Perhaps in 4.3 BSD? Tom Truscott