Diff for /embedaddon/sudo/src/ttyname.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2012/10/09 09:29:52 version 1.1.1.3, 2013/07/22 10:46:13
Line 1 Line 1
 /*  /*
 * 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   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
Line 23 Line 23
 #endif  #endif
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/param.h>  
 #include <sys/stat.h>  #include <sys/stat.h>
 #if defined(MAJOR_IN_MKDEV)  #if defined(MAJOR_IN_MKDEV)
 # include <sys/mkdev.h>  # include <sys/mkdev.h>
Line 71 Line 70
 # endif  # endif
 #endif  #endif
 #if defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined (HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV) || defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV)  #if defined(HAVE_STRUCT_KINFO_PROC_P_TDEV) || defined (HAVE_STRUCT_KINFO_PROC_KP_EPROC_E_TDEV) || defined(HAVE_STRUCT_KINFO_PROC2_P_TDEV)
   # include <sys/param.h>
 # include <sys/sysctl.h>  # include <sys/sysctl.h>
 #elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)  #elif defined(HAVE_STRUCT_KINFO_PROC_KI_TDEV)
   # include <sys/param.h>
 # include <sys/sysctl.h>  # include <sys/sysctl.h>
 # include <sys/user.h>  # include <sys/user.h>
 #endif  #endif
Line 81 Line 82
 #elif defined(HAVE_SYS_PROCFS_H)  #elif defined(HAVE_SYS_PROCFS_H)
 # include <sys/procfs.h>  # include <sys/procfs.h>
 #endif  #endif
   #ifdef HAVE_PSTAT_GETPROC
   # include <sys/param.h>
   # include <sys/pstat.h>
   #endif
   
 #include "sudo.h"  #include "sudo.h"
   
Line 155  sudo_ttyname_dev(dev_t tdev) Line 160  sudo_ttyname_dev(dev_t tdev)
   
     debug_return_str(estrdup(tty));      debug_return_str(estrdup(tty));
 }  }
#else#elif defined(HAVE_STRUCT_PSINFO_PR_TTYDEV) || defined(HAVE_PSTAT_GETPROC) || defined(__linux__)
 /*  /*
  * Devices to search before doing a breadth-first scan.   * Devices to search before doing a breadth-first scan.
  */   */
Line 180  static char *ignore_devs[] = { Line 185  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.
  */   */
staticstatic char *
char *sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin)sudo_ttyname_scan(const char *dir, dev_t rdev, bool builtin)
 {  {
    DIR *d;    DIR *d = NULL;
     char pathbuf[PATH_MAX], **subdirs = NULL, *devname = NULL;      char pathbuf[PATH_MAX], **subdirs = NULL, *devname = NULL;
     size_t sdlen, d_len, len, num_subdirs = 0, max_subdirs = 0;      size_t sdlen, d_len, len, num_subdirs = 0, max_subdirs = 0;
     struct dirent *dp;      struct dirent *dp;
Line 194  char *sudo_ttyname_scan(const char *dir, dev_t rdev, b Line 199  char *sudo_ttyname_scan(const char *dir, dev_t rdev, b
     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",
           (unsigned int)rdev, dir);
   
     sdlen = strlen(dir);      sdlen = strlen(dir);
     if (dir[sdlen - 1] == '/')      if (dir[sdlen - 1] == '/')
         sdlen--;          sdlen--;
Line 239  char *sudo_ttyname_scan(const char *dir, dev_t rdev, b Line 247  char *sudo_ttyname_scan(const char *dir, dev_t rdev, b
                 continue;                  continue;
         }          }
 # if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(DTTOIF)  # if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(DTTOIF)
        /* Use d_type to avoid a stat() if possible. */        /*
        /* Convert d_type to stat-style type bits but follow links. */         * Convert dp->d_type to sb.st_mode to avoid a stat(2) if possible.
        if (dp->d_type != DT_LNK && dp->d_type != DT_CHR)         * 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)
             sb.st_mode = DTTOIF(dp->d_type);              sb.st_mode = DTTOIF(dp->d_type);
         else          else
 # endif  # endif
Line 260  char *sudo_ttyname_scan(const char *dir, dev_t rdev, b Line 271  char *sudo_ttyname_scan(const char *dir, dev_t rdev, b
         }          }
         if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) {          if (S_ISCHR(sb.st_mode) && sb.st_rdev == rdev) {
             devname = estrdup(pathbuf);              devname = estrdup(pathbuf);
            break;            sudo_debug_printf(SUDO_DEBUG_INFO, "resolved dev %u as %s",
                 (unsigned int)rdev, pathbuf);
             goto done;
         }          }
     }      }
     closedir(d);  
   
     /* 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; devname == NULL && i < num_subdirs; i++)
         devname = sudo_ttyname_scan(subdirs[i], rdev, false);          devname = sudo_ttyname_scan(subdirs[i], rdev, false);
   
 done:  done:
       if (d != NULL)
           closedir(d);
     for (i = 0; i < num_subdirs; i++)      for (i = 0; i < num_subdirs; i++)
         efree(subdirs[i]);          efree(subdirs[i]);
     efree(subdirs);      efree(subdirs);
Line 290  sudo_ttyname_dev(dev_t rdev) Line 304  sudo_ttyname_dev(dev_t rdev)
     debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL)      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);          len = strlen(devname);
         if (devname[len - 1] == '/') {          if (devname[len - 1] == '/') {
             /* Special case /dev/pts */  
             if (strcmp(devname, "/dev/pts/") == 0) {              if (strcmp(devname, "/dev/pts/") == 0) {
                   /* Special case /dev/pts */
                 (void)snprintf(buf, sizeof(buf), "%spts/%u", _PATH_DEV,                  (void)snprintf(buf, sizeof(buf), "%spts/%u", _PATH_DEV,
                     (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 = estrdup(buf);                          tty = estrdup(buf);
                         break;  
                     }  
                 }                  }
                continue;                sudo_debug_printf(SUDO_DEBUG_INFO, "comparing dev %u to %s: %s",
                     (unsigned int)rdev, buf, tty ? "yes" : "no");
             } else {
                 /* Traverse directory */
                 tty = sudo_ttyname_scan(devname, rdev, true);
             }              }
             /* Traverse directory */  
             tty = sudo_ttyname_scan(devname, rdev, true);  
         } 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 = estrdup(devname);                      tty = estrdup(devname);
                     break;  
                 }  
             }              }
         }          }
     }      }
Line 332  sudo_ttyname_dev(dev_t rdev) Line 344  sudo_ttyname_dev(dev_t rdev)
 #if defined(sudo_kp_tdev)  #if defined(sudo_kp_tdev)
 /*  /*
  * Return a string from ttyname() containing the tty to which the process is   * 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 * attached or NULL if the process has no controlling tty.
 * 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 *  char *
 get_process_ttyname(void)  get_process_ttyname(void)
Line 342  get_process_ttyname(void) Line 352  get_process_ttyname(void)
     char *tty = NULL;      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);
    int i, mib[6], rc;    int mib[6], rc;
     debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)      debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
   
     /*      /*
     * Lookup tty for this process and, failing that, our parent.     * Lookup controlling tty for this process via sysctl.
     * Even if we redirect std{in,out,err} the kernel should still know.     * This will work even if std{in,out,err} are redirected.
      */       */
    for (i = 0; tty == NULL && i < 2; i++) {    mib[0] = CTL_KERN;
        mib[0] = CTL_KERN;    mib[1] = SUDO_KERN_PROC;
        mib[1] = SUDO_KERN_PROC;    mib[2] = KERN_PROC_PID;
        mib[2] = KERN_PROC_PID;    mib[3] = (int)getpid();
        mib[3] = i ? (int)getppid() : (int)getpid();    mib[4] = sizeof(*ki_proc);
        mib[4] = sizeof(*ki_proc);    mib[5] = 1;
        mib[5] = 1;    do {
        do {        size += size / 10;
            size += size / 10;        ki_proc = erealloc(ki_proc, size);
            ki_proc = erealloc(ki_proc, size);        rc = sysctl(mib, sudo_kp_namelen, ki_proc, &size, NULL, 0);
            rc = sysctl(mib, sudo_kp_namelen, ki_proc, &size, NULL, 0);    } while (rc == -1 && errno == ENOMEM);
        } while (rc == -1 && errno == ENOMEM);    if (rc != -1) {
        if (rc != -1) {        if (ki_proc->sudo_kp_tdev != (dev_t)-1) {
            if (ki_proc->sudo_kp_tdev != (dev_t)-1) {            tty = sudo_ttyname_dev(ki_proc->sudo_kp_tdev);
                tty = sudo_ttyname_dev(ki_proc->sudo_kp_tdev);            if (tty == NULL) {
                if (tty == NULL) {                sudo_debug_printf(SUDO_DEBUG_WARN,
                    sudo_debug_printf(SUDO_DEBUG_WARN,                    "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 {  
             sudo_debug_printf(SUDO_DEBUG_WARN,  
                 "unable to resolve tty via KERN_PROC: %s", strerror(errno));  
         }          }
       } else {
           sudo_debug_printf(SUDO_DEBUG_WARN,
               "unable to resolve tty via KERN_PROC: %s", strerror(errno));
     }      }
     efree(ki_proc);      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);      debug_return_str(tty);
 }  }
 #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   * 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 * attached or NULL if the process has no controlling tty.
 * parent).  First tries /proc/pid/psinfo, then /proc/ppid/psinfo. 
 * Falls back on ttyname of std{in,out,err} if that fails. 
  */   */
 char *  char *
 get_process_ttyname(void)  get_process_ttyname(void)
Line 400  get_process_ttyname(void) Line 398  get_process_ttyname(void)
     char path[PATH_MAX], *tty = NULL;      char path[PATH_MAX], *tty = NULL;
     struct psinfo psinfo;      struct psinfo psinfo;
     ssize_t nread;      ssize_t nread;
    int i, fd;    int fd;
     debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)      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 pr_ttydev in /proc/pid/psinfo. */
    for (i = 0; tty == NULL && i < 2; i++) {    snprintf(path, sizeof(path), "/proc/%u/psinfo", (unsigned int)getpid());
        (void)snprintf(path, sizeof(path), "/proc/%u/psinfo",    if ((fd = open(path, O_RDONLY, 0)) != -1) {
            i ? (unsigned int)getppid() : (unsigned int)getpid()); 
        if ((fd = open(path, O_RDONLY, 0)) == -1) 
            continue; 
         nread = read(fd, &psinfo, sizeof(psinfo));          nread = read(fd, &psinfo, sizeof(psinfo));
         close(fd);          close(fd);
        if (nread == (ssize_t)sizeof(psinfo) && psinfo.pr_ttydev != (dev_t)-1) {        if (nread == (ssize_t)sizeof(psinfo)) {
            tty = sudo_ttyname_dev(psinfo.pr_ttydev);            dev_t rdev = (dev_t)psinfo.pr_ttydev;
 #if defined(_AIX) && defined(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);      debug_return_str(tty);
 }  }
 #elif defined(__linux__)  #elif defined(__linux__)
 /*  /*
  * Return a string from ttyname() containing the tty to which the process is   * 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 * attached or NULL if the process has no controlling tty.
 * parent).  First tries field 7 in /proc/pid/stat, then /proc/ppid/stat. 
 * Falls back on ttyname of std{in,out,err} if that fails. 
  */   */
 char *  char *
 get_process_ttyname(void)  get_process_ttyname(void)
 {  {
    char *line = NULL, *tty = NULL;    char path[PATH_MAX], *line = NULL, *tty = NULL;
     size_t linesize = 0;      size_t linesize = 0;
     ssize_t len;      ssize_t len;
    int i;    FILE *fp;
     debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)      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++) {    snprintf(path, sizeof(path), "/proc/%u/stat", (unsigned int)getpid());
        FILE *fp;    if ((fp = fopen(path, "r")) != NULL) {
        char path[PATH_MAX]; 
        (void)snprintf(path, sizeof(path), "/proc/%u/stat", 
            i ? (unsigned int)getppid() : (unsigned int)getpid()); 
        if ((fp = fopen(path, "r")) == NULL) 
            continue; 
         len = getline(&line, &linesize, fp);          len = getline(&line, &linesize, fp);
         fclose(fp);          fclose(fp);
         if (len != -1) {          if (len != -1) {
Line 467  get_process_ttyname(void) Line 453  get_process_ttyname(void)
                 }                  }
             }              }
         }          }
           efree(line);
     }      }
     efree(line);  
   
    /* If all else fails, fall back on ttyname(). */    debug_return_str(tty);
    if (tty == NULL) {}
        if ((tty = ttyname(STDIN_FILENO)) != NULL ||#elif HAVE_PSTAT_GETPROC
            (tty = ttyname(STDOUT_FILENO)) != NULL ||/*
            (tty = ttyname(STDERR_FILENO)) != NULL) * Return a string from ttyname() containing the tty to which the process is
            tty = estrdup(tty); * attached or NULL if the process has no controlling tty.
    } */
 char *
 get_process_ttyname(void)
 {
     struct pst_status pstat;
     char *tty = NULL;
     debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
   
       /* Try to determine the tty from psdev in struct pst_status. */
       if (pstat_getproc(&pstat, sizeof(pstat), 0, (int)getpid()) != -1) {
           if (pstat.pst_term.psd_major != -1 && pstat.pst_term.psd_minor != -1) {
               tty = sudo_ttyname_dev(makedev(pstat.pst_term.psd_major,
                   pstat.pst_term.psd_minor));
           }
       }
     debug_return_str(tty);      debug_return_str(tty);
 }  }
 #else  #else
 /*  /*
  * Return a string from ttyname() containing the tty to which the process is   * 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. * attached or NULL if the process has no controlling tty.
 * parent). 
  */   */
 char *  char *
 get_process_ttyname(void)  get_process_ttyname(void)

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>