summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/ttyname.c
diff options
context:
space:
mode:
authord <d@openbsd.org>1998-11-20 11:18:22 +0000
committerd <d@openbsd.org>1998-11-20 11:18:22 +0000
commit92efb7350713770eeac379dc990eaecbee107aa1 (patch)
tree9e7a54e9f5f807b6269323fc5be9480298ad6de5 /lib/libc/gen/ttyname.c
parentMove atomic_lock code from asm to C with inline asm; (diff)
downloadwireguard-openbsd-92efb7350713770eeac379dc990eaecbee107aa1.tar.xz
wireguard-openbsd-92efb7350713770eeac379dc990eaecbee107aa1.zip
Add thread-safety to libc, so that libc_r will build (on i386 at least).
All POSIX libc api now there (to P1003.1c/D10) (more md stuff is needed for other libc/arch/*) (setlogin is no longer a special syscall) Add -pthread option to gcc (that makes it use -lc_r and -D_POSIX_THREADS). Doc some re-entrant routines Add libc_r to intro(3) dig() uses some libc srcs and an extra -I was needed there. Add more md stuff to libc_r. Update includes for the pthreads api Update libc_r TODO
Diffstat (limited to 'lib/libc/gen/ttyname.c')
-rw-r--r--lib/libc/gen/ttyname.c78
1 files changed, 64 insertions, 14 deletions
diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c
index 192072a208f..a18b68fdd2c 100644
--- a/lib/libc/gen/ttyname.c
+++ b/lib/libc/gen/ttyname.c
@@ -32,7 +32,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: ttyname.c,v 1.5 1998/08/27 06:42:16 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: ttyname.c,v 1.6 1998/11/20 11:18:40 d Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -44,13 +44,49 @@ static char rcsid[] = "$OpenBSD: ttyname.c,v 1.5 1998/08/27 06:42:16 deraadt Exp
#include <string.h>
#include <unistd.h>
#include <paths.h>
+#include <limits.h>
+#include <errno.h>
+#include "thread_private.h"
-static char buf[sizeof(_PATH_DEV) + MAXNAMLEN];
-static char *oldttyname __P((int, struct stat *));
+static char buf[TTY_NAME_MAX];
+static int oldttyname __P((int, struct stat *, char *, size_t));
+static int __ttyname_r_basic __P((int, char *, size_t));
+
+int
+ttyname_r(int fd, char *buf, size_t buflen)
+{
+ int ret;
+
+ if ((ret = _FD_LOCK(fd, FD_READ, NULL)) == 0) {
+ ret = __ttyname_r_basic(fd, buf, buflen);
+ _FD_UNLOCK(fd, FD_READ);
+ }
+ return ret;
+}
char *
-ttyname(fd)
+ttyname(int fd)
+{
+ _THREAD_PRIVATE_KEY(ttyname)
+ char * bufp = (char*) _THREAD_PRIVATE(ttyname, buf, NULL);
+ int err;
+
+ if (bufp == NULL)
+ return NULL;
+ err = ttyname_r(fd, bufp, sizeof buf);
+ if (err) {
+ errno = err;
+ return NULL;
+ }
+ else
+ return bufp;
+}
+
+static int
+__ttyname_r_basic(fd, buf, len)
int fd;
+ char *buf;
+ size_t len;
{
struct stat sb;
struct termios ttyb;
@@ -63,10 +99,14 @@ ttyname(fd)
/* Must be a terminal. */
if (tcgetattr(fd, &ttyb) < 0)
- return (NULL);
+ return (errno);
/* Must be a character device. */
- if (fstat(fd, &sb) || !S_ISCHR(sb.st_mode))
- return (NULL);
+ if (fstat(fd, &sb))
+ return (errno);
+ if (!S_ISCHR(sb.st_mode))
+ return (ENOTTY);
+ if (len < sizeof(_PATH_DEV))
+ return (ERANGE);
memcpy(buf, _PATH_DEV, sizeof(_PATH_DEV));
@@ -77,40 +117,50 @@ ttyname(fd)
key.data = &bkey;
key.size = sizeof(bkey);
if (!(db->get)(db, &key, &data, 0)) {
+ if (data.size > len - (sizeof(_PATH_DEV) - 1)) {
+ (void)(db->close)(db);
+ return (ERANGE);
+ }
memcpy(buf + sizeof(_PATH_DEV) - 1, data.data,
data.size);
(void)(db->close)(db);
- return (buf);
+ return (0);
}
(void)(db->close)(db);
}
- return (oldttyname(fd, &sb));
+ return (oldttyname(fd, &sb, buf, len));
}
/* ARGSUSED */
-static char *
-oldttyname(fd, sb)
+static int
+oldttyname(fd, sb, buf, len)
int fd;
struct stat *sb;
+ char *buf;
+ size_t len;
{
register struct dirent *dirp;
register DIR *dp;
struct stat dsb;
if ((dp = opendir(_PATH_DEV)) == NULL)
- return (NULL);
+ return (errno);
while ((dirp = readdir(dp))) {
if (dirp->d_fileno != sb->st_ino)
continue;
+ if (dirp->d_namlen > len - sizeof(_PATH_DEV)) {
+ (void)closedir(dp);
+ return (ERANGE);
+ }
memcpy(buf + sizeof(_PATH_DEV) - 1, dirp->d_name,
dirp->d_namlen + 1);
if (stat(buf, &dsb) || sb->st_dev != dsb.st_dev ||
sb->st_ino != dsb.st_ino)
continue;
(void)closedir(dp);
- return (buf);
+ return (0);
}
(void)closedir(dp);
- return (NULL);
+ return (ENOTTY);
}