Undocumented 4.2 tty driver features
Steve Summit
stevesu at azure.UUCP
Thu Aug 22 14:17:50 AEST 1985
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
More information about the Comp.unix.wizards
mailing list