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