changeset 13266:ddd7bebf854c

ttyname_r: Make it work on MacOS X 10.4 and Solaris 10.
author Bruno Haible <bruno@clisp.org>
date Sun, 25 Apr 2010 20:57:52 +0200
parents d12a380d8ac1
children d6ab91053834
files ChangeLog doc/posix-functions/ttyname_r.texi lib/ttyname_r.c lib/unistd.in.h m4/ttyname_r.m4 m4/unistd_h.m4 modules/unistd
diffstat 7 files changed, 72 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+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.
--- a/doc/posix-functions/ttyname_r.texi
+++ b/doc/posix-functions/ttyname_r.texi
@@ -11,11 +11,11 @@
 @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
--- 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;
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -1164,12 +1164,23 @@
 #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
--- 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_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
--- 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 @@
   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])
--- a/modules/unistd
+++ b/modules/unistd
@@ -118,6 +118,7 @@
 	      -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' \