/* Change the ownership and access permission of the slave pseudo terminal associated with the master pseudo terminal specified by FD. */ int grantpt (int fd) { #if !defined __ASSUME_DEVPTS__ struct statfs fsbuf; # ifdef PATH_MAX char _buf[PATH_MAX]; # else char _buf[512]; # endif char *buf = _buf; if (pts_name (fd, &buf, sizeof (_buf))) return -1; if (statfs (buf, &fsbuf) < 0) return -1; /* If the slave pseudo terminal lives on a `devpts' filesystem, the ownership and access permission are already set. */ if (fsbuf.f_type != DEVPTS_SUPER_MAGIC && fsbuf.f_type != DEVFS_SUPER_MAGIC) return __unix_grantpt (fd); #endif return 0; }
/* Create pseudo tty master slave pair and set terminal attributes according to TERMP and WINP. Return handles for both ends in AMASTER and ASLAVE, and return the name of the slave end in NAME. */ int openpty (int *amaster, int *aslave, char *name, const struct termios *termp, const struct winsize *winp) { #ifdef PATH_MAX char _buf[PATH_MAX]; #else char _buf[512]; #endif char *buf = _buf; int master, slave; master = getpt (); if (master == -1) return -1; if (grantpt (master)) goto fail; if (unlockpt (master)) goto fail; if (pts_name (master, &buf, sizeof (_buf))) goto fail; slave = open (buf, O_RDWR | O_NOCTTY); if (slave == -1) { if (buf != _buf) free (buf); goto fail; } /* XXX Should we ignore errors here? */ if(termp) tcsetattr (slave, TCSAFLUSH, termp); if (winp) ioctl (slave, TIOCSWINSZ, winp); *amaster = master; *aslave = slave; if (name != NULL) strcpy (name, buf); if (buf != _buf) free (buf); return 0; fail: close (master); return -1; }
/* Change the ownership and access permission of the slave pseudo terminal associated with the master pseudo terminal specified by FD. */ int grantpt (int fd) { struct statfs fsbuf; char _buf[PATH_MAX]; char *buf = _buf; if (pts_name (fd, &buf, sizeof (_buf))) return -1; if (__libc_statfs (buf, &fsbuf) < 0) return -1; /* If the slave pseudo terminal lives on a `devpts' filesystem, the ownership and access permission are already set. */ if (fsbuf.f_type != DEVPTS_SUPER_MAGIC && fsbuf.f_type != DEVFS_SUPER_MAGIC) return __unix_grantpt (fd); return 0; }
/* Change the ownership and access permission of the slave pseudo terminal associated with the master pseudo terminal specified by FD. */ int grantpt (int fd) { struct statfs fsbuf; #ifdef PATH_MAX char _buf[PATH_MAX]; #else char _buf[512]; #endif char *buf = _buf; if (__builtin_expect (pts_name (fd, &buf, sizeof (_buf)), 0)) { int save_errno = errno; /* Check, if the file descriptor is valid. pts_name returns the wrong errno number, so we cannot use that. */ if (__libc_fcntl (fd, F_GETFD) == -1 && errno == EBADF) return -1; /* If the filedescriptor is no TTY, grantpt has to set errno to EINVAL. */ if (save_errno == ENOTTY) __set_errno (EINVAL); else __set_errno (save_errno); return -1; } if (__statfs (buf, &fsbuf) < 0) return -1; /* If the slave pseudo terminal lives on a `devpts' filesystem, the ownership and access permission are already set. */ if (fsbuf.f_type == DEVPTS_SUPER_MAGIC || fsbuf.f_type == DEVFS_SUPER_MAGIC) return 0; return __unix_grantpt (fd); }
/* Change the ownership and access permission of the slave pseudo terminal associated with the master pseudo terminal specified by FD. */ int grantpt (int fd) { int retval = -1; #ifdef PATH_MAX char _buf[PATH_MAX]; #else char _buf[512]; #endif char *buf = _buf; struct stat64 st; if (__glibc_unlikely (pts_name (fd, &buf, sizeof (_buf), &st))) { int save_errno = errno; /* Check, if the file descriptor is valid. pts_name returns the wrong errno number, so we cannot use that. */ if (__libc_fcntl (fd, F_GETFD) == -1 && errno == EBADF) return -1; /* If the filedescriptor is no TTY, grantpt has to set errno to EINVAL. */ if (save_errno == ENOTTY) __set_errno (EINVAL); else __set_errno (save_errno); return -1; } /* Make sure that we own the device. */ uid_t uid = __getuid (); if (st.st_uid != uid) { if (__chown (buf, uid, st.st_gid) < 0) goto helper; } static int tty_gid = -1; if (__glibc_unlikely (tty_gid == -1)) { char *grtmpbuf; struct group grbuf; size_t grbuflen = __sysconf (_SC_GETGR_R_SIZE_MAX); struct group *p; /* Get the group ID of the special `tty' group. */ if (grbuflen == (size_t) -1L) /* `sysconf' does not support _SC_GETGR_R_SIZE_MAX. Try a moderate value. */ grbuflen = 1024; grtmpbuf = (char *) __alloca (grbuflen); __getgrnam_r (TTY_GROUP, &grbuf, grtmpbuf, grbuflen, &p); if (p != NULL) tty_gid = p->gr_gid; } gid_t gid = tty_gid == -1 ? __getgid () : tty_gid; /* Make sure the group of the device is that special group. */ if (st.st_gid != gid) { if (__chown (buf, uid, gid) < 0) goto helper; } /* Make sure the permission mode is set to readable and writable by the owner, and writable by the group. */ if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)) { if (__chmod (buf, S_IRUSR|S_IWUSR|S_IWGRP) < 0) goto helper; } retval = 0; goto cleanup; /* We have to use the helper program if it is available. */ helper:; #ifdef HAVE_PT_CHOWN pid_t pid = __fork (); if (pid == -1) goto cleanup; else if (pid == 0) { /* Disable core dumps. */ struct rlimit rl = { 0, 0 }; __setrlimit (RLIMIT_CORE, &rl); /* We pass the master pseudo terminal as file descriptor PTY_FILENO. */ if (fd != PTY_FILENO) if (__dup2 (fd, PTY_FILENO) < 0) _exit (FAIL_EBADF); # ifdef CLOSE_ALL_FDS CLOSE_ALL_FDS (); # endif execle (_PATH_PT_CHOWN, basename (_PATH_PT_CHOWN), NULL, NULL); _exit (FAIL_EXEC); } else { int w; if (__waitpid (pid, &w, 0) == -1) goto cleanup; if (!WIFEXITED (w)) __set_errno (ENOEXEC); else switch (WEXITSTATUS (w)) { case 0: retval = 0; break; case FAIL_EBADF: __set_errno (EBADF); break; case FAIL_EINVAL: __set_errno (EINVAL); break; case FAIL_EACCES: __set_errno (EACCES); break; case FAIL_EXEC: __set_errno (ENOEXEC); break; case FAIL_ENOMEM: __set_errno (ENOMEM); break; default: assert(! "getpt: internal error: invalid exit code from pt_chown"); } } #endif cleanup: if (buf != _buf) free (buf); return retval; }
/* Change the ownership and access permission of the slave pseudo terminal associated with the master pseudo terminal specified by FD. */ int grantpt (int fd) { int retval = -1; #ifdef PATH_MAX char _buf[PATH_MAX]; #else char _buf[512]; #endif char *buf = _buf; struct stat st; uid_t uid; gid_t gid; pid_t pid; if (pts_name (fd, &buf, sizeof (_buf))) return -1; if (stat(buf, &st) < 0) goto cleanup; /* Make sure that we own the device. */ uid = getuid (); if (st.st_uid != uid) { if (chown (buf, uid, st.st_gid) < 0) goto helper; } gid = getgid (); /* Make sure the group of the device is that special group. */ if (st.st_gid != gid) { if (chown (buf, uid, gid) < 0) goto helper; } /* Make sure the permission mode is set to readable and writable by the owner, and writable by the group. */ if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)) { if (chmod (buf, S_IRUSR|S_IWUSR|S_IWGRP) < 0) goto helper; } retval = 0; goto cleanup; /* We have to use the helper program. */ helper: pid = vfork (); if (pid == -1) goto cleanup; else if (pid == 0) { /* Disable core dumps. */ struct rlimit rl = { 0, 0 }; setrlimit (RLIMIT_CORE, &rl); /* We pase the master pseudo terminal as file descriptor PTY_FILENO. */ if (fd != PTY_FILENO) if (dup2 (fd, PTY_FILENO) < 0) _exit (FAIL_EBADF); execle (_PATH_PT_CHOWN, _PATH_PT_CHOWN, NULL, NULL); _exit (FAIL_EXEC); } else { int w; if (waitpid (pid, &w, 0) == -1) goto cleanup; if (!WIFEXITED (w)) errno = ENOEXEC; else switch (WEXITSTATUS(w)) { case 0: retval = 0; break; case FAIL_EBADF: errno = EBADF; break; case FAIL_EINVAL: errno = EINVAL; break; case FAIL_EACCES: errno = EACCES; break; case FAIL_EXEC: errno = ENOEXEC; break; default: assert(! "getpt: internal error: invalid exit code from pt_chown"); } } cleanup: if (buf != _buf) free (buf); return retval; }