ttyname.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* Copyright (C) 1991-2019 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <http://www.gnu.org/licenses/>. */
  14. #include <errno.h>
  15. #include <limits.h>
  16. #include <stddef.h>
  17. #include <dirent.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <termios.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <_itoa.h>
  25. #include "ttyname.h"
  26. #if 0
  27. /* Is this used anywhere? It is not exported. */
  28. char *__ttyname;
  29. #endif
  30. static char *getttyname (const char *dev, const struct stat64 *mytty,
  31. int save, int *dostat);
  32. libc_freeres_ptr (static char *getttyname_name);
  33. static char *
  34. attribute_compat_text_section
  35. getttyname (const char *dev, const struct stat64 *mytty, int save, int *dostat)
  36. {
  37. static size_t namelen;
  38. struct stat64 st;
  39. DIR *dirstream;
  40. struct dirent64 *d;
  41. size_t devlen = strlen (dev) + 1;
  42. dirstream = __opendir (dev);
  43. if (dirstream == NULL)
  44. {
  45. *dostat = -1;
  46. return NULL;
  47. }
  48. /* Prepare for the loop. If we already have a buffer copy the directory
  49. name we look at into it. */
  50. if (devlen < namelen)
  51. *((char *) __mempcpy (getttyname_name, dev, devlen - 1)) = '/';
  52. while ((d = __readdir64 (dirstream)) != NULL)
  53. if ((d->d_fileno == mytty->st_ino || *dostat)
  54. && strcmp (d->d_name, "stdin")
  55. && strcmp (d->d_name, "stdout")
  56. && strcmp (d->d_name, "stderr"))
  57. {
  58. size_t dlen = _D_ALLOC_NAMLEN (d);
  59. if (devlen + dlen > namelen)
  60. {
  61. free (getttyname_name);
  62. namelen = 2 * (devlen + dlen); /* Big enough. */
  63. getttyname_name = malloc (namelen);
  64. if (! getttyname_name)
  65. {
  66. *dostat = -1;
  67. /* Perhaps it helps to free the directory stream buffer. */
  68. (void) __closedir (dirstream);
  69. return NULL;
  70. }
  71. *((char *) __mempcpy (getttyname_name, dev, devlen - 1)) = '/';
  72. }
  73. memcpy (&getttyname_name[devlen], d->d_name, dlen);
  74. if (__xstat64 (_STAT_VER, getttyname_name, &st) == 0
  75. && is_mytty (mytty, &st))
  76. {
  77. (void) __closedir (dirstream);
  78. #if 0
  79. __ttyname = getttyname_name;
  80. #endif
  81. __set_errno (save);
  82. return getttyname_name;
  83. }
  84. }
  85. (void) __closedir (dirstream);
  86. __set_errno (save);
  87. return NULL;
  88. }
  89. /* Static buffer in `ttyname'. */
  90. libc_freeres_ptr (static char *ttyname_buf);
  91. /* Return the pathname of the terminal FD is open on, or NULL on errors.
  92. The returned storage is good only until the next call to this function. */
  93. char *
  94. ttyname (int fd)
  95. {
  96. static size_t buflen;
  97. char procname[30];
  98. struct stat64 st, st1;
  99. int dostat = 0;
  100. int doispty = 0;
  101. char *name;
  102. int save = errno;
  103. struct termios term;
  104. /* isatty check, tcgetattr is used because it sets the correct
  105. errno (EBADF resp. ENOTTY) on error. */
  106. if (__glibc_unlikely (__tcgetattr (fd, &term) < 0))
  107. return NULL;
  108. if (__fxstat64 (_STAT_VER, fd, &st) < 0)
  109. return NULL;
  110. /* We try using the /proc filesystem. */
  111. *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';
  112. if (buflen == 0)
  113. {
  114. buflen = 4095;
  115. ttyname_buf = (char *) malloc (buflen + 1);
  116. if (ttyname_buf == NULL)
  117. {
  118. buflen = 0;
  119. return NULL;
  120. }
  121. }
  122. ssize_t len = __readlink (procname, ttyname_buf, buflen);
  123. if (__glibc_likely (len != -1))
  124. {
  125. if ((size_t) len >= buflen)
  126. return NULL;
  127. #define UNREACHABLE_LEN strlen ("(unreachable)")
  128. if (len > UNREACHABLE_LEN
  129. && memcmp (ttyname_buf, "(unreachable)", UNREACHABLE_LEN) == 0)
  130. {
  131. memmove (ttyname_buf, ttyname_buf + UNREACHABLE_LEN,
  132. len - UNREACHABLE_LEN);
  133. len -= UNREACHABLE_LEN;
  134. }
  135. /* readlink need not terminate the string. */
  136. ttyname_buf[len] = '\0';
  137. /* Verify readlink result, fall back on iterating through devices. */
  138. if (ttyname_buf[0] == '/'
  139. && __xstat64 (_STAT_VER, ttyname_buf, &st1) == 0
  140. && is_mytty (&st, &st1))
  141. return ttyname_buf;
  142. doispty = 1;
  143. }
  144. if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
  145. {
  146. name = getttyname ("/dev/pts", &st, save, &dostat);
  147. }
  148. else
  149. {
  150. __set_errno (save);
  151. name = NULL;
  152. }
  153. if (!name && dostat != -1)
  154. {
  155. name = getttyname ("/dev", &st, save, &dostat);
  156. }
  157. if (!name && dostat != -1)
  158. {
  159. dostat = 1;
  160. name = getttyname ("/dev", &st, save, &dostat);
  161. }
  162. if (!name && doispty && is_pty (&st))
  163. {
  164. /* We failed to figure out the TTY's name, but we can at least
  165. signal that we did verify that it really is a PTY slave.
  166. This happens when we have inherited the file descriptor from
  167. a different mount namespace. */
  168. __set_errno (ENODEV);
  169. return NULL;
  170. }
  171. return name;
  172. }