Loading...
stdlib/grantpt.c Libc-498 Libc-1583.0.14
--- Libc/Libc-498/stdlib/grantpt.c
+++ Libc/Libc-1583.0.14/stdlib/grantpt.c
@@ -21,7 +21,11 @@
  * @APPLE_LICENSE_HEADER_END@
  */
 
+#include <os/assumes.h>
+#include <os/once_private.h>
+#include <pthread.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -44,13 +48,26 @@
 /*
  * grantpt call for cloning pty implementation.
  *
- * Change UID and GID of slave pty associated with master pty whose
+ * Change UID and GID of replica pty associated with primary pty whose
  * fd is provided, to the real UID and real GID of the calling thread.
  */
 int
 grantpt(int fd)
 {
 	return ioctl(fd, TIOCPTYGRANT);
+}
+
+// defined by TIOCPTYGNAME
+#define PTSNAME_MAX_SIZE 128
+
+static pthread_key_t ptsname_buffer_specific_key;
+static os_once_t ptsname_once;
+
+static void
+ptsname_once_init(void *ctx __unused)
+{
+	int ret = pthread_key_create(&ptsname_buffer_specific_key, free);
+	os_assert_zero(ret);
 }
 
 /*
@@ -62,30 +79,65 @@
 char *
 ptsname(int fd)
 {
-	static char ptsnamebuf[ 128];	/* ioctl knows length */
+	os_once(&ptsname_once, NULL, ptsname_once_init);
+	char *ptsnamebuf = pthread_getspecific(ptsname_buffer_specific_key);
+
+	if (ptsnamebuf == NULL) {
+		ptsnamebuf = malloc(PTSNAME_MAX_SIZE);
+		os_assert(ptsnamebuf);
+
+		int error = pthread_setspecific(ptsname_buffer_specific_key, ptsnamebuf);
+		os_assert_zero(error);
+	}
+
+	int error = ptsname_r(fd, ptsnamebuf, PTSNAME_MAX_SIZE);
+
+	return error ? NULL : ptsnamebuf;
+}
+
+int
+ptsname_r(int fd, char *buffer, size_t buflen)
+{
 	int error;
-	char *retval = NULL;
 	struct stat sbuf;
+	char ptsnamebuf[PTSNAME_MAX_SIZE];
+
+	if (!buffer) {
+		errno = EINVAL;
+		return -1;
+	}
 
 	error = ioctl(fd, TIOCPTYGNAME, ptsnamebuf);
-	if (!error) {
-		/*
-		 * XXX TSD
-		 *
-		 * POSIX: Handle device rename test case, which is expected
-		 * to fail if the pty has been renamed.
-		 */
-		if (stat(ptsnamebuf, &sbuf) == 0)
-			retval = ptsnamebuf;
+	if (error) {
+		return -1;
 	}
 
-	return (retval);
+	/*
+	 * XXX TSD
+	 *
+	 * POSIX: Handle device rename test case, which is expected
+	 * to fail if the pty has been renamed.
+	 */
+	error = stat(ptsnamebuf, &sbuf);
+	if (error) {
+		return -1;
+	}
+
+	size_t len = strlen(ptsnamebuf) + 1;
+	if (buflen < len) {
+		errno = ERANGE;
+		return -1;
+	}
+
+	memcpy(buffer, ptsnamebuf, len);
+
+	return 0;
 }
 
 /*
  * unlockpt call for cloning pty implementation.
  *
- * Unlock the slave pty associated with the master to which fd refers.
+ * Unlock the replica pty associated with the primary to which fd refers.
  */
 int
 unlockpt(int fd)