From: Bruno Haible <bruno@clisp.org>
To: bug-gnulib@gnu.org
Subject: ttyname_r: Work around bug on Android 4.3
Date: Sat, 26 Jan 2019 15:28:23 +0100 [thread overview]
Message-ID: <3060189.LFMIQ8Pqr8@omega> (raw)
On Android 4.3, I'm seeing this test failure:
FAIL: test-ttyname_r
====================
int ttyname_r(int, char*, size_t)(3) is not implemented on Android
../../gltests/test-ttyname_r.c:45: assertion 'ttyname_r (fd, buf, 1) == ERANGE' failed
FAIL test-ttyname_r (exit status: 139)
The cause is that 'ttyname_r' (as well as 'ttyname') is just a stub on this
platform. This patch fixes it.
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.
diff --git a/doc/posix-functions/ttyname.texi b/doc/posix-functions/ttyname.texi
index df5c387..5b9ff5a 100644
--- a/doc/posix-functions/ttyname.texi
+++ b/doc/posix-functions/ttyname.texi
@@ -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
diff --git a/doc/posix-functions/ttyname_r.texi b/doc/posix-functions/ttyname_r.texi
index ea84242..ad108a6 100644
--- a/doc/posix-functions/ttyname_r.texi
+++ b/doc/posix-functions/ttyname_r.texi
@@ -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:
diff --git a/lib/ttyname_r.c b/lib/ttyname_r.c
index 67f559d..5d921ab 100644
--- a/lib/ttyname_r.c
+++ b/lib/ttyname_r.c
@@ -24,13 +24,41 @@
#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.
diff --git a/m4/ttyname_r.m4 b/m4/ttyname_r.m4
index b17dcfb..051de0c 100644
--- a/m4/ttyname_r.m4
+++ b/m4/ttyname_r.m4
@@ -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
])
reply other threads:[~2019-01-26 14:28 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3060189.LFMIQ8Pqr8@omega \
--to=bruno@clisp.org \
--cc=bug-gnulib@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).