]> granicus.if.org Git - sudo/commitdiff
Move tty name lookup code to its own file.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 13 Jan 2012 11:11:23 +0000 (06:11 -0500)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 13 Jan 2012 11:11:23 +0000 (06:11 -0500)
--HG--
branch : 1.7

Makefile.in
sudo.c
sudo.h
ttyname.c [new file with mode: 0644]

index e5fbda7cb44aedb0f8be8aa56819f7e37299a7c8..7a92ef936414fafee3d18398fb3193d3d60b35ed 100644 (file)
@@ -114,9 +114,9 @@ SRCS = aix.c alias.c alloc.c audit.c boottime.c bsm_audit.c check.c \
        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 \
@@ -139,7 +139,7 @@ COMMON_OBJS = alias.o alloc.o defaults.o error.o gram.o \
 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
 
@@ -391,6 +391,8 @@ testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/li
        $(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
diff --git a/sudo.c b/sudo.c
index bdd64df44157f145bf0c8a827057fc40a0189c47..e5235ecf6a294d3e23a1fe42a10de21f0a20924b 100644 (file)
--- a/sudo.c
+++ b/sudo.c
@@ -582,118 +582,6 @@ main(argc, argv, envp)
     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.
@@ -739,7 +627,7 @@ init_vars(envp)
        }
     }
 
-    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;
diff --git a/sudo.h b/sudo.h
index bbb80ac232a7ac4cb766b14daa18cf066b62f4dc..36edf22cb48c8810c429fcad231c54a8e796987c 100644 (file)
--- a/sudo.h
+++ b/sudo.h
@@ -356,6 +356,9 @@ YY_DECL;
 /* 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;
diff --git a/ttyname.c b/ttyname.c
new file mode 100644 (file)
index 0000000..68a1e38
--- /dev/null
+++ b/ttyname.c
@@ -0,0 +1,160 @@
+/*
+ * 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 */