diff options
Diffstat (limited to 'libc/termios/ttyname.c')
-rw-r--r-- | libc/termios/ttyname.c | 90 |
1 files changed, 60 insertions, 30 deletions
diff --git a/libc/termios/ttyname.c b/libc/termios/ttyname.c index 2aa009104..f7f066e61 100644 --- a/libc/termios/ttyname.c +++ b/libc/termios/ttyname.c @@ -4,39 +4,69 @@ #include <sys/stat.h> #include <dirent.h> +static char * __check_dir_for_tty_match(char * dirname, struct stat *st) +{ + DIR *fp; + struct stat dst; + struct dirent *d; + static char name[NAME_MAX]; + + fp = opendir(dirname); + if (fp == 0) + return 0; + strcpy(name, dirname); + strcat(name, "/"); + + while ((d = readdir(fp)) != 0) { + strcpy(name + sizeof(dirname), d->d_name); + if (stat(name, &dst) == 0 + && st->st_dev == dst.st_dev && st->st_ino == dst.st_ino) { + closedir(fp); + return name; + } + } + closedir(fp); + return NULL; +} + +/* 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; { - static char dev[] = "/dev"; - struct stat st, dst; - DIR *fp; - struct dirent *d; - static char name[NAME_MAX]; - int noerr = errno; - - if (fstat(fd, &st) < 0) - return 0; - if (!isatty(fd)) { - __set_errno(ENOTTY); - return 0; - } + char *the_name = NULL; + struct stat st; + int noerr = errno; - fp = opendir(dev); - if (fp == 0) - return 0; - strcpy(name, dev); - strcat(name, "/"); - - while ((d = readdir(fp)) != 0) { - strcpy(name + sizeof(dev), d->d_name); - if (stat(name, &dst) == 0 - && st.st_dev == dst.st_dev && st.st_ino == dst.st_ino) { - closedir(fp); - __set_errno(noerr); - return name; - } - } - closedir(fp); - __set_errno(noerr); + if (fstat(fd, &st) < 0) return 0; + + 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))) + goto cool_found_it; + + /* Lets try /dev/tts next (be devfs compatible) */ + if ( (the_name=__check_dir_for_tty_match("/dev/tts", &st))) + goto cool_found_it; + + /* Lets try /dev/pts next */ + if ( (the_name=__check_dir_for_tty_match("/dev/pts", &st))) + goto cool_found_it; + + /* Lets try walking through /dev last */ + if ( (the_name=__check_dir_for_tty_match("/dev", &st))) + goto cool_found_it; + +cool_found_it: + __set_errno(noerr); + return the_name; } |