Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Mar 2004 15:21:31 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        "Jordan K. Hubbard" <jkh@queasyweasel.com>
Cc:        freebsd-arch@freebsd.org
Subject:   Re: Another conformance question...  This time fputs(). 
Message-ID:  <20040303150647.Y5253@gamplex.bde.org>
In-Reply-To: <E7470FE8-6C82-11D8-9000-000393BB9222@queasyweasel.com>
References:  <1060DC2A-6C31-11D8-9000-000393BB9222@queasyweasel.com> <E7470FE8-6C82-11D8-9000-000393BB9222@queasyweasel.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 2 Mar 2004, Jordan K. Hubbard wrote:

> It's also not clear to me why ENODEV is being returned, though I'm not
> as inclined to blame isatty() since it appears to do the right thing:
>
> #include <stdio.h>
> #include <fcntl.h>
> #include <errno.h>
>
> main() {
>          int fd, ret;
>
>          fd = open("/dev/null", O_RDONLY);
>          ret = isatty(fd);
>          printf("ret = %d, errno = %d\n", ret, errno);
>          close(fd);
> }
>
> Prints:	ret = 0, errno = 25

This is because someone fixed /dev/null but not /dev/zero (I misread
this in my previous reply).  They are implemented in the same file,
but only 1 has this bug.  From null.c:

%%%
static struct cdevsw null_cdevsw = {
	.d_version =	D_VERSION,
	.d_read =	(d_read_t *)nullop,
	.d_write =	null_write,
	.d_ioctl =	null_ioctl,
	.d_name =	"null",
	.d_maj =	CDEV_MAJOR,
};

static struct cdevsw zero_cdevsw = {
	.d_version =	D_VERSION,
	.d_read =	zero_read,
	.d_write =	null_write,
	.d_name =	"zero",
	.d_maj =	CDEV_MAJOR,
	.d_flags =	D_MMAP_ANON,
};
%%%

/dev/null has a special ioctl function "null_ioctl" which does the right
thing without having to do anything (the existence of an ioctl function
means that at least 1 ioctl is supported, so ENOTTY is correct for the
unsupported ones).

/dev/zero doesn't have any ioctl function, so it gets the default which
is enodev() (which just returns ENODEV).  This is almost correct --
ENODEV means that ioctls are completely unsupported, which is technically
correct.  However, it is surprising -- ENOTTY is the errno for most
types of files including regular ones.

> All isatty() does is call tcgetattr(), it doesn't do an
> ioctl(...TIOCGETA...).

Yes it does; see another reply.  (tcgetattr() is tcsetattr(3), not a
hypothetical tcsetattr(2) syscall.  It happens to be implemented using
an old ioctl.)

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040303150647.Y5253>