Imported Upstream version 1.8.6p8
[debian/sudo] / src / ttyname.c
index aa06acf729af7a59ed9229b87ce820cf81b31829..b86ee55797f98e8c82b6e333c5e2e7a92af12eb0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2012-2013 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
@@ -180,10 +180,10 @@ static char *ignore_devs[] = {
 /*
  * Do a breadth-first scan of dir looking for the specified device.
  */
-static
-char *sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin)
+static char *
+sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin)
 {
-    DIR *d;
+    DIR *d = NULL;
     char pathbuf[PATH_MAX], **subdirs = NULL, *devname = NULL;
     size_t sdlen, d_len, len, num_subdirs = 0, max_subdirs = 0;
     struct dirent *dp;
@@ -260,16 +260,17 @@ char *sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin)
        }
        if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) {
            devname = estrdup(pathbuf);
-           break;
+           goto done;
        }
     }
-    closedir(d);
 
     /* Search subdirs if we didn't find it in the root level. */
     for (i = 0; devname == NULL && i < num_subdirs; i++)
        devname = sudo_ttyname_scan(subdirs[i], rdev, false);
 
 done:
+    if (d != NULL)
+       closedir(d);
     for (i = 0; i < num_subdirs; i++)
        efree(subdirs[i]);
     efree(subdirs);
@@ -290,31 +291,27 @@ sudo_ttyname_dev(dev_t rdev)
     debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL)
 
     /*
-     * First check search_devs.
+     * First check search_devs for common tty devices.
      */
-    for (sd = search_devs; (devname = *sd) != NULL; sd++) {
+    for (sd = search_devs; tty == NULL && (devname = *sd) != NULL; sd++) {
        len = strlen(devname);
        if (devname[len - 1] == '/') {
-           /* Special case /dev/pts */
            if (strcmp(devname, "/dev/pts/") == 0) {
+               /* Special case /dev/pts */
                (void)snprintf(buf, sizeof(buf), "%spts/%u", _PATH_DEV,
                    (unsigned int)minor(rdev));
                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 = estrdup(buf);
-                       break;
-                   }
                }
-               continue;
+           } else {
+               /* Traverse directory */
+               tty = sudo_ttyname_scan(devname, rdev, true);
            }
-           /* Traverse directory */
-           tty = sudo_ttyname_scan(devname, rdev, true);
        } else {
            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 = estrdup(devname);
-                   break;
-               }
            }
        }
     }
@@ -377,14 +374,6 @@ get_process_ttyname(void)
     }
     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);
-    }
-
     debug_return_str(tty);
 }
 #elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV)
@@ -398,7 +387,6 @@ char *
 get_process_ttyname(void)
 {
     char path[PATH_MAX], *tty = NULL;
-    struct stat sb;
     struct psinfo psinfo;
     ssize_t nread;
     int i, fd;
@@ -412,19 +400,17 @@ get_process_ttyname(void)
            continue;
        nread = read(fd, &psinfo, sizeof(psinfo));
        close(fd);
-       if (nread == (ssize_t)sizeof(psinfo) && psinfo.pr_ttydev != (dev_t)-1) {
-           tty = sudo_ttyname_dev(psinfo.pr_ttydev);
+       if (nread == (ssize_t)sizeof(psinfo)) {
+           dev_t rdev = (dev_t)psinfo.pr_ttydev;
+#ifdef DEVNO64
+           if (psinfo.pr_ttydev & DEVNO64)
+               rdev = makedev(major64(psinfo.pr_ttydev), minor64(psinfo.pr_ttydev));
+#endif
+           if (rdev != (dev_t)-1)
+               tty = sudo_ttyname_dev(rdev);
        }
     }
 
-    /* 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);
 }
 #elif defined(__linux__)
@@ -443,7 +429,7 @@ get_process_ttyname(void)
     int i;
     debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
 
-    /* Try to determine the tty from pr_ttydev in /proc/pid/psinfo. */
+    /* Try to determine the tty from tty_nr in /proc/pid/stat. */
     for (i = 0; tty == NULL && i < 2; i++) {
        FILE *fp;
        char path[PATH_MAX];
@@ -471,14 +457,6 @@ get_process_ttyname(void)
     }
     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