#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, use it. */
+#if HAVE_TTYNAME_R
+ /* This code is multithread-safe. */
+ /* On Solaris, ttyname_r always fails if buflen < 128. So provide a buffer
+ that is large enough. */
+ char largerbuf[512];
+# if HAVE_POSIXDECL_TTYNAME_R
+ int err =
+ (buflen < sizeof (largerbuf)
+ ? ttyname_r (fd, largerbuf, sizeof (largerbuf))
+ : ttyname_r (fd, buf, buflen <= INT_MAX ? buflen : INT_MAX));
+ if (err != 0)
+ return err;
+ if (buflen < sizeof (largerbuf))
+ {
+ size_t namelen = strlen (largerbuf);
+ if (namelen > buflen)
+ return ERANGE;
+ memcpy (buf, largerbuf, namelen);
+ }
+# else
+ char *name =
+ (buflen < sizeof (largerbuf)
+ ? ttyname_r (fd, largerbuf, sizeof (largerbuf))
+ : 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);
+ }
+# endif
+ return 0;
+#elif HAVE_TTYNAME
/* Note: This is not multithread-safe. */
char *name;
size_t namelen;