diff options
author | Andreas Schwab <schwab@redhat.com> | 2009-11-30 15:01:58 +0100 |
---|---|---|
committer | Andreas Schwab <schwab@redhat.com> | 2009-11-30 15:01:58 +0100 |
commit | 54ff413202df84fc1e90d5299a9eb55f2bf4eb31 (patch) | |
tree | 2e5c0006e2aaf0514cf30373e9b3ff1dc0c1fe6b /sysdeps | |
parent | b127b8513f55a7d1a9312f32740914ed764f080c (diff) | |
parent | b55ec98c6490b944593243c7da54dda1796e3f84 (diff) |
Merge remote branch 'origin/master' into fedora/master
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/unix/grantpt.c | 59 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/grantpt.c | 42 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ptsname.c | 37 |
3 files changed, 97 insertions, 41 deletions
diff --git a/sysdeps/unix/grantpt.c b/sysdeps/unix/grantpt.c index 8c299e9147..260e8273f8 100644 --- a/sysdeps/unix/grantpt.c +++ b/sysdeps/unix/grantpt.c @@ -38,7 +38,7 @@ this buffer, a sufficiently long buffer is allocated using malloc, and returned in PTS. 0 is returned upon success, -1 otherwise. */ static int -pts_name (int fd, char **pts, size_t buf_len) +pts_name (int fd, char **pts, size_t buf_len, struct stat64 *stp) { int rv; char *buf = *pts; @@ -49,7 +49,7 @@ pts_name (int fd, char **pts, size_t buf_len) if (buf_len) { - rv = __ptsname_r (fd, buf, buf_len); + rv = __ptsname_internal (fd, buf, buf_len, stp); if (rv != 0) { if (rv == ENOTTY) @@ -108,15 +108,8 @@ grantpt (int fd) #endif char *buf = _buf; struct stat64 st; - char *grtmpbuf; - struct group grbuf; - size_t grbuflen = __sysconf (_SC_GETGR_R_SIZE_MAX); - struct group *p; - uid_t uid; - gid_t gid; - pid_t pid; - - if (__builtin_expect (pts_name (fd, &buf, sizeof (_buf)), 0)) + + if (__builtin_expect (pts_name (fd, &buf, sizeof (_buf), &st), 0)) { int save_errno = errno; @@ -126,34 +119,42 @@ grantpt (int fd) return -1; /* If the filedescriptor is no TTY, grantpt has to set errno - to EINVAL. */ + to EINVAL. */ if (save_errno == ENOTTY) - __set_errno (EINVAL); + __set_errno (EINVAL); else __set_errno (save_errno); return -1; } - if (__xstat64 (_STAT_VER, buf, &st) < 0) - goto cleanup; - /* Make sure that we own the device. */ - uid = __getuid (); + uid_t uid = __getuid (); if (st.st_uid != uid) { if (__chown (buf, uid, st.st_gid) < 0) goto helper; } - /* 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); - gid = p ? p->gr_gid : __getgid (); + static int tty_gid = -1; + if (__builtin_expect (tty_gid == -1, 0)) + { + 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) @@ -174,9 +175,9 @@ grantpt (int fd) goto cleanup; /* We have to use the helper program. */ - helper: + helper:; - pid = __fork (); + pid_t pid = __fork (); if (pid == -1) goto cleanup; else if (pid == 0) @@ -190,6 +191,10 @@ grantpt (int fd) 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); } diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c new file mode 100644 index 0000000000..f2fc60f83a --- /dev/null +++ b/sysdeps/unix/sysv/linux/grantpt.c @@ -0,0 +1,42 @@ +#include <assert.h> +#include <ctype.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <stdlib.h> +#include <unistd.h> + +#include "not-cancel.h" +#include "pty-private.h" + + +/* Close all file descriptors except the one specified. */ +static void +close_all_fds (void) +{ + DIR *dir = __opendir ("/proc/self/fd"); + if (dir != NULL) + { + struct dirent64 *d; + while ((d = __readdir64 (dir)) != NULL) + if (isdigit (d->d_name[0])) + { + char *endp; + long int fd = strtol (d->d_name, &endp, 10); + if (*endp == '\0' && fd != PTY_FILENO && fd != dirfd (dir)) + close_not_cancel_no_status (fd); + } + + __closedir (dir); + + int nullfd = open_not_cancel_2 (_PATH_DEVNULL, O_RDONLY); + assert (nullfd == STDIN_FILENO); + nullfd = open_not_cancel_2 (_PATH_DEVNULL, O_WRONLY); + assert (nullfd == STDOUT_FILENO); + __dup2 (STDOUT_FILENO, STDERR_FILENO); + } +} +#define CLOSE_ALL_FDS() close_all_fds() + +#include <sysdeps/unix/grantpt.c> diff --git a/sysdeps/unix/sysv/linux/ptsname.c b/sysdeps/unix/sysv/linux/ptsname.c index 9c364b18b4..129d09085e 100644 --- a/sysdeps/unix/sysv/linux/ptsname.c +++ b/sysdeps/unix/sysv/linux/ptsname.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1998, 2000, 2001, 2002, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998. @@ -67,14 +67,10 @@ ptsname (int fd) } -/* Store at most BUFLEN characters of the pathname of the slave pseudo - terminal associated with the master FD is open on in BUF. - Return 0 on success, otherwise an error number. */ int -__ptsname_r (int fd, char *buf, size_t buflen) +__ptsname_internal (int fd, char *buf, size_t buflen, struct stat64 *stp) { int save_errno = errno; - struct stat64 st; unsigned int ptyno; if (buf == NULL) @@ -93,7 +89,7 @@ __ptsname_r (int fd, char *buf, size_t buflen) if (__ioctl (fd, TIOCGPTN, &ptyno) == 0) { /* Buffer we use to print the number in. For a maximum size for - `int' of 8 bytes we never need more than 20 digits. */ + `int' of 8 bytes we never need more than 20 digits. */ char numbuf[21]; const char *devpts = _PATH_DEVPTS; const size_t devptslen = strlen (_PATH_DEVPTS); @@ -121,21 +117,23 @@ __ptsname_r (int fd, char *buf, size_t buflen) return ERANGE; } - if (__fxstat64 (_STAT_VER, fd, &st) < 0) + if (__fxstat64 (_STAT_VER, fd, stp) < 0) return errno; /* Check if FD really is a master pseudo terminal. */ - if (! MASTER_P (st.st_rdev)) + if (! MASTER_P (stp->st_rdev)) { __set_errno (ENOTTY); return ENOTTY; } - ptyno = minor (st.st_rdev); + ptyno = minor (stp->st_rdev); +#if __LINUX_KERNEL_VERSION >= 131443 /* This is for the old BSD pseudo terminals. As of Linux - 2.1.115 these are no longer supported. */ - if (major (st.st_rdev) == 4) + 2.1.115 these are no longer supported. */ + if (major (stp->st_rdev) == 4) ptyno -= 128; +#endif if (ptyno / 16 >= strlen (__libc_ptyname1)) { @@ -149,12 +147,12 @@ __ptsname_r (int fd, char *buf, size_t buflen) p[2] = '\0'; } - if (__xstat64 (_STAT_VER, buf, &st) < 0) + if (__xstat64 (_STAT_VER, buf, stp) < 0) return errno; /* Check if the name we're about to return really corresponds to a slave pseudo terminal. */ - if (! S_ISCHR (st.st_mode) || ! SLAVE_P (st.st_rdev)) + if (! S_ISCHR (stp->st_mode) || ! SLAVE_P (stp->st_rdev)) { /* This really is a configuration problem. */ __set_errno (ENOTTY); @@ -164,4 +162,15 @@ __ptsname_r (int fd, char *buf, size_t buflen) __set_errno (save_errno); return 0; } + + +/* Store at most BUFLEN characters of the pathname of the slave pseudo + terminal associated with the master FD is open on in BUF. + Return 0 on success, otherwise an error number. */ +int +__ptsname_r (int fd, char *buf, size_t buflen) +{ + struct stat64 st; + return __ptsname_internal (fd, buf, buflen, &st); +} weak_alias (__ptsname_r, ptsname_r) |