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. */
|
/* Define to 1 if you have the `_innetgr' function. */
|
||||||
#undef HAVE__INNETGR
|
#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. */
|
/* Define to 1 if the compiler supports the C99 __func__ variable. */
|
||||||
#undef HAVE___FUNC__
|
#undef HAVE___FUNC__
|
||||||
|
|
||||||
|
28
configure
vendored
28
configure
vendored
@@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# 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/>.
|
# Report bugs to <http://www.sudo.ws/bugs/>.
|
||||||
#
|
#
|
||||||
@@ -570,8 +570,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='sudo'
|
PACKAGE_NAME='sudo'
|
||||||
PACKAGE_TARNAME='sudo'
|
PACKAGE_TARNAME='sudo'
|
||||||
PACKAGE_VERSION='1.8.5'
|
PACKAGE_VERSION='1.8.5b8'
|
||||||
PACKAGE_STRING='sudo 1.8.5'
|
PACKAGE_STRING='sudo 1.8.5b8'
|
||||||
PACKAGE_BUGREPORT='http://www.sudo.ws/bugs/'
|
PACKAGE_BUGREPORT='http://www.sudo.ws/bugs/'
|
||||||
PACKAGE_URL=''
|
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.
|
# 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.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
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]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1512,7 +1512,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of sudo 1.8.5:";;
|
short | recursive ) echo "Configuration of sudo 1.8.5b8:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1730,7 +1730,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
sudo configure 1.8.5
|
sudo configure 1.8.5b8
|
||||||
generated by GNU Autoconf 2.68
|
generated by GNU Autoconf 2.68
|
||||||
|
|
||||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||||
@@ -2434,7 +2434,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
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
|
generated by GNU Autoconf 2.68. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@@ -15271,6 +15271,16 @@ cat >>confdefs.h <<_ACEOF
|
|||||||
#define HAVE_STRUCT_PSINFO_PR_TTYDEV 1
|
#define HAVE_STRUCT_PSINFO_PR_TTYDEV 1
|
||||||
_ACEOF
|
_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
|
fi
|
||||||
|
|
||||||
@@ -20608,7 +20618,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
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
|
generated by GNU Autoconf 2.68. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -20674,7 +20684,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
sudo config.status 1.8.5
|
sudo config.status 1.8.5b8
|
||||||
configured by $0, generated by GNU Autoconf 2.68,
|
configured by $0, generated by GNU Autoconf 2.68,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ dnl Process this file with GNU autoconf to produce a configure script.
|
|||||||
dnl
|
dnl
|
||||||
dnl Copyright (c) 1994-1996,1998-2012 Todd C. Miller <Todd.Miller@courtesan.com>
|
dnl Copyright (c) 1994-1996,1998-2012 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
dnl
|
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])
|
AC_CONFIG_HEADER([config.h pathnames.h])
|
||||||
dnl
|
dnl
|
||||||
dnl Note: this must come after AC_INIT
|
dnl Note: this must come after AC_INIT
|
||||||
@@ -2007,7 +2007,7 @@ AC_HEADER_DIRENT
|
|||||||
AC_HEADER_TIME
|
AC_HEADER_TIME
|
||||||
AC_HEADER_STDBOOL
|
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(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
|
#ifdef HAVE_PROCFS_H
|
||||||
#include <procfs.h>
|
#include <procfs.h>
|
||||||
#endif
|
#endif
|
||||||
|
216
src/ttyname.c
216
src/ttyname.c
@@ -51,6 +51,7 @@
|
|||||||
#endif /* HAVE_UNISTD_H */
|
#endif /* HAVE_UNISTD_H */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.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)
|
#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>
|
# include <sys/sysctl.h>
|
||||||
#elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
|
#elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
|
||||||
@@ -90,6 +91,86 @@
|
|||||||
# define sudo_kp_namelen 4
|
# define sudo_kp_namelen 4
|
||||||
#endif
|
#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)
|
#if defined(sudo_kp_tdev)
|
||||||
/*
|
/*
|
||||||
* Return a string from ttyname() containing the tty to which the process is
|
* 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);
|
rc = sysctl(mib, sudo_kp_namelen, ki_proc, &size, NULL, 0);
|
||||||
} while (rc == -1 && errno == ENOMEM);
|
} while (rc == -1 && errno == ENOMEM);
|
||||||
if (rc != -1) {
|
if (rc != -1) {
|
||||||
char *dev = devname(ki_proc->sudo_kp_tdev, S_IFCHR);
|
if (ki_proc->sudo_kp_tdev != (dev_t)-1) {
|
||||||
/* Some versions of devname() return NULL, others do not. */
|
tty = sudo_ttyname_dev(ki_proc->sudo_kp_tdev);
|
||||||
if (dev == NULL || *dev == '?' || *dev == '#') {
|
if (tty == NULL) {
|
||||||
sudo_debug_printf(SUDO_DEBUG_WARN,
|
sudo_debug_printf(SUDO_DEBUG_WARN,
|
||||||
"unable to map device number %u to name",
|
"unable to map device number %u to name",
|
||||||
ki_proc->sudo_kp_tdev);
|
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);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sudo_debug_printf(SUDO_DEBUG_WARN,
|
sudo_debug_printf(SUDO_DEBUG_WARN,
|
||||||
@@ -157,14 +230,11 @@ get_process_ttyname(void)
|
|||||||
debug_return_str(tty);
|
debug_return_str(tty);
|
||||||
}
|
}
|
||||||
#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
|
#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
|
* 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
|
* 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,
|
* parent). First tries /proc/pid/psinfo, then /proc/ppid/psinfo.
|
||||||
* or our parent's if that doesn't work.
|
* Falls back on ttyname of std{in,out,err} if that fails.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
get_process_ttyname(void)
|
get_process_ttyname(void)
|
||||||
@@ -176,68 +246,100 @@ get_process_ttyname(void)
|
|||||||
int i, fd;
|
int i, fd;
|
||||||
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
|
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
|
||||||
|
|
||||||
if ((tty = ttyname(STDIN_FILENO)) == NULL &&
|
/* Try to determine the tty from pr_ttydev in /proc/pid/psinfo. */
|
||||||
(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++) {
|
for (i = 0; tty == NULL && i < 2; i++) {
|
||||||
snprintf(path, sizeof(path), "/proc/%u/psinfo",
|
(void)snprintf(path, sizeof(path), "/proc/%u/psinfo",
|
||||||
i ? (unsigned int)getppid() : (unsigned int)getpid());
|
i ? (unsigned int)getppid() : (unsigned int)getpid());
|
||||||
if ((fd = open(path, O_RDONLY, 0)) == -1)
|
if ((fd = open(path, O_RDONLY, 0)) == -1)
|
||||||
continue;
|
continue;
|
||||||
nread = read(fd, &psinfo, sizeof(psinfo));
|
nread = read(fd, &psinfo, sizeof(psinfo));
|
||||||
close(fd);
|
close(fd);
|
||||||
if (nread != (ssize_t)sizeof(psinfo) || psinfo.pr_ttydev == PRNODEV)
|
if (nread == (ssize_t)sizeof(psinfo) && psinfo.pr_ttydev != (dev_t)-1) {
|
||||||
continue;
|
tty = sudo_ttyname_dev(psinfo.pr_ttydev);
|
||||||
(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
debug_return_str(tty);
|
||||||
|
}
|
||||||
|
#elif defined(__linux__)
|
||||||
/*
|
/*
|
||||||
* Return a string from ttyname() containing the tty to which the process is
|
* 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
|
* 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
|
* parent). First tries field 7 in /proc/pid/stat, then /proc/ppid/stat.
|
||||||
* entry.
|
* Falls back on ttyname of std{in,out,err} if that fails.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
get_process_ttyname(void)
|
get_process_ttyname(void)
|
||||||
{
|
{
|
||||||
char path[PATH_MAX], *tty = NULL;
|
char *line = NULL, *tty = NULL;
|
||||||
struct stat sb;
|
size_t linesize = 0;
|
||||||
pid_t ppid;
|
ssize_t len;
|
||||||
int i, fd;
|
int i;
|
||||||
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
|
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
|
||||||
|
|
||||||
if ((tty = ttyname(STDIN_FILENO)) == NULL &&
|
/* Try to determine the tty from pr_ttydev in /proc/pid/psinfo. */
|
||||||
(tty = ttyname(STDOUT_FILENO)) == NULL &&
|
for (i = 0; tty == NULL && i < 2; i++) {
|
||||||
(tty = ttyname(STDERR_FILENO)) == NULL) {
|
FILE *fp;
|
||||||
/* No tty for child, check the parent via /proc. */
|
char path[PATH_MAX];
|
||||||
ppid = getppid();
|
(void)snprintf(path, sizeof(path), "/proc/%u/stat",
|
||||||
for (i = STDIN_FILENO; i <= STDERR_FILENO && tty == NULL; i++) {
|
i ? (unsigned int)getppid() : (unsigned int)getpid());
|
||||||
snprintf(path, sizeof(path), "/proc/%u/fd/%d",
|
if ((fp = fopen(path, "r")) == NULL)
|
||||||
(unsigned int)ppid, i);
|
continue;
|
||||||
fd = open(path, O_RDONLY|O_NOCTTY|O_NONBLOCK, 0);
|
len = getline(&line, &linesize, fp);
|
||||||
if (fd != -1) {
|
fclose(fp);
|
||||||
tty = ttyname(fd);
|
if (len != -1) {
|
||||||
close(fd);
|
/* 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));
|
debug_return_str(estrdup(tty));
|
||||||
}
|
}
|
||||||
#endif /* !sudo_kp_tdev && !HAVE_STRUCT_PSINFO_PR_TTYDEV */
|
#endif
|
||||||
|
Reference in New Issue
Block a user