Rototill code to determine the tty. For Linux, we now look up the
tty device in /proc/pid/stat instead of trying to open /proc/pid/fd/[0-2]. The sudo_ttyname_dev() function maps the given device number to a string. On BSD, we can use devname(). On Solaris, _ttyname_dev() does what we want. TODO: write /dev/ traversal code for the generic sudo_ttyname_dev().
This commit is contained 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__
|
||||
|
||||
|
28
configure
vendored
28
configure
vendored
@@ -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 <http://www.sudo.ws/bugs/>.
|
||||
#
|
||||
@@ -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\\"
|
||||
|
||||
|
@@ -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 <Todd.Miller@courtesan.com>
|
||||
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 <procfs.h>
|
||||
#endif
|
||||
|
234
src/ttyname.c
234
src/ttyname.c
@@ -51,6 +51,7 @@
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#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 <sys/sysctl.h>
|
||||
#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
|
||||
|
Reference in New Issue
Block a user