summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-06-15 19:24:08 +0000
committerEric Andersen <andersen@codepoet.org>2002-06-15 19:24:08 +0000
commite01d0733f5fc7afcd609f9eee4071705610a1db5 (patch)
treea53d191bea9300b9cd2ef3f4b08114d4d4317c0f
parent3fa6fbe68b8b65bc7427b3686ba47c16767269f5 (diff)
Implement ttyname_r
-Erik
-rw-r--r--libc/termios/ttyname.c78
1 files changed, 50 insertions, 28 deletions
diff --git a/libc/termios/ttyname.c b/libc/termios/ttyname.c
index e6c28adc2..2be496366 100644
--- a/libc/termios/ttyname.c
+++ b/libc/termios/ttyname.c
@@ -4,69 +4,91 @@
#include <sys/stat.h>
#include <dirent.h>
-static char * __check_dir_for_tty_match(char * dirname, struct stat *st)
+static int __check_dir_for_tty_match(char * dirname, struct stat *st, char *buf, size_t buflen)
{
DIR *fp;
+ int len;
struct stat dst;
struct dirent *d;
- static char name[NAME_MAX];
fp = opendir(dirname);
- if (fp == 0)
- return 0;
- strcpy(name, dirname);
- strcat(name, "/");
+ if (fp == NULL)
+ return errno;
+ strncpy(buf, dirname, buflen);
+ strncat(buf, "/", buflen);
+ len = strlen(dirname) + 1;
while ((d = readdir(fp)) != 0) {
- strcpy(name + strlen(dirname) + 1, d->d_name);
- if (stat(name, &dst) == 0
- && st->st_dev == dst.st_dev && st->st_ino == dst.st_ino) {
+ strncpy(buf+len, d->d_name, buflen);
+ buf[buflen]='\0';
+ if (stat(buf, &dst) == 0 && st->st_dev == dst.st_dev
+ && st->st_ino == dst.st_ino)
+ {
closedir(fp);
- return name;
+ return 0;
}
}
closedir(fp);
- return NULL;
+ return ENOTTY;
+}
+
+/* This is a fairly slow approach. We do a linear search through some
+ * directories looking for a match. Yes this is lame. But it should
+ * work, should be small, and will return names that match what is on
+ * disk. Another approach we could use would be to use the info in
+ * /proc/self/fd, but that is even more lame since it requires /proc */
+
+char *ttyname(int fd)
+{
+ static char name[NAME_MAX];
+ ttyname_r(fd, name, NAME_MAX);
+ return(name);
}
-/* This is a failly slow approach. We do a linear search through
- * some directories looking for a match. Yes this is lame. But
- * it should work, should be small, and will return names that match
- * what is on disk.
- *
- * Another approach we could use would be to use the info in /proc/self/fd */
-char *ttyname(fd)
-int fd;
+int ttyname_r(int fd, char *buf, size_t buflen)
{
- char *the_name = NULL;
+ int noerr;
struct stat st;
- int noerr = errno;
+ noerr = errno;
+ if (!buf) {
+ noerr = EINVAL;
+ goto cool_found_it;
+ }
+ /* Make sure we have enough space to return "/dev/pts/0" */
+ if (buflen < 10) {
+ noerr = ERANGE;
+ goto cool_found_it;
+ }
+ if (!isatty (fd)) {
+ noerr = ENOTTY;
+ goto cool_found_it;
+ }
if (fstat(fd, &st) < 0)
- return 0;
-
+ return errno;
if (!isatty(fd)) {
noerr = ENOTTY;
goto cool_found_it;
}
/* Lets try /dev/vc first (be devfs compatible) */
- if ( (the_name=__check_dir_for_tty_match("/dev/vc", &st)))
+ if ( (noerr=__check_dir_for_tty_match("/dev/vc", &st, buf, buflen)))
goto cool_found_it;
/* Lets try /dev/tts next (be devfs compatible) */
- if ( (the_name=__check_dir_for_tty_match("/dev/tts", &st)))
+ if ( (noerr=__check_dir_for_tty_match("/dev/tts", &st, buf, buflen)))
goto cool_found_it;
/* Lets try /dev/pts next */
- if ( (the_name=__check_dir_for_tty_match("/dev/pts", &st)))
+ if ( (noerr=__check_dir_for_tty_match("/dev/pts", &st, buf, buflen)))
goto cool_found_it;
/* Lets try walking through /dev last */
- if ( (the_name=__check_dir_for_tty_match("/dev", &st)))
+ if ( (noerr=__check_dir_for_tty_match("/dev", &st, buf, buflen)))
goto cool_found_it;
cool_found_it:
__set_errno(noerr);
- return the_name;
+ return noerr;
}
+