Blame lib/getlogin_r.c

Packit 8f70b4
/* Provide a working getlogin_r for systems which lack it.
Packit 8f70b4
Packit 8f70b4
   Copyright (C) 2005-2007, 2010-2018 Free Software Foundation, Inc.
Packit 8f70b4
Packit 8f70b4
   This program is free software; you can redistribute it and/or modify
Packit 8f70b4
   it under the terms of the GNU General Public License as published by
Packit 8f70b4
   the Free Software Foundation; either version 3, or (at your option)
Packit 8f70b4
   any later version.
Packit 8f70b4
Packit 8f70b4
   This program is distributed in the hope that it will be useful,
Packit 8f70b4
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
   GNU General Public License for more details.
Packit 8f70b4
Packit 8f70b4
   You should have received a copy of the GNU General Public License
Packit 8f70b4
   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit 8f70b4
Packit 8f70b4
/* Written by Paul Eggert, Derek Price, and Bruno Haible.  */
Packit 8f70b4
Packit 8f70b4
#include <config.h>
Packit 8f70b4
Packit 8f70b4
/* Specification.  */
Packit 8f70b4
#include <unistd.h>
Packit 8f70b4
Packit 8f70b4
#include <errno.h>
Packit 8f70b4
#include <string.h>
Packit 8f70b4
Packit 8f70b4
#include "malloca.h"
Packit 8f70b4
Packit 8f70b4
#if defined _WIN32 && ! defined __CYGWIN__
Packit 8f70b4
# define WIN32_LEAN_AND_MEAN
Packit 8f70b4
# include <windows.h>
Packit 8f70b4
#else
Packit 8f70b4
# if !HAVE_DECL_GETLOGIN
Packit 8f70b4
extern char *getlogin (void);
Packit 8f70b4
# endif
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/* See unistd.in.h for documentation.  */
Packit 8f70b4
int
Packit 8f70b4
getlogin_r (char *name, size_t size)
Packit 8f70b4
{
Packit 8f70b4
#undef getlogin_r
Packit 8f70b4
#if defined _WIN32 && ! defined __CYGWIN__
Packit 8f70b4
  /* Native Windows platform.  */
Packit 8f70b4
  DWORD sz;
Packit 8f70b4
Packit 8f70b4
  /* When size > 0x7fff, the doc says that GetUserName will fail.
Packit 8f70b4
     Actually, on Windows XP SP3, it succeeds.  But let's be safe,
Packit 8f70b4
     for the sake of older Windows versions.  */
Packit 8f70b4
  if (size > 0x7fff)
Packit 8f70b4
    size = 0x7fff;
Packit 8f70b4
  sz = size;
Packit 8f70b4
  if (!GetUserName (name, &sz))
Packit 8f70b4
    {
Packit 8f70b4
      if (GetLastError () == ERROR_INSUFFICIENT_BUFFER)
Packit 8f70b4
        /* In this case, the doc says that sz contains the required size, but
Packit 8f70b4
           actually, on Windows XP SP3, it contains 2 * the required size.  */
Packit 8f70b4
        return ERANGE;
Packit 8f70b4
      else
Packit 8f70b4
        return ENOENT;
Packit 8f70b4
    }
Packit 8f70b4
  return 0;
Packit 8f70b4
#elif HAVE_GETLOGIN_R
Packit 8f70b4
  /* Platform with a getlogin_r() function.  */
Packit 8f70b4
  int ret = getlogin_r (name, size);
Packit 8f70b4
Packit 8f70b4
  if (ret == 0)
Packit 8f70b4
    {
Packit 8f70b4
      const char *nul = memchr (name, '\0', size);
Packit 8f70b4
      if (nul == NULL)
Packit 8f70b4
        /* name contains a truncated result.  */
Packit 8f70b4
        return ERANGE;
Packit 8f70b4
      if (size > 0 && nul == name + size - 1)
Packit 8f70b4
        {
Packit 8f70b4
          /* strlen(name) == size-1.  Determine whether the untruncated result
Packit 8f70b4
             would have had length size-1 or size.  */
Packit 8f70b4
          char *room = (char *) malloca (size + 1);
Packit 8f70b4
          if (room == NULL)
Packit 8f70b4
            return ENOMEM;
Packit 8f70b4
          ret = getlogin_r (room, size + 1);
Packit 8f70b4
          /* The untruncated result should be the same as in the first call.  */
Packit 8f70b4
          if (ret == 0 && memcmp (name, room, size) != 0)
Packit 8f70b4
            /* The untruncated result would have been different.  */
Packit 8f70b4
            ret = ERANGE;
Packit 8f70b4
          freea (room);
Packit 8f70b4
        }
Packit 8f70b4
    }
Packit 8f70b4
  return ret;
Packit 8f70b4
#else
Packit 8f70b4
  /* Platform with a getlogin() function.  */
Packit 8f70b4
  char *n;
Packit 8f70b4
  size_t nlen;
Packit 8f70b4
Packit 8f70b4
  errno = 0;
Packit 8f70b4
  n = getlogin ();
Packit 8f70b4
  if (!n)
Packit 8f70b4
    /* ENOENT is a reasonable errno value if getlogin returns NULL.  */
Packit 8f70b4
    return (errno != 0 ? errno : ENOENT);
Packit 8f70b4
Packit 8f70b4
  nlen = strlen (n);
Packit 8f70b4
  if (size <= nlen)
Packit 8f70b4
    return ERANGE;
Packit 8f70b4
  memcpy (name, n, nlen + 1);
Packit 8f70b4
  return 0;
Packit 8f70b4
#endif
Packit 8f70b4
}