This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Cleanup of pty code


Hi,

I have cleaned up the pty code.  There are some changes that make the
code more robust (I had some problems with the old `grantpt'
implementation.  It assumed that if the user was OK, everything else
was too, which generally is was not the case.  It tries to set the
owner group and access permissions itself before calling the helper
program).  There are also some changes that make the code work better
with new kernels (> 2.1.115) with the `devpts' filesystem.  `grantpt'
now checks if the slave lives on a `devpts' filesystem.  If so it
doesn't do anything (assuming that the `devpts' has been set up
right).  Otherwise it falls back on the old method.

There may be some problems with using `grantpt' on 2.1.7x < kernel <
2.1.115, but I was told this does not really matter.  It works fine
with 2.0.x kernels.

Remember to create some `/dev/pts/?' nodes (with the `devpts'
filesystem unmounted).  Otherwise it may be impossible to use pty's
when `devpts' filesystem is not mounted.

Mark

PS Uli, the patch doesn't remove `login/pty-internal.h', since I
cannot get PRCS to generate that part.  Please remove it by hand.


1998-09-17  Mark Kettenis  <kettenis@phys.uva.nl>
	
	* login/pty-internal.h: Removed.  Moved constants related to the
	`grantpt' helper program protocol to ...
	* login/pty-private.h: ... here.  New file.
	* sysdeps/unix/sysv/linux/ptsname.c (ptsname): Reimplementation
	to make the function work with kernels >= 2.1.115.
	* sysdeps/unix/sysv/linux/getpt.c (getpt): Reimplement to call BSD
	version if using the cloning device fails.
	* sysdeps/unix/sysv/linux/grantpt.c: New file.
	* sysdeps/unix/sysv/linux/unlockpt.c: General cleanup.
	* sysdeps/unix/bsd/getpt.c (__getpt): Largely rewritten to allow
	use by Linux specific code.
	* sysdeps/unix/bsd/unlockpt.c: General cleanup.
	* sysdeps/unix/grantpt.c: Largely rewritten.  (pts_name): New
	function.  (grantpt): Use pts_name, check group and permission
	mode in addition to owner.  Try to set the owner, group and
	permission mode first without invoking the helper program.
	* login/programs/pt_chown.c: Largely rewritten.  Add argp and
	internationalization support.  Use symbolic constants instead of
	hardwired numbers for permission mode.
	* sysdeps/unix/bsd/ptsname.c: New file.


Index: login/programs/pt_chown.c
--- 0.15/login/programs/pt_chown.c Mon, 10 Aug 1998 21:28:35 +0200 kettenis (libc/46_pt_chown.c 1.1 644)
+++ Local.14(w)/login/programs/pt_chown.c Thu, 17 Sep 1998 23:28:03 +0200 kettenis (libc/37_pt_chown.c 1.1 644)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998 Free Software Foundation, Inc.
+/* pt_chmod - helper program for `grantpt'.
+   Copyright (C) 1998 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by C. Scott Ananian <cananian@alumni.princeton.edu>, 1998.
 
@@ -17,72 +18,136 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-/* pt_chmod.c ... securely implement grantpt in user-land.  */
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <argp.h>
 #include <errno.h>
-#include <stdio.h>
+#include <error.h>
 #include <grp.h>
+#include <libintl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "pty-private.h"
+
+/* Get libc version number.  */
+#include "../version.h"
 
-#include "pty-internal.h"
-#define Str(x) _Str(x)
-#define _Str(x) #x
+#define PACKAGE _libc_intl_domainname
 
-void
-usage (void)
+/* Name and version of program.  */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+/* Function to print some extra text in the help message.  */
+static char *more_help (int key, const char *text, void *input);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  NULL, NULL, NULL, NULL, NULL, more_help
+};
+
+
+/* Print the version information.  */
+static void
+print_version (FILE *stream, struct argp_state *state)
 {
-  fprintf (stderr, _("usage: pt_chown FD>&%s\n"
-		     "This program is used internally by grantpt(3).\n"),
-	   Str (PTY_FD));
-  exit (0);
+  fprintf (stream, "pt_chmod (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"), "1998");
 }
 
-void
-bad_installation (void)
+static char *
+more_help (int key, const char *text, void *input)
 {
-  fputs (_("pt_chown: installation problem: "
-	   "This program needs to be setuid root.\n"), stderr);
-  exit (FAIL_EXEC);
+  char *cp;
+  
+  switch (key)
+    {
+    case ARGP_KEY_HELP_PRE_DOC:
+      asprintf (&cp, gettext ("\
+Set the owner, group and access permission of the terminal passed on\
+ file descriptor `%d'.  This is the helper program for the `grantpt'\
+ function.  It is not intended to be run directly from the command\
+ line.\n"),
+		PTY_FILENO);
+      return cp;
+    case ARGP_KEY_HELP_EXTRA:
+      /* We print some extra information.  */
+      asprintf (&cp, gettext ("\
+The owner is set to the current user, the group is set to `%s',\
+ and the access permission is set to `%o'.\n\n\
+%s"),
+		TTY_GROUP, S_IRUSR|S_IWUSR|S_IWGRP, gettext ("\
+Report bugs using the `glibcbug' script to <bugs@gnu.org>.\n"));
+      return cp;
+    default:
+      break;
+    }
+  return (char *) text;
 }
 
 int
-main (int argc, char **argv)
+main (int argc, char *argv[])
 {
-  struct group *grp;
-  struct stat s;
   char *pty;
+  int remaining;
+  struct stat st;
+  struct group *p;
   gid_t gid;
-  uid_t uid;
 
-  if (argc != 1)
-    usage ();
-  if (geteuid () != 0)
-    bad_installation ();
+  /* Set locale via LC_ALL.  */
+  setlocale (LC_ALL, "");
+
+  /* Set the text message domain.  */
+  textdomain (PACKAGE);
 
-  grp = getgrnam (TTY_GROUP);
-  gid = grp ? grp->gr_gid : getgid ();
-  uid = getuid ();
+  /* parse and process arguments.  */
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
 
-  /* Check that fd is a valid pty master -- call ptsname().  */
-  pty = ptsname (PTY_FD);
+  if (remaining < argc)
+    {
+      /* We should not be called with any non-option parameters.  */
+      error (0, 0, gettext ("too many arguments"));
+      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
+		 program_invocation_short_name);
+      exit (EXIT_FAILURE);
+    }
+  
+  /* Check if we are properly installed.  */
+  if (geteuid () != 0)
+    error (FAIL_EXEC, 0, gettext ("needs to be installed setuid `root'"));
+
+  /* Check that PTY_FILENO is a valid master pseudo terminal.  */
+  pty = ptsname (PTY_FILENO);
   if (pty == NULL)
     return errno == EBADF ? FAIL_EBADF : FAIL_EINVAL;
-  close (PTY_FD);
+  close (PTY_FILENO);
 
-  /* Check that target file is a character device.  */
-  if (stat (pty, &s))
-    return FAIL_EINVAL; /* This should only fail if pty doesn't exist.  */
-  if (!S_ISCHR (s.st_mode))
+  /* Check that the returned slave pseudo terminal is a
+     character device.  */
+  if (stat (pty, &st) < 0 || !S_ISCHR(st.st_mode))
     return FAIL_EINVAL;
 
-  if (chmod (pty, 0620))
-    return FAIL_EACCES;  /* XXX: Probably not true. */
+  /* Get the group ID of the special `tty' group.  */
+  p = getgrnam (TTY_GROUP);
+  gid = p ? p->gr_gid : getgid ();
+
+  /* Set the owner to the real user ID, and the group to that special
+     group ID.  */
+  if (chown (pty, getuid (), gid) < 0)
+    return FAIL_EACCES;
 
-  if (chown (pty, uid, gid))
+  /* Set the permission mode to readable and writable by the owner,
+     and writable by the group.  */
+  if (chmod (pty, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
     return FAIL_EACCES;
 
-  return 0;
+  exit (EXIT_SUCCESS);
 }
Index: sysdeps/unix/grantpt.c
--- 0.15/sysdeps/unix/grantpt.c Mon, 10 Aug 1998 21:28:35 +0200 kettenis (libc/47_grantpt.c 1.1 644)
+++ Local.14(w)/sysdeps/unix/grantpt.c Tue, 15 Sep 1998 01:54:54 +0200 kettenis (libc/38_grantpt.c 1.2 644)
@@ -17,65 +17,158 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <assert.h>
 #include <errno.h>
+#include <grp.h>
+#include <limits.h>
 #include <stdlib.h>
-#include <unistd.h>
+#include <string.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
-#include <assert.h>
+#include "pty-private.h"
 
-#include "pty-internal.h"
 
-/* Given a fd on a master pseudoterminal, chown the file associated
-   with the slave to the calling process, and set its group and
-   mode appropriately.  Note that this is an unprivileged operation. */
-
-/* This "generic Unix" implementation works because we provide the program
-   /usr/libexec/pt_chown, and it only depends on ptsname() working. */
-static const char helper[] = LIBEXECDIR "/pt_chown";
-static const char *const argv[] = { "pt_chown", NULL };
+/* Return the result of ptsname_r in the buffer pointed to by PTS,
+   which should be of length BUF_LEN.  If it is too long to fit in
+   this buffer, a sufficiently long buffer is allocated using malloc,
+   and returned in PTS.  0 is returned upon success, -1 otherwise.  */
+static int
+pts_name (int fd, char **pts, size_t buf_len)
+{
+  int rv;
+  char *buf = *pts;
+
+  for (;;)
+    {
+      char *new_buf;
 
+      if (buf_len)
+	{
+	  rv = ptsname_r (fd, buf, buf_len);
+
+	  if (rv != 0 || memchr (buf, '\0', buf_len))
+	    /* We either got an error, or we succeeded and the
+	       returned name fit in the buffer.  */
+	    break;
+
+	  /* Try again with a longer buffer.  */
+	  buf_len += buf_len;	/* Double it */
+	}
+      else
+	/* No initial buffer; start out by mallocing one.  */
+	buf_len = 128;		/* First time guess.  */
+
+      if (buf != *pts)
+	/* We've already malloced another buffer at least once.  */
+	new_buf = realloc (buf, buf_len);
+      else
+	new_buf = malloc (buf_len);
+      if (! new_buf)
+	{
+	  rv = -1;
+	  __set_errno (ENOMEM);
+	  break;
+	}
+      buf = new_buf;
+    }
+
+  if (rv == 0)
+    *pts = buf;		/* Return buffer to the user.  */
+  else if (buf != *pts)
+    free (buf);		/* Free what we malloced when returning an error.  */
+
+  return rv;
+}
+
+/* Change the ownership and access permission of the slave pseudo
+   terminal associated with the master pseudo terminal specified
+   by FD.  */
 int
-grantpt (fd)
-     int fd;
+grantpt (int fd)
 {
+#ifdef PATH_MAX
+  char _buf[PATH_MAX];
+#else
+  char _buf[512];
+#endif
+  char *buf = _buf;
   struct stat st;
-  int w, pid;
-  char namebuf[PTYNAMELEN];
+  char *grtmpbuf;
+  struct group grbuf;
+  size_t grbuflen = __sysconf (_SC_GETGR_R_SIZE_MAX);
+  struct group *p;
+  uid_t uid;
+  gid_t gid;
+  pid_t pid;
 
-  /* Some systems do it for us.  */
-  if (__ptsname_r (fd, namebuf, PTYNAMELEN) != 0)
+  if (pts_name (fd, &buf, sizeof (_buf)))
     return -1;
-  if (__xstat (_STAT_VER, namebuf, &st) != 0)
+  
+  if (__stat (buf, &st) < 0)
     return -1;
 
-  if (st.st_uid == __getuid ())
-    return 0;
+  /* Make sure that we own the device.  */
+  uid = __getuid ();
+  if (st.st_uid != uid)
+    {
+      if (__chown (buf, uid, st.st_gid) < 0)
+	goto helper;
+    }
+
+  /* Get the group ID of the special `tty' group.  */
+  if (grbuflen == -1)
+    /* `sysconf' does not support _SC_GETGR_R_SIZE_MAX.
+       Try a moderate value.  */
+    grbuflen = 1024;
+  grtmpbuf = (char *) __alloca (grbuflen);
+  getgrnam_r (TTY_GROUP, &grbuf, grtmpbuf, grbuflen, &p);
+  gid = p ? p->gr_gid : __getgid ();
+
+  /* Make sure the group of the device is that special group.  */
+  if (st.st_gid != gid)
+    {
+      if (__chown (buf, uid, gid) < 0)
+	goto helper;
+    }
+
+  /* Make sure the permission mode is set to readable and writable by
+     the owner, and writable by the group.  */
+  if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP))
+    {
+      if (__chmod (buf, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
+	goto helper;
+    }
+
+  return 0;
 
-  /* We have to do it in user space.  */
+  /* We have to use the helper program.  */
+ helper:
 
   pid = __fork ();
   if (pid == -1)
     return -1;
   else if (pid == 0)
     {
-      /* Disable core dumps in the child.  */
-      struct rlimit off = { 0, 0 };
-      setrlimit (RLIMIT_CORE, &off);
-
-      /* The helper does its thing on fd PTY_FD.  */
-      if (fd != PTY_FD)
-	if (__dup2 (fd, PTY_FD) == -1)
+      /* Disable core dumps.  */
+      struct rlimit rl = { 0, 0 };
+      setrlimit (RLIMIT_CORE, &rl);
+
+      /* We pase the master pseudo terminal as file descriptor PTY_FILENO.  */
+      if (fd != PTY_FILENO)
+	if (__dup2 (fd, PTY_FILENO) < 0)
 	  _exit (FAIL_EBADF);
 
-      __execve (helper, (char *const *) argv, 0);
+      execle (_PATH_PT_CHOWN, basename (_PATH_PT_CHOWN), NULL, NULL);
       _exit (FAIL_EXEC);
     }
   else
     {
+      int w;
+      
       if (__waitpid (pid, &w, 0) == -1)
 	return -1;
       if (!WIFEXITED (w))
@@ -106,6 +199,5 @@
 	  }
     }
 
-  /* Success.  */
   return 0;
 }
Index: sysdeps/unix/bsd/unlockpt.c
--- 0.15/sysdeps/unix/bsd/unlockpt.c Mon, 10 Aug 1998 21:28:35 +0200 kettenis (libc/48_unlockpt.c 1.1 644)
+++ Local.14(w)/sysdeps/unix/bsd/unlockpt.c Sat, 29 Aug 1998 21:42:54 +0200 kettenis (libc/39_unlockpt.c 1.3 644)
@@ -17,25 +17,21 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
+#include <paths.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
-#include "pty-internal.h"
-
-/* Given a fd on a master pseudoterminal, clear a kernel lock so that
-   the slave can be opened.  This is to avoid a race between opening the
-   master and calling grantpt() to take possession of the slave.
-
-   BSD doesn't have this lock, but what it does have is revoke(). */
 
+/* Unlock the slave pseudo terminal associated with the master pseudo
+   terminal specified by FD.  */
 int
-unlockpt (fd)
-     int fd;
+unlockpt (int fd)
 {
-  char buf[PTYNAMELEN];
+  char buf[sizeof (_PATH_TTY) + 2];
 
-  if (__ptsname_r (fd, buf, PTYNAMELEN))
+  /* BSD doesn't have a lock, but it does have `revoke'.  */
+  if (__ptsname_r (fd, buf, sizeof (buf)))
     return -1;
-
   return revoke (buf);
 }
Index: sysdeps/unix/bsd/getpt.c
--- 0.15/sysdeps/unix/bsd/getpt.c Mon, 10 Aug 1998 21:28:35 +0200 kettenis (libc/49_getpt.c 1.1 644)
+++ Local.14(w)/sysdeps/unix/bsd/getpt.c Thu, 17 Sep 1998 02:08:04 +0200 kettenis (libc/40_getpt.c 1.3 644)
@@ -17,43 +17,67 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <sys/types.h>
-#include <fcntl.h>
 #include <errno.h>
-#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+
+/* Prefix for master pseudo terminal nodes.  */
+#define _PATH_PTY "/dev/pty"
+
 
-#include "pty-internal.h"
+/* Letters indicating a series of pseudo terminals.  */
+#ifndef PTYNAME1
+#define PTYNAME1 "pqrsPQRS"
+#endif
+const char *__libc_ptyname1 = PTYNAME1;
 
-/* Per the FreeBSD-3.0 manpages: pty masters are named
-   /dev/pty[p-sP-S][0-9a-v].  I hope EIO is the right
-   errno in the "already open" case; it doesn't say.  */
-static const char pn1[] = "pqrsPQRS";
-static const char pn2[] = "0123456789abcdefghijklmnopqrstuv";
+/* Letters indicating the position within a series.  */
+#ifndef PTYNAME2
+#define PTYNAME2 "0123456789abcdefghijklmnopqrstuv";
+#endif
+const char *__libc_ptyname2 = PTYNAME2;
 
-/* Open the master side of a pseudoterminal and return its file
-   descriptor, or -1 on error.  BSD version.  */
+
+/* Open a master pseudo terminal and return its file descriptor.  */
 int
-__getpt ()
+__getpt (void)
 {
-  int fd;
-  const char *i, *j;
-  char namebuf[PTYNAMELEN];
-
-  strcpy (namebuf, "/dev/pty");
-  namebuf[10] = '\0';
-  for (i = pn1; *i; ++i)
+  char buf[sizeof (_PATH_PTY) + 2];
+  const char *p, *q;
+  char *s;
+  
+  s = __stpcpy (buf, _PATH_PTY);
+  s[0] = '?';
+  s[1] = '?';
+  s[2] = 0;
+
+  for (p = __libc_ptyname1; *p; p++)
     {
-      namebuf[8] = *i;
-      for (j = pn2; *j; ++j)
-        {
-	  namebuf[9] = *j;
-	  fd = open (namebuf, O_RDWR);
+      s[0] = *p;
+
+      for (q = __libc_ptyname2; *q; q++)
+	{
+	  int fd;
+	  
+	  s[1] = *q;
+	  
+	  fd = __open (buf, O_RDWR);
 	  if (fd != -1)
-	    return fd;
+	    {
+	      if (__isatty (fd))
+		return fd;
+	      
+	      __close (fd);
+	      continue;
+	    }
+	  
 	  if (errno != EIO)
 	    return -1;
-        }
+	}
     }
+
   __set_errno (ENFILE);
   return -1;
 }
Index: sysdeps/unix/sysv/linux/unlockpt.c
--- 0.15/sysdeps/unix/sysv/linux/unlockpt.c Mon, 10 Aug 1998 21:28:35 +0200 kettenis (libc/50_unlockpt.c 1.1 644)
+++ Local.14(w)/sysdeps/unix/sysv/linux/unlockpt.c Wed, 26 Aug 1998 17:39:39 +0200 kettenis (libc/41_unlockpt.c 1.2 644)
@@ -17,33 +17,33 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <sys/ioctl.h>
-#include <termios.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+
 
-/* Given a fd on a master pseudoterminal, clear a kernel lock so that
-   the slave can be opened.  This is to avoid a race between opening the
-   master and calling grantpt() to take possession of the slave.  */
+/* Unlock the slave pseudo terminal associated with the master pseudo
+   terminal specified by FD.  */
 int
-unlockpt (fd)
-     int fd __attribute__ ((unused));
+unlockpt (int fd)
 {
 #ifdef TIOCSPTLCK
-  int serrno = errno;
+  int save_errno = errno;
   int unlock = 0;
 
   if (__ioctl (fd, TIOCSPTLCK, &unlock))
     {
       if (errno == EINVAL)
 	{
-	  __set_errno (serrno);
+	  __set_errno (save_errno);
 	  return 0;
 	}
       else
 	return -1;
     }
 #endif
-  /* On pre-/dev/ptmx kernels this function should be a no-op.  */
+  /* If we have no TIOCSPTLCK ioctl, all slave pseudo terminals are
+     unlocked by default.  */
   return 0;
 }
Index: sysdeps/unix/sysv/linux/getpt.c
--- 0.15/sysdeps/unix/sysv/linux/getpt.c Mon, 10 Aug 1998 21:28:35 +0200 kettenis (libc/51_getpt.c 1.1 644)
+++ Local.14(w)/sysdeps/unix/sysv/linux/getpt.c Wed, 26 Aug 1998 17:39:39 +0200 kettenis (libc/42_getpt.c 1.2 644)
@@ -17,33 +17,26 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <sys/types.h>
-#include <fcntl.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
-#include <string.h>
 
-#include "pty-internal.h"
+/* Path to the master pseudo terminal cloning device.  */
+#define _PATH_DEVPTMX "/dev/ptmx"
 
-/* Per Documentation/devices.txt: pty masters are /dev/pty[p-za-e][0-9a-f].
-   These strings are used also in ptsname.c. */
-const char __ptyname1[] = "pqrstuvwxyzabcde";
-const char __ptyname2[] = "0123456789abcdef";
+/* Prototype for function that opens BSD-style master pseudo-terminals.  */
+int __bsd_getpt (void);
 
-/* Open the master side of a pseudoterminal and return its file
-   descriptor, or -1 on error.  Linux version. */
+/* Open a master pseudo terminal and return its file descriptor.  */
 int
-__getpt ()
+__getpt (void)
 {
-  int fd;
-  const char *i, *j;
   static int have_dev_ptmx = 1;
-  char namebuf[PTYNAMELEN];
+  int fd;
 
-  /* The new way:  */
   if (have_dev_ptmx)
     {
-      fd = __open ("/dev/ptmx", O_RDWR);
+      fd = __open (_PATH_DEVPTMX, O_RDWR);
       if (fd != -1)
 	return fd;
       else
@@ -55,23 +48,11 @@
 	}
     }
 
-  /* The old way: */
-  strcpy (namebuf, "/dev/pty");
-  namebuf[10] = '\0';
-  for (i = __ptyname1; *i; ++i)
-    {
-      namebuf[8] = *i;
-      for (j = __ptyname2; *j; ++j)
-        {
-	  namebuf[9] = *j;
-	  fd = __open (namebuf, O_RDWR);
-	  if (fd != -1)
-	    return fd;
-	  if (errno != EIO)
-	    return -1;
-        }
-    }
-  __set_errno (ENFILE);
-  return -1;
+  return __bsd_getpt ();
 }
-weak_alias (__getpt, getpt)
+
+#define PTYNAME1 "pqrstuvwxyzabcde";
+#define PTYNAME2 "0123456789abcdef";
+
+#define __getpt __bsd_getpt
+#include <sysdeps/unix/bsd/getpt.c>
Index: sysdeps/unix/sysv/linux/ptsname.c
--- 0.15/sysdeps/unix/sysv/linux/ptsname.c Mon, 10 Aug 1998 21:28:35 +0200 kettenis (libc/b/0_ptsname.c 1.1 644)
+++ Local.14(w)/sysdeps/unix/sysv/linux/ptsname.c Thu, 17 Sep 1998 02:07:20 +0200 kettenis (libc/43_ptsname.c 1.2 644)
@@ -17,50 +17,50 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <sys/types.h>
+#include <errno.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/sysmacros.h>
 #include <termios.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
 #include <unistd.h>
 
-#include "pty-internal.h"
-
 #include <stdio-common/_itoa.h>
-#include <sys/sysmacros.h>
 
-/* Given the file descriptor of a master pty, return the pathname
-   of the associated slave.  */
+/* Directory where we can find the slave pty nodes.  */
+#define _PATH_DEVPTS "/dev/pts/"
 
-static char namebuf[PTYNAMELEN];
-extern const char __ptyname1[], __ptyname2[]; /* Defined in getpt.c.  */
+/* The are declared in getpt.c.  */
+extern const char *__libc_ptyname1;
+extern const char *__libc_ptyname2;
 
+/* Static buffer for `ptsname'.  */
+static char buffer[sizeof (_PATH_DEVPTS) + 20];
+
+
+/* Return the pathname of the pseudo terminal slave assoicated with
+   the master FD is open on, or NULL on errors.
+   The returned storage is good until the next call to this function.  */
 char *
-ptsname (fd)
-     int fd;
+ptsname (int fd)
 {
-  return __ptsname_r (fd, namebuf, PTYNAMELEN) != 0 ? NULL : namebuf;
+  return __ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer;
 }
 
+
+/* Store at most BUFLEN characters of the pathname of the slave pseudo
+   terminal associated with the master FD is open on in BUF.
+   Return 0 on success, otherwise an error number.  */
 int
-__ptsname_r (fd, buf, buflen)
-     int fd;
-     char *buf;
-     size_t buflen;
+__ptsname_r (int fd, char *buf, size_t buflen)
 {
+  int save_errno = errno;
   struct stat st;
-  int save = errno;
   int ptyno;
-  char nbuf[PTYNAMELEN], idbuf[6];
-  char *cp;
-
-#ifdef TIOCGPTN
-  static int tiocgptn_works = 1;
-#endif
-
-  if (!buf)
+  
+  if (buf == NULL)
     {
       __set_errno (EINVAL);
       return EINVAL;
@@ -73,61 +73,60 @@
     }
 
 #ifdef TIOCGPTN
-  if (tiocgptn_works)
+  if (__ioctl (fd, TIOCGPTN, &ptyno) == 0)
     {
-      if (__ioctl (fd, TIOCGPTN, &ptyno) == 0)
-	goto gotit;
-      else
+      /* Buffer we use to print the number in.  For a maximum size for
+         `int' of 8 bytes we never need more than 20 digits.  */
+      char numbuf[21];
+      const char *devpts = _PATH_DEVPTS;
+      const size_t devptslen = strlen (devpts);
+      char *p;
+
+      numbuf[20] = '\0';
+      p = _itoa_word (ptyno, &numbuf[20], 10, 0);
+
+      if (buflen < devptslen + strlen (p) + 1)
 	{
-	  if(errno != EINVAL)
-	    return errno;
-	  else
-	    tiocgptn_works = 0;
+	  __set_errno (ERANGE);
+	  return ERANGE;
 	}
-    }
-#endif
-  if (__fxstat (_STAT_VER, fd, &st) < 0)
-    return errno;
 
-  ptyno = minor (st.st_rdev);
-  if (major (st.st_rdev) == 4)
-    ptyno -= 128;
-
-#ifdef TIOCGPTN
- gotit:
+      __stpcpy (__stpcpy (buf, devpts), p);
+    }
+  else if (errno == EINVAL)
 #endif
-  /* Two different possible naming schemes for pty slaves:
-     the SVr4 way.  */
-
-  idbuf[5] = '\0';
-  __stpcpy (__stpcpy (nbuf, "/dev/pts/"),
-	    _itoa_word (ptyno, &idbuf[5], 10, 0));
-  if (__xstat (_STAT_VER, nbuf, &st) < 0)
     {
-      if (errno != ENOENT)
-	return errno;
-
-      /* ...and the BSD way.  */
-      nbuf[5]  = 't';
-      nbuf[7]  = 'y';
-      nbuf[8]  = __ptyname1[ptyno / 16];
-      nbuf[9]  = __ptyname2[ptyno % 16];
-      nbuf[10] = '\0';
+      char *p;
+      
+      if (buflen < strlen (_PATH_TTY) + 3)
+	{
+	  __set_errno (ERANGE);
+	  return ERANGE;
+	}
 
-      if (__xstat (_STAT_VER, nbuf, &st) < 0)
+      if (__fstat (fd, &st) < 0)
 	return errno;
-    }
 
-  if (buflen < strlen (nbuf) + 1)
-    {
-      __set_errno (ERANGE);
-      return ERANGE;
-    }
+      ptyno = minor (st.st_rdev);
+      if (major (st.st_rdev) == 4)
+	ptyno -= 128;
 
-  cp = __stpncpy (buf, nbuf, buflen);
-  cp[0] = '\0';
+      if (ptyno / 16 >= strlen (__libc_ptyname1))
+	{
+	  __set_errno (ENOTTY);
+	  return ENOTTY;
+	}
+      
+      p = __stpcpy (buf, _PATH_TTY);
+      p[0] = __libc_ptyname1[ptyno / 16];
+      p[1] = __libc_ptyname2[ptyno % 16];
+      p[2] = '\0';
+    }
+    
+  if (__stat (buf, &st) < 0)
+    return errno;
 
-  __set_errno (save);
+  __set_errno (save_errno);
   return 0;
 }
 weak_alias (__ptsname_r, ptsname_r)
Index: login/pty-private.h
--- libc/login/pty-private.h Thu, 17 Sep 1998 23:37:53 +0200 kettenis ()
+++ libc/login/pty-private.h Mon, 10 Aug 1998 21:24:44 +0200 kettenis (libc/44_pty-privat 1.1 644)
@@ -0,0 +1,42 @@
+/* Internal defenitions and declarations for pseudo terminal functions.
+   Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Zack Weinberg <zack@rabi.phys.columbia.edu>, 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _PTY_PRIVATE_H
+#define _PTY_PRIVATE_H 1
+
+/* The group slave pseudo terminals belong to.  */
+#define TTY_GROUP "tty"
+
+/* The file descriptor connected to the master pseudo terminal.  */
+#define PTY_FILENO 3
+
+/* Path to the helper program that implements `grantpt' in user space.  */
+#define _PATH_PT_CHOWN LIBEXECDIR "/pt_chown"
+
+/* Exit codes for the helper program.  */
+enum  /* failure modes */
+{
+  FAIL_EBADF = 1,
+  FAIL_EINVAL,
+  FAIL_EACCES,
+  FAIL_EXEC
+};
+
+#endif /* pty-private.h  */
Index: sysdeps/unix/bsd/ptsname.c
--- libc/sysdeps/unix/bsd/ptsname.c Thu, 17 Sep 1998 23:37:53 +0200 kettenis ()
+++ libc/sysdeps/unix/bsd/ptsname.c Sat, 29 Aug 1998 21:49:06 +0200 kettenis (libc/45_ptsname.c 1.3 644)
@@ -0,0 +1,78 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <errno.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* Static buffer for `ptsname'.  */
+static char buffer[sizeof (_PATH_TTY) + 2];
+
+
+/* Return the pathname of the pseudo terminal slave assoicated with
+   the master FD is open on, or NULL on errors.
+   The returned storage is good until the next call to this function.  */
+char *
+ptsname (int fd)
+{
+  return __ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer;
+}
+
+
+/* Store at most BUFLEN characters of the pathname of the slave pseudo
+   terminal associated with the master FD is open on in BUF.
+   Return 0 on success, otherwise an error number.  */
+int
+__ptsname_r (int fd, char *buf, size_t buflen)
+{
+  int save_errno = errno;
+  struct stat st;
+
+  if (buf == NULL)
+    {
+      __set_errno (EINVAL);
+      return EINVAL;
+    }
+
+  if (!__isatty (fd))
+    {
+      __set_errno (ENOTTY);
+      return ENOTTY;
+    }
+
+  if (buflen < strlen (_PATH_TTY) + 3)
+    {
+      __set_errno (ERANGE);
+      return ERANGE;
+    }
+  
+  if (__ttyname_r (fd, buf, buflen) != 0)
+    return errno;
+
+  buf[sizeof (_PATH_DEV) - 1] = 't';
+  
+  if (__stat (buf, &st) < 0)
+    return errno;
+
+  __set_errno (save_errno);
+  return 0;
+}
+weak_alias (__ptsname_r, ptsname_r)
Index: sysdeps/unix/sysv/linux/grantpt.c
--- libc/sysdeps/unix/sysv/linux/grantpt.c Thu, 17 Sep 1998 23:37:53 +0200 kettenis ()
+++ libc/sysdeps/unix/sysv/linux/grantpt.c Wed, 16 Sep 1998 22:00:02 +0200 kettenis (libc/b/22_grantpt.c  644)
@@ -0,0 +1,64 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/statfs.h>
+
+/* Constant that identifies the `devpts' filesystem.  */
+#define DEVPTS_SUPER_MAGIC	0x1cd1
+
+/* Prototype for function that changes ownership and access permission
+   for slave pseudo terminals that do not live on a `devpts'
+   filesystem.  */
+int __unix_grantpt (int fd);
+
+/* Prototype for private function that gets the name of the slave
+   pseudo terminal in a safe way.  */
+static int pts_name (int fd, char **pts, size_t buf_len);
+
+/* Change the ownership and access permission of the slave pseudo
+   terminal associated with the master pseudo terminal specified
+   by FD.  */
+int
+grantpt (int fd)
+{
+  struct statfs fsbuf;
+#ifdef PATH_MAX
+  char _buf[PATH_MAX];
+#else
+  char _buf[512];
+#endif
+  char *buf = _buf;
+
+  if (pts_name (fd, &buf, sizeof (_buf)))
+    return -1;
+  
+  if (__statfs (buf, &fsbuf) < 0)
+    return -1;
+
+  /* If the slave pseudo terminal lives on a `devpts' filesystem, the
+     ownership and access permission are already set.  */
+  if (fsbuf.f_type == DEVPTS_SUPER_MAGIC)
+    return 0;
+
+  return __unix_grantpt (fd);
+}
+
+#define grantpt __unix_grantpt
+#include <sysdeps/unix/grantpt.c>
Only in 0.15: login/pty-internal.h


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]