diff --git a/config.h.in b/config.h.in
index 05f14b5fc..0574a4df7 100644
--- a/config.h.in
+++ b/config.h.in
@@ -666,6 +666,9 @@
/* Define to 1 if you have the `_innetgr' function. */
#undef HAVE__INNETGR
+/* Define to 1 if you have the `_ttyname_dev' function. */
+#undef HAVE__TTYNAME_DEV
+
/* Define to 1 if the compiler supports the C99 __func__ variable. */
#undef HAVE___FUNC__
diff --git a/configure b/configure
index 134c19d6f..aa3cd3041 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for sudo 1.8.5.
+# Generated by GNU Autoconf 2.68 for sudo 1.8.5b8.
#
# Report bugs to .
#
@@ -570,8 +570,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sudo'
PACKAGE_TARNAME='sudo'
-PACKAGE_VERSION='1.8.5'
-PACKAGE_STRING='sudo 1.8.5'
+PACKAGE_VERSION='1.8.5b8'
+PACKAGE_STRING='sudo 1.8.5b8'
PACKAGE_BUGREPORT='http://www.sudo.ws/bugs/'
PACKAGE_URL=''
@@ -1447,7 +1447,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sudo 1.8.5 to adapt to many kinds of systems.
+\`configure' configures sudo 1.8.5b8 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1512,7 +1512,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sudo 1.8.5:";;
+ short | recursive ) echo "Configuration of sudo 1.8.5b8:";;
esac
cat <<\_ACEOF
@@ -1730,7 +1730,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sudo configure 1.8.5
+sudo configure 1.8.5b8
generated by GNU Autoconf 2.68
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2434,7 +2434,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sudo $as_me 1.8.5, which was
+It was created by sudo $as_me 1.8.5b8, which was
generated by GNU Autoconf 2.68. Invocation command line was
$ $0 $@
@@ -15271,6 +15271,16 @@ cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_PSINFO_PR_TTYDEV 1
_ACEOF
+for ac_func in _ttyname_dev
+do :
+ ac_fn_c_check_func "$LINENO" "_ttyname_dev" "ac_cv_func__ttyname_dev"
+if test "x$ac_cv_func__ttyname_dev" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE__TTYNAME_DEV 1
+_ACEOF
+
+fi
+done
fi
@@ -20608,7 +20618,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sudo $as_me 1.8.5, which was
+This file was extended by sudo $as_me 1.8.5b8, which was
generated by GNU Autoconf 2.68. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20674,7 +20684,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sudo config.status 1.8.5
+sudo config.status 1.8.5b8
configured by $0, generated by GNU Autoconf 2.68,
with options \\"\$ac_cs_config\\"
diff --git a/configure.in b/configure.in
index bedf548ad..1cbc83664 100644
--- a/configure.in
+++ b/configure.in
@@ -3,7 +3,7 @@ dnl Process this file with GNU autoconf to produce a configure script.
dnl
dnl Copyright (c) 1994-1996,1998-2012 Todd C. Miller
dnl
-AC_INIT([sudo], [1.8.5], [http://www.sudo.ws/bugs/], [sudo])
+AC_INIT([sudo], [1.8.5b8], [http://www.sudo.ws/bugs/], [sudo])
AC_CONFIG_HEADER([config.h pathnames.h])
dnl
dnl Note: this must come after AC_INIT
@@ -2007,7 +2007,7 @@ AC_HEADER_DIRENT
AC_HEADER_TIME
AC_HEADER_STDBOOL
AC_CHECK_HEADERS(malloc.h netgroup.h paths.h spawn.h utime.h utmpx.h sys/sockio.h sys/bsdtypes.h sys/select.h sys/stropts.h sys/sysmacros.h)
-AC_CHECK_HEADERS([procfs.h] [sys/procfs.h], [AC_CHECK_MEMBERS(struct psinfo.pr_ttydev, [], [], [AC_INCLUDES_DEFAULT
+AC_CHECK_HEADERS([procfs.h] [sys/procfs.h], [AC_CHECK_MEMBERS(struct psinfo.pr_ttydev, [AC_CHECK_FUNCS(_ttyname_dev)], [], [AC_INCLUDES_DEFAULT
#ifdef HAVE_PROCFS_H
#include
#endif
diff --git a/src/ttyname.c b/src/ttyname.c
index 395cba823..f7d119082 100644
--- a/src/ttyname.c
+++ b/src/ttyname.c
@@ -51,6 +51,7 @@
#endif /* HAVE_UNISTD_H */
#include
#include
+#include
#if defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined (HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV) || defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV)
# include
#elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
@@ -90,6 +91,86 @@
# define sudo_kp_namelen 4
#endif
+#if defined(sudo_kp_tdev)
+/*
+ * Like ttyname() but uses a dev_t instead of an open fd.
+ * Caller is responsible for freeing the returned string.
+ * The BSD version uses devname()
+ */
+static char *
+sudo_ttyname_dev(dev_t tdev)
+{
+ char *dev, *tty = NULL;
+ debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL)
+
+ /* Some versions of devname() return NULL on failure, others do not. */
+ dev = devname(tdev, S_IFCHR);
+ if (dev != NULL && *dev != '?' && *dev != '#') {
+ if (*dev != '/') {
+ /* devname() doesn't use the /dev/ prefix, add one... */
+ size_t len = sizeof(_PATH_DEV) + strlen(dev);
+ tty = emalloc(len);
+ strlcpy(tty, _PATH_DEV, len);
+ strlcat(tty, dev, len);
+ } else {
+ /* Should not happen but just in case... */
+ tty = estrdup(dev);
+ }
+ }
+ debug_return_str(tty);
+}
+#elif defined(HAVE__TTYNAME_DEV)
+extern char *_ttyname_dev(dev_t rdev, char *buffer, size_t buflen);
+
+/*
+ * Like ttyname() but uses a dev_t instead of an open fd.
+ * Caller is responsible for freeing the returned string.
+ * This version is just a wrapper around _ttyname_dev().
+ */
+static char *
+sudo_ttyname_dev(dev_t tdev)
+{
+ char buf[TTYNAME_MAX], *tty;
+ struct stat sb;
+ debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL)
+
+ /* Check if it is a pseudo-tty slave, falling back on _ttyname_dev() */
+ (void)snprintf(buf, sizeof(buf), "%spts/%u", _PATH_DEV,
+ (unsigned int)minor(tdev));
+ if (stat(buf, &sb) == 0 && sb.st_rdev == tdev) {
+ tty = buf;
+ } else {
+ tty = _ttyname_dev(tdev, buf, sizeof(buf));
+ }
+
+ debug_return_str(estrdup(tty));
+}
+#else
+/*
+ * Like ttyname() but uses a dev_t instead of an open fd.
+ * Caller is responsible for freeing the returned string.
+ * Generic version.
+ */
+static char *
+sudo_ttyname_dev(dev_t tdev)
+{
+ char buf[PATH_MAX], *tty = NULL;
+ struct stat sb;
+ debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL)
+
+ /* First, check if it is a pseudo-tty slave. */
+ (void)snprintf(buf, sizeof(buf), "%spts/%u", _PATH_DEV,
+ (unsigned int)minor(tdev));
+ if (stat(buf, &sb) == 0 && sb.st_rdev == tdev) {
+ tty = buf;
+ } else {
+ /* XXX - fallback to scanning /dev/ */
+ }
+
+ debug_return_str(estrdup(tty));
+}
+#endif
+
#if defined(sudo_kp_tdev)
/*
* Return a string from ttyname() containing the tty to which the process is
@@ -123,21 +204,13 @@ get_process_ttyname(void)
rc = sysctl(mib, sudo_kp_namelen, ki_proc, &size, NULL, 0);
} while (rc == -1 && errno == ENOMEM);
if (rc != -1) {
- char *dev = devname(ki_proc->sudo_kp_tdev, S_IFCHR);
- /* Some versions of devname() return NULL, others do not. */
- if (dev == NULL || *dev == '?' || *dev == '#') {
- sudo_debug_printf(SUDO_DEBUG_WARN,
- "unable to map device number %u to name",
- ki_proc->sudo_kp_tdev);
- } else if (*dev != '/') {
- /* devname() doesn't use the /dev/ prefix, add one... */
- size_t len = sizeof(_PATH_DEV) + strlen(dev);
- tty = emalloc(len);
- strlcpy(tty, _PATH_DEV, len);
- strlcat(tty, dev, len);
- } else {
- /* Should not happen but just in case... */
- tty = estrdup(dev);
+ if (ki_proc->sudo_kp_tdev != (dev_t)-1) {
+ tty = sudo_ttyname_dev(ki_proc->sudo_kp_tdev);
+ if (tty == NULL) {
+ sudo_debug_printf(SUDO_DEBUG_WARN,
+ "unable to map device number %u to name",
+ ki_proc->sudo_kp_tdev);
+ }
}
} else {
sudo_debug_printf(SUDO_DEBUG_WARN,
@@ -157,14 +230,11 @@ get_process_ttyname(void)
debug_return_str(tty);
}
#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
-# ifndef PRNODEV
-# define PRNODEV ((dev_t)-1)
-# endif
/*
* Return a string from ttyname() containing the tty to which the process is
* attached or NULL if there is no tty associated with the process (or its
- * parent). First tries std{in,out,err} then falls back to our /proc entry,
- * or our parent's if that doesn't work.
+ * parent). First tries /proc/pid/psinfo, then /proc/ppid/psinfo.
+ * Falls back on ttyname of std{in,out,err} if that fails.
*/
char *
get_process_ttyname(void)
@@ -176,68 +246,100 @@ get_process_ttyname(void)
int i, fd;
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
- if ((tty = ttyname(STDIN_FILENO)) == NULL &&
- (tty = ttyname(STDOUT_FILENO)) == NULL &&
- (tty = ttyname(STDERR_FILENO)) == NULL) {
- /*
- * No tty hooked up to std{in,out,err}, check /proc.
- * We try to map pr_ttydev in psinfo to /dev/pts/N
- */
- for (i = 0; tty == NULL && i < 2; i++) {
- snprintf(path, sizeof(path), "/proc/%u/psinfo",
- i ? (unsigned int)getppid() : (unsigned int)getpid());
- if ((fd = open(path, O_RDONLY, 0)) == -1)
- continue;
- nread = read(fd, &psinfo, sizeof(psinfo));
- close(fd);
- if (nread != (ssize_t)sizeof(psinfo) || psinfo.pr_ttydev == PRNODEV)
- continue;
- (void)snprintf(path, sizeof(path), "%spts/%u", _PATH_DEV,
- (unsigned int)minor(psinfo.pr_ttydev));
- if (stat(path, &sb) == 0 && sb.st_rdev == psinfo.pr_ttydev) {
- fd = open(path, O_RDONLY|O_NOCTTY|O_NONBLOCK, 0);
- if (fd != -1) {
- tty = ttyname(fd);
- close(fd);
- }
- }
+ /* Try to determine the tty from pr_ttydev in /proc/pid/psinfo. */
+ for (i = 0; tty == NULL && i < 2; i++) {
+ (void)snprintf(path, sizeof(path), "/proc/%u/psinfo",
+ i ? (unsigned int)getppid() : (unsigned int)getpid());
+ if ((fd = open(path, O_RDONLY, 0)) == -1)
+ continue;
+ nread = read(fd, &psinfo, sizeof(psinfo));
+ close(fd);
+ if (nread == (ssize_t)sizeof(psinfo) && psinfo.pr_ttydev != (dev_t)-1) {
+ tty = sudo_ttyname_dev(psinfo.pr_ttydev);
}
}
- debug_return_str(estrdup(tty));
+ /* If all else fails, fall back on ttyname(). */
+ if (tty == NULL) {
+ if ((tty = ttyname(STDIN_FILENO)) != NULL ||
+ (tty = ttyname(STDOUT_FILENO)) != NULL ||
+ (tty = ttyname(STDERR_FILENO)) != NULL)
+ tty = estrdup(tty);
+ }
+
+ debug_return_str(tty);
}
-#else
+#elif defined(__linux__)
/*
* Return a string from ttyname() containing the tty to which the process is
* attached or NULL if there is no tty associated with the process (or its
- * parent). First tries std{in,out,err} then falls back to our parent's /proc
- * entry.
+ * parent). First tries field 7 in /proc/pid/stat, then /proc/ppid/stat.
+ * Falls back on ttyname of std{in,out,err} if that fails.
*/
char *
get_process_ttyname(void)
{
- char path[PATH_MAX], *tty = NULL;
- struct stat sb;
- pid_t ppid;
- int i, fd;
+ char *line = NULL, *tty = NULL;
+ size_t linesize = 0;
+ ssize_t len;
+ int i;
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
- if ((tty = ttyname(STDIN_FILENO)) == NULL &&
- (tty = ttyname(STDOUT_FILENO)) == NULL &&
- (tty = ttyname(STDERR_FILENO)) == NULL) {
- /* No tty for child, check the parent via /proc. */
- ppid = getppid();
- for (i = STDIN_FILENO; i <= STDERR_FILENO && tty == NULL; i++) {
- snprintf(path, sizeof(path), "/proc/%u/fd/%d",
- (unsigned int)ppid, i);
- fd = open(path, O_RDONLY|O_NOCTTY|O_NONBLOCK, 0);
- if (fd != -1) {
- tty = ttyname(fd);
- close(fd);
+ /* Try to determine the tty from pr_ttydev in /proc/pid/psinfo. */
+ for (i = 0; tty == NULL && i < 2; i++) {
+ FILE *fp;
+ char path[PATH_MAX];
+ (void)snprintf(path, sizeof(path), "/proc/%u/stat",
+ i ? (unsigned int)getppid() : (unsigned int)getpid());
+ if ((fp = fopen(path, "r")) == NULL)
+ continue;
+ len = getline(&line, &linesize, fp);
+ fclose(fp);
+ if (len != -1) {
+ /* Field 7 is the tty dev (0 if no tty) */
+ char *cp = line;
+ int field = 1;
+ while (*cp != '\0') {
+ if (*cp++ == ' ') {
+ if (++field == 7) {
+ dev_t tdev = (dev_t)atoi(cp);
+ if (tdev > 0)
+ tty = sudo_ttyname_dev(tdev);
+ break;
+ }
+ }
}
}
}
+ efree(line);
+
+ /* If all else fails, fall back on ttyname(). */
+ if (tty == NULL) {
+ if ((tty = ttyname(STDIN_FILENO)) != NULL ||
+ (tty = ttyname(STDOUT_FILENO)) != NULL ||
+ (tty = ttyname(STDERR_FILENO)) != NULL)
+ tty = estrdup(tty);
+ }
+
+ debug_return_str(tty);
+}
+#else
+/*
+ * Return a string from ttyname() containing the tty to which the process is
+ * attached or NULL if there is no tty associated with the process.
+ * parent).
+ */
+char *
+get_process_ttyname(void)
+{
+ char *tty;
+ debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
+
+ if ((tty = ttyname(STDIN_FILENO)) == NULL) {
+ if ((tty = ttyname(STDOUT_FILENO)) == NULL)
+ tty = ttyname(STDERR_FILENO);
+ }
debug_return_str(estrdup(tty));
}
-#endif /* !sudo_kp_tdev && !HAVE_STRUCT_PSINFO_PR_TTYDEV */
+#endif