Blame src/ttyname_r.c

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