about summary refs log tree commit diff
path: root/grp/initgroups.c
diff options
context:
space:
mode:
Diffstat (limited to 'grp/initgroups.c')
-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 ();