Thu Jan 18 00:32:43 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
[kopensolaris-gnu/glibc.git] / grp / grpread.c
index fe3ad00..1fed32f 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1995 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
@@ -22,6 +22,7 @@ Cambridge, MA 02139, USA.  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
 #include <grp.h>
 
 /* This is the function that all the others are based on.
@@ -30,10 +31,8 @@ Cambridge, MA 02139, USA.  */
 /* Structure containing info kept by each __grpread caller.  */
 typedef struct
   {
-#define        NAME_SIZE       9
-#define        PASSWD_SIZE     21
-#define        MEMLIST_SIZE    1001
-    char name[NAME_SIZE], passwd[PASSWD_SIZE], memlist[MEMLIST_SIZE];
+    char *buf;
+    size_t buflen;
     size_t max_members;
     char **members;
     struct group g;
@@ -44,15 +43,18 @@ typedef struct
 PTR
 DEFUN_VOID(__grpalloc)
 {
-  grpread_info *info = (PTR) malloc(sizeof(grpread_info));
+  grpread_info *info = (PTR) malloc (sizeof(grpread_info));
   if (info == NULL)
     return NULL;
 
+  info->buf = NULL;
+  info->buflen = 0;
+
   info->max_members = 5;
-  info->members = (char **) malloc(5 * sizeof(char *));
+  info->members = (char **) malloc (5 * sizeof(char *));
   if (info->members == NULL)
     {
-      free((PTR) info);
+      free ((PTR) info);
       return NULL;
     }
 
@@ -64,8 +66,8 @@ struct group *
 DEFUN(__grpread, (stream, g), FILE *stream AND PTR CONST g)
 {
   register grpread_info *CONST info = (grpread_info *) g;
+  char *start, *end;
   register size_t i;
-  register char *s;
 
   /* Idiocy checks.  */
   if (stream == NULL)
@@ -74,30 +76,91 @@ DEFUN(__grpread, (stream, g), FILE *stream AND PTR CONST g)
       return NULL;
     }
 
-  if (fscanf(stream, "%8[^:]:%20[^:]:%hd:%1000[^\n]\n",
-            info->name, info->passwd, &info->g.gr_gid, info->memlist) != 4)
+  do
+    if (__getline (&info->buf, &info->buflen, stream) == -1)
+      return NULL;
+  while (info->buf[0] == '#');
+
+  start = info->buf;
+  end = strchr (start, ':');
+  if (end == NULL)
+    return NULL;
+  *end = '\0';
+  info->g.gr_name = start;
+
+  start = end + 1;
+  end = strchr (start, ':');
+  if (end == NULL)
+    return NULL;
+  *end = '\0';
+  info->g.gr_passwd = start;
+
+  info->g.gr_gid = (gid_t) strtol (end + 1, &end, 10);
+  if (*end != ':')
     return NULL;
 
-  /* Turn the comma-separated list into an array.  */
   i = 0;
-  for (s = strtok(info->memlist, ","); s != NULL;
-       s = strtok((char *) NULL, ","))
+  do
     {
+      start = end + 1;
+      end = strchr (start, ',');
+      if (end == NULL)
+       {
+         end = strchr (start, '\n');
+         if (end == start)
+           break;
+         if (end == NULL)
+           return NULL;
+         *end = '\0';
+         end = NULL;
+       }
+      else
+       *end = '\0';
+
       if (i == info->max_members - 2)
        {
          info->max_members += 5;
          info->members = (char **)
-           realloc((PTR) info->members, info->max_members * sizeof(char *));
+           realloc ((PTR) info->members, info->max_members * sizeof (char *));
          if (info->members == NULL)
            return NULL;
        }
 
-      info->members[i++] = s;
-    }
+      info->members[i++] = start;
+    } while (end != NULL);
   info->members[i] = NULL;
-
-  info->g.gr_name = info->name;
-  info->g.gr_passwd = info->passwd;
   info->g.gr_mem = info->members;
+
   return &info->g;
 }
+
+
+struct group *
+__grpscan (void **info, int (*selector) (struct group *))
+{
+  FILE *stream;
+  struct group *p;
+
+  if (*info == NULL)
+    {
+      *info = __grpalloc ();
+      if (info == NULL)
+       return NULL;
+    }
+
+  stream = __grpopen ();
+  if (stream == NULL)
+    return NULL;
+
+  p = NULL;
+  while (! feof (stream))
+    {
+      p = __grpread (stream, *info);
+      if (p && (*selector) (p))
+       break;
+      p = NULL;
+    }
+
+  (void) fclose (stream);
+  return p;
+}