dan@rna.UUCP (Dan Ts'o) (11/02/88)
Sorry for being so lazy, but can someone send me a C routine for the USG System V termio equivalent of the old Rand empty(fd) call. The empty(fd) call took a file descriptor argument, usually a tty, and returned 1 if there were no characters in the queue to read (would block if read(fd) were issued) and 0 if there were bytes to read. It also worked on pipes, but I don't care about that feature at this point. I have the 4BSD equivalent, which just uses ioctl(FIONREAD) to return how many characters are in the queue. So what is the System V equivalent ? Thanks. Please email responses. Cheers, Dan Ts'o 212-570-7671 Dept. Neurobiology dan@rna.rockefeller.edu Rockefeller Univ. ...cmcl2!rna!dan 1230 York Ave. rna!dan@nyu.arpa NY, NY 10021 tso@rockefeller.arpa tso@rockvax.bitnet
ka@june.cs.washington.edu (Kenneth Almquist) (11/09/88)
Dan Ts'o <dan@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
jbayer@ispi.UUCP (id for use with uunet/usenet) (11/09/88)
In article <6373@june.cs.washington.edu>, ka@june.cs.washington.edu (Kenneth Almquist) writes: > Dan Ts'o <dan@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 */