about summary refs log tree commit diff
path: root/hesiod/nss_hesiod/hesiod-grp.c
diff options
context:
space:
mode:
Diffstat (limited to 'hesiod/nss_hesiod/hesiod-grp.c')
-rw-r--r--hesiod/nss_hesiod/hesiod-grp.c117
1 files changed, 113 insertions, 4 deletions
diff --git a/hesiod/nss_hesiod/hesiod-grp.c b/hesiod/nss_hesiod/hesiod-grp.c
index e08b9dca8c..c0b56ac214 100644
--- a/hesiod/nss_hesiod/hesiod-grp.c
+++ b/hesiod/nss_hesiod/hesiod-grp.c
@@ -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.
 
@@ -17,14 +17,15 @@
    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;
+}