summaryrefslogtreecommitdiff
path: root/lib/ttyname_r.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2019-01-26 11:56:31 +0100
committerBruno Haible <bruno@clisp.org>2019-01-26 14:58:09 +0100
commit0c4342cb67e62f981c654c5fa830bd76cc3bd68f (patch)
tree087ed063eb917af15390f87d953e1e2872466e4f /lib/ttyname_r.c
parent3324e9ccfc3b8369ba857884c398b251e3d2da41 (diff)
downloadgnulib-0c4342cb67e62f981c654c5fa830bd76cc3bd68f.tar.gz
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.
Diffstat (limited to 'lib/ttyname_r.c')
-rw-r--r--lib/ttyname_r.c30
1 files changed, 29 insertions, 1 deletions
diff --git a/lib/ttyname_r.c b/lib/ttyname_r.c
index 67f559d2e6..5d921ab19b 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.