diff -ruN a/lib/getugroups.c b/lib/getugroups.c --- a/lib/getugroups.c 2024-04-10 20:11:58.434321202 +0900 +++ b/lib/getugroups.c 2024-04-10 20:15:11.853008324 +0900 @@ -19,6 +19,9 @@ #include +/* We do not need this code if getgrouplist(3) is available. */ +#ifndef HAVE_GETGROUPLIST + #include "getugroups.h" #include @@ -131,3 +134,4 @@ } #endif /* HAVE_GRP_H */ +#endif /* have getgrouplist */ diff -ruN a/lib/mgetgroups.c b/lib/mgetgroups.c --- a/lib/mgetgroups.c 2024-04-10 20:11:58.438321382 +0900 +++ b/lib/mgetgroups.c 2024-04-10 20:15:11.854008369 +0900 @@ -120,9 +120,17 @@ /* else no username, so fall through and use getgroups. */ #endif - max_n_groups = (username - ? getugroups (0, NULL, username, gid) - : getgroups (0, NULL)); + if (!username) + max_n_groups = getgroups(0, NULL); + else + { +#ifdef HAVE_GETGROUPLIST + max_n_groups = 0; + getgrouplist (username, gid, NULL, &max_n_groups); +#else + max_n_groups = getugroups (0, NULL, username, gid); +#endif + } /* If we failed to count groups because there is no supplemental group support, then return an array containing just GID. @@ -144,10 +152,25 @@ if (g == NULL) return -1; - ng = (username - ? getugroups (max_n_groups, g, username, gid) - : getgroups (max_n_groups - (gid != (gid_t) -1), - g + (gid != (gid_t) -1))); + if (!username) + ng = getgroups (max_n_groups - (gid != (gid_t)-1), g + (gid != (gid_t)-1)); + else + { +#ifdef HAVE_GETGROUPLIST + int e; + ng = max_n_groups; + while ((e = getgrouplist (username, gid, g, &ng)) == -1 + && ng > max_n_groups) + { + max_n_groups = ng; + g = xrealloc (g, max_n_groups * sizeof (GETGROUPS_T)); + } + if (e == -1) + ng = -1; +#else + ng = getugroups (max_n_groups, g, username, gid); +#endif + } if (ng < 0) { diff -ruN a/m4/jm-macros.m4 b/m4/jm-macros.m4 --- a/m4/jm-macros.m4 2024-01-01 22:27:23.000000000 +0900 +++ b/m4/jm-macros.m4 2024-04-10 20:16:13.349770362 +0900 @@ -67,6 +67,7 @@ fallocate fchown fchmod + getgrouplist setgroups sethostname siginterrupt