Blame src/ttyname_r.c

Packit Service 672cf4
/* ttyname_r.c - A ttyname_r() replacement.
Packit Service 6c01f9
   Copyright (C) 2003, 2004, 2012 g10 Code GmbH
Packit Service 6c01f9
Packit Service 6c01f9
   This file is part of GPGME.
Packit Service 6c01f9
Packit Service 6c01f9
   GPGME is free software; you can redistribute it and/or modify it
Packit Service 6c01f9
   under the terms of the GNU Lesser General Public License as
Packit Service 6c01f9
   published by the Free Software Foundation; either version 2.1 of
Packit Service 6c01f9
   the License, or (at your option) any later version.
Packit Service 6c01f9
Packit Service 6c01f9
   GPGME is distributed in the hope that it will be useful, but
Packit Service 6c01f9
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 6c01f9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 6c01f9
   Lesser General Public License for more details.
Packit Service 6c01f9
Packit Service 6c01f9
   You should have received a copy of the GNU Lesser General Public
Packit Service 6c01f9
   License along with this program; if not, see <https://www.gnu.org/licenses/>.
Packit Service 672cf4
 */
Packit Service 672cf4
Packit Service 672cf4
#if HAVE_CONFIG_H
Packit Service 672cf4
#include <config.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
#include <stdlib.h>
Packit Service 672cf4
#include <errno.h>
Packit Service 672cf4
#include <string.h>
Packit Service 672cf4
#ifdef HAVE_UNISTD_H
Packit Service 672cf4
# include <unistd.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
Packit Service 672cf4

Packit Service 672cf4
#if !HAVE_TTYNAME_R && defined(__GNUC__)
Packit Service 672cf4
# warning ttyname is not thread-safe, and ttyname_r is missing
Packit Service 672cf4
#endif
Packit Service 672cf4
Packit Service 672cf4
/* For Android we force the use of our replacement code.  */
Packit Service 672cf4
#if HAVE_ANDROID_SYSTEM
Packit Service 672cf4
# undef HAVE_TTYNAME_R
Packit Service 672cf4
#endif
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
int
Packit Service 672cf4
_gpgme_ttyname_r (int fd, char *buf, size_t buflen)
Packit Service 672cf4
{
Packit Service 672cf4
#if HAVE_TTYNAME_R
Packit Service 672cf4
# if HAVE_BROKEN_TTYNAME_R
Packit Service 672cf4
   /* Solaris fails if BUFLEN is less than 128. OSF/1 5.1 completely
Packit Service 672cf4
      ignores BUFLEN.  We use a large buffer to woraround this.  */
Packit Service 672cf4
  {
Packit Service 672cf4
    char largebuf[512];
Packit Service 672cf4
    size_t namelen;
Packit Service 672cf4
    int rc;
Packit Service 672cf4
Packit Service 672cf4
#  if HAVE_POSIXDECL_TTYNAME_R
Packit Service 672cf4
    if (buflen < sizeof (largebuf))
Packit Service 672cf4
      {
Packit Service 672cf4
        rc = ttyname_r (fd, largebuf, (int)sizeof (largebuf));
Packit Service 672cf4
        if (!rc)
Packit Service 672cf4
          {
Packit Service 672cf4
            namelen = strlen (largebuf) + 1;
Packit Service 672cf4
            if (namelen > buflen)
Packit Service 672cf4
              rc = ERANGE;
Packit Service 672cf4
            else
Packit Service 672cf4
              memcpy (buf, largebuf, namelen);
Packit Service 672cf4
          }
Packit Service 672cf4
      }
Packit Service 672cf4
    else
Packit Service 672cf4
      rc = ttyname_r (fd, buf, (int)buflen);
Packit Service 672cf4
Packit Service 672cf4
#  else /*!HAVE_POSIXDECL_TTYNAME_R*/
Packit Service 672cf4
    char *name;
Packit Service 672cf4
Packit Service 672cf4
    if (buflen < sizeof (largebuf))
Packit Service 672cf4
      name = ttyname_r (fd, largebuf, (int)sizeof (largebuf));
Packit Service 672cf4
    else
Packit Service 672cf4
      name = ttyname_r (fd, buf, (int)buflen);
Packit Service 672cf4
    rc = name? 0 : (errno? errno : -1);
Packit Service 672cf4
    if (!rc && buf != name)
Packit Service 672cf4
      {
Packit Service 672cf4
        namelen = strlen (name) + 1;
Packit Service 672cf4
        if (namelen > buflen)
Packit Service 672cf4
          rc = ERANGE;
Packit Service 672cf4
        else
Packit Service 672cf4
          memmove (buf, name, namelen);
Packit Service 672cf4
      }
Packit Service 672cf4
#  endif
Packit Service 672cf4
Packit Service 672cf4
    return rc;
Packit Service 672cf4
  }
Packit Service 672cf4
# else /*!HAVE_BROKEN_TTYNAME_R*/
Packit Service 672cf4
  {
Packit Service 672cf4
    int rc;
Packit Service 672cf4
Packit Service 672cf4
#  if HAVE_POSIXDECL_TTYNAME_R
Packit Service 672cf4
Packit Service 672cf4
    rc = ttyname_r (fd, buf, buflen);
Packit Service 672cf4
Packit Service 672cf4
#  else /*!HAVE_POSIXDECL_TTYNAME_R*/
Packit Service 672cf4
    char *name;
Packit Service 672cf4
    size_t namelen;
Packit Service 672cf4
Packit Service 672cf4
    name = ttyname_r (fd, buf, (int)buflen);
Packit Service 672cf4
    rc = name? 0 : (errno? errno : -1);
Packit Service 672cf4
    if (!rc && buf != name)
Packit Service 672cf4
      {
Packit Service 672cf4
        namelen = strlen (name) + 1;
Packit Service 672cf4
        if (namelen > buflen)
Packit Service 672cf4
          rc = ERANGE;
Packit Service 672cf4
        else
Packit Service 672cf4
          memmove (buf, name, namelen);
Packit Service 672cf4
      }
Packit Service 672cf4
#  endif
Packit Service 672cf4
Packit Service 672cf4
    return rc;
Packit Service 672cf4
  }
Packit Service 672cf4
# endif /*!HAVE_BROKEN_TTYNAME_R*/
Packit Service 672cf4
#else /*!HAVE_TTYNAME_R*/
Packit Service 672cf4
  char *tty;
Packit Service 672cf4
Packit Service 672cf4
# if HAVE_W32_SYSTEM || HAVE_ANDROID_SYSTEM
Packit Service 672cf4
  /* We use this default one for now.  AFAICS we only need it to be
Packit Service 672cf4
     passed to gpg and in turn to pinentry.  Providing a replacement
Packit Service 672cf4
     is needed because elsewhere we bail out on error or Android
Packit Service 672cf4
     provided ttyname_r prints an error message if used. */
Packit Service 672cf4
  tty = "/dev/tty";
Packit Service 672cf4
# else
Packit Service 672cf4
  tty = ttyname (fd);
Packit Service 672cf4
  if (!tty)
Packit Service 672cf4
    return errno? errno : -1;
Packit Service 672cf4
# endif
Packit Service 672cf4
Packit Service 672cf4
  strncpy (buf, tty, buflen);
Packit Service 672cf4
  buf[buflen - 1] = '\0';
Packit Service 672cf4
  return (strlen (tty) >= buflen) ? ERANGE : 0;
Packit Service 672cf4
#endif /*!HAVE_TTYNAME_R*/
Packit Service 672cf4
}