root/maint/gnulib/lib/ptsname_r.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ptsname_r

   1 /* Determine name of the slave side of a pseudo-terminal.
   2    Copyright (C) 1998, 2002, 2010-2021 Free Software Foundation, Inc.
   3 
   4    This file is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU Lesser General Public License as
   6    published by the Free Software Foundation; either version 2.1 of the
   7    License, or (at your option) any later version.
   8 
   9    This file is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 #include <config.h>
  18 
  19 /* Specification.  */
  20 #include <stdlib.h>
  21 
  22 #include <errno.h>
  23 #include <fcntl.h>
  24 #include <string.h>
  25 #include <sys/stat.h>
  26 #include <unistd.h>
  27 
  28 #ifndef _PATH_TTY
  29 # define _PATH_TTY "/dev/tty"
  30 #endif
  31 #ifndef _PATH_DEV
  32 # define _PATH_DEV "/dev/"
  33 #endif
  34 
  35 /* Get the major, minor macros.  */
  36 #if MAJOR_IN_MKDEV
  37 # include <sys/mkdev.h>
  38 #endif
  39 #if MAJOR_IN_SYSMACROS
  40 # include <sys/sysmacros.h>
  41 #endif
  42 
  43 #ifdef __sun
  44 /* Get ioctl() and 'struct strioctl'.  */
  45 # include <stropts.h>
  46 /* Get ISPTM.  */
  47 # include <sys/stream.h>
  48 # include <sys/ptms.h>
  49 # include <stdio.h>
  50 #endif
  51 
  52 #if defined _AIX || defined __osf__
  53 /* Get ioctl(), ISPTM.  */
  54 # include <sys/ioctl.h>
  55 # include <stdio.h>
  56 #endif
  57 
  58 #if defined __DragonFly__
  59 /* Get fdevname_r().  */
  60 # include <stdlib.h>
  61 #endif
  62 
  63 /* Store at most BUFLEN characters of the pathname of the slave pseudo
  64    terminal associated with the master FD is open on in BUF.
  65    Return 0 on success, otherwise an error number.  */
  66 int
  67 ptsname_r (int fd, char *buf, size_t buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 #undef ptsname_r
  69 {
  70 #if HAVE_ESSENTIALLY_WORKING_PTSNAME_R
  71   int ret = ptsname_r (fd, buf, buflen);
  72   if (ret == 0)
  73     return 0;
  74   else
  75     return errno;
  76 #elif defined __DragonFly__
  77   int saved_errno = errno;
  78   char tmpbuf[5 + 4 + 10 + 1];
  79   int ret;
  80   int n;
  81   if (buf == NULL)
  82     {
  83       errno = EINVAL;
  84       return errno;
  85     }
  86   /* The result of fdevname_r is typically of the form ptm/N.  */
  87   ret = fdevname_r (fd, tmpbuf + 5, sizeof (tmpbuf) - 5);
  88   if (ret < 0 || strncmp (tmpbuf + 5, "ptm/", 4) != 0)
  89     {
  90       errno = ENOTTY;
  91       return errno;
  92     }
  93   /* Turn it into /dev/pts/N.  */
  94   memcpy (tmpbuf, "/dev/pts/", 5 + 4);
  95   n = strlen (tmpbuf);
  96   if (n >= buflen)
  97     {
  98       errno = ERANGE;
  99       return errno;
 100     }
 101   memcpy (buf, tmpbuf, n + 1);
 102   /* Don't do a final stat(), since the file name /dev/pts/N does not actually
 103      exist.  */
 104   errno = saved_errno;
 105   return 0;
 106 #else
 107   int saved_errno = errno;
 108   struct stat st;
 109 
 110   if (buf == NULL)
 111     {
 112       errno = EINVAL;
 113       return errno;
 114     }
 115 
 116 # if defined __sun /* Solaris */
 117   if (fstat (fd, &st) < 0)
 118     return errno;
 119   if (!S_ISCHR (st.st_mode))
 120     {
 121       errno = ENOTTY;
 122       return errno;
 123     }
 124   {
 125     /* Master ptys can be recognized through a STREAMS ioctl.  See
 126        "STREAMS-based Pseudo-Terminal Subsystem"
 127        <https://docs.oracle.com/cd/E18752_01/html/816-4855/termsub15-44781.html>
 128        and "STREAMS ioctl commands"
 129        <https://docs.oracle.com/cd/E18752_01/html/816-5177/streamio-7i.html>
 130      */
 131     struct strioctl ioctl_arg;
 132     ioctl_arg.ic_cmd = ISPTM;
 133     ioctl_arg.ic_timout = 0;
 134     ioctl_arg.ic_len = 0;
 135     ioctl_arg.ic_dp = NULL;
 136 
 137     if (ioctl (fd, I_STR, &ioctl_arg) < 0)
 138       {
 139         errno = ENOTTY;
 140         return errno;
 141       }
 142   }
 143   {
 144     char tmpbuf[9 + 10 + 1];
 145     int n = sprintf (tmpbuf, "/dev/pts/%u", minor (st.st_rdev));
 146     if (n >= buflen)
 147       {
 148         errno = ERANGE;
 149         return errno;
 150       }
 151     memcpy (buf, tmpbuf, n + 1);
 152   }
 153 # elif defined _AIX || defined __osf__ /* AIX, OSF/1 */
 154   /* This implementation returns /dev/pts/N, like ptsname() does.
 155      Whereas the generic implementation below returns /dev/ttypN.
 156      Both are correct, but let's be consistent with ptsname().  */
 157   if (fstat (fd, &st) < 0)
 158     return errno;
 159   if (!S_ISCHR (st.st_mode))
 160     {
 161       errno = ENOTTY;
 162       return errno;
 163     }
 164   {
 165     int ret;
 166     int dev;
 167     char tmpbuf[9 + 10 + 1];
 168     int n;
 169 #  ifdef _AIX
 170     ret = ioctl (fd, ISPTM, &dev);
 171 #  endif
 172 #  ifdef __osf__
 173     ret = ioctl (fd, ISPTM, NULL);
 174     dev = ret;
 175 #  endif
 176     if (ret < 0)
 177       {
 178         errno = ENOTTY;
 179         return errno;
 180       }
 181     n = sprintf (tmpbuf, "/dev/pts/%u", minor (dev));
 182     if (n >= buflen)
 183       {
 184         errno = ERANGE;
 185         return errno;
 186       }
 187     memcpy (buf, tmpbuf, n + 1);
 188   }
 189 # else
 190   if (!isatty (fd))
 191     {
 192 #  if ISATTY_FAILS_WITHOUT_SETTING_ERRNO && defined F_GETFL /* IRIX, Solaris */
 193       /* Set errno.  */
 194       if (fcntl (fd, F_GETFL) != -1)
 195         errno = ENOTTY;
 196 #  else
 197       /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY).  */
 198 #  endif
 199       return errno;
 200     }
 201 
 202   if (buflen < strlen (_PATH_TTY) + 3)
 203     {
 204       errno = ERANGE;
 205       return errno;
 206     }
 207 
 208   int err = ttyname_r (fd, buf, buflen);
 209   if (err != 0)
 210     {
 211       errno = err;
 212       return errno;
 213     }
 214 
 215   if (strncmp(buf, "/dev/pts/", strlen("/dev/pts/")) != 0)
 216     buf[sizeof (_PATH_DEV) - 1] = 't';
 217 # endif
 218 
 219   if (stat (buf, &st) < 0 && errno != EOVERFLOW)
 220     return errno;
 221 
 222   errno = saved_errno;
 223   return 0;
 224 #endif
 225 }

/* [previous][next][first][last][top][bottom][index][help] */