/* Store at most BUFLEN character of the pathname of the terminal FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ttyname_r (int fd, char *buf, size_t buflen) { struct stat st; int dostat = 0; int save = errno; int ret; /* Test for the absolute minimal size. This makes life easier inside the loop. */ if (!buf) { __set_errno (EINVAL); return EINVAL; } if (buflen < (int) (sizeof (dev) + 1)) { __set_errno (ERANGE); return ERANGE; } if (!__isatty (fd)) { __set_errno (ENOTTY); return ENOTTY; } if (fstat (fd, &st) < 0) return errno; /* Prepare the result buffer. */ memcpy (buf, dev, sizeof (dev) - 1); buf[sizeof (dev) - 1] = '/'; buflen -= sizeof (dev); #ifdef _STATBUF_ST_RDEV ret = getttyname_r (fd, buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (fd, buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif if (ret && dostat != -1) { dostat = 1; #ifdef _STATBUF_ST_RDEV ret = getttyname_r (fd, buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (fd, buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } return ret; }
/* Store at most BUFLEN character of the pathname of the terminal FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ttyname_r (int fd, char *buf, size_t buflen) { struct stat64 st; int save = errno; int ret; if (buflen < sizeof ("/dev/pty/slv/")) { __set_errno (ERANGE); return ERANGE; } if (!__isatty (fd)) { __set_errno (ENOTTY); return ENOTTY; } if (__fxstat64 (_STAT_VER, fd, &st) < 0) return errno; /* Prepare the result buffer. */ memcpy (buf, "/dev/pty/slv/", sizeof ("/dev/pty/slv/")); buflen -= sizeof ("/dev/pty/slv/") - 1; ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save); if (ret) { memcpy (buf, "/dev/pty/mst/", sizeof ("/dev/pty/mst/")); ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save); } return ret; }
/* Store at most BUFLEN character of the pathname of the terminal FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ttyname_r (int fd, char *buf, size_t buflen) { char procname[30]; struct stat64 st, st1; int dostat = 0; int save = errno; /* Test for the absolute minimal size. This makes life easier inside the loop. */ if (!buf) { __set_errno (EINVAL); return EINVAL; } if (buflen < sizeof ("/dev/pts/")) { __set_errno (ERANGE); return ERANGE; } /* isatty check, tcgetattr is used because it sets the correct errno (EBADF resp. ENOTTY) on error. */ struct termios term; if (__glibc_unlikely (__tcgetattr (fd, &term) < 0)) return errno; if (__fxstat64 (_STAT_VER, fd, &st) < 0) return errno; /* We try using the /proc filesystem. */ *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0'; ssize_t ret = __readlink (procname, buf, buflen - 1); if (__glibc_unlikely (ret == -1 && errno == ENAMETOOLONG)) { __set_errno (ERANGE); return ERANGE; } if (__glibc_likely (ret != -1)) { #define UNREACHABLE_LEN strlen ("(unreachable)") if (ret > UNREACHABLE_LEN && memcmp (buf, "(unreachable)", UNREACHABLE_LEN) == 0) { memmove (buf, buf + UNREACHABLE_LEN, ret - UNREACHABLE_LEN); ret -= UNREACHABLE_LEN; } /* readlink need not terminate the string. */ buf[ret] = '\0'; /* Verify readlink result, fall back on iterating through devices. */ if (buf[0] == '/' && __xstat64 (_STAT_VER, buf, &st1) == 0 #ifdef _STATBUF_ST_RDEV && S_ISCHR (st1.st_mode) && st1.st_rdev == st.st_rdev #else && st1.st_ino == st.st_ino && st1.st_dev == st.st_dev #endif ) return 0; } /* Prepare the result buffer. */ memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/")); buflen -= sizeof ("/dev/pts/") - 1; if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode)) { #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } else { __set_errno (save); ret = ENOENT; } if (ret && dostat != -1) { buf[sizeof ("/dev/") - 1] = '\0'; buflen += sizeof ("pts/") - 1; #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } if (ret && dostat != -1) { buf[sizeof ("/dev/") - 1] = '\0'; dostat = 1; #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } return ret; }
/* Store at most BUFLEN character of the pathname of the terminal FD is open on in BUF. Return 0 on success, otherwise an error number. */ int __ttyname_r (int fd, char *buf, size_t buflen) { char procname[30]; struct stat64 st, st1; int dostat = 0; int save = errno; int ret; /* Test for the absolute minimal size. This makes life easier inside the loop. */ if (!buf) { __set_errno (EINVAL); return EINVAL; } if (buflen < sizeof ("/dev/pts/")) { __set_errno (ERANGE); return ERANGE; } /* We try using the /proc filesystem. */ *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0'; ret = __readlink (procname, buf, buflen - 1); if (ret == -1 && errno == ENOENT) { __set_errno (EBADF); return EBADF; } if (!__isatty (fd)) { __set_errno (ENOTTY); return ENOTTY; } if (ret == -1 && errno == ENAMETOOLONG) { __set_errno (ERANGE); return ERANGE; } if (ret != -1 && buf[0] != '[') { buf[ret] = '\0'; return 0; } if (__fxstat64 (_STAT_VER, fd, &st) < 0) return errno; /* Prepare the result buffer. */ memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/")); buflen -= sizeof ("/dev/pts/") - 1; if (__xstat64 (_STAT_VER, buf, &st1) == 0 && S_ISDIR (st1.st_mode)) { #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } else { __set_errno (save); ret = ENOENT; } if (ret && dostat != -1) { buf[sizeof ("/dev/") - 1] = '\0'; buflen += sizeof ("pts/") - 1; #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } if (ret && dostat != -1) { buf[sizeof ("/dev/") - 1] = '\0'; dostat = 1; #ifdef _STATBUF_ST_RDEV ret = getttyname_r (buf, buflen, st.st_rdev, st.st_ino, save, &dostat); #else ret = getttyname_r (buf, buflen, st.st_dev, st.st_ino, save, &dostat); #endif } return ret; }