1 From b5891a57b586ef6ff78bb752d62915b78cd58d7e Mon Sep 17 00:00:00 2001
2 From: Zack Weinberg <zackw@panix.com>
3 Date: Sun, 2 Apr 2023 15:07:58 -0400
4 Subject: [PATCH 12/29] Overhaul AC_TYPE_GETGROUPS and AC_FUNC_GETGROUPS.
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 AC_TYPE_GETGROUPS is the last remaining use of AC_EGREP_HEADER in
10 stock Autoconf macros. It uses it only when cross compiling, as a
11 fallback from an AC_RUN_IFELSE check, testing for a bug in system
12 headers from the late 1980s or early 1990s, where gid_t *existed*
13 but the second argument to getgroups needed to be an array of int,
14 and this didn’t cause a compile error (i.e. the system headers
15 declare getgroups with no prototype or an incorrect prototype).
16 AC_FUNC_GETGROUPS also uses AC_RUN_IFELSE to test for obscure
17 problems specific to long-obsolete Unixes.
19 The downsides of AC_RUN_IFELSE and AC_EGREP_HEADER seem more severe
20 than the chances of someone compiling a current-generation program,
21 that uses getgroups, on an OS old enough to have one of the really
22 nasty bugs. Accordingly, this patch changes AC_FUNC_GETGROUPS to use
23 a host_os-based *blacklist* both in native and cross compilation.
24 This is limited to the two host_os values for which either our old
25 code, or Gnulib, documented a serious bug: ultrix* and nextstep*.
26 Currently it does not try to pin down the exact version ranges subject
27 to the bugs — that would require research by someone with access to
28 the full history of these OSes.
30 An incorrect guess by this blacklist can be overridden by setting
31 ac_cv_func_getgroups_works in config.site. AC_TYPE_GETGROUPS, for its
32 part, now does a series of regular old AC_COMPILE_IFELSE checks to
33 probe the prototype of getgroups, and considers that good enough.
35 While I was in there I noticed that AC_FUNC_GETGROUPS does not
36 AC_SUBST a documented output variable, and that the name of this
37 variable is misspelled in the manual.
39 * lib/autoconf/functions.m4 (AC_FUNC_GETGROUPS): Use AC_SEARCH_LIBS
40 to probe for getgroups. Use an AC_CANONICAL_HOST-based blacklist
41 for bug detection, not AC_RUN_IFELSE. AC_SUBST the GETGROUPS_LIB
43 * lib/autoconf/types.m4 (AC_TYPE_GETGROUPS): Check only the prototype
44 of getgroups, using AC_COMPILE_IFELSE; do not use either AC_RUN_IFELSE
46 * doc/autoconf.texi: Update to match. Correct misspelling of
48 * tests.local.at (_AT_CHECK_ENV): Allow GETGROUPS_LIB output variable.
50 Upstream-Status: Backport
51 Signed-off-by: Khem Raj <raj.khem@gmail.com>
54 doc/autoconf.texi | 25 ++++++----
55 lib/autoconf/functions.m4 | 61 ++++++++++++------------
56 lib/autoconf/types.m4 | 97 ++++++++++++++++++++++++---------------
58 5 files changed, 120 insertions(+), 76 deletions(-)
60 diff --git a/NEWS b/NEWS
61 index 53c57ff59..8e4ecc1bf 100644
64 @@ -38,6 +38,17 @@ GNU Autoconf NEWS - User visible changes.
65 This matters only for uses that, contrary to the documentation
66 and despite warnings, use m4_divert with numbered diversions.
68 +*** AC_FUNC_GETGROUPS and AC_TYPE_GETGROUPS no longer run test programs.
69 + These macros were testing for OS bugs that we believe are at least
70 + twenty years in the past. Most operating systems are now trusted to
71 + provide an accurate prototype for getgroups in unistd.h, and to
72 + implement it as specified in POSIX.
74 + AC_FUNC_GETGROUPS still includes a short blacklist of OSes with
75 + known, severe bugs in getgroups. It can be overridden using
76 + config.site. If you encounter a mistake in this blacklist
77 + please report it to bug-autoconf.
81 *** New macro AC_SYS_YEAR2038.
82 diff --git a/doc/autoconf.texi b/doc/autoconf.texi
83 index 037c8055f..5d5f613e6 100644
84 --- a/doc/autoconf.texi
85 +++ b/doc/autoconf.texi
86 @@ -5257,17 +5257,26 @@ and also contains workarounds for other portability problems of
87 @defmac AC_FUNC_GETGROUPS
88 @acindex{FUNC_GETGROUPS}
89 @cvindex HAVE_GETGROUPS
90 -@ovindex GETGROUPS_LIBS
91 +@ovindex GETGROUPS_LIB
93 @prindex @code{getgroups}
94 @caindex func_getgroups_works
95 -If the @code{getgroups} function is available and works,
96 -define @code{HAVE_GETGROUPS}. Set @code{GETGROUPS_LIBS} to any libraries
97 -needed to get that function. This macro runs @code{AC_TYPE_GETGROUPS}.
99 -This macro is obsolescent. New programs need not use this macro. But
100 -they may want to use the Gnulib module @code{getgroups}, which provides
101 -workarounds to other portability problems of this function.
102 +Perform all the checks performed by @code{AC_TYPE_GETGROUPS}
103 +(@pxref{AC_TYPE_GETGROUPS}).
104 +Then, if the @code{getgroups} function is available
105 +and known to work correctly, define @code{HAVE_GETGROUPS}.
106 +Set the output variable @code{GETGROUPS_LIB} to any libraries
107 +needed to get that function.
109 +This macro relies on a list of systems with known, serious bugs in
110 +@code{getgroups}. If this list mis-identifies your system's
111 +@code{getgroups} as buggy, or as not buggy, you can override it by
112 +setting the cache variable @code{ac_cv_func_getgroups_works} in a
113 +@file{config.site} file (@pxref{Site Defaults}). Please also report the
114 +error to @email{bug-autoconf@@gnu.org, the Autoconf Bugs mailing list}.
116 +The Gnulib module @code{getgroups} provides workarounds for additional,
117 +less severe portability problems with this function.
120 @anchor{AC_FUNC_GETLOADAVG}
121 diff --git a/lib/autoconf/functions.m4 b/lib/autoconf/functions.m4
122 index 655d6ba8f..74512e97d 100644
123 --- a/lib/autoconf/functions.m4
124 +++ b/lib/autoconf/functions.m4
125 @@ -698,47 +698,46 @@ AS_IF([test "$ac_cv_func_fseeko_ftello" = "need _LARGEFILE_SOURCE"],
126 # When cross-compiling, assume getgroups is broken.
127 AN_FUNCTION([getgroups], [AC_FUNC_GETGROUPS])
128 AC_DEFUN([AC_FUNC_GETGROUPS],
129 -[AC_REQUIRE([AC_TYPE_GETGROUPS])dnl
130 -AC_REQUIRE([AC_TYPE_SIZE_T])dnl
131 -AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles
132 -AC_CHECK_FUNC(getgroups)
133 +[AC_REQUIRE([AC_CANONICAL_HOST])dnl
134 +AC_REQUIRE([AC_TYPE_GETGROUPS])dnl
136 -# If we don't yet have getgroups, see if it's in -lbsd.
137 +# On older systems getgroups might be in -lbsd.
138 # This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1.
140 -if test $ac_cv_func_getgroups = no; then
141 - AC_CHECK_LIB(bsd, getgroups, [GETGROUPS_LIB=-lbsd])
144 -# Run the program to test the functionality of the system-supplied
145 -# getgroups function only if there is such a function.
148 +AC_SEARCH_LIBS([getgroups], [bsd],
149 + [test "$ac_res" = "none required" || GETGROUPS_LIB="$ac_res"
150 + ac_cv_func_getgroups=yes],
151 + [ac_cv_func_getgroups=no])
153 +AC_SUBST([GETGROUPS_LIB])
155 +# Known severe bugs in getgroups on particular systems.
156 +# - On Ultrix 4.3 and NextSTEP 3.2, getgroups (0, 0) is reported to
157 +# fail, rather than returning the number of supplementary groups as
158 +# it ought to. We do not know the exact range of releases affected
160 +# We currently reject all versions of the systems with known bugs, and
161 +# no other systems. Please send corrections to bug-autoconf@gnu.org.
162 if test $ac_cv_func_getgroups = yes; then
163 + # This AC_CACHE_CHECK exists so that one may override an incorrect
164 + # guess by setting ac_cv_func_getgroups_works in a config.site file.
165 AC_CACHE_CHECK([for working getgroups], ac_cv_func_getgroups_works,
166 - [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
167 - [[/* On Ultrix 4.3, getgroups (0, 0) always fails. */
168 - return getgroups (0, 0) == -1;]])],
169 - [ac_cv_func_getgroups_works=yes],
170 - [ac_cv_func_getgroups_works=no],
171 - [case "$host_os" in # ((
172 - # Guess yes on glibc systems.
173 - *-gnu*) ac_cv_func_getgroups_works="guessing yes" ;;
174 - # If we don't know, assume the worst.
175 - *) ac_cv_func_getgroups_works="guessing no" ;;
178 + [AS_CASE([$host_os],
179 + [ultrix* | nextstep*],
180 + [ac_cv_func_getgroups_works=no # getgroups(0,0) fails
182 + [ac_cv_func_getgroups_works=yes])])
184 ac_cv_func_getgroups_works=no
186 -case "$ac_cv_func_getgroups_works" in
188 - AC_DEFINE(HAVE_GETGROUPS, 1,
189 - [Define to 1 if your system has a working 'getgroups' function.])
193 +if test $ac_cv_func_getgroups_works = yes; then
194 + AC_DEFINE(HAVE_GETGROUPS, 1,
195 + [Define to 1 if your system has a working 'getgroups' function.])
197 ])# AC_FUNC_GETGROUPS
200 # _AC_LIBOBJ_GETLOADAVG
201 # ---------------------
202 # Set up the AC_LIBOBJ replacement of 'getloadavg'.
203 diff --git a/lib/autoconf/types.m4 b/lib/autoconf/types.m4
204 index ef2456135..af3872b2f 100644
205 --- a/lib/autoconf/types.m4
206 +++ b/lib/autoconf/types.m4
207 @@ -258,44 +258,69 @@ AN_IDENTIFIER([ptrdiff_t], [AC_CHECK_TYPES])
210 AC_DEFUN([AC_TYPE_GETGROUPS],
211 +dnl We now unconditionally assume that if <unistd.h> has a prototype for
212 +dnl getgroups, it is accurate; and that if <unistd.h> does _not_ declare
213 +dnl getgroups with a prototype, the second argument is an array of int.
214 +dnl (Older versions of Autoconf made these assumptions only when cross
215 +dnl compiling.) See AC_FUNC_GETGROUPS, over in functions.m4, for why
216 +dnl this uses AC_COMPILE_IFELSE rather than AC_LINK_IFELSE.
217 [AC_REQUIRE([AC_TYPE_UID_T])dnl
218 -AC_CACHE_CHECK(type of array argument to getgroups, ac_cv_type_getgroups,
219 -[AC_RUN_IFELSE([AC_LANG_SOURCE(
220 -[[/* Thanks to Mike Rendell for this test. */
221 -]AC_INCLUDES_DEFAULT[
224 -#define MAX(x, y) ((x) > (y) ? (x) : (y))
229 - gid_t gidset[NGID];
231 - union { gid_t gval; long int lval; } val;
234 - for (i = 0; i < NGID; i++)
235 - gidset[i] = val.gval;
236 - n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1,
238 - /* Exit non-zero if getgroups seems to require an array of ints. This
239 - happens when gid_t is short int but getgroups modifies an array
241 - return n > 0 && gidset[n] != val.gval;
243 - [ac_cv_type_getgroups=gid_t],
244 - [ac_cv_type_getgroups=int],
245 - [ac_cv_type_getgroups=cross])
246 -if test $ac_cv_type_getgroups = cross; then
247 - dnl When we can't run the test program (we are cross compiling), presume
248 - dnl that <unistd.h> has either an accurate prototype for getgroups or none.
249 - dnl Old systems without prototypes probably use int.
250 - AC_EGREP_HEADER([getgroups.*int.*gid_t], unistd.h,
251 - ac_cv_type_getgroups=gid_t, ac_cv_type_getgroups=int)
253 +AC_CACHE_CHECK([type of array argument to getgroups], ac_cv_type_getgroups,
254 +[# If AC_TYPE_UID_T says there isn't any gid_t typedef, then we can skip
256 +AS_IF([test $ac_cv_type_gid_t = no],
257 + [ac_cv_type_getgroups=int],
258 + [# Test programs below rely on strict type checking of extern declarations:
259 + # 'extern int getgroups(int, int *); extern int getgroups(int, pid_t *);'
260 + # is valid in C89 if and only if pid_t is a typedef for int. Unlike
261 + # anything involving either an assignment or a function call, compilers
262 + # tend to make this kind of type mismatch a hard error, not just an
263 + # "incompatible pointer types" warning.
264 + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
265 +[AC_INCLUDES_DEFAULT
266 +[extern int getgroups(int, gid_t *);]],
267 +[[return !(getgroups(0, 0) >= 0);]])],
268 + [ac_getgroups_gidarray=yes],
269 + [ac_getgroups_gidarray=no])
270 + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
271 +[AC_INCLUDES_DEFAULT
272 +[extern int getgroups(int, int *);]],
273 +[[return !(getgroups(0, 0) >= 0);]])],
274 + [ac_getgroups_intarray=yes],
275 + [ac_getgroups_intarray=no])
277 + AS_CASE([int:$ac_getgroups_intarray,gid:$ac_getgroups_gidarray],
278 + [int:yes,gid:no], [ac_cv_type_getgroups=int],
279 + [int:no,gid:yes], [ac_cv_type_getgroups=gid_t],
280 + [int:yes,gid:yes], [
281 + # Both programs compiled - this means *either* that getgroups
282 + # was declared with no prototype, in which case we should use int,
283 + # or that it was declared prototyped but gid_t is a typedef for int,
284 + # in which case we should use gid_t. Distinguish the two cases
285 + # by testing if the compiler catches a blatantly incorrect function
286 + # signature for getgroups.
287 + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
288 +[AC_INCLUDES_DEFAULT
289 +[extern int getgroups(int, float);]],
290 +[[return !(getgroups(0, 0) >= 0);]])], [
291 + # Compiler did not catch incorrect argument list;
292 + # getgroups is unprototyped.
293 + ac_cv_type_getgroups=int
295 + # Compiler caught incorrect argument list;
296 + # gid_t is a typedef for int.
297 + ac_cv_type_getgroups=gid_t
300 + # Both programs failed to compile - this probably means getgroups
301 + # wasn't declared at all. Use 'int', as this is probably a very
302 + # old system where the type _would have been_ int.
303 + ac_cv_type_getgroups=int
306 +])dnl AC_CACHE_CHECK
307 AC_DEFINE_UNQUOTED(GETGROUPS_T, $ac_cv_type_getgroups,
308 - [Define to the type of elements in the array set by
309 + [Define to the type of elements in the array argument to
310 'getgroups'. Usually this is either 'int' or 'gid_t'.])
311 ])# AC_TYPE_GETGROUPS
313 diff --git a/tests/local.at b/tests/local.at
314 index 64a9fb264..db49f84a9 100644
317 @@ -401,7 +401,7 @@ if test -f state-env.before && test -f state-env.after; then
318 [interpval|PATH_SEPARATOR],
319 [GFC|F77_DUMMY_MAIN|f77_(case|underscore)],
320 [FC(_DUMMY_MAIN|FLAGS|LIBS|FLAGS_[fF]|_MODEXT|_MODINC|_MODOUT|_DEFINE)?],
321 - [ALLOCA|GETLOADAVG_LIBS|KMEM_GROUP|NEED_SETGID|POW_LIB],
322 + [ALLOCA|GETGROUPS_LIB|GETLOADAVG_LIBS|KMEM_GROUP|NEED_SETGID|POW_LIB],
323 [AWK|LEX|LEXLIB|LEX_OUTPUT_ROOT|LN_S|M4|MKDIR_P|AR|RANLIB|SET_MAKE|YACC],