OSDN Git Service

Implement ttyname_r
authorEric Andersen <andersen@codepoet.org>
Sat, 15 Jun 2002 19:24:08 +0000 (19:24 -0000)
committerEric Andersen <andersen@codepoet.org>
Sat, 15 Jun 2002 19:24:08 +0000 (19:24 -0000)
 -Erik

libc/termios/ttyname.c

index e6c28ad..2be4963 100644 (file)
@@ -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;
 }
+