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>