Beispiel #1
0
/* Change the ownership and access permission of the slave pseudo
   terminal associated with the master pseudo terminal specified
   by FD.  */
int
grantpt (int fd)
{
#if !defined __ASSUME_DEVPTS__
  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 && fsbuf.f_type != DEVFS_SUPER_MAGIC)
  return __unix_grantpt (fd);
#endif
  return 0;
}
Beispiel #2
0
/* Create pseudo tty master slave pair and set terminal attributes
   according to TERMP and WINP.  Return handles for both ends in
   AMASTER and ASLAVE, and return the name of the slave end in NAME.  */
int
openpty (int *amaster, int *aslave, char *name,
	 const struct termios *termp, const struct winsize *winp)
{
#ifdef PATH_MAX
  char _buf[PATH_MAX];
#else
  char _buf[512];
#endif
  char *buf = _buf;
  int master, slave;

  master = getpt ();
  if (master == -1)
    return -1;

  if (grantpt (master))
    goto fail;

  if (unlockpt (master))
    goto fail;

  if (pts_name (master, &buf, sizeof (_buf)))
    goto fail;

  slave = open (buf, O_RDWR | O_NOCTTY);
  if (slave == -1)
    {
      if (buf != _buf)
	free (buf);

      goto fail;
    }

  /* XXX Should we ignore errors here?  */
  if(termp)
    tcsetattr (slave, TCSAFLUSH, termp);
  if (winp)
    ioctl (slave, TIOCSWINSZ, winp);

  *amaster = master;
  *aslave = slave;
  if (name != NULL)
    strcpy (name, buf);

  if (buf != _buf)
    free (buf);
  return 0;

 fail:
  close (master);
  return -1;
}
Beispiel #3
0
/* 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;
  char _buf[PATH_MAX];
  char *buf = _buf;

  if (pts_name (fd, &buf, sizeof (_buf)))
    return -1;

  if (__libc_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 && fsbuf.f_type != DEVFS_SUPER_MAGIC)
    return __unix_grantpt (fd);

  return 0;
}
Beispiel #4
0
/* 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 (__builtin_expect (pts_name (fd, &buf, sizeof (_buf)), 0))
    {
      int save_errno = errno;

      /* Check, if the file descriptor is valid. pts_name returns the
	 wrong errno number, so we cannot use that.  */
      if (__libc_fcntl (fd, F_GETFD) == -1 && errno == EBADF)
	return -1;

       /* If the filedescriptor is no TTY, grantpt has to set errno
          to EINVAL.  */
       if (save_errno == ENOTTY)
         __set_errno (EINVAL);
       else
	 __set_errno (save_errno);

       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 || fsbuf.f_type == DEVFS_SUPER_MAGIC)
    return 0;

  return __unix_grantpt (fd);
}
Beispiel #5
0
/* Change the ownership and access permission of the slave pseudo
   terminal associated with the master pseudo terminal specified
   by FD.  */
int
grantpt (int fd)
{
  int retval = -1;
#ifdef PATH_MAX
  char _buf[PATH_MAX];
#else
  char _buf[512];
#endif
  char *buf = _buf;
  struct stat64 st;

  if (__glibc_unlikely (pts_name (fd, &buf, sizeof (_buf), &st)))
    {
      int save_errno = errno;

      /* Check, if the file descriptor is valid.  pts_name returns the
	 wrong errno number, so we cannot use that.  */
      if (__libc_fcntl (fd, F_GETFD) == -1 && errno == EBADF)
	return -1;

       /* If the filedescriptor is no TTY, grantpt has to set errno
	  to EINVAL.  */
       if (save_errno == ENOTTY)
	 __set_errno (EINVAL);
       else
	 __set_errno (save_errno);

       return -1;
    }

  /* Make sure that we own the device.  */
  uid_t uid = __getuid ();
  if (st.st_uid != uid)
    {
      if (__chown (buf, uid, st.st_gid) < 0)
	goto helper;
    }

  static int tty_gid = -1;
  if (__glibc_unlikely (tty_gid == -1))
    {
      char *grtmpbuf;
      struct group grbuf;
      size_t grbuflen = __sysconf (_SC_GETGR_R_SIZE_MAX);
      struct group *p;

      /* Get the group ID of the special `tty' group.  */
      if (grbuflen == (size_t) -1L)
	/* `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);
      if (p != NULL)
	tty_gid = p->gr_gid;
    }
  gid_t gid = tty_gid == -1 ? __getgid () : tty_gid;

  /* 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;
    }

  retval = 0;
  goto cleanup;

  /* We have to use the helper program if it is available.  */
 helper:;

#ifdef HAVE_PT_CHOWN
  pid_t pid = __fork ();
  if (pid == -1)
    goto cleanup;
  else if (pid == 0)
    {
      /* Disable core dumps.  */
      struct rlimit rl = { 0, 0 };
      __setrlimit (RLIMIT_CORE, &rl);

      /* We pass the master pseudo terminal as file descriptor PTY_FILENO.  */
      if (fd != PTY_FILENO)
	if (__dup2 (fd, PTY_FILENO) < 0)
	  _exit (FAIL_EBADF);

# ifdef CLOSE_ALL_FDS
      CLOSE_ALL_FDS ();
# endif

      execle (_PATH_PT_CHOWN, basename (_PATH_PT_CHOWN), NULL, NULL);
      _exit (FAIL_EXEC);
    }
  else
    {
      int w;

      if (__waitpid (pid, &w, 0) == -1)
	goto cleanup;
      if (!WIFEXITED (w))
	__set_errno (ENOEXEC);
      else
	switch (WEXITSTATUS (w))
	  {
	  case 0:
	    retval = 0;
	    break;
	  case FAIL_EBADF:
	    __set_errno (EBADF);
	    break;
	  case FAIL_EINVAL:
	    __set_errno (EINVAL);
	    break;
	  case FAIL_EACCES:
	    __set_errno (EACCES);
	    break;
	  case FAIL_EXEC:
	    __set_errno (ENOEXEC);
	    break;
	  case FAIL_ENOMEM:
	    __set_errno (ENOMEM);
	    break;

	  default:
	    assert(! "getpt: internal error: invalid exit code from pt_chown");
	  }
    }
#endif

 cleanup:
  if (buf != _buf)
    free (buf);

  return retval;
}
Beispiel #6
0
/* Change the ownership and access permission of the slave pseudo
   terminal associated with the master pseudo terminal specified
   by FD.  */
int
grantpt (int fd)
{
  int retval = -1;
#ifdef PATH_MAX
  char _buf[PATH_MAX];
#else
  char _buf[512];
#endif
  char *buf = _buf;
  struct stat st;
  uid_t uid;
  gid_t gid;
  pid_t pid;

  if (pts_name (fd, &buf, sizeof (_buf)))
    return -1;

  if (stat(buf, &st) < 0)
    goto cleanup;

  /* Make sure that we own the device.  */
  uid = getuid ();
  if (st.st_uid != uid)
    {
      if (chown (buf, uid, st.st_gid) < 0)
	goto helper;
    }

  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;
    }

  retval = 0;
  goto cleanup;

  /* We have to use the helper program.  */
 helper:

  pid = vfork ();
  if (pid == -1)
    goto cleanup;
  else if (pid == 0)
    {
      /* 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);

      execle (_PATH_PT_CHOWN, _PATH_PT_CHOWN, NULL, NULL);
      _exit (FAIL_EXEC);
    }
  else
    {
      int w;

      if (waitpid (pid, &w, 0) == -1)
	goto cleanup;
      if (!WIFEXITED (w))
	errno = ENOEXEC;
      else
	switch (WEXITSTATUS(w))
	  {
	  case 0:
	    retval = 0;
	    break;
	  case FAIL_EBADF:
	    errno = EBADF;
	    break;
	  case FAIL_EINVAL:
	    errno = EINVAL;
	    break;
	  case FAIL_EACCES:
	    errno = EACCES;
	    break;
	  case FAIL_EXEC:
	    errno = ENOEXEC;
	    break;

	  default:
	    assert(! "getpt: internal error: invalid exit code from pt_chown");
	  }
    }

 cleanup:
  if (buf != _buf)
    free (buf);

  return retval;
}