summaryrefslogtreecommitdiff
path: root/hesiod
diff options
context:
space:
mode:
Diffstat (limited to 'hesiod')
-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;
+}