empty() for USG UNIX ?
id for use with uunet/usenet
jbayer at ispi.UUCP
Thu Nov 10 01:22:37 AEST 1988
In article <6373 at june.cs.washington.edu>, ka at june.cs.washington.edu (Kenneth Almquist) writes:
> Dan Ts'o <dan at rna.rockefeller.edu> asks for a System V routine to test
> whether data is available to be read on a file descriptor referring to a
> slow device (such as a tty). I doubt that such a routine can be written.
> Depending on what you are doing, you may be able to use FNDELAY mode to
> get the same effect. Code like:
>
> ioctl(fd, FIONREAD, (char *)&nchars);
> if (nchars) {
> count = read(fd, buf, sizeof(buf));
> Code to process input.
> } else {
> Do something else.
> }
>
> becomes:
>
> fcntl(fd, F_SETFL, FNDELAY);
> if ((count = read(fd, buf, sizeof(buf))) != 0) {
> Code to process input.
> } else {
> Do something else.
> }
>
> These two pieces of code are approximately equivalent, but the former
> contains a race condition. (The fact that characters are available to
> be read when the FIONREAD ioctl is performed doesn't mean that these
> characters will still be around by the time the code gets around to
> performing the read.) So the latter version of the code is preferable
> on systems that support both.
> Kenneth Almquist
I have also had the same problem (of needing to know whether a character
is ready at a terminal). I was able to solve it by using the following
routines, which were taking from the book called "Advanced Unix Programaming"
written by Marc J. Rochkind, pages 79-81
void setblock(fd, on) /* turn blocking on or off */
int fd;
BOOLEAN on;
{
static int blockf, nonblockf;
static BOOLEAN first = TRUE;
int flags;
if (first) {
first = FALSE;
if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
syserr("fcntl");
blockf = flags & ~O_NDELAY; /* make sure O_NDELAY is off */
nonblockf = flags & O_NDELAY; /* make sure O_NDELAY is on */
}
if (fcntl(fd, F_SETFL, on ? blockf : nonblockf) == -1)
syserr("fcntl2");
} /* setblock */
#define EMPTY '\0'
static char cbuf = EMPTY;
BOOLEAN cready() /* is a character ready */
{
if (cbuf != EMPTY)
return (TRUE);
setblock(0,FALSE);
switch (read(0, &cbuf, 1)) {
case -1:
syserr("read");
case 0:
return (FALSE); /* could be EOF too */
default:
return (TRUE);
}
} /* cready */
int cget() /* get a character */
{
char c;
if (cbuf != EMPTYY) {
c = cbuf;
cbuf = EMPTY;
return (c & 0377); /* prevent sign extension */
}
setblock(0,TRUE);
switch (read(0, &c, 1)) {
case -1:
syserr("read");
case 0:
return (-1); /* must be eof */
default:
return (c & 0377);
}
} /* cget */
More information about the Comp.unix.wizards
mailing list