diff options
Diffstat (limited to 'nis/nss_nis/nis-initgroups.c')
-rw-r--r-- | nis/nss_nis/nis-initgroups.c | 121 |
1 files changed, 66 insertions, 55 deletions
diff --git a/nis/nss_nis/nis-initgroups.c b/nis/nss_nis/nis-initgroups.c index a5a3ba6144..33a9662b4c 100644 --- a/nis/nss_nis/nis-initgroups.c +++ b/nis/nss_nis/nis-initgroups.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1998-2000,2002,2003,2004,2006 Free Software Foundation, Inc. +/* Copyright (C) 1998-2000, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. @@ -30,7 +30,6 @@ #include <sys/param.h> #include "nss-nis.h" -#include <libnsl.h> /* Get the declaration of the parser function. */ #define ENTNAME grent @@ -38,6 +37,47 @@ #define EXTERN_PARSER #include <nss/nss_files/files-parse.c> +struct response_t +{ + struct response_t *next; + char val[0]; +}; + +struct intern_t +{ + struct response_t *start; + struct response_t *next; +}; +typedef struct intern_t intern_t; + +static int +saveit (int instatus, char *inkey, int inkeylen, char *inval, + int invallen, char *indata) +{ + intern_t *intern = (intern_t *) indata; + + if (instatus != YP_TRUE) + return 1; + + if (inkey && inkeylen > 0 && inval && invallen > 0) + { + struct response_t *newp = malloc (sizeof (struct response_t) + + invallen + 1); + if (newp == NULL) + return 1; /* We have no error code for out of memory */ + + if (intern->start == NULL) + intern->start = newp; + else + intern->next->next = newp; + intern->next = newp; + + newp->next = NULL; + *((char *) mempcpy (newp->val, inval, invallen)) = '\0'; + } + + return 0; +} static enum nss_status internal_setgrent (char *domainname, intern_t *intern) @@ -45,72 +85,41 @@ internal_setgrent (char *domainname, intern_t *intern) struct ypall_callback ypcb; enum nss_status status; - ypcb.foreach = _nis_saveit; + intern->start = NULL; + + ypcb.foreach = saveit; ypcb.data = (char *) intern; status = yperr2nss (yp_all (domainname, "group.byname", &ypcb)); - - /* Mark the last buffer as full. */ - if (intern->next != NULL) - intern->next->size = intern->offset; - intern->next = intern->start; - intern->offset = 0; return status; } - static enum nss_status internal_getgrent_r (struct group *grp, char *buffer, size_t buflen, int *errnop, intern_t *intern) { + struct parser_data *data = (void *) buffer; + int parse_res; + char *p; + if (intern->start == NULL) return NSS_STATUS_NOTFOUND; /* Get the next entry until we found a correct one. */ - int parse_res; do { - struct response_t *bucket = intern->next; - - if (__builtin_expect (intern->offset >= bucket->size, 0)) - { - if (bucket->next == NULL) - return NSS_STATUS_NOTFOUND; - - /* We look at all the content in the current bucket. Go on - to the next. */ - bucket = intern->next = bucket->next; - intern->offset = 0; - } - - char *p; - for (p = &bucket->mem[intern->offset]; isspace (*p); ++p) - ++intern->offset; + if (intern->next == NULL) + return NSS_STATUS_NOTFOUND; - size_t len = strlen (p) + 1; - if (__builtin_expect (len > buflen, 0)) - { - *errnop = ERANGE; - return NSS_STATUS_TRYAGAIN; - } + p = strncpy (buffer, intern->next->val, buflen); + while (isspace (*p)) + ++p; - /* We unfortunately have to copy the data in the user-provided - buffer because that buffer might be around for a very long - time and the servent structure must remain valid. If we would - rely on the BUCKET memory the next 'setservent' or 'endservent' - call would destroy it. - - The important thing is that it is a single NUL-terminated - string. This is what the parsing routine expects. */ - p = memcpy (buffer, &bucket->mem[intern->offset], len); - - parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen, - errnop); - if (__builtin_expect (parse_res == -1, 0)) + parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop); + if (parse_res == -1) return NSS_STATUS_TRYAGAIN; - - intern->offset += len; + intern->next = intern->next->next; } while (!parse_res); @@ -157,12 +166,13 @@ initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size, ssize_t keylen = snprintf (key, sizeof (key), "unix.%lu@%s", (unsigned long int) uid, domainname); + enum nss_status retval; char *result; int reslen; - int yperr = yp_match (domainname, "netid.byname", key, keylen, &result, - &reslen); - if (__builtin_expect (yperr != YPERR_SUCCESS, 0)) - return yperr2nss (yperr); + retval = yperr2nss (yp_match (domainname, "netid.byname", key, keylen, + &result, &reslen)); + if (retval != NSS_STATUS_SUCCESS) + return retval; /* Parse the result: following the colon is a comma separated list of group IDs. */ @@ -197,6 +207,7 @@ initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size, if (*start == *size) { /* Need a bigger buffer. */ + gid_t *newgroups; long int newsize; if (limit > 0 && *size == limit) @@ -208,7 +219,7 @@ initgroups_netid (uid_t uid, gid_t group, long int *start, long int *size, else newsize = MIN (limit, 2 * *size); - gid_t *newgroups = realloc (groups, newsize * sizeof (*groups)); + newgroups = realloc (groups, newsize * sizeof (*groups)); if (newgroups == NULL) goto errout; *groupsp = groups = newgroups; @@ -236,7 +247,7 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start, return NSS_STATUS_UNAVAIL; /* Check whether we are supposed to use the netid.byname map. */ - if (_nsl_default_nss () & NSS_FLAG_NETID_AUTHORITATIVE) + if (_nis_default_nss () & NSS_FLAG_NETID_AUTHORITATIVE) { /* We need the user ID. */ uid_t uid; @@ -251,7 +262,7 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start, size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); char *tmpbuf; enum nss_status status; - intern_t intern = { NULL, NULL, 0 }; + intern_t intern = { NULL, NULL }; gid_t *groups = *groupsp; status = internal_setgrent (domainname, &intern); |