root/maint/gnulib/lib/ttyname_r.c

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

DEFINITIONS

This source file includes following definitions.
  1. ttyname_r

   1 /* Determine name of a terminal.
   2 
   3    Copyright (C) 2010-2021 Free Software Foundation, Inc.
   4 
   5    This file is free software: you can redistribute it and/or modify
   6    it under the terms of the GNU Lesser General Public License as
   7    published by the Free Software Foundation; either version 2.1 of the
   8    License, or (at your option) any later version.
   9 
  10    This file is distributed in the hope that it will be useful,
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13    GNU Lesser General Public License for more details.
  14 
  15    You should have received a copy of the GNU Lesser General Public License
  16    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  17 
  18 /* Written by Bruno Haible <bruno@clisp.org>, 2010.  */
  19 
  20 #include <config.h>
  21 
  22 #include <unistd.h>
  23 
  24 #include <errno.h>
  25 #include <limits.h>
  26 #include <string.h>
  27 #if defined __ANDROID__
  28 # include <stdio.h>
  29 #endif
  30 
  31 int
  32 ttyname_r (int fd, char *buf, size_t buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 #undef ttyname_r
  34 {
  35 #if defined __ANDROID__
  36   /* On Android, read the result from the /proc file system.  */
  37   if (!isatty (fd))
  38     /* We rely on isatty to set errno properly (i.e. EBADF or ENOTTY).  */
  39     return errno;
  40   else if (buflen == 0)
  41     return ERANGE;
  42   else
  43     {
  44       char procfile[14+11+1];
  45       char largerbuf[512];
  46       ssize_t ret;
  47       sprintf (procfile, "/proc/self/fd/%d", fd);
  48       ret = (buflen < sizeof (largerbuf)
  49              ? readlink (procfile, largerbuf, sizeof (largerbuf))
  50              : readlink (procfile, buf, buflen <= INT_MAX ? buflen : INT_MAX));
  51       if (ret < 0)
  52         return errno;
  53       if ((size_t) ret >= buflen)
  54         return ERANGE;
  55       if (buflen < sizeof (largerbuf))
  56         memcpy (buf, largerbuf, (size_t) ret);
  57       buf[(size_t) ret] = '\0';
  58       return 0;
  59     }
  60 #elif HAVE_TTYNAME_R
  61   /* When ttyname_r exists, use it.  */
  62   /* This code is multithread-safe.  */
  63   /* On Solaris, ttyname_r always fails if buflen < 128.  On OSF/1 5.1,
  64      ttyname_r ignores the buffer size and assumes the buffer is large enough.
  65      So provide a buffer that is large enough.  */
  66   char largerbuf[512];
  67 # if HAVE_POSIXDECL_TTYNAME_R
  68   int err =
  69     (buflen < sizeof (largerbuf)
  70      ? ttyname_r (fd, largerbuf, sizeof (largerbuf))
  71      : ttyname_r (fd, buf, buflen <= INT_MAX ? buflen : INT_MAX));
  72   if (err != 0)
  73     return err;
  74   if (buflen < sizeof (largerbuf))
  75     {
  76       size_t namelen = strlen (largerbuf) + 1;
  77       if (namelen > buflen)
  78         return ERANGE;
  79       memcpy (buf, largerbuf, namelen);
  80     }
  81 # else
  82   char *name =
  83     (buflen < sizeof (largerbuf)
  84      ? ttyname_r (fd, largerbuf, sizeof (largerbuf))
  85      : ttyname_r (fd, buf, buflen <= INT_MAX ? buflen : INT_MAX));
  86   if (name == NULL)
  87     return errno;
  88   if (name != buf)
  89     {
  90       size_t namelen = strlen (name) + 1;
  91       if (namelen > buflen)
  92         return ERANGE;
  93       memmove (buf, name, namelen);
  94     }
  95 # endif
  96   return 0;
  97 #elif HAVE_TTYNAME
  98   /* Note: This is not multithread-safe.  */
  99   char *name;
 100   size_t namelen;
 101 
 102   name = ttyname (fd);
 103   if (name == NULL)
 104     return errno;
 105   namelen = strlen (name) + 1;
 106   if (namelen > buflen)
 107     return ERANGE;
 108   memcpy (buf, name, namelen);
 109   return 0;
 110 #else
 111   /* Platforms like mingw: no ttys exist at all.  */
 112   return ENOTTY;
 113 #endif
 114 }

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