summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--doc/posix-functions/ttyname_r.texi6
-rw-r--r--lib/ttyname_r.c20
-rw-r--r--lib/unistd.in.h15
-rw-r--r--m4/ttyname_r.m420
-rw-r--r--m4/unistd_h.m43
-rw-r--r--modules/unistd1
7 files changed, 72 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 1571c78951..2726d7b12b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
2010-04-25 Bruno Haible <bruno@clisp.org>
+ ttyname_r: Make it work on MacOS X 10.4 and Solaris 10.
+ * m4/ttyname_r.m4 (gl_FUNC_TTYNAME_R): Test whether the system function
+ has the POSIX declaration. Set REPLACE_TTYNAME_R if not.
+ * lib/ttyname_r.c: Include <limits.h>.
+ (ttyname_r): Define using the system's ttyname_r function, if it exists
+ and not on Solaris.
+ * lib/unistd.in.h (ttyname_r): Replace function if REPLACE_TTYNAME_R is
+ set.
+ * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Initialize REPLACE_TTYNAME_R.
+ * modules/unistd (Makefile.am): Substitute REPLACE_TTYNAME_R.
+ * doc/posix-functions/ttyname_r.texi: Mark the problem as fixed.
+ Reported by Simon Josefsson.
+
+2010-04-25 Bruno Haible <bruno@clisp.org>
+
Mention effects of _POSIX_PTHREAD_SEMANTICS on Solaris.
* doc/posix-functions/asctime_r.texi: Mention the Solaris problem.
* doc/posix-functions/ctime_r.texi: Likewise.
diff --git a/doc/posix-functions/ttyname_r.texi b/doc/posix-functions/ttyname_r.texi
index ab1d186cad..4780390e2e 100644
--- a/doc/posix-functions/ttyname_r.texi
+++ b/doc/posix-functions/ttyname_r.texi
@@ -11,11 +11,11 @@ Portability problems fixed by Gnulib:
@item
This function is missing on some platforms:
NetBSD 3.0, mingw, BeOS.
+@item
+This function has an incompatible declaration on some platforms:
+MacOS X 10.4, Solaris 10 (when @code{_POSIX_PTHREAD_SEMANTICS} is not defined).
@end itemize
Portability problems not fixed by Gnulib:
@itemize
-@item
-This function has an incompatible declaration on some platforms:
-MacOS X 10.4, Solaris 10 (when @code{_POSIX_PTHREAD_SEMANTICS} is not defined).
@end itemize
diff --git a/lib/ttyname_r.c b/lib/ttyname_r.c
index dc8b923f1b..d3e58eb21d 100644
--- a/lib/ttyname_r.c
+++ b/lib/ttyname_r.c
@@ -22,12 +22,30 @@
#include <unistd.h>
#include <errno.h>
+#include <limits.h>
#include <string.h>
int
ttyname_r (int fd, char *buf, size_t buflen)
+#undef ttyname_r
{
-#if HAVE_TTYNAME
+ /* When ttyname_r exists and works, use it.
+ But on Solaris 10, ttyname_r is broken: it returns NULL in situations
+ when ttyname finds the result. */
+#if HAVE_TTYNAME_R && !defined __sun
+ /* This code is multithread-safe. */
+ char *name = ttyname_r (fd, buf, buflen <= INT_MAX ? buflen : INT_MAX);
+ if (name == NULL)
+ return errno;
+ if (name != buf)
+ {
+ size_t namelen = strlen (name) + 1;
+ if (namelen > buflen)
+ return ERANGE;
+ memmove (buf, name, namelen);
+ }
+ return 0;
+#elif HAVE_TTYNAME
/* Note: This is not multithread-safe. */
char *name;
size_t namelen;
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 7302d6d3e1..b1f07434ff 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -1164,12 +1164,23 @@ _GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - "
#if @GNULIB_TTYNAME_R@
/* Store at most BUFLEN characters of the pathname of the terminal FD is
open on in BUF. Return 0 on success, otherwise an error number. */
-# if !@HAVE_TTYNAME_R@
+# if @REPLACE_TTYNAME_R@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef ttyname_r
+# define ttyname_r rpl_ttyname_r
+# endif
+_GL_FUNCDECL_RPL (ttyname_r, int,
+ (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (ttyname_r, int,
+ (int fd, char *buf, size_t buflen));
+# else
+# if !@HAVE_TTYNAME_R@
_GL_FUNCDECL_SYS (ttyname_r, int,
(int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2)));
-# endif
+# endif
_GL_CXXALIAS_SYS (ttyname_r, int,
(int fd, char *buf, size_t buflen));
+# endif
_GL_CXXALIASWARN (ttyname_r);
#elif defined GNULIB_POSIXCHECK
# undef ttyname_r
diff --git a/m4/ttyname_r.m4 b/m4/ttyname_r.m4
index 54a8676888..ce4737498d 100644
--- a/m4/ttyname_r.m4
+++ b/m4/ttyname_r.m4
@@ -1,4 +1,4 @@
-# ttyname_r.m4 serial 1
+# ttyname_r.m4 serial 2
dnl Copyright (C) 2010 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -11,6 +11,24 @@ AC_DEFUN([gl_FUNC_TTYNAME_R],
AC_CHECK_FUNCS([ttyname_r])
if test $ac_cv_func_ttyname_r = no; then
HAVE_TTYNAME_R=0
+ else
+ dnl On MacOS X 10.4 and Solaris 10 the return type is 'char *', not 'int'.
+ AC_CACHE_CHECK([whether ttyname_r is compatible with its POSIX signature],
+ [gl_cv_func_ttyname_r_posix],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <stddef.h>
+ #include <unistd.h>]],
+ [[*ttyname_r (0, NULL, 0);]])
+ ],
+ [gl_cv_func_ttyname_r_posix=no],
+ [gl_cv_func_ttyname_r_posix=yes])
+ ])
+ if test $gl_cv_func_ttyname_r_posix = no; then
+ REPLACE_TTYNAME_R=1
+ fi
+ fi
+ if test $HAVE_TTYNAME_R = 0 || test $REPLACE_TTYNAME_R = 1; then
AC_LIBOBJ([ttyname_r])
gl_PREREQ_TTYNAME_R
fi
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index 8c2eec64a6..b26d0a92ac 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 45
+# unistd_h.m4 serial 46
dnl Copyright (C) 2006-2010 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -144,6 +144,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
REPLACE_RMDIR=0; AC_SUBST([REPLACE_RMDIR])
REPLACE_SLEEP=0; AC_SUBST([REPLACE_SLEEP])
REPLACE_SYMLINK=0; AC_SUBST([REPLACE_SYMLINK])
+ REPLACE_TTYNAME_R=0; AC_SUBST([REPLACE_TTYNAME_R])
REPLACE_UNLINK=0; AC_SUBST([REPLACE_UNLINK])
REPLACE_UNLINKAT=0; AC_SUBST([REPLACE_UNLINKAT])
REPLACE_USLEEP=0; AC_SUBST([REPLACE_USLEEP])
diff --git a/modules/unistd b/modules/unistd
index 86c6b41f29..9ab6835f71 100644
--- a/modules/unistd
+++ b/modules/unistd
@@ -118,6 +118,7 @@ unistd.h: unistd.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
-e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \
-e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \
-e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \
+ -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \
-e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \
-e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \
-e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \