Looking at that test's source code, the test was clearly incorrect for Unix-like systems, as it incorrectly assumed a 1-1 mapping between user names and user IDs. I fixed that in Gnulib by installing the attached patch. Wolfgang, could you please try this on your Linux from Scratch system? You can do that by downloading these two files:

http://git.savannah.gnu.org/cgit/gnulib.git/plain/tests/test-getlogin.c
http://git.savannah.gnu.org/cgit/gnulib.git/plain/tests/test-getlogin_r.c

Use the first to replace the existing test-getlogin.c in your coreutils source directory, and put the second next to the first.

>From 237ea098c82e141713964931f96a37fa6d6cda12 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Mon, 10 Jul 2017 11:56:48 -0700
Subject: [PATCH] =?UTF-8?q?getlogin:=20don=E2=80=99t=20assume=20one=20name?=
 =?UTF-8?q?=20per=20uid?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Problem reported by Wolfgang F. Muthmann (Bug#27640).
* modules/getlogin-tests (Files): Add tests/test-getlogin_r.c.
(ttyname): Remove test.
* modules/getlogin_r-tests (ttyname): Remove test.
* tests/test-getlogin.c: Replace this near-clone of test-getlogin_r.c
with ‘#define TEST_LOGIN’ followed by ‘#include "test-getlogin_r.c"’.
* tests/test-getlogin_r.c: If TEST_GETLOGIN is defined, test
getlogin rather than getlogin_r.  This avoids code duplication.
(main): Use isatty and fstat rather than ttyname and stat.
Use getpwnam instead of getpwuid, to be portable to test platforms
that have multiple login names for the same uid.
---
 ChangeLog                |  15 +++++++
 modules/getlogin-tests   |   2 +-
 modules/getlogin_r-tests |   1 -
 tests/test-getlogin.c    | 112 +----------------------------------------------
 tests/test-getlogin_r.c  |  35 +++++++++------
 5 files changed, 39 insertions(+), 126 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index af99a9c..e5bfb7e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2017-07-10  Paul Eggert  <egg...@cs.ucla.edu>
+
+	getlogin: don’t assume one name per uid
+	Problem reported by Wolfgang F. Muthmann (Bug#27640).
+	* modules/getlogin-tests (Files): Add tests/test-getlogin_r.c.
+	(ttyname): Remove test.
+	* modules/getlogin_r-tests (ttyname): Remove test.
+	* tests/test-getlogin.c: Replace this near-clone of test-getlogin_r.c
+	with ‘#define TEST_LOGIN’ followed by ‘#include "test-getlogin_r.c"’.
+	* tests/test-getlogin_r.c: If TEST_GETLOGIN is defined, test
+	getlogin rather than getlogin_r.  This avoids code duplication.
+	(main): Use isatty and fstat rather than ttyname and stat.
+	Use getpwnam instead of getpwuid, to be portable to test platforms
+	that have multiple login names for the same uid.
+
 2017-07-10  Tim Rühsen  <tim.rueh...@gmx.de>
             Bruno Haible  <br...@clisp.org>
 
diff --git a/modules/getlogin-tests b/modules/getlogin-tests
index c8cdb05..d7d6aea 100644
--- a/modules/getlogin-tests
+++ b/modules/getlogin-tests
@@ -1,12 +1,12 @@
 Files:
 tests/test-getlogin.c
+tests/test-getlogin_r.c
 tests/signature.h
 tests/macros.h
 
 Depends-on:
 
 configure.ac:
-AC_CHECK_FUNCS_ONCE([ttyname])
 
 Makefile.am:
 TESTS += test-getlogin
diff --git a/modules/getlogin_r-tests b/modules/getlogin_r-tests
index 868b1b6..845658f 100644
--- a/modules/getlogin_r-tests
+++ b/modules/getlogin_r-tests
@@ -6,7 +6,6 @@ tests/macros.h
 Depends-on:
 
 configure.ac:
-AC_CHECK_FUNCS_ONCE([ttyname])
 
 Makefile.am:
 TESTS += test-getlogin_r
diff --git a/tests/test-getlogin.c b/tests/test-getlogin.c
index 86b2a9e..6a6d269 100644
--- a/tests/test-getlogin.c
+++ b/tests/test-getlogin.c
@@ -1,110 +1,2 @@
-/* Test of getting user name.
-   Copyright (C) 2010-2017 Free Software Foundation, Inc.
-
-   This program is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/* Written by Bruno Haible <br...@clisp.org>, 2010.  */
-
-#include <config.h>
-
-#include <unistd.h>
-
-#include "signature.h"
-SIGNATURE_CHECK (getlogin, char *, (void));
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
-# include <pwd.h>
-#endif
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "macros.h"
-
-int
-main (void)
-{
-  char *buf;
-
-  /* Test value.  */
-  buf = getlogin ();
-  if (buf == NULL)
-    {
-      if (errno == ENOENT)
-        {
-          /* This can happen on GNU/Linux.  */
-          fprintf (stderr, "Skipping test: no entry in utmp file.\n");
-          return 77;
-        }
-
-      /* getlogin() fails when stdin is not connected to a tty.  */
-      ASSERT (errno == ENOTTY
-              || errno == EINVAL /* seen on Linux/SPARC */
-              || errno == ENXIO
-             );
-#if !defined __hpux /* On HP-UX 11.11 it fails anyway.  */
-      ASSERT (! isatty (0));
-#endif
-      fprintf (stderr, "Skipping test: stdin is not a tty.\n");
-      return 77;
-    }
-
-  /* Compare against the value from the environment.  */
-#if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
-  /* Unix platform */
-  {
-# if HAVE_TTYNAME
-    const char *tty;
-    struct stat stat_buf;
-    struct passwd *pwd;
-
-    tty = ttyname (STDIN_FILENO);
-    if (tty == NULL)
-      {
-         fprintf (stderr, "Skipping test: stdin is not a tty.\n");
-         return 77;
-      }
-
-    ASSERT (stat (tty, &stat_buf) == 0);
-
-    pwd = getpwuid (stat_buf.st_uid);
-    if (! pwd)
-      {
-        long int uid = stat_buf.st_uid;
-        fprintf (stderr, "Skipping test: no name found for uid %ld\n", uid);
-        return 77;
-      }
-
-    ASSERT (strcmp (pwd->pw_name, buf) == 0);
-# endif
-  }
-#endif
-#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
-  /* Native Windows platform.
-     Note: This test would fail on Cygwin in an ssh session, because sshd
-     sets USERNAME=SYSTEM.  */
-  {
-    const char *name = getenv ("USERNAME");
-    if (name != NULL && name[0] != '\0')
-      ASSERT (strcmp (buf, name) == 0);
-  }
-#endif
-
-  return 0;
-}
+#define TEST_GETLOGIN
+#include "test-getlogin_r.c"
diff --git a/tests/test-getlogin_r.c b/tests/test-getlogin_r.c
index f7cdc3a..0a7e105 100644
--- a/tests/test-getlogin_r.c
+++ b/tests/test-getlogin_r.c
@@ -21,7 +21,11 @@
 #include <unistd.h>
 
 #include "signature.h"
+#ifdef TEST_GETLOGIN
+SIGNATURE_CHECK (getlogin, char *, (void));
+#else
 SIGNATURE_CHECK (getlogin_r, int, (char *, size_t));
+#endif
 
 #include <errno.h>
 #include <stdio.h>
@@ -40,11 +44,17 @@ SIGNATURE_CHECK (getlogin_r, int, (char *, size_t));
 int
 main (void)
 {
+  /* Test value.  */
+#ifdef TEST_GETLOGIN
+  char *buf = getlogin ();
+  int err = buf ? 0 : errno;
+  ASSERT (buf || err);
+#else
   /* Test with a large enough buffer.  */
   char buf[1024];
-  int err;
+  int err = getlogin_r (buf, sizeof buf);
+#endif
 
-  err = getlogin_r (buf, sizeof (buf));
   if (err != 0)
     {
       if (err == ENOENT)
@@ -54,7 +64,7 @@ main (void)
           return 77;
         }
 
-      /* getlogin_r() fails when stdin is not connected to a tty.  */
+      /* It fails when stdin is not connected to a tty.  */
       ASSERT (err == ENOTTY
               || err == EINVAL /* seen on Linux/SPARC */
               || err == ENXIO
@@ -70,30 +80,25 @@ main (void)
 #if !((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__)
   /* Unix platform */
   {
-# if HAVE_TTYNAME
-    const char *tty;
     struct stat stat_buf;
     struct passwd *pwd;
 
-    tty = ttyname (STDIN_FILENO);
-    if (tty == NULL)
+    if (!isatty (STDIN_FILENO))
       {
          fprintf (stderr, "Skipping test: stdin is not a tty.\n");
          return 77;
       }
 
-    ASSERT (stat (tty, &stat_buf) == 0);
+    ASSERT (fstat (STDIN_FILENO, &stat_buf) == 0);
 
-    pwd = getpwuid (stat_buf.st_uid);
+    pwd = getpwnam (buf);
     if (! pwd)
       {
-         fprintf (stderr, "Skipping test: no name found for uid %d\n",
-                  stat_buf.st_uid);
-         return 77;
+        fprintf (stderr, "Skipping test: %s: no such user\n", buf);
+        return 77;
       }
 
-    ASSERT (strcmp (pwd->pw_name, buf) == 0);
-# endif
+    ASSERT (pwd->pw_uid == stat_buf.st_uid);
   }
 #endif
 #if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
@@ -107,6 +112,7 @@ main (void)
   }
 #endif
 
+#ifndef TEST_GETLOGIN
   /* Test with a small buffer.  */
   {
     char smallbuf[1024];
@@ -130,6 +136,7 @@ main (void)
     ASSERT (getlogin_r (hugebuf, sizeof (hugebuf)) == 0);
     ASSERT (strcmp (hugebuf, buf) == 0);
   }
+#endif
 
   return 0;
 }
-- 
2.9.4

Reply via email to