Avoid needless memory allocation when resolving the tty name.

This commit is contained in:
Todd C. Miller
2015-07-19 20:19:22 -06:00
parent c0b8e71488
commit d96f8bcabb
4 changed files with 152 additions and 114 deletions

View File

@@ -26,6 +26,7 @@
# include <strings.h> # include <strings.h>
#endif /* HAVE_STRINGS_H */ #endif /* HAVE_STRINGS_H */
#include <unistd.h> #include <unistd.h>
#include <limits.h>
#include <errno.h> #include <errno.h>
#include "sudo_compat.h" #include "sudo_compat.h"
@@ -36,18 +37,20 @@
__dso_public int main(int argc, char *argv[]); __dso_public int main(int argc, char *argv[]);
int sudo_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER; int sudo_debug_instance = SUDO_DEBUG_INSTANCE_INITIALIZER;
extern char *get_process_ttyname(void); extern char *get_process_ttyname(char *name, size_t namelen);
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
char *tty_libc = NULL, *tty_sudo; char *tty_libc = NULL, *tty_sudo = NULL;
char pathbuf[PATH_MAX];
int rval = 1; int rval = 1;
initprogname(argc > 0 ? argv[0] : "check_ttyname"); initprogname(argc > 0 ? argv[0] : "check_ttyname");
/* Lookup tty name using kernel info if possible. */ /* Lookup tty name using kernel info if possible. */
tty_sudo = get_process_ttyname(); if (get_process_ttyname(pathbuf, sizeof(pathbuf)) != NULL)
tty_sudo = pathbuf;
#if defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV) || \ #if defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV) || \
defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || \ defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || \
@@ -78,6 +81,5 @@ main(int argc, char *argv[])
tty_sudo ? tty_sudo : "none", tty_libc ? tty_libc : "none"); tty_sudo ? tty_sudo : "none", tty_libc ? tty_libc : "none");
} }
free(tty_sudo);
exit(rval); exit(rval);
} }

View File

@@ -449,7 +449,7 @@ oom:
static char ** static char **
get_user_info(struct user_details *ud) get_user_info(struct user_details *ud)
{ {
char *cp, **user_info, cwd[PATH_MAX]; char *cp, **user_info, path[PATH_MAX];
struct passwd *pw; struct passwd *pw;
int fd, i = 0; int fd, i = 0;
debug_decl(get_user_info, SUDO_DEBUG_UTIL) debug_decl(get_user_info, SUDO_DEBUG_UTIL)
@@ -518,23 +518,22 @@ get_user_info(struct user_details *ud)
if ((cp = get_user_groups(ud)) != NULL) if ((cp = get_user_groups(ud)) != NULL)
user_info[++i] = cp; user_info[++i] = cp;
if (getcwd(cwd, sizeof(cwd)) != NULL) { if (getcwd(path, sizeof(path)) != NULL) {
user_info[++i] = sudo_new_key_val("cwd", cwd); user_info[++i] = sudo_new_key_val("cwd", path);
if (user_info[i] == NULL) if (user_info[i] == NULL)
goto bad; goto bad;
ud->cwd = user_info[i] + sizeof("cwd=") - 1; ud->cwd = user_info[i] + sizeof("cwd=") - 1;
} }
if ((cp = get_process_ttyname()) == NULL) { if (get_process_ttyname(path, sizeof(path)) != NULL) {
/* tty may not always be present */ user_info[++i] = sudo_new_key_val("tty", path);
if (errno == ENOMEM)
goto bad;
} else {
user_info[++i] = sudo_new_key_val("tty", cp);
if (user_info[i] == NULL) if (user_info[i] == NULL)
goto bad; goto bad;
ud->tty = user_info[i] + sizeof("tty=") - 1; ud->tty = user_info[i] + sizeof("tty=") - 1;
free(cp); } else {
/* tty may not always be present */
if (errno != ENOENT)
goto bad;
} }
cp = sudo_gethostname(); cp = sudo_gethostname();

View File

@@ -242,7 +242,7 @@ char *getenv_unhooked(const char *name);
int get_net_ifs(char **addrinfo); int get_net_ifs(char **addrinfo);
/* ttyname.c */ /* ttyname.c */
char *get_process_ttyname(void); char *get_process_ttyname(char *name, size_t namelen);
/* signal.c */ /* signal.c */
struct sigaction; struct sigaction;

View File

@@ -96,52 +96,52 @@
#if defined(sudo_kp_tdev) #if defined(sudo_kp_tdev)
/* /*
* Like ttyname() but uses a dev_t instead of an open fd. * Like ttyname() but uses a dev_t instead of an open fd.
* Caller is responsible for freeing the returned string. * Returns name on success and NULL on failure, setting errno.
* The BSD version uses devname() * The BSD version uses devname().
*/ */
static char * static char *
sudo_ttyname_dev(dev_t tdev) sudo_ttyname_dev(dev_t tdev, char *name, size_t namelen)
{ {
char *dev, *tty = NULL; char *dev;
debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL) debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL)
/* Some versions of devname() return NULL on failure, others do not. */ /* Some versions of devname() return NULL on failure, others do not. */
dev = devname(tdev, S_IFCHR); dev = devname(tdev, S_IFCHR);
if (dev != NULL && *dev != '?' && *dev != '#') { if (dev != NULL && *dev != '?' && *dev != '#') {
if (*dev != '/') { if (strlcpy(name, _PATH_DEV, namelen) < namelen &&
/* devname() doesn't use the /dev/ prefix, add one... */ strlcat(name, dev, namelen) < namelen)
size_t len = sizeof(_PATH_DEV) + strlen(dev); debug_return_str(name);
if ((tty = malloc(len)) != NULL) { errno = ERANGE;
strlcpy(tty, _PATH_DEV, len);
strlcat(tty, dev, len);
}
} else {
/* Should not happen but just in case... */
tty = strdup(dev);
}
} else { } else {
/* Not all versions of devname() set errno. */ /* Not all versions of devname() set errno. */
errno = ENOENT; errno = ENOENT;
} }
debug_return_str(tty); debug_return_str(NULL);
} }
#elif defined(HAVE__TTYNAME_DEV) #elif defined(HAVE__TTYNAME_DEV)
extern char *_ttyname_dev(dev_t rdev, char *buffer, size_t buflen); extern char *_ttyname_dev(dev_t rdev, char *buffer, size_t buflen);
/* /*
* Like ttyname() but uses a dev_t instead of an open fd. * Like ttyname() but uses a dev_t instead of an open fd.
* Caller is responsible for freeing the returned string. * Returns name on success and NULL on failure, setting errno.
* This version is just a wrapper around _ttyname_dev(). * This version is just a wrapper around _ttyname_dev().
*/ */
static char * static char *
sudo_ttyname_dev(dev_t tdev) sudo_ttyname_dev(dev_t tdev, char *name, size_t namelen)
{ {
char buf[TTYNAME_MAX], *tty; int serrno = errno;
debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL) debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL)
tty = _ttyname_dev(tdev, buf, sizeof(buf)); /*
* _ttyname_dev() sets errno to ERANGE if namelen is too small
* but does not modify it if tdev is not found.
*/
errno = ENOENT;
if (_ttyname_dev(tdev, name, namelen) == NULL)
debug_return_str(NULL);
errno = serrno;
debug_return_str(tty ? strdup(tty) : NULL); debug_return_str(name);
} }
#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__linux__) #elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__linux__)
/* /*
@@ -167,29 +167,30 @@ static char *ignore_devs[] = {
/* /*
* Do a breadth-first scan of dir looking for the specified device. * Do a breadth-first scan of dir looking for the specified device.
* Returns name on success and NULL on failure, setting errno.
*/ */
static char * static char *
sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin) sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin, char *name, size_t namelen)
{ {
DIR *d = NULL;
char pathbuf[PATH_MAX], **subdirs = NULL, *devname = NULL;
size_t sdlen, num_subdirs = 0, max_subdirs = 0; size_t sdlen, num_subdirs = 0, max_subdirs = 0;
char pathbuf[PATH_MAX], **subdirs = NULL;
char *rval = NULL;
struct dirent *dp; struct dirent *dp;
unsigned int i; unsigned int i;
DIR *d = NULL;
debug_decl(sudo_ttyname_scan, SUDO_DEBUG_UTIL) debug_decl(sudo_ttyname_scan, SUDO_DEBUG_UTIL)
if (dir[0] == '\0' || (d = opendir(dir)) == NULL) if (dir[0] == '\0' || (d = opendir(dir)) == NULL)
goto done; goto done;
sudo_debug_printf(SUDO_DEBUG_INFO, "scanning for dev %u in %s", sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
(unsigned int)rdev, dir); "scanning for dev %u in %s", (unsigned int)rdev, dir);
sdlen = strlen(dir); sdlen = strlen(dir);
if (dir[sdlen - 1] == '/') if (dir[sdlen - 1] == '/')
sdlen--; sdlen--;
if (sdlen + 1 >= sizeof(pathbuf)) { if (sdlen + 1 >= sizeof(pathbuf)) {
errno = ENAMETOOLONG; errno = ERANGE;
sudo_warn("%.*s/", (int)sdlen, dir);
goto done; goto done;
} }
memcpy(pathbuf, dir, sdlen); memcpy(pathbuf, dir, sdlen);
@@ -233,17 +234,29 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin)
} }
# if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(DTTOIF) # if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(DTTOIF)
/* /*
* Convert dp->d_type to sb.st_mode to avoid a stat(2) if possible. * Avoid excessive stat() calls by checking dp->d_type.
* We can't use it for links (since we want to follow them) or
* char devs (since we need st_rdev to compare the device number).
*/ */
if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK && dp->d_type != DT_CHR) { switch (dp->d_type) {
sb.st_mode = DTTOIF(dp->d_type); case DT_CHR:
sb.st_rdev = 0; /* quiet ccc-analyzer false positive */ case DT_LNK:
} else case DT_UNKNOWN:
# endif /* Could be a character device, stat() it. */
if (stat(pathbuf, &sb) == -1) if (stat(pathbuf, &sb) == -1)
continue; continue;
break;
case DT_DIR:
/* Directory, no need to stat() it. */
sb.st_mode = DTTOIF(dp->d_type);
sb.st_rdev = 0; /* quiet ccc-analyzer false positive */
break;
default:
/* Not a character device, link or directory, skip it. */
continue;
}
# else
if (stat(pathbuf, &sb) == -1)
continue;
# endif
if (S_ISDIR(sb.st_mode)) { if (S_ISDIR(sb.st_mode)) {
if (!builtin) { if (!builtin) {
/* Add to list of subdirs to search. */ /* Add to list of subdirs to search. */
@@ -265,16 +278,23 @@ sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin)
continue; continue;
} }
if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) { if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) {
devname = strdup(pathbuf); sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
sudo_debug_printf(SUDO_DEBUG_INFO, "resolved dev %u as %s", "resolved dev %u as %s", (unsigned int)rdev, pathbuf);
(unsigned int)rdev, pathbuf); if (strlcpy(name, pathbuf, namelen) < namelen) {
rval = name;
} else {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to store %s, have %zu, need %zu",
pathbuf, namelen, strlen(pathbuf) + 1);
errno = ERANGE;
}
goto done; goto done;
} }
} }
/* Search subdirs if we didn't find it in the root level. */ /* Search subdirs if we didn't find it in the root level. */
for (i = 0; devname == NULL && i < num_subdirs; i++) for (i = 0; rval == NULL && i < num_subdirs; i++)
devname = sudo_ttyname_scan(subdirs[i], rdev, false); rval = sudo_ttyname_scan(subdirs[i], rdev, false, name, namelen);
done: done:
if (d != NULL) if (d != NULL)
@@ -282,20 +302,21 @@ done:
for (i = 0; i < num_subdirs; i++) for (i = 0; i < num_subdirs; i++)
free(subdirs[i]); free(subdirs[i]);
free(subdirs); free(subdirs);
debug_return_str(devname); debug_return_str(rval);
} }
/* /*
* Like ttyname() but uses a dev_t instead of an open fd. * Like ttyname() but uses a dev_t instead of an open fd.
* Caller is responsible for freeing the returned string. * Returns name on success and NULL on failure, setting errno.
* Generic version. * Generic version.
*/ */
static char * static char *
sudo_ttyname_dev(dev_t rdev) sudo_ttyname_dev(dev_t rdev, char *name, size_t namelen)
{ {
char buf[PATH_MAX], **sd, *devname;
char *rval = NULL;
struct stat sb; struct stat sb;
size_t len; size_t len;
char buf[PATH_MAX], **sd, *devname, *tty = NULL;
debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL) debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL)
/* /*
@@ -310,22 +331,31 @@ sudo_ttyname_dev(dev_t rdev)
(unsigned int)minor(rdev)); (unsigned int)minor(rdev));
if (stat(buf, &sb) == 0) { if (stat(buf, &sb) == 0) {
if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) { if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) {
tty = strdup(buf); sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
"comparing dev %u to %s: match!",
(unsigned int)rdev, buf);
if (strlcpy(name, buf, namelen) < namelen)
rval = name;
else
errno = ERANGE;
goto done; goto done;
} }
} }
sudo_debug_printf(SUDO_DEBUG_INFO, "comparing dev %u to %s: %s", sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
(unsigned int)rdev, buf, tty ? "yes" : "no"); "comparing dev %u to %s: no", (unsigned int)rdev, buf);
} else { } else {
/* Traverse directory */ /* Traverse directory */
tty = sudo_ttyname_scan(devname, rdev, true); rval = sudo_ttyname_scan(devname, rdev, true, name, namelen);
if (tty != NULL || errno == ENOMEM) if (rval != NULL || errno == ENOMEM)
goto done; goto done;
} }
} else { } else {
if (stat(devname, &sb) == 0) { if (stat(devname, &sb) == 0) {
if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) { if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) {
tty = strdup(devname); if (strlcpy(name, devname, namelen) < namelen)
rval = name;
else
errno = ERANGE;
goto done; goto done;
} }
} }
@@ -335,24 +365,24 @@ sudo_ttyname_dev(dev_t rdev)
/* /*
* Not found? Do a breadth-first traversal of /dev/. * Not found? Do a breadth-first traversal of /dev/.
*/ */
tty = sudo_ttyname_scan(_PATH_DEV, rdev, false); rval = sudo_ttyname_scan(_PATH_DEV, rdev, false, name, namelen);
done: done:
debug_return_str(tty); debug_return_str(rval);
} }
#endif #endif
#if defined(sudo_kp_tdev) #if defined(sudo_kp_tdev)
/* /*
* Return a string from ttyname() containing the tty to which the process is * Store the name of the tty to which the process is attached in name.
* attached or NULL if the process has no controlling tty. * Returns name on success and NULL on failure, setting errno.
*/ */
char * char *
get_process_ttyname(void) get_process_ttyname(char *name, size_t namelen)
{ {
char *tty = NULL;
struct sudo_kinfo_proc *ki_proc = NULL; struct sudo_kinfo_proc *ki_proc = NULL;
size_t size = sizeof(*ki_proc); size_t size = sizeof(*ki_proc);
char *rval = NULL;
int mib[6], rc; int mib[6], rc;
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL) debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
@@ -379,30 +409,30 @@ get_process_ttyname(void)
} while (rc == -1 && errno == ENOMEM); } while (rc == -1 && errno == ENOMEM);
if (rc != -1) { if (rc != -1) {
if ((dev_t)ki_proc->sudo_kp_tdev != (dev_t)-1) { if ((dev_t)ki_proc->sudo_kp_tdev != (dev_t)-1) {
tty = sudo_ttyname_dev(ki_proc->sudo_kp_tdev); rval = sudo_ttyname_dev(ki_proc->sudo_kp_tdev, name, namelen);
if (tty == NULL) { if (rval == NULL) {
sudo_debug_printf(SUDO_DEBUG_WARN, sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"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 { } else {
sudo_debug_printf(SUDO_DEBUG_WARN, sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to resolve tty via KERN_PROC: %s", strerror(errno)); "unable to resolve tty via KERN_PROC");
} }
free(ki_proc); free(ki_proc);
debug_return_str(tty); debug_return_str(rval);
} }
#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) #elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
/* /*
* Return a string from ttyname() containing the tty to which the process is * Store the name of the tty to which the process is attached in name.
* attached or NULL if the process has no controlling tty. * Returns name on success and NULL on failure, setting errno.
*/ */
char * char *
get_process_ttyname(void) get_process_ttyname(char *name, size_t namelen)
{ {
char path[PATH_MAX], *tty = NULL; char path[PATH_MAX], *rval = NULL;
struct psinfo psinfo; struct psinfo psinfo;
ssize_t nread; ssize_t nread;
int fd; int fd;
@@ -420,25 +450,26 @@ get_process_ttyname(void)
rdev = makedev(major64(psinfo.pr_ttydev), minor64(psinfo.pr_ttydev)); rdev = makedev(major64(psinfo.pr_ttydev), minor64(psinfo.pr_ttydev));
#endif #endif
if (rdev != (dev_t)-1) if (rdev != (dev_t)-1)
tty = sudo_ttyname_dev(rdev); rval = sudo_ttyname_dev(rdev, name, namelen);
} }
} }
if (tty == NULL) if (rval == NULL)
sudo_debug_printf(SUDO_DEBUG_WARN, sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to resolve tty via %s: %s", path, strerror(errno)); "unable to resolve tty via %s", path);
debug_return_str(tty); debug_return_str(rval);
} }
#elif defined(__linux__) #elif defined(__linux__)
/* /*
* Return a string from ttyname() containing the tty to which the process is * Store the name of the tty to which the process is attached in name.
* attached or NULL if the process has no controlling tty. * Returns name on success and NULL on failure, setting errno.
*/ */
char * char *
get_process_ttyname(void) get_process_ttyname(char *name, size_t namelen)
{ {
char path[PATH_MAX], *line = NULL, *tty = NULL; char path[PATH_MAX], *line = NULL;
char *rval = NULL;
size_t linesize = 0; size_t linesize = 0;
ssize_t len; ssize_t len;
FILE *fp; FILE *fp;
@@ -465,7 +496,7 @@ get_process_ttyname(void)
"%s: tty device %s: %s", path, cp, errstr); "%s: tty device %s: %s", path, cp, errstr);
} }
if (tdev > 0) if (tdev > 0)
tty = sudo_ttyname_dev(tdev); rval = sudo_ttyname_dev(tdev, name, namelen);
break; break;
} }
cp = ep + 1; cp = ep + 1;
@@ -475,22 +506,22 @@ get_process_ttyname(void)
free(line); free(line);
} }
if (tty == NULL) if (rval == NULL)
sudo_debug_printf(SUDO_DEBUG_WARN, sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to resolve tty via %s: %s", path, strerror(errno)); "unable to resolve tty via %s", path);
debug_return_str(tty); debug_return_str(rval);
} }
#elif defined(HAVE_PSTAT_GETPROC) #elif defined(HAVE_PSTAT_GETPROC)
/* /*
* Return a string from ttyname() containing the tty to which the process is * Store the name of the tty to which the process is attached in name.
* attached or NULL if the process has no controlling tty. * Returns name on success and NULL on failure, setting errno.
*/ */
char * char *
get_process_ttyname(void) get_process_ttyname(char *name, size_t namelen)
{ {
struct pst_status pstat; struct pst_status pstat;
char *tty = NULL; char *rval = NULL;
int rc; int rc;
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL) debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
@@ -501,23 +532,23 @@ get_process_ttyname(void)
rc = pstat_getproc(&pstat, sizeof(pstat), (size_t)0, (int)getpid()); rc = pstat_getproc(&pstat, sizeof(pstat), (size_t)0, (int)getpid());
if (rc != -1 || errno == EOVERFLOW) { if (rc != -1 || errno == EOVERFLOW) {
if (pstat.pst_term.psd_major != -1 && pstat.pst_term.psd_minor != -1) { if (pstat.pst_term.psd_major != -1 && pstat.pst_term.psd_minor != -1) {
tty = sudo_ttyname_dev(makedev(pstat.pst_term.psd_major, rval = sudo_ttyname_dev(makedev(pstat.pst_term.psd_major,
pstat.pst_term.psd_minor)); pstat.pst_term.psd_minor), name, namelen);
} }
} }
if (tty == NULL) if (rval == NULL)
sudo_debug_printf(SUDO_DEBUG_WARN, sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to resolve tty via pstat: %s", strerror(errno)); "unable to resolve tty via pstat");
debug_return_str(tty); debug_return_str(rval);
} }
#else #else
/* /*
* Return a string from ttyname() containing the tty to which the process is * Store the name of the tty to which the process is attached in name.
* attached or NULL if the process has no controlling tty. * Returns name on success and NULL on failure, setting errno.
*/ */
char * char *
get_process_ttyname(void) get_process_ttyname(char *name, size_t namelen)
{ {
char *tty; char *tty;
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL) debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
@@ -526,12 +557,18 @@ get_process_ttyname(void)
if ((tty = ttyname(STDOUT_FILENO)) == NULL) if ((tty = ttyname(STDOUT_FILENO)) == NULL)
tty = ttyname(STDERR_FILENO); tty = ttyname(STDERR_FILENO);
} }
if (tty == NULL) { if (tty != NULL) {
sudo_debug_printf(SUDO_DEBUG_WARN, if (strlcpy(name, tty, namelen) < namelen)
"unable to resolve tty via ttyname: %s", strerror(errno)); debug_return_str(name);
debug_return_str(NULL); errno = ERANGE;
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to store tty from ttyname");
} else {
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
"unable to resolve tty via ttyname");
errno = ENOENT;
} }
debug_return_str(strdup(tty)); debug_return_str(NULL);
} }
#endif #endif