1 /* Provide a working getlogin_r for systems which lack it. 2 3 Copyright (C) 2005-2007, 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 Paul Eggert, Derek Price, and Bruno Haible. */ 19 20 #include <config.h> 21 22 /* Specification. */ 23 #include <unistd.h> 24 25 #include <errno.h> 26 #include <string.h> 27 28 #include "malloca.h" 29 30 #if defined _WIN32 && ! defined __CYGWIN__ 31 # define WIN32_LEAN_AND_MEAN 32 # include <windows.h> 33 /* Don't assume that UNICODE is not defined. */ 34 # undef GetUserName 35 # define GetUserName GetUserNameA 36 #else 37 # if !HAVE_DECL_GETLOGIN 38 extern char *getlogin (void); 39 # endif 40 #endif 41 42 /* See unistd.in.h for documentation. */ 43 int 44 getlogin_r (char *name, size_t size) /* */ 45 { 46 #undef getlogin_r 47 #if defined _WIN32 && ! defined __CYGWIN__ 48 /* Native Windows platform. */ 49 DWORD sz; 50 51 /* When size > 0x7fff, the doc says that GetUserName will fail. 52 Actually, on Windows XP SP3, it succeeds. But let's be safe, 53 for the sake of older Windows versions. */ 54 if (size > 0x7fff) 55 size = 0x7fff; 56 sz = size; 57 if (!GetUserName (name, &sz)) 58 { 59 if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) 60 /* In this case, the doc says that sz contains the required size, but 61 actually, on Windows XP SP3, it contains 2 * the required size. */ 62 return ERANGE; 63 else 64 return ENOENT; 65 } 66 return 0; 67 #elif HAVE_GETLOGIN_R 68 /* Platform with a getlogin_r() function. */ 69 int ret = getlogin_r (name, size); 70 71 if (ret == 0) 72 { 73 const char *nul = memchr (name, '\0', size); 74 if (nul == NULL) 75 /* name contains a truncated result. */ 76 return ERANGE; 77 if (size > 0 && nul == name + size - 1) 78 { 79 /* strlen(name) == size-1. Determine whether the untruncated result 80 would have had length size-1 or size. */ 81 char *room = (char *) malloca (size + 1); 82 if (room == NULL) 83 return ENOMEM; 84 ret = getlogin_r (room, size + 1); 85 /* The untruncated result should be the same as in the first call. */ 86 if (ret == 0 && memcmp (name, room, size) != 0) 87 /* The untruncated result would have been different. */ 88 ret = ERANGE; 89 freea (room); 90 } 91 } 92 return ret; 93 #else 94 /* Platform with a getlogin() function. */ 95 char *n; 96 size_t nlen; 97 98 errno = 0; 99 n = getlogin (); 100 if (!n) 101 /* ENOENT is a reasonable errno value if getlogin returns NULL. */ 102 return (errno != 0 ? errno : ENOENT); 103 104 nlen = strlen (n); 105 if (size <= nlen) 106 return ERANGE; 107 memcpy (name, n, nlen + 1); 108 return 0; 109 #endif 110 }