Blame src/ttyname_r.c

Packit d7e8d0
/* ttyname_r.c - A ttyname_r() replacement.
Packit Service 30b792
 * Copyright (C) 2003, 2004, 2012 g10 Code GmbH
Packit Service 30b792
 *
Packit Service 30b792
 * This file is part of GPGME.
Packit Service 30b792
 *
Packit Service 30b792
 * GPGME is free software; you can redistribute it and/or modify it
Packit Service 30b792
 * under the terms of the GNU Lesser General Public License as
Packit Service 30b792
 * published by the Free Software Foundation; either version 2.1 of
Packit Service 30b792
 * the License, or (at your option) any later version.
Packit Service 30b792
 *
Packit Service 30b792
 * GPGME is distributed in the hope that it will be useful, but
Packit Service 30b792
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 30b792
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 30b792
 * Lesser General Public License for more details.
Packit Service 30b792
 *
Packit Service 30b792
 * You should have received a copy of the GNU Lesser General Public
Packit Service 30b792
 * License along with this program; if not, see <https://gnu.org/licenses/>.
Packit Service 30b792
 * SPDX-License-Identifier: LGPL-2.1-or-later
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
}