diff options
Diffstat (limited to 'hesiod')
-rw-r--r-- | hesiod/nss_hesiod/hesiod-grp.c | 117 |
1 files changed, 113 insertions, 4 deletions
diff --git a/hesiod/nss_hesiod/hesiod-grp.c b/hesiod/nss_hesiod/hesiod-grp.c index e08b9dc..c0b56ac 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; +} |