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.bugs.sys5 mailing list