Bug 191931 - ttyname(3): incorrect description of [EBADF] and [ENOTTY] errors in manual page
Summary: ttyname(3): incorrect description of [EBADF] and [ENOTTY] errors in manual page
Status: Closed FIXED
Alias: None
Product: Documentation
Classification: Unclassified
Component: Books & Articles (show other bugs)
Version: Latest
Hardware: Any Any
: --- Affects Some People
Assignee: Jilles Tjoelker
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-17 20:21 UTC by Enji Cooper
Modified: 2015-02-08 22:31 UTC (History)
1 user (show)

See Also:
jilles: mfc-stable10+
jilles: mfc-stable9-
jilles: mfc-stable8-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Enji Cooper freebsd_committer freebsd_triage 2014-07-17 20:21:16 UTC
The manpage for isatty/ttyname_r on FreeBSD and the OpenGroup site says that isatty/ttyname_r should return false/-1 and set ENOTTY if the file descriptor provided is invalid. The problem is that the glue code in libc doesn't convert the errno retrieved from tcgetattr properly in lib/libc/gen/isatty.c (which subsequently gets used in lib/libc/gen/ttyname.c), so the errno raised is actually EBADF. This issue was found by the NetBSD libc ATF testcases.

Example:

% cat /root/test_isatty_negative_one.c
#include <assert.h>
#include <errno.h>
#include <unistd.h>

int
main(void)
{

        assert(!isatty(-1));
        assert(errno == ENOTTY);

        return (0);
}
% /root/test_isatty_negative_one
Assertion failed: (errno == ENOTTY), function main, file /root/test_isatty_negative_one.c, line 10.
Abort trap (core dumped)
[root@freebsd-10-x64 /scratch/tools]# truss /root/test_isatty_negative_one
mmap(0x0,32768,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34366140416 (0x80061b000)
issetugid(0x80081b240,0x7fffffffefc1,0x40,0x0,0xffff80080081c27f,0x0) = 0 (0x0)
lstat("/etc",{ mode=drwxr-xr-x ,inode=3129984,size=2560,blksize=32768 }) = 0 (0x0)
lstat("/etc/libmap.conf",{ mode=-rw-r--r-- ,inode=3130403,size=47,blksize=32768 }) = 0 (0x0)
open("/etc/libmap.conf",O_CLOEXEC,01760)         = 3 (0x3)
fstat(3,{ mode=-rw-r--r-- ,inode=3130403,size=47,blksize=32768 }) = 0 (0x0)
mmap(0x0,47,PROT_READ,MAP_PRIVATE,3,0x0)         = 34366173184 (0x800623000)
close(3)                                         = 0 (0x0)
lstat("/usr",{ mode=drwxr-xr-x ,inode=1364352,size=512,blksize=32768 }) = 0 (0x0)
lstat("/usr/local",{ mode=drwxr-xr-x ,inode=1364363,size=512,blksize=32768 }) = 0 (0x0)
lstat("/usr/local/etc",{ mode=drwxr-xr-x ,inode=1453098,size=512,blksize=32768 }) = 0 (0x0)
lstat("/usr/local/etc/libmap.d",0x7fffffffc738)  ERR#2 'No such file or directory'
munmap(0x800623000,47)                           = 0 (0x0)
open("/var/run/ld-elf.so.hints",O_CLOEXEC,030360000) = 3 (0x3)
read(3,"Ehnt\^A\0\0\0\M^@\0\0\0j\0\0\0\0"...,128) = 128 (0x80)
lseek(3,0x80,SEEK_SET)                           = 128 (0x80)
read(3,"/lib:/usr/lib:/usr/lib/compat:/u"...,106) = 106 (0x6a)
close(3)                                         = 0 (0x0)
access("/lib/libc.so.7",0)                       = 0 (0x0)
open("/lib/libc.so.7",O_CLOEXEC,030373770)       = 3 (0x3)
fstat(3,{ mode=-r--r--r-- ,inode=722308,size=1486376,blksize=32768 }) = 0 (0x0)
mmap(0x0,4096,PROT_READ,MAP_PRIVATE|MAP_PREFAULT_READ,3,0x0) = 34366173184 (0x800623000)
mmap(0x0,3751936,PROT_NONE,MAP_PRIVATE|MAP_ANON|MAP_NOCORE,-1,0x0) = 34368241664 (0x80081c000)
mmap(0x80081c000,1441792,PROT_READ|PROT_EXEC,MAP_PRIVATE|MAP_FIXED|MAP_NOCORE|MAP_PREFAULT_READ,3,0x0) = 34368241664 (0x80081c000)
mmap(0x800b7c000,45056,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED|MAP_PREFAULT_READ,3,0x160000) = 34371780608 (0x800b7c000)
mmap(0x800b87000,167936,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED|MAP_ANON,-1,0x0) = 34371825664 (0x800b87000)
munmap(0x800623000,4096)                         = 0 (0x0)
close(3)                                         = 0 (0x0)
munmap(0x800622000,4096)                         = 0 (0x0)
mmap(0x0,102400,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34366169088 (0x800622000)
sysarch(0x81,0x7fffffffe118,0x4,0x0,0xffffffffffab8090,0x8080808080808080) = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)                 = 0 (0x0)
readlink("/etc/malloc.conf",0x7fffffffd840,1024) ERR#2 'No such file or directory'
issetugid(0x800955e3e,0x7fffffffd840,0xffffffffffffffff,0x2,0x39,0xffffffff0fffffff) = 0 (0x0)
mmap(0x0,4194304,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34371993600 (0x800bb0000)
munmap(0x800bb0000,4194304)                      = 0 (0x0)
mmap(0x0,8384512,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34371993600 (0x800bb0000)
munmap(0x800bb0000,327680)                       = 0 (0x0)
munmap(0x801000000,3862528)                      = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)                 = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)                 = 0 (0x0)
ioctl(-1,TIOCGETA,0xffffead0)                    ERR#9 'Bad file descriptor'
Assertion failed: (errno == ENOTTY), function main, file /root/test_isatty_negative_one.c, line 10.
write(2,"Assertion failed: (errno == ENOT"...,100) = 100 (0x64)
sigprocmask(SIG_SETMASK,SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGEMT|SIGFPE|SIGKILL|SIGBUS|SIGSEGV|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
getpid()                                         = 92137 (0x167e9)
kill(92137,SIGABRT)                              = 0 (0x0)
SIGNAL 6 (SIGABRT)
process exit, rval = 0
Comment 1 Jilles Tjoelker freebsd_committer freebsd_triage 2014-07-17 20:47:06 UTC
This looks like a bug in the standard that was fixed for POSIX.1-2008/SUSv4, which has the expected [EBADF] (invalid file descriptor) and [ENOTTY] (not a terminal) error conditions. According to the change history, the erratum is SD5-XSH-ERN-100.
Comment 2 Enji Cooper freebsd_committer freebsd_triage 2014-07-17 21:05:55 UTC
(Moving over to documentation)

The manpage on FreeBSD needs to be fixed then. I'll take care of filing the bug on NetBSD for the testcase.
Comment 3 commit-hook freebsd_committer freebsd_triage 2014-07-18 21:30:50 UTC
A commit references this bug:

Author: jilles
Date: Fri Jul 18 21:29:59 UTC 2014
New revision: 268857
URL: http://svnweb.freebsd.org/changeset/base/268857

Log:
  ttyname(3): Fix EBADF/ENOTTY error descriptions.

  Also, make sure to document the return values and errors for all three
  functions in the man page.

  PR:		191931
  MFC after:	1 week

Changes:
  head/lib/libc/gen/ttyname.3
Comment 4 Jilles Tjoelker freebsd_committer freebsd_triage 2014-10-29 21:23:13 UTC
Convert to new MFC flags.
Comment 5 commit-hook freebsd_committer freebsd_triage 2015-02-08 22:29:55 UTC
A commit references this bug:

Author: jilles
Date: Sun Feb  8 22:29:07 UTC 2015
New revision: 278417
URL: https://svnweb.freebsd.org/changeset/base/278417

Log:
  MFC r268857: ttyname(3): Fix EBADF/ENOTTY error descriptions.

  Also, make sure to document the return values and errors for all three
  functions in the man page.

  PR:		191931

Changes:
_U  stable/10/
  stable/10/lib/libc/gen/ttyname.3