diff options
author | Bruno Haible <bruno@clisp.org> | 2019-01-26 11:56:31 +0100 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2019-01-26 14:58:09 +0100 |
commit | 0c4342cb67e62f981c654c5fa830bd76cc3bd68f (patch) | |
tree | 087ed063eb917af15390f87d953e1e2872466e4f /lib/ttyname_r.c | |
parent | 3324e9ccfc3b8369ba857884c398b251e3d2da41 (diff) | |
download | gnulib-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.c | 30 |
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. |