]> Savannah Git Hosting - gnulib.git/commitdiff
ttyname_r: Work around bug on Android 4.3.
authorBruno Haible <bruno@clisp.org>
Sat, 26 Jan 2019 10:56:31 +0000 (11:56 +0100)
committerBruno Haible <bruno@clisp.org>
Sat, 26 Jan 2019 13:58:09 +0000 (14:58 +0100)
* m4/ttyname_r.m4 (gl_FUNC_TTYNAME_R): Test whether ttyname_r is a stub.
* lib/ttyname_r.c (ttyname_r): Implement for Android.
* doc/posix-functions/ttyname_r.texi: Mention the Android bug.
* doc/posix-functions/ttyname.texi: Likewise.

ChangeLog
doc/posix-functions/ttyname.texi
doc/posix-functions/ttyname_r.texi
lib/ttyname_r.c
m4/ttyname_r.m4

index 812b423895b4322db0a722dd3c134e19752c1dcd..44c15eb151942e27962b43b46b9e19812bddcb65 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2019-01-26  Bruno Haible  <bruno@clisp.org>
+
+       ttyname_r: Work around bug on Android 4.3.
+       * m4/ttyname_r.m4 (gl_FUNC_TTYNAME_R): Test whether ttyname_r is a stub.
+       * lib/ttyname_r.c (ttyname_r): Implement for Android.
+       * doc/posix-functions/ttyname_r.texi: Mention the Android bug.
+       * doc/posix-functions/ttyname.texi: Likewise.
+
 2019-01-25  Bruno Haible  <bruno@clisp.org>
 
        getprogname: Port to Android 4.3.
index df5c387ac477bdda72251f7ebcf4690b71a5497b..5b9ff5aee28db1306bb416894f333239555880b5 100644 (file)
@@ -15,4 +15,8 @@ Portability problems not fixed by Gnulib:
 @item
 This function is missing on some platforms:
 mingw, MSVC 14.
+@item
+This function is just a stub that produces an error message on standard error
+on some platforms:
+Android 4.3.
 @end itemize
index ea842423e19afb47a53042a21f117753f12aaccb..ad108a65b377af62a7176885968c0103f272f6b2 100644 (file)
@@ -26,6 +26,10 @@ OSF/1 5.1.
 This function refuses to do anything when the output buffer is less than 128
 bytes large, on some platforms:
 Solaris 11 2010-11.
+@item
+This function is just a stub that produces an error message on standard error
+on some platforms:
+Android 4.3.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 67f559d2e696cdba953ed4a9988fcf57a73057c1..5d921ab19bbe917f9e3a55acf53bce00adcefa05 100644 (file)
 #include <errno.h>
 #include <limits.h>
 #include <string.h>
+#if defined __ANDROID__
+# include <stdio.h>
+#endif
 
 int
 ttyname_r (int fd, char *buf, size_t buflen)
 #undef ttyname_r
 {
+#if defined __ANDROID__
+  /* On Android, read the result from the /proc file system.  */
+  if (!isatty (fd))
+    /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY).  */
+    return errno;
+  else if (buflen == 0)
+    return ERANGE;
+  else
+    {
+      char procfile[14+11+1];
+      char largerbuf[512];
+      ssize_t ret;
+      sprintf (procfile, "/proc/self/fd/%d", fd);
+      ret = (buflen < sizeof (largerbuf)
+             ? readlink (procfile, largerbuf, sizeof (largerbuf))
+             : readlink (procfile, buf, buflen <= INT_MAX ? buflen : INT_MAX));
+      if (ret < 0)
+        return errno;
+      if ((size_t) ret >= buflen)
+        return ERANGE;
+      if (buflen < sizeof (largerbuf))
+        memcpy (buf, largerbuf, (size_t) ret);
+      buf[(size_t) ret] = '\0';
+      return 0;
+    }
+#elif HAVE_TTYNAME_R
   /* When ttyname_r exists, use it.  */
-#if HAVE_TTYNAME_R
   /* This code is multithread-safe.  */
   /* On Solaris, ttyname_r always fails if buflen < 128.  On OSF/1 5.1,
      ttyname_r ignores the buffer size and assumes the buffer is large enough.
index b17dcfbe23d5f478d19c0b85998636af3c2b4930..051de0caa88d2d02f5cbe4a7c8aff38c5ce65a6d 100644 (file)
@@ -1,4 +1,4 @@
-# ttyname_r.m4 serial 9
+# ttyname_r.m4 serial 10
 dnl Copyright (C) 2010-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -45,24 +45,55 @@ AC_DEFUN([gl_FUNC_TTYNAME_R],
       dnl anything when the output buffer is less than 128 bytes large.
       dnl On OSF/1 5.1, ttyname_r ignores the buffer size and assumes the
       dnl buffer is large enough.
+      dnl On Android 4.3, ttyname_r is a stub that prints
+      dnl "int ttyname_r(int, char*, size_t)(3) is not implemented on Android"
+      dnl on stderr and returns -ERANGE.
       AC_REQUIRE([AC_CANONICAL_HOST])
-      AC_CACHE_CHECK([whether ttyname_r works with small buffers],
-        [gl_cv_func_ttyname_r_works],
-        [
-          dnl Initial guess, used when cross-compiling or when /dev/tty cannot
-          dnl be opened.
-changequote(,)dnl
-          case "$host_os" in
-                      # Guess no on Solaris.
-            solaris*) gl_cv_func_ttyname_r_works="guessing no" ;;
-                      # Guess no on OSF/1.
-            osf*)     gl_cv_func_ttyname_r_works="guessing no" ;;
-                      # Guess yes otherwise.
-            *)        gl_cv_func_ttyname_r_works="guessing yes" ;;
+      case "$host_os" in
+        linux*-android*)
+          AC_CACHE_CHECK([whether ttyname_r works at least minimally],
+            [gl_cv_func_ttyname_r_not_stub],
+            [AC_RUN_IFELSE(
+               [AC_LANG_SOURCE([[
+#include <errno.h>
+#include <unistd.h>
+int
+main (void)
+{
+  char buf[80];
+  close(2);
+  return ttyname_r (-1, buf, sizeof (buf)) == -ERANGE;
+}]])],
+               [gl_cv_func_ttyname_r_not_stub=yes],
+               [gl_cv_func_ttyname_r_not_stub=no],
+               [# Guess no on Android.
+                gl_cv_func_ttyname_r_not_stub="guessing no"
+               ])
+            ])
+          case "$gl_cv_func_ttyname_r_not_stub" in
+            *yes) ;;
+            *) REPLACE_TTYNAME_R=1 ;;
           esac
+          ;;
+      esac
+      if test $REPLACE_TTYNAME_R = 0; then
+        AC_CACHE_CHECK([whether ttyname_r works with small buffers],
+          [gl_cv_func_ttyname_r_works],
+          [
+            dnl Initial guess, used when cross-compiling or when /dev/tty cannot
+            dnl be opened.
+changequote(,)dnl
+            case "$host_os" in
+                        # Guess no on Solaris.
+              solaris*) gl_cv_func_ttyname_r_works="guessing no" ;;
+                        # Guess no on OSF/1.
+              osf*)     gl_cv_func_ttyname_r_works="guessing no" ;;
+                        # Guess yes otherwise.
+              *)        gl_cv_func_ttyname_r_works="guessing yes" ;;
+            esac
 changequote([,])dnl
-          AC_RUN_IFELSE(
-            [AC_LANG_SOURCE([[
+            AC_RUN_IFELSE(
+              [AC_LANG_SOURCE([[
 #include <fcntl.h>
 #include <unistd.h>
 int
@@ -81,16 +112,17 @@ main (void)
     result |= 18;
   return result;
 }]])],
-            [gl_cv_func_ttyname_r_works=yes],
-            [case $? in
-               17 | 18) gl_cv_func_ttyname_r_works=no ;;
-             esac],
-            [:])
-        ])
-      case "$gl_cv_func_ttyname_r_works" in
-        *yes) ;;
-        *) REPLACE_TTYNAME_R=1 ;;
-      esac
+              [gl_cv_func_ttyname_r_works=yes],
+              [case $? in
+                 17 | 18) gl_cv_func_ttyname_r_works=no ;;
+               esac],
+              [:])
+          ])
+        case "$gl_cv_func_ttyname_r_works" in
+          *yes) ;;
+          *) REPLACE_TTYNAME_R=1 ;;
+        esac
+      fi
     fi
   fi
 ])