diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2017-07-10 11:56:48 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-07-10 12:02:09 -0700 |
commit | 24605b2f03bfa8367a9149835c687c9073aacc2c (patch) | |
tree | 55ef05fadaeaec93569187156a7db516a362717c | |
parent | 8cb994d1fc4a957359780e1a4187b4f250c1cea5 (diff) | |
download | gnulib-24605b2f03bfa8367a9149835c687c9073aacc2c.tar.gz |
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.
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | modules/getlogin-tests | 2 | ||||
-rw-r--r-- | modules/getlogin_r-tests | 1 | ||||
-rw-r--r-- | tests/test-getlogin.c | 112 | ||||
-rw-r--r-- | tests/test-getlogin_r.c | 35 |
5 files changed, 39 insertions, 126 deletions
@@ -1,3 +1,18 @@ +2017-07-10 Paul Eggert <eggert@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.ruehsen@gmx.de> Bruno Haible <bruno@clisp.org> diff --git a/modules/getlogin-tests b/modules/getlogin-tests index c8cdb05eb0..d7d6aeafa8 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 868b1b6f73..845658fdc2 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 86b2a9ef1f..6a6d26964b 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 <bruno@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 f7cdc3a7d3..0a7e105dd3 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; } |