Add initgroups support.
authordrepper <drepper>
Fri, 9 Jul 1999 09:58:10 +0000 (09:58 +0000)
committerdrepper <drepper>
Fri, 9 Jul 1999 09:58:10 +0000 (09:58 +0000)
hesiod/nss_hesiod/hesiod-grp.c

index e08b9dc..c0b56ac 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
 
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <bits/libc-lock.h>
+#include <ctype.h>
 #include <errno.h>
-#include <hesiod.h>
-#include <nss.h>
 #include <grp.h>
+#include <hesiod.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <nss.h>
+#include <bits/libc-lock.h>
 
 /* Get the declaration of the parser function.  */
 #define ENTNAME grent
@@ -150,3 +151,111 @@ _nss_hesiod_getgrgid_r (gid_t gid, struct group *grp,
 
   return status;
 }
+
+static int
+internal_gid_in_list (const gid_t *list, const gid_t g, long int len)
+{
+  while (len > 0)
+    {
+      if (*list == g)
+       return 1;
+      --len;
+      ++list;
+    }
+  return 0;
+}
+
+static enum nss_status
+internal_gid_from_group (void *context, const char *groupname, gid_t *group)
+{
+  char **grp_res;
+  enum nss_status status = NSS_STATUS_NOTFOUND;
+
+  grp_res = hesiod_resolve (context, groupname, "group");
+  if (grp_res != NULL && *grp_res != NULL)
+    {
+      char *p = *grp_res;
+
+      while (*p != '\0' && *p != ':')
+       ++p;
+      while (*p != '\0' && *p == ':')
+       ++p;
+      while (*p != '\0' && *p != ':')
+       ++p;
+      while (*p != '\0' && *p == ':')
+       ++p;
+      if (*p == ':')
+       {
+         char *endp;
+         char *q = ++p;
+
+         q = p;
+         while (*q != '\0' && *q != ':')
+           ++q;
+
+         *group = strtol (p, &endp, 10);
+         if (endp == q && endp != p)
+           status = NSS_STATUS_SUCCESS;
+        }
+      hesiod_free_list (context, grp_res);
+    }
+  return status;
+}
+
+enum nss_status
+_nss_hesiod_initgroups (const char *user, gid_t group, long int *start,
+                        long int *size, gid_t *groups, long int limit,
+                        int *errnop)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+  char **list = NULL;
+  char *p;
+  void *context;
+
+  if (hesiod_init (&context) == -1)
+    return NSS_STATUS_UNAVAIL;
+
+  list = hesiod_resolve (context, user, "grplist");
+
+  if (list == NULL)
+    {
+      hesiod_end(context);
+      return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
+    }
+
+  if (!internal_gid_in_list (groups, group, *start) && *start < limit)
+    groups[(*start)++] = group;
+
+  p = *list;
+  while (*p != '\0' && *start < limit)
+    {
+      char *endp;
+      char *q;
+
+      status = NSS_STATUS_NOTFOUND;
+
+      q = p;
+      while (*q != '\0' && *q != ':')
+       ++q;
+
+      if (*q != '\0')
+       *q++ = '\0';
+
+      group = strtol (p, &endp, 10);
+      if (*endp == '\0' && endp != p)
+       status = NSS_STATUS_SUCCESS;
+      else
+       status = internal_gid_from_group (context, p, &group);
+
+      if (status == NSS_STATUS_SUCCESS
+         && !internal_gid_in_list (groups, group, *start))
+       groups[(*start)++] = group;
+
+      p = q;
+    }
+
+  hesiod_free_list (context, list);
+  hesiod_end(context);
+
+  return NSS_STATUS_SUCCESS;
+}