aboutsummaryrefslogtreecommitdiff
path: root/grp
diff options
context:
space:
mode:
Diffstat (limited to 'grp')
-rw-r--r--grp/initgroups.c76
1 files changed, 45 insertions, 31 deletions
diff --git a/grp/initgroups.c b/grp/initgroups.c
index a659f0d3ae..2ca90ab18d 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 ();