Xref: utzoo comp.unix.wizards:12263 comp.bugs.sys5:682 Path: utzoo!utgpu!attcan!uunet!ispi!jbayer From: jbayer@ispi.UUCP (id for use with uunet/usenet) Newsgroups: comp.unix.wizards,comp.bugs.sys5 Subject: Re: empty() for USG UNIX ? Summary: look-ahead on serial lines Message-ID: <247@ispi.UUCP> Date: 9 Nov 88 15:22:37 GMT References: <292@rna.UUCP> <6373@june.cs.washington.edu> Organization: Intelligent Software Products, Inc. Lines: 97 In article <6373@june.cs.washington.edu>, ka@june.cs.washington.edu (Kenneth Almquist) writes: > Dan Ts'o 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 */