diff options
Diffstat (limited to 'grp/initgroups.c')
-rw-r--r-- | grp/initgroups.c | 76 |
1 files changed, 45 insertions, 31 deletions
diff --git a/grp/initgroups.c b/grp/initgroups.c index a659f0d..2ca90ab 100644 --- a/grp/initgroups.c +++ b/grp/initgroups.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1989, 1991, 1993, 1996 Free Software Foundation, Inc. +/* Copyright (C) 1989, 1991, 1993, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,10 +17,11 @@ Boston, MA 02111-1307, USA. */ #include <alloca.h> -#include <unistd.h> -#include <string.h> +#include <errno.h> #include <grp.h> #include <limits.h> +#include <string.h> +#include <unistd.h> #include <sys/types.h> @@ -32,7 +33,7 @@ initgroups (user, group) const char *user; gid_t group; { -#if defined (NGROUPS_MAX) && NGROUPS_MAX == 0 +#if defined NGROUPS_MAX && NGROUPS_MAX == 0 /* No extra groups allowed. */ return 0; @@ -42,9 +43,10 @@ initgroups (user, group) struct group grpbuf, *g; size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *tmpbuf; - register size_t n; + size_t n; size_t ngroups; gid_t *groups; + int status; #ifdef NGROUPS_MAX # define limit NGROUPS_MAX @@ -67,32 +69,44 @@ initgroups (user, group) n = 0; groups[n++] = group; - while (__getgrent_r (&grpbuf, tmpbuf, buflen, &g) >= 0) - if (g->gr_gid != group) - { - register char **m; - - for (m = g->gr_mem; *m != NULL; ++m) - if (strcmp (*m, user) == 0) - { - /* Matches user. Insert this group. */ - if (n == ngroups && limit <= 0) - { - /* Need a bigger buffer. */ - groups = memcpy (__alloca (ngroups * 2 * sizeof *groups), - groups, ngroups * sizeof *groups); - ngroups *= 2; - } - - groups[n++] = g->gr_gid; - - if (n == limit) - /* Can't take any more groups; stop searching. */ - goto done; - - break; - } - } + do + { + while ((status = __getgrent_r (&grpbuf, tmpbuf, buflen, &g)) != 0 + && errno == ERANGE) + { + buflen *= 2; + tmpbuf = __alloca (buflen); + } + + if (status == 0 && g->gr_gid != group) + { + char **m; + + for (m = g->gr_mem; *m != NULL; ++m) + if (strcmp (*m, user) == 0) + { + /* Matches user. Insert this group. */ + if (n == ngroups && limit <= 0) + { + /* Need a bigger buffer. */ + gid_t *newgrp; + newgrp = __alloca (ngroups * 2 * sizeof *groups); + groups = memcpy (newgrp, groups, ngroups * sizeof *groups); + ngroups *= 2; + } + + groups[n++] = g->gr_gid; + + if (n == limit) + /* Can't take any more groups; stop searching. */ + goto done; + + break; + } + } + } + while (status == 0); + done: endgrent (); |