parse_args.c pwutil.c set_perms.c setsid.c sigaction.c snprintf.c \
strcasecmp.c strerror.c strlcat.c strlcpy.c strsignal.c sudo.c \
sudo_noexec.c sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c \
- toke.c toke.l toke_util.c tsgetgrpw.c utimes.c vasgroups.c visudo.c \
- zero_bytes.c redblack.c selinux.c sesh.c sudoreplay.c getdate.c \
- getdate.y getline.c timestr.c $(AUTH_SRCS)
+ toke.c toke.l toke_util.c tsgetgrpw.c ttyname.c utimes.c vasgroups.c \
+ visudo.c zero_bytes.c redblack.c selinux.c sesh.c sudoreplay.c \
+ getdate.c getdate.y getline.c timestr.c $(AUTH_SRCS)
AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \
auth/kerb4.c auth/kerb5.c auth/pam.c auth/passwd.c auth/rfc1938.c \
SUDO_OBJS = $(AUTH_OBJS) @SUDO_OBJS@ audit.o boottime.o check.o env.o \
exec.o gettime.o goodpath.o fileops.o find_path.o \
interfaces.o lbuf.o logging.o logwrap.o parse.o parse_args.o \
- set_perms.o sudo.o sudo_edit.o sudo_nss.o tgetpass.o
+ set_perms.o sudo.o sudo_edit.o sudo_nss.o tgetpass.o ttyname.o
VISUDO_OBJS = visudo.o fileops.o gettime.o goodpath.o find_path.o
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/testsudoers.c
tgetpass.o: $(srcdir)/tgetpass.c $(SUDODEP)
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tgetpass.c
+ttyname.o: $(srcdir)/ttyname.c $(SUDODEP)
+ $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/ttyname.c
timestr.o: $(srcdir)/timestr.c $(srcdir)/missing.h config.h
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/timestr.c
toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/toke.h $(devdir)/gram.h
exit(0); /* not reached */
}
-/*
- * How to access the tty device number in struct kinfo_proc.
- */
-#if defined(HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV)
-# define sudo_kp_tdev kp_eproc.e_tdev
-# define sudo_kp_namelen 4
-#else
-# if defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
-# define sudo_kp_tdev ki_tdev
-# define sudo_kp_namelen 4
-# else
-# if defined(HAVE_STRUCT_KINFO_PROC_P_TDEV)
-# define sudo_kp_tdev p_tdev
-# define sudo_kp_namelen 6
-# endif
-# endif
-#endif
-
-#ifdef sudo_kp_tdev
-/*
- * 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 sysctl using the current pid, then the parent's pid.
- * Falls back on ttyname of std{in,out,err} if that fails.
- */
-static char *
-get_process_tty(void)
-{
- char *tty = NULL;
- struct kinfo_proc *ki_proc = NULL;
- size_t size = sizeof(*ki_proc);
- int i, mib[6], rc;
-
- /*
- * Lookup tty for this process and, failing that, our parent.
- * Even if we redirect std{in,out,err} the kernel should still know.
- */
- for (i = 0; tty == NULL && i < 2; i++) {
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = i ? (int)getppid() : (int)getpid();
- mib[4] = sizeof(*ki_proc);
- mib[5] = 1;
- do {
- size += size / 10;
- ki_proc = erealloc(ki_proc, size);
- 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 != '#') {
- 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);
- }
- }
- }
- efree(ki_proc);
- }
-
- /* 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);
- }
-
- return 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 (or its
- * parent). First tries std{in,out,err} then falls back to the parent's /proc
- * entry. We could try following the parent all the way to pid 1 but
- * /proc/%d/status is system-specific (text on Linux, a struct on Solaris).
- */
-static char *
-get_process_tty(void)
-{
- char path[PATH_MAX], *tty = NULL;
- pid_t ppid;
- int i, fd;
-
- 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/%d/fd/%d", ppid, i);
- fd = open(path, O_RDONLY|O_NOCTTY, 0);
- if (fd != -1) {
- tty = ttyname(fd);
- close(fd);
- }
- }
- }
-
- return estrdup(tty);
-}
-#endif /* sudo_kp_tdev */
-
/*
* Initialize timezone, set umask, fill in ``sudo_user'' struct and
* load the ``interfaces'' array.
}
}
- if ((p = get_process_tty()) != NULL) {
+ if ((p = get_process_ttyname()) != NULL) {
user_tty = user_ttypath = p;
if (strncmp(user_tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
user_tty += sizeof(_PATH_DEV) - 1;
/* zero_bytes.c */
void zero_bytes __P((volatile void *, size_t));
+/* ttyname.c */
+char *get_process_ttyname __P((void));
+
/* Only provide extern declarations outside of sudo.c. */
#ifndef _SUDO_MAIN
extern struct sudo_user sudo_user;
--- /dev/null
+/*
+ * Copyright (c) 2012 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
+# include <memory.h>
+# endif
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <errno.h>
+#include <fcntl.h>
+#if defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined (HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV)
+# include <sys/sysctl.h>
+#elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
+# include <sys/sysctl.h>
+# include <sys/user.h>
+#endif
+
+#include "sudo.h"
+
+/*
+ * How to access the tty device number in struct kinfo_proc.
+ */
+#if defined(HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV)
+# define sudo_kp_tdev kp_eproc.e_tdev
+# define sudo_kp_namelen 4
+#elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
+# define sudo_kp_tdev ki_tdev
+# define sudo_kp_namelen 4
+#elif defined(HAVE_STRUCT_KINFO_PROC_P_TDEV)
+# define sudo_kp_tdev p_tdev
+# define sudo_kp_namelen 6
+#endif
+
+#ifdef sudo_kp_tdev
+/*
+ * 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 sysctl using the current pid, then the parent's pid.
+ * Falls back on ttyname of std{in,out,err} if that fails.
+ */
+char *
+get_process_ttyname()
+{
+ char *tty = NULL;
+ struct kinfo_proc *ki_proc = NULL;
+ size_t size = sizeof(*ki_proc);
+ int i, mib[6], rc;
+
+ /*
+ * Lookup tty for this process and, failing that, our parent.
+ * Even if we redirect std{in,out,err} the kernel should still know.
+ */
+ for (i = 0; tty == NULL && i < 2; i++) {
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = i ? (int)getppid() : (int)getpid();
+ mib[4] = sizeof(*ki_proc);
+ mib[5] = 1;
+ do {
+ size += size / 10;
+ ki_proc = erealloc(ki_proc, size);
+ 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 != '#') {
+ 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);
+ }
+ }
+ }
+ efree(ki_proc);
+ }
+
+ /* 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);
+ }
+
+ return 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 (or its
+ * parent). First tries std{in,out,err} then falls back to the parent's /proc
+ * entry. We could try following the parent all the way to pid 1 but
+ * /proc/%d/status is system-specific (text on Linux, a struct on Solaris).
+ */
+char *
+get_process_ttyname()
+{
+ char path[PATH_MAX], *tty = NULL;
+ pid_t ppid;
+ int i, fd;
+
+ 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/%d/fd/%d", ppid, i);
+ fd = open(path, O_RDONLY|O_NOCTTY, 0);
+ if (fd != -1) {
+ tty = ttyname(fd);
+ close(fd);
+ }
+ }
+ }
+
+ return estrdup(tty);
+}
+#endif /* sudo_kp_tdev */