[PATCH] kpty weirdness (was: Re: kdelibs/kdecore)

Oswald Buddenhagen ossi at kde.org
Thu Jan 15 21:01:41 GMT 2004


On Thu, Jan 15, 2004 at 09:24:16PM +0100, Waldo Bastian wrote:
> > /me looks at waldo, the supposed (co-)maintainer of that stuff. :)
> >
> 
> Can you repost the patch?
> 
sure ... *grmpf* ;)
once with -w (for reading the changes) and once without -w (for reading
the patched source). :)

greetings

-- 
Hi! I'm a .signature virus! Copy me into your ~/.signature, please!
--
Chaos, panic, and disorder - my work here is done.
-------------- next part --------------
Index: kpty.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdecore/kpty.cpp,v
retrieving revision 1.18
diff -U2 -w -r1.18 kpty.cpp
--- kpty.cpp	13 Jan 2004 01:02:29 -0000	1.18
+++ kpty.cpp	15 Jan 2004 20:58:28 -0000
@@ -159,5 +159,5 @@
 struct KPtyPrivate {
    KPtyPrivate() : 
-     xonXoff(false), needGrantPty(false),
+     xonXoff(false),
      masterFd(-1), slaveFd(-1)
    { 
@@ -168,5 +168,4 @@
 
    bool xonXoff : 1;
-   bool needGrantPty : 1;
    int masterFd;
    int slaveFd;
@@ -204,13 +203,6 @@
 
   // We try, as we know them, one by one.
-#if defined(HAVE_OPENPTY)
-  if (openpty(&d->masterFd, &d->slaveFd, NULL, NULL, NULL) == 0)
-  {
-    d->ttyName = ttyname(d->slaveFd);
-    goto gotpty2;
-  }
-#endif
 
-#if defined(HAVE_PTSNAME)
+#if defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT)
 #ifdef _AIX
   d->masterFd = ::open("/dev/ptc",O_RDWR);
@@ -222,6 +214,7 @@
     char *ptsn = ptsname(d->masterFd);
     if (ptsn) {
+        grantpt(d->masterFd);
         d->ttyName = ptsn;
-        goto gotpty1;
+        goto gotpty;
     } else {
        ::close(d->masterFd);
@@ -254,6 +247,18 @@
         }
 #endif /* sun */
-        if (geteuid() == 0 || access(d->ttyName.data(),R_OK|W_OK) == 0)
-          goto gotpty1; // Success !!
+        if (!access(d->ttyName.data(),R_OK|W_OK)) // checks availability based on permission bits
+        {
+          if (!geteuid())
+          {
+            struct group* p = getgrnam(TTY_GROUP);
+            if (!p)
+              p = getgrnam("wheel");
+            gid_t gid = p ? p->gr_gid : getgid ();
+
+            chown(d->ttyName.data(), getuid(), gid);
+            chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
+          }
+          goto gotpty;
+        }
         ::close(d->masterFd);
         d->masterFd = -1;
@@ -265,28 +270,11 @@
   return false;
 
- gotpty1:
-#if defined(HAVE_GRANTPT)
-  grantpt(d->masterFd);
-#else
-  {
-    /* Get the group ID of the special `tty' group.  */
-    struct group* p = getgrnam(TTY_GROUP);    /* posix */
-    gid_t gid = p ? p->gr_gid : getgid ();    /* posix */
-
-    chown(d->ttyName.data(), getuid(), gid);
-    chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
-  }
-#endif
- gotpty2:
+ gotpty:
   struct stat st;
   if (stat(d->ttyName.data(), &st))
     return false; // this just cannot happen ... *cough*
-  d->needGrantPty = st.st_uid != getuid() || (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH));
-
-#ifdef BSD
-  revoke(d->ttyName.data());
-#endif
-
-  if (!chownpty(true))
+  if (((st.st_uid != getuid()) ||
+       (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
+      !chownpty(true))
   {
     kdWarning(175)
@@ -295,10 +283,13 @@
   }
 
+#ifdef BSD
+  revoke(d->ttyName.data());
+#endif
+
 #ifdef HAVE_UNLOCKPT
   unlockpt(d->masterFd);
 #endif
 
-  if (d->slaveFd < 0) { // slave pty not yet opened?
-    d->slaveFd = ::open(d->ttyName, O_RDWR);
+  d->slaveFd = ::open(d->ttyName.data(), O_RDWR);
     if (d->slaveFd < 0)
     {
@@ -308,5 +299,4 @@
       return false;
     }
-  }
 
 #if (defined(__svr4__) || defined(__sgi__))
@@ -348,7 +338,17 @@
    if (d->masterFd < 0)
       return;
-   chown(d->ttyName.data(), 0, 0);
+   // don't bother resetting unix98 pty, it will go away after closing master anyway.
+   if (memcmp(d->ttyName.data(), "/dev/pts/", 9)) {
+      if (!geteuid()) {
+         struct stat st;
+         if (!stat(d->ttyName.data(), &st)) {
+            chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
    chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+	 }
+      } else {
+         fcntl(d->masterFd, F_SETFD, 0);
    chownpty(false);
+      }
+   }
    ::close(d->slaveFd);
    ::close(d->masterFd);
@@ -492,8 +492,4 @@
 bool KPty::chownpty(bool grant)
 {
-  if (!d->needGrantPty)
-    return true;
-
-  fcntl(d->masterFd, F_SETFD, 0);
   KProcess proc;
   proc << locate("exe", BASE_CHOWN) << (grant?"--grant":"--revoke") << QString::number(d->masterFd);
Index: kgrantpty.c
===================================================================
RCS file: /home/kde/kdelibs/kdecore/kgrantpty.c,v
retrieving revision 1.13
diff -U2 -w -r1.13 kgrantpty.c
--- kgrantpty.c	20 Nov 2003 15:53:10 -0000	1.13
+++ kgrantpty.c	15 Jan 2004 20:58:28 -0000
@@ -25,6 +25,7 @@
  */
 
+#include <config.h>
+
 #include <sys/types.h>
-#include <sys/param.h> /* for BSD */
 #include <errno.h>
 #include <grp.h>
@@ -46,5 +47,4 @@
 int main (int argc, char *argv[])
 {
-  char*         pty;
   struct stat   st;
   struct group* p;
@@ -72,27 +72,16 @@
   }
 
-  /* setup parameters for the operation ***********************************/
-
-  if (!strcmp(argv[1],"--grant"))
-  {
-    uid = getuid(); /* current user id */
-    mod = S_IRUSR | S_IWUSR | S_IWGRP;
-  }
-  else
-  {
-    uid = 0;        /* root */
-    mod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-  }
-  /* Get the group ID of the special `tty' group.  */
-  p = getgrnam(TTY_GROUP);            /* posix */
-  gid = p ? p->gr_gid : getgid ();    /* posix */
   fd = atoi(argv[2]);
 
-  /* get slave pty name from master pty file handle in PTY_FILENO *********/
-
+  /* get slave pty name from master pty file handle *********/
+#ifdef HAVE_PTSNAME
+  tty = ptsname(fd);
+  if (!tty)
+#endif
+  {
   /* Check that fd is a valid master pseudo terminal.  */
-  pty = ttyname(fd);          /* posix */
+    char *pty = ttyname(fd);
 
-#if defined(BSD_PTY_HACK)
+#ifdef BSD_PTY_HACK
   if (pty == NULL)
   {
@@ -111,9 +100,4 @@
     struct stat dsb;
 
-    if (uid == 0) {
-      p = getgrnam("wheel");
-      gid = p ? p->gr_gid : getgid();
-    }
-
     if (fstat(fd, &dsb) != -1) {
       if ((dp = opendir(_PATH_DEV)) != NULL) {
@@ -140,8 +124,7 @@
     return 1; /* FAIL */
   }
-  close(fd);
 
   /* matches /dev/pty?? */
-  if (strlen(pty) < 8 || strncmp(pty,"/dev/pty",8))
+    if (memcmp(pty,"/dev/pty",8))
   {
     fprintf(stderr,"%s: determined a strange pty name `%s'.\n",argv[0],pty);
@@ -152,4 +135,5 @@
   strcpy(tty,"/dev/tty");
   strcat(tty,pty+8);
+  }
 
   /* Check that the returned slave pseudo terminal is a character device.  */
@@ -160,4 +144,22 @@
   }
 
+  /* setup parameters for the operation ***********************************/
+
+  if (!strcmp(argv[1],"--grant"))
+  {
+    uid = getuid();
+    p = getgrnam(TTY_GROUP);
+    if (!p)
+      p = getgrnam("wheel");
+    gid = p ? p->gr_gid : getgid ();
+    mod = S_IRUSR | S_IWUSR | S_IWGRP;
+  }
+  else
+  {
+    uid = 0;
+    gid = st.st_gid == getgid () ? 0 : -1;
+    mod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  }
+
   /* Perform the actual chown/chmod ************************************/
 
@@ -174,12 +176,4 @@
   }
 
-#ifdef BSD
-  if (revoke(tty) < 0)
-  {
-    fprintf(stderr,"%s: cannot revoke %s: %s\n",argv[0],tty,strerror(errno));
-    return 1; /* FAIL */
-  }
-#endif
-
   return 0; /* OK */
 }
-------------- next part --------------
Index: kpty.cpp
===================================================================
RCS file: /home/kde/kdelibs/kdecore/kpty.cpp,v
retrieving revision 1.18
diff -U2 -r1.18 kpty.cpp
--- kpty.cpp	13 Jan 2004 01:02:29 -0000	1.18
+++ kpty.cpp	15 Jan 2004 20:59:49 -0000
@@ -159,5 +159,5 @@
 struct KPtyPrivate {
    KPtyPrivate() : 
-     xonXoff(false), needGrantPty(false),
+     xonXoff(false),
      masterFd(-1), slaveFd(-1)
    { 
@@ -168,5 +168,4 @@
 
    bool xonXoff : 1;
-   bool needGrantPty : 1;
    int masterFd;
    int slaveFd;
@@ -204,13 +203,6 @@
 
   // We try, as we know them, one by one.
-#if defined(HAVE_OPENPTY)
-  if (openpty(&d->masterFd, &d->slaveFd, NULL, NULL, NULL) == 0)
-  {
-    d->ttyName = ttyname(d->slaveFd);
-    goto gotpty2;
-  }
-#endif
 
-#if defined(HAVE_PTSNAME)
+#if defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT)
 #ifdef _AIX
   d->masterFd = ::open("/dev/ptc",O_RDWR);
@@ -222,6 +214,7 @@
     char *ptsn = ptsname(d->masterFd);
     if (ptsn) {
+        grantpt(d->masterFd);
         d->ttyName = ptsn;
-        goto gotpty1;
+        goto gotpty;
     } else {
        ::close(d->masterFd);
@@ -254,6 +247,18 @@
         }
 #endif /* sun */
-        if (geteuid() == 0 || access(d->ttyName.data(),R_OK|W_OK) == 0)
-          goto gotpty1; // Success !!
+        if (!access(d->ttyName.data(),R_OK|W_OK)) // checks availability based on permission bits
+        {
+          if (!geteuid())
+          {
+            struct group* p = getgrnam(TTY_GROUP);
+            if (!p)
+              p = getgrnam("wheel");
+            gid_t gid = p ? p->gr_gid : getgid ();
+
+            chown(d->ttyName.data(), getuid(), gid);
+            chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
+          }
+          goto gotpty;
+        }
         ::close(d->masterFd);
         d->masterFd = -1;
@@ -265,28 +270,11 @@
   return false;
 
- gotpty1:
-#if defined(HAVE_GRANTPT)
-  grantpt(d->masterFd);
-#else
-  {
-    /* Get the group ID of the special `tty' group.  */
-    struct group* p = getgrnam(TTY_GROUP);    /* posix */
-    gid_t gid = p ? p->gr_gid : getgid ();    /* posix */
-
-    chown(d->ttyName.data(), getuid(), gid);
-    chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IWGRP);
-  }
-#endif
- gotpty2:
+ gotpty:
   struct stat st;
   if (stat(d->ttyName.data(), &st))
     return false; // this just cannot happen ... *cough*
-  d->needGrantPty = st.st_uid != getuid() || (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH));
-
-#ifdef BSD
-  revoke(d->ttyName.data());
-#endif
-
-  if (!chownpty(true))
+  if (((st.st_uid != getuid()) ||
+       (st.st_mode & (S_IRGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH))) &&
+      !chownpty(true))
   {
     kdWarning(175)
@@ -295,17 +283,19 @@
   }
 
+#ifdef BSD
+  revoke(d->ttyName.data());
+#endif
+
 #ifdef HAVE_UNLOCKPT
   unlockpt(d->masterFd);
 #endif
 
-  if (d->slaveFd < 0) { // slave pty not yet opened?
-    d->slaveFd = ::open(d->ttyName, O_RDWR);
-    if (d->slaveFd < 0)
-    {
-      kdWarning(175) << "Can't open slave pseudo teletype" << endl;
-      ::close(d->masterFd);
-      d->masterFd = -1;
-      return false;
-    }
+  d->slaveFd = ::open(d->ttyName.data(), O_RDWR);
+  if (d->slaveFd < 0)
+  {
+    kdWarning(175) << "Can't open slave pseudo teletype" << endl;
+    ::close(d->masterFd);
+    d->masterFd = -1;
+    return false;
   }
 
@@ -348,7 +338,17 @@
    if (d->masterFd < 0)
       return;
-   chown(d->ttyName.data(), 0, 0);
-   chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
-   chownpty(false);
+   // don't bother resetting unix98 pty, it will go away after closing master anyway.
+   if (memcmp(d->ttyName.data(), "/dev/pts/", 9)) {
+      if (!geteuid()) {
+         struct stat st;
+         if (!stat(d->ttyName.data(), &st)) {
+            chown(d->ttyName.data(), 0, st.st_gid == getgid() ? 0 : -1);
+            chmod(d->ttyName.data(), S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+	 }
+      } else {
+         fcntl(d->masterFd, F_SETFD, 0);
+         chownpty(false);
+      }
+   }
    ::close(d->slaveFd);
    ::close(d->masterFd);
@@ -492,8 +492,4 @@
 bool KPty::chownpty(bool grant)
 {
-  if (!d->needGrantPty)
-    return true;
-
-  fcntl(d->masterFd, F_SETFD, 0);
   KProcess proc;
   proc << locate("exe", BASE_CHOWN) << (grant?"--grant":"--revoke") << QString::number(d->masterFd);
Index: kgrantpty.c
===================================================================
RCS file: /home/kde/kdelibs/kdecore/kgrantpty.c,v
retrieving revision 1.13
diff -U2 -r1.13 kgrantpty.c
--- kgrantpty.c	20 Nov 2003 15:53:10 -0000	1.13
+++ kgrantpty.c	15 Jan 2004 20:59:49 -0000
@@ -25,6 +25,7 @@
  */
 
+#include <config.h>
+
 #include <sys/types.h>
-#include <sys/param.h> /* for BSD */
 #include <errno.h>
 #include <grp.h>
@@ -46,5 +47,4 @@
 int main (int argc, char *argv[])
 {
-  char*         pty;
   struct stat   st;
   struct group* p;
@@ -72,84 +72,68 @@
   }
 
-  /* setup parameters for the operation ***********************************/
-
-  if (!strcmp(argv[1],"--grant"))
-  {
-    uid = getuid(); /* current user id */
-    mod = S_IRUSR | S_IWUSR | S_IWGRP;
-  }
-  else
-  {
-    uid = 0;        /* root */
-    mod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-  }
-  /* Get the group ID of the special `tty' group.  */
-  p = getgrnam(TTY_GROUP);            /* posix */
-  gid = p ? p->gr_gid : getgid ();    /* posix */
   fd = atoi(argv[2]);
 
-  /* get slave pty name from master pty file handle in PTY_FILENO *********/
-
-  /* Check that fd is a valid master pseudo terminal.  */
-  pty = ttyname(fd);          /* posix */
-
-#if defined(BSD_PTY_HACK)
-  if (pty == NULL)
+  /* get slave pty name from master pty file handle *********/
+#ifdef HAVE_PTSNAME
+  tty = ptsname(fd);
+  if (!tty)
+#endif
   {
-  /*
-    Hack to make kgrantpty work on some versions of FreeBSD (and possibly
-    other systems): ttyname(3) does not work with a file descriptor opened
-    on a /dev/pty?? device.
-
-    Instead, this code looks through all the devices in /dev for a device
-    which has the same inode as our PTY_FILENO descriptor... if found, we
-    have the name for our pty.
-  */
-
-    struct dirent *dirp;
-    DIR *dp;
-    struct stat dsb;
-
-    if (uid == 0) {
-      p = getgrnam("wheel");
-      gid = p ? p->gr_gid : getgid();
-    }
+    /* Check that fd is a valid master pseudo terminal.  */
+    char *pty = ttyname(fd);
 
-    if (fstat(fd, &dsb) != -1) {
-      if ((dp = opendir(_PATH_DEV)) != NULL) {
-        while ((dirp = readdir(dp))) {
-          if (dirp->d_fileno != dsb.st_ino)
-            continue;
-	  pty = malloc(sizeof(_PATH_DEV) + strlen(dirp->d_name));
-	  if (pty) {
-	    strcpy(pty, _PATH_DEV);
-	    strcat(pty, dirp->d_name);
+#ifdef BSD_PTY_HACK
+    if (pty == NULL)
+    {
+    /*
+      Hack to make kgrantpty work on some versions of FreeBSD (and possibly
+      other systems): ttyname(3) does not work with a file descriptor opened
+      on a /dev/pty?? device.
+
+      Instead, this code looks through all the devices in /dev for a device
+      which has the same inode as our PTY_FILENO descriptor... if found, we
+      have the name for our pty.
+    */
+
+      struct dirent *dirp;
+      DIR *dp;
+      struct stat dsb;
+
+      if (fstat(fd, &dsb) != -1) {
+        if ((dp = opendir(_PATH_DEV)) != NULL) {
+          while ((dirp = readdir(dp))) {
+            if (dirp->d_fileno != dsb.st_ino)
+              continue;
+            pty = malloc(sizeof(_PATH_DEV) + strlen(dirp->d_name));
+            if (pty) {
+              strcpy(pty, _PATH_DEV);
+              strcat(pty, dirp->d_name);
+            }
+            break;
           }
-	  break;
-        }
 
-        (void) closedir(dp);
+          (void) closedir(dp);
+        }
       }
     }
-  }
 #endif
 
-  if (pty == NULL)
-  {
-    fprintf(stderr,"%s: cannot determine pty name.\n",argv[0]);
-    return 1; /* FAIL */
-  }
-  close(fd);
+    if (pty == NULL)
+    {
+      fprintf(stderr,"%s: cannot determine pty name.\n",argv[0]);
+      return 1; /* FAIL */
+    }
 
-  /* matches /dev/pty?? */
-  if (strlen(pty) < 8 || strncmp(pty,"/dev/pty",8))
-  {
-    fprintf(stderr,"%s: determined a strange pty name `%s'.\n",argv[0],pty);
-    return 1; /* FAIL */
-  }
+    /* matches /dev/pty?? */
+    if (memcmp(pty,"/dev/pty",8))
+    {
+      fprintf(stderr,"%s: determined a strange pty name `%s'.\n",argv[0],pty);
+      return 1; /* FAIL */
+    }
 
-  tty = malloc(strlen(pty) + 1);
-  strcpy(tty,"/dev/tty");
-  strcat(tty,pty+8);
+    tty = malloc(strlen(pty) + 1);
+    strcpy(tty,"/dev/tty");
+    strcat(tty,pty+8);
+  }
 
   /* Check that the returned slave pseudo terminal is a character device.  */
@@ -160,4 +144,22 @@
   }
 
+  /* setup parameters for the operation ***********************************/
+
+  if (!strcmp(argv[1],"--grant"))
+  {
+    uid = getuid();
+    p = getgrnam(TTY_GROUP);
+    if (!p)
+      p = getgrnam("wheel");
+    gid = p ? p->gr_gid : getgid ();
+    mod = S_IRUSR | S_IWUSR | S_IWGRP;
+  }
+  else
+  {
+    uid = 0;
+    gid = st.st_gid == getgid () ? 0 : -1;
+    mod = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  }
+
   /* Perform the actual chown/chmod ************************************/
 
@@ -174,12 +176,4 @@
   }
 
-#ifdef BSD
-  if (revoke(tty) < 0)
-  {
-    fprintf(stderr,"%s: cannot revoke %s: %s\n",argv[0],tty,strerror(errno));
-    return 1; /* FAIL */
-  }
-#endif
-
   return 0; /* OK */
 }


More information about the kde-core-devel mailing list