]> granicus.if.org Git - sudo/commitdiff
Check for SVR4-style struct psinfo.pr_ttydev and use that to determine
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 10 Apr 2012 19:53:41 +0000 (15:53 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 10 Apr 2012 19:53:41 +0000 (15:53 -0400)
the tty if std{in,out,err} are not ttys.

config.h.in
configure
configure.in
src/ttyname.c

index 45211d83c88d57bef63753ca148e973585d0652a..05f14b5fc6477ea088f93fb679e86586c2b50e74 100644 (file)
 /* Define to 1 if you have the `priv_set' function. */
 #undef HAVE_PRIV_SET
 
+/* Define to 1 if you have the <procfs.h> header file. */
+#undef HAVE_PROCFS_H
+
 /* Define to 1 if you have the <project.h> header file. */
 #undef HAVE_PROJECT_H
 
 /* Define to 1 if `p_tdev' is a member of `struct kinfo_proc'. */
 #undef HAVE_STRUCT_KINFO_PROC_P_TDEV
 
+/* Define to 1 if `pr_ttydev' is a member of `struct psinfo'. */
+#undef HAVE_STRUCT_PSINFO_PR_TTYDEV
+
 /* Define if your struct sockadr has an sa_len field. */
 #undef HAVE_STRUCT_SOCKADDR_SA_LEN
 
    */
 #undef HAVE_SYS_NDIR_H
 
+/* Define to 1 if you have the <sys/procfs.h> header file. */
+#undef HAVE_SYS_PROCFS_H
+
 /* Define to 1 if you have the <sys/select.h> header file. */
 #undef HAVE_SYS_SELECT_H
 
index 7584a798bac933709ff7a0375f7e220659260811..134c19d6fbfb8ba695a66b453848781068b4ce07 100755 (executable)
--- a/configure
+++ b/configure
@@ -2150,6 +2150,63 @@ fi
 
 } # ac_fn_c_check_header_mongrel
 
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$4=yes"
+else
+  eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+
 # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
 # --------------------------------------------
 # Tries to find the compile-time value of EXPR in a program that includes
@@ -2328,63 +2385,6 @@ rm -f conftest.val
 
 } # ac_fn_c_compute_int
 
-# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
-# ----------------------------------------------------
-# Tries to find if the field MEMBER exists in type AGGR, after including
-# INCLUDES, setting cache variable VAR accordingly.
-ac_fn_c_check_member ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
-$as_echo_n "checking for $2.$3... " >&6; }
-if eval \${$4+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$5
-int
-main ()
-{
-static $2 ac_aggr;
-if (ac_aggr.$3)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  eval "$4=yes"
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$5
-int
-main ()
-{
-static $2 ac_aggr;
-if (sizeof ac_aggr.$3)
-return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  eval "$4=yes"
-else
-  eval "$4=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$4
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_member
-
 # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
 # ---------------------------------------------
 # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
 
 done
 
+for ac_header in procfs.h sys/procfs.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ ac_fn_c_check_member "$LINENO" "struct psinfo" "pr_ttydev" "ac_cv_member_struct_psinfo_pr_ttydev" "$ac_includes_default
+#ifdef HAVE_PROCFS_H
+#include <procfs.h>
+#endif
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h>
+#endif
+
+"
+if test "x$ac_cv_member_struct_psinfo_pr_ttydev" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_PSINFO_PR_TTYDEV 1
+_ACEOF
+
+
+fi
+
+break
+fi
+
+done
+
 # Check whether --enable-largefile was given.
 if test "${enable_largefile+set}" = set; then :
   enableval=$enable_largefile;
index 14bfe25f6a44366106c28bca9643c1018ee08741..bedf548ad3fc4355365a550962ffeceec17073b7 100644 (file)
@@ -2007,6 +2007,15 @@ 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
+#ifdef HAVE_PROCFS_H
+#include <procfs.h>
+#endif
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h>
+#endif
+])]
+break)
 dnl
 dnl Check for large file support.  HP-UX 11.23 has a broken sys/type.h
 dnl when large files support is enabled so work around it.
index 4bd10e510f83a3330c9f08da4abc66b8b785748b..499bfa872354781b57cd67906803256d73382342 100644 (file)
 
 #include <config.h>
 
+/* Large files not supported by procfs.h */
+#if defined(HAVE_PROCFS_H) || defined(HAVE_SYS_PROCFS_H)
+# undef _FILE_OFFSET_BITS
+# undef _LARGE_FILES
+#endif
+
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/stat.h>
 # include <sys/sysctl.h>
 # include <sys/user.h>
 #endif
+#if defined(HAVE_PROCFS_H)
+# include <procfs.h>
+#elif defined(HAVE_SYS_PROCFS_H)
+# include <sys/procfs.h>
+#endif
 
 #include "sudo.h"
 
@@ -79,7 +90,7 @@
 # define sudo_kp_namelen       4
 #endif
 
-#ifdef sudo_kp_tdev
+#if defined(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
@@ -145,13 +156,59 @@ get_process_ttyname(void)
 
     debug_return_str(tty);
 }
+#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
+/*
+ * 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.
+ */
+char *
+get_process_ttyname(void)
+{
+    char path[PATH_MAX], *tty = NULL;
+    struct stat sb;
+    struct psinfo psinfo;
+    ssize_t nread;
+    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);
+               }
+           }
+       }
+    }
+
+    debug_return_str(estrdup(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 SVR4).
+ * parent).  First tries std{in,out,err} then falls back to our parent's /proc
+ * entry.
  */
 char *
 get_process_ttyname(void)
@@ -168,26 +225,8 @@ get_process_ttyname(void)
        /* 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", (int)ppid, i);
-           if (stat(path, &sb) != 0)
-               continue;
-           /*
-            * SVR4-style /proc doesn't allow /proc/pid/fd/[0-2]
-            * to be used if it is a device and sets the mode to 0000.
-            * Linux-style /proc uses a link to the actual tty.
-            */
-           if (S_ISCHR(sb.st_mode) &&
-               (sb.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) == 0) {
-               /*
-                * We can't open it but maybe we can determine
-                * the pts device using the minor number.
-                */
-               dev_t fd_dev = sb.st_rdev;
-               (void)snprintf(path, sizeof(path), "/dev/pts/%u",
-                   (unsigned int)minor(sb.st_rdev));
-               if (stat(path, &sb) != 0 || sb.st_rdev != fd_dev)
-                   continue;
-           }
+           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);
@@ -198,4 +237,4 @@ get_process_ttyname(void)
 
     debug_return_str(estrdup(tty));
 }
-#endif /* sudo_kp_tdev */
+#endif /* !sudo_kp_tdev && !HAVE_STRUCT_PSINFO_PR_TTYDEV */