Increase buffer if it is too small.
authordrepper <drepper>
Wed, 3 Dec 1997 22:53:16 +0000 (22:53 +0000)
committerdrepper <drepper>
Wed, 3 Dec 1997 22:53:16 +0000 (22:53 +0000)
grp/initgroups.c

index a659f0d..2ca90ab 100644 (file)
@@ -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
    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 ();