+2017-04-22 Bruno Haible <bruno@clisp.org>
+
+ getlogin_r: Work around bug in Mac OS X 10.12.
+ * m4/getlogin_r.m4 (gl_FUNC_GETLOGIN_R): Test also against the Mac OS X
+ bug.
+ * lib/getlogin_r.c (getlogin_r): When getlogin_r returns a string of the
+ given size minus 1, call getlogin_r a second time, on a larger buffer.
+ * modules/getlogin_r (Depends-on): Add malloca.
+ * doc/posix-functions/getlogin_r.texi: Mention the Mac OS X bug.
+
2017-04-22 Paul Eggert <eggert@cs.ucla.edu>
parse-datetime: fix %z and prefer signed int
@item
This function returns a truncated result, instead of failing with error code
@code{ERANGE}, when the buffer is not large enough, on some platforms:
-OSF/1 5.1.
+Mac OS X 10.12, OSF/1 5.1.
@end itemize
Portability problems not fixed by Gnulib:
#include <errno.h>
#include <string.h>
+#include "malloca.h"
+
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
/* Platform with a getlogin_r() function. */
int ret = getlogin_r (name, size);
- if (ret == 0 && memchr (name, '\0', size) == NULL)
- /* name contains a truncated result. */
- return ERANGE;
+ if (ret == 0)
+ {
+ const char *nul = memchr (name, '\0', size);
+ if (nul == NULL)
+ /* name contains a truncated result. */
+ return ERANGE;
+ if (size > 0 && nul == name + size - 1)
+ {
+ /* strlen(name) == size-1. Determine whether the untruncated result
+ would have had length size-1 or size. */
+ char *room = (char *) malloca (size + 1);
+ if (room == NULL)
+ return ENOMEM;
+ ret = getlogin_r (room, size + 1);
+ /* The untruncated result should be the same as in the first call. */
+ if (ret == 0 && memcmp (name, room, size) != 0)
+ /* The untruncated result would have been different. */
+ ret = ERANGE;
+ freea (room);
+ }
+ }
return ret;
#else
/* Platform with a getlogin() function. */
-#serial 11
+#serial 12
# Copyright (C) 2005-2007, 2009-2017 Free Software Foundation, Inc.
#
HAVE_GETLOGIN_R=0
else
HAVE_GETLOGIN_R=1
- dnl On OSF/1 5.1, getlogin_r returns a truncated result if the buffer is
- dnl not large enough.
+ dnl On Mac OS X 10.12 and OSF/1 5.1, getlogin_r returns a truncated result
+ dnl if the buffer is not large enough.
AC_REQUIRE([AC_CANONICAL_HOST])
AC_CACHE_CHECK([whether getlogin_r works with small buffers],
[gl_cv_func_getlogin_r_works],
dnl Initial guess, used when cross-compiling.
changequote(,)dnl
case "$host_os" in
- # Guess no on OSF/1.
- osf*) gl_cv_func_getlogin_r_works="guessing no" ;;
- # Guess yes otherwise.
- *) gl_cv_func_getlogin_r_works="guessing yes" ;;
+ # Guess no on Mac OS X, OSF/1.
+ darwin* | osf*) gl_cv_func_getlogin_r_works="guessing no" ;;
+ # Guess yes otherwise.
+ *) gl_cv_func_getlogin_r_works="guessing yes" ;;
esac
changequote([,])dnl
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
#include <stddef.h>
+#include <string.h>
#include <unistd.h>
#if !HAVE_DECL_GETLOGIN_R
extern
char buf[100];
if (getlogin_r (buf, 0) == 0)
- result |= 16;
+ result |= 1;
if (getlogin_r (buf, 1) == 0)
- result |= 17;
+ result |= 2;
+ if (getlogin_r (buf, 100) == 0)
+ {
+ size_t n = strlen (buf);
+ if (getlogin_r (buf, n) == 0)
+ result |= 4;
+ }
return result;
}]])],
[gl_cv_func_getlogin_r_works=yes],
- [case $? in
- 16 | 17) gl_cv_func_getlogin_r_works=no ;;
- esac
- ],
+ [gl_cv_func_getlogin_r_works=no],
[:])
])
case "$gl_cv_func_getlogin_r_works" in
Depends-on:
unistd
extensions
+malloca [test $HAVE_GETLOGIN_R = 0 || test $REPLACE_GETLOGIN_R = 1]
memchr [test $HAVE_GETLOGIN_R = 0 || test $REPLACE_GETLOGIN_R = 1]
configure.ac: