POSIX does not require ptsname() to set errno on failure, and FreeBSD 8.2 leaves it unchanged.
* lib/ptsname_r.c (ptsname_r): Guarantee errno on ptsname failure. * doc/posix-functions/ptsname.texi (ptsname): Document the issue. Signed-off-by: Eric Blake <ebl...@redhat.com> --- ChangeLog | 4 ++++ doc/posix-functions/ptsname.texi | 3 +++ lib/ptsname_r.c | 14 +++++++++++++- 3 files changed, 20 insertions(+), 1 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70172b4..d7326ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2011-11-07 Eric Blake <ebl...@redhat.com> + ptsname_r: work around FreeBSD issue + * lib/ptsname_r.c (ptsname_r): Guarantee errno on ptsname failure. + * doc/posix-functions/ptsname.texi (ptsname): Document the issue. + ptsname_r: port to Solaris * m4/ptsname_r.m4 (gl_FUNC_PTSNAME_R): Also check for ptsname. * m4/ptsname.m4 (gl_FUNC_PTSNAME): Optimize check. diff --git a/doc/posix-functions/ptsname.texi b/doc/posix-functions/ptsname.texi index 2584af8..3ad5fc1 100644 --- a/doc/posix-functions/ptsname.texi +++ b/doc/posix-functions/ptsname.texi @@ -25,6 +25,9 @@ ptsname This function is not thread-safe on some platforms: Cygwin 1.7.9. Likewise, the gnulib replacement is not thread-safe. +@item +As allowed by POSIX, this function does not set errno on some platforms: +FreeBSD 8.2. @end itemize Note that the Gnulib module @code{ptsname_r} is a version of this diff --git a/lib/ptsname_r.c b/lib/ptsname_r.c index e200f34..c4b1c69 100644 --- a/lib/ptsname_r.c +++ b/lib/ptsname_r.c @@ -23,6 +23,8 @@ #if HAVE_PTSNAME +# include <fcntl.h> + /* Store at most BUFLEN characters of the pathname of the slave pseudo terminal associated with the master FD is open on in BUF. Return 0 on success, otherwise an error number. */ @@ -31,15 +33,25 @@ ptsname_r (int fd, char *buf, size_t buflen) { /* This assumes nothing else directly calls ptsname(). */ char *name; + int saved_errno = errno; if (!buf) return errno = EINVAL; + + /* Work around FreeBSD 8.2 ptsname(-1) that fails to set errno. */ + saved_errno = errno; + errno = 0; name = ptsname (fd); if (!name) - return errno; + { + if (!errno && fcntl (fd, F_GETFL) >= 0) + errno = ENOTTY; + return errno; + } if (buflen <= strlen (name)) return errno = ERANGE; strcpy (buf, name); + errno = saved_errno; return 0; } -- 1.7.4.4