ttyname.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #include <errno.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <sys/stat.h>
  5. #include <dirent.h>
  6. static int __check_dir_for_tty_match(char * dirname, struct stat *st, char *buf, size_t buflen)
  7. {
  8. DIR *fp;
  9. int len;
  10. struct stat dst;
  11. struct dirent *d;
  12. fp = opendir(dirname);
  13. if (fp == NULL)
  14. return errno;
  15. strncpy(buf, dirname, buflen);
  16. strncat(buf, "/", buflen);
  17. len = strlen(dirname) + 1;
  18. while ((d = readdir(fp)) != 0) {
  19. strncpy(buf+len, d->d_name, buflen);
  20. buf[buflen]='\0';
  21. #if 0
  22. /* Stupid filesystems like cramfs fail to guarantee that
  23. * st_ino and st_dev uniquely identify a file, contrary to
  24. * SuSv3, so we cannot be quite so precise as to require an
  25. * exact match. Settle for something less... Grumble... */
  26. if (lstat(buf, &dst) == 0 &&
  27. st->st_dev == dst.st_dev && st->st_ino == dst.st_ino)
  28. #else
  29. if (lstat(buf, &dst) == 0 &&
  30. S_ISCHR(dst.st_mode) && st->st_rdev == dst.st_rdev)
  31. #endif
  32. {
  33. closedir(fp);
  34. return 0;
  35. }
  36. }
  37. closedir(fp);
  38. return ENOTTY;
  39. }
  40. /* This is a fairly slow approach. We do a linear search through some
  41. * directories looking for a match. Yes this is lame. But it should
  42. * work, should be small, and will return names that match what is on
  43. * disk. Another approach we could use would be to use the info in
  44. * /proc/self/fd, but that is even more lame since it requires /proc */
  45. char *ttyname(int fd)
  46. {
  47. static char name[NAME_MAX];
  48. ttyname_r(fd, name, NAME_MAX);
  49. return(name);
  50. }
  51. int ttyname_r(int fd, char *buf, size_t buflen)
  52. {
  53. int noerr;
  54. struct stat st;
  55. noerr = errno;
  56. if (buf==NULL) {
  57. noerr = EINVAL;
  58. goto cool_found_it;
  59. }
  60. /* Make sure we have enough space to return "/dev/pts/0" */
  61. if (buflen < 10) {
  62. noerr = ERANGE;
  63. goto cool_found_it;
  64. }
  65. if (!isatty (fd)) {
  66. noerr = ENOTTY;
  67. goto cool_found_it;
  68. }
  69. if (fstat(fd, &st) < 0)
  70. return errno;
  71. if (!isatty(fd)) {
  72. noerr = ENOTTY;
  73. goto cool_found_it;
  74. }
  75. /* Lets try /dev/vc first (be devfs compatible) */
  76. if ( (noerr=__check_dir_for_tty_match("/dev/vc", &st, buf, buflen)) == 0)
  77. goto cool_found_it;
  78. /* Lets try /dev/tts next (be devfs compatible) */
  79. if ( (noerr=__check_dir_for_tty_match("/dev/tts", &st, buf, buflen)) == 0)
  80. goto cool_found_it;
  81. /* Lets try /dev/pts next */
  82. if ( (noerr=__check_dir_for_tty_match("/dev/pts", &st, buf, buflen)) == 0)
  83. goto cool_found_it;
  84. /* Lets try walking through /dev last */
  85. if ( (noerr=__check_dir_for_tty_match("/dev", &st, buf, buflen)) == 0)
  86. goto cool_found_it;
  87. cool_found_it:
  88. __set_errno(noerr);
  89. return noerr;
  90. }