/*
*
* cache.c
*
* NIS map cache maintance code
*
* Author: Landon Fuller <landonblue@circus-foundation.org>
*
* Copyright (c) 2000-2001 InfoSpace, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by InfoSpace, Inc.
* and its contributors.
* 4. Neither the name of InfoSpace, Inc nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "../../../autoconf.h"
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#else
#include <string.h>
#endif
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <lber.h>
#include <ldap.h>
#include "yp.h"
#include "ldap.h"
#include "cache.h"
extern struct ldaprefs ldaprefs;
static char *user_attributes [] = {
"uid",
"userpassword",
"uidnumber",
"gidnumber",
"gecos",
"homedirectory",
"loginshell",
NULL
};
static char *group_attributes [] = {
"cn",
"userpassword",
"gidnumber",
"memberuid",
NULL
};
static char *nis_attributes [] = {
"cn",
"nismapentry",
"nismapname",
NULL
};
static char *fix_password(char **values)
{
char **valptr;
char *pwd = NULL;
char *buffer;
for (valptr = values; *valptr != NULL; valptr++)
{
if(!strncasecmp(*valptr, CRYPT, CRYPT_SIZE))
{
pwd = *valptr;
break;
}
}
if (pwd == NULL)
{
pwd = "x";
} else {
pwd += CRYPT_SIZE;
}
buffer = safe_strdup(pwd);
return(buffer);
}
static void fill_pwinfo(struct pwinfo *pwinfo)
{
pwinfo->uid = NULL;
pwinfo->userpassword = NULL;
pwinfo->uidnumber = NULL;
pwinfo->gidnumber = NULL;
pwinfo->gecos = NULL;
pwinfo->homedirectory = NULL;
pwinfo->loginshell = NULL;
pwinfo->size = 0;
}
static void fill_gwinfo(struct gwinfo *gwinfo)
{
gwinfo->cn = NULL;
gwinfo->userpassword = NULL;
gwinfo->gidnumber = NULL;
gwinfo->memberuid = NULL;
gwinfo->size = 0;
}
static void fill_nisinfo(struct nisinfo *nisinfo)
{
nisinfo->cn = NULL;
nisinfo->nismapentry = NULL;
nisinfo->nismapname = NULL;
}
static int check_pwinfo(struct pwinfo *pwinfo)
{
if (!pwinfo->uid)
{
return (YP_YPERR);
}
if (!pwinfo->userpassword)
{
return (YP_YPERR);
}
if (!pwinfo->uidnumber)
{
return (YP_YPERR);
}
if (!pwinfo->gidnumber)
{
return (YP_YPERR);
}
if (!pwinfo->gecos)
{
pwinfo->gecos = safe_strdup("");
}
if (!pwinfo->homedirectory)
{
return (YP_YPERR);
}
if (!pwinfo->loginshell)
{
return (YP_YPERR);
}
return (YP_TRUE);
}
static int check_gwinfo(struct gwinfo *gwinfo)
{
if (!gwinfo->cn)
{
return (YP_YPERR);
}
if (!gwinfo->userpassword)
{
return (YP_YPERR);
}
if (!gwinfo->gidnumber)
{
return (YP_YPERR);
}
if (!gwinfo->memberuid)
{
gwinfo->memberuid = safe_strdup("");
}
return (YP_TRUE);
}
static int check_nisinfo(struct nisinfo *nisinfo)
{
if (!nisinfo->cn)
{
return (YP_YPERR);
}
if (!nisinfo->nismapentry)
{
return (YP_YPERR);
}
if (!nisinfo->nismapname)
{
return (YP_YPERR);
}
return (YP_TRUE);
}
static void clean_pwinfo(struct pwinfo *pwinfo)
{
if(pwinfo->uid)
free(pwinfo->uid);
if(pwinfo->userpassword)
free(pwinfo->userpassword);
if(pwinfo->uidnumber)
free(pwinfo->uidnumber);
if(pwinfo->gidnumber)
free(pwinfo->gidnumber);
if(pwinfo->gecos)
free(pwinfo->gecos);
if(pwinfo->homedirectory)
free(pwinfo->homedirectory);
if(pwinfo->loginshell)
free(pwinfo->loginshell);
free(pwinfo);
}
static void clean_gwinfo(struct gwinfo *gwinfo)
{
if (gwinfo->cn)
free(gwinfo->cn);
if (gwinfo->userpassword)
free(gwinfo->userpassword);
if (gwinfo->gidnumber)
free(gwinfo->gidnumber);
if (gwinfo->memberuid)
free(gwinfo->memberuid);
free(gwinfo);
}
static void clean_nisinfo(struct nisinfo *nisinfo)
{
if(nisinfo->cn)
free(nisinfo->cn);
if(nisinfo->nismapentry)
free(nisinfo->nismapentry);
if(nisinfo->nismapname)
free(nisinfo->nismapname);
free(nisinfo);
}
int assemble_passwd(valdat *val, LDAPMessage *user, struct pwinfo *pwinfo)
{
ypstat rval;
char *attr;
BerElement *ber = NULL;
rval = YP_YPERR;
fill_pwinfo(pwinfo);
for (attr = ldap_first_attribute (ldaprefs.ldap, user, &ber); attr; attr = ldap_next_attribute (ldaprefs.ldap, user, ber))
{
char **values;
values = ldap_get_values (ldaprefs.ldap, user, attr);
if (values)
{
if(!strcasecmp(attr, "uid"))
{
pwinfo->uid = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "userpassword"))
{
pwinfo->userpassword = safe_strdup("*");
pwinfo->size += strlen("*");
} else
if(!strcasecmp(attr, "uidnumber"))
{
pwinfo->uidnumber = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "gidnumber"))
{
pwinfo->gidnumber = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "gecos"))
{
pwinfo->gecos = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "homedirectory"))
{
pwinfo->homedirectory = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "loginshell"))
{
pwinfo->loginshell = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
}
ldap_value_free(values);
}
}
if (check_pwinfo(pwinfo) == YP_TRUE)
{
val->valdat_len = pwinfo->size + PWLINE_SIZE;
val->valdat_val = safe_malloc(val->valdat_len + 1);
sprintf(val->valdat_val, PWLINE, pwinfo->uid, pwinfo->userpassword, pwinfo->uidnumber, pwinfo->gidnumber, pwinfo->gecos, pwinfo->homedirectory, pwinfo->loginshell);
rval = YP_TRUE;
} else {
rval = YP_NOKEY;
}
return (rval);
}
int assemble_master_passwd(valdat *val, LDAPMessage *user, struct pwinfo *pwinfo)
{
ypstat rval;
char *attr;
BerElement *ber = NULL;
rval = YP_YPERR;
fill_pwinfo(pwinfo);
for (attr = ldap_first_attribute (ldaprefs.ldap, user, &ber); attr; attr = ldap_next_attribute (ldaprefs.ldap, user, ber))
{
char **values;
values = ldap_get_values (ldaprefs.ldap, user, attr);
if (values)
{
if(!strcasecmp(attr, "uid"))
{
pwinfo->uid = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "userpassword"))
{
pwinfo->userpassword = fix_password(values);
pwinfo->size += strlen(pwinfo->userpassword);
} else
if(!strcasecmp(attr, "uidnumber"))
{
pwinfo->uidnumber = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "gidnumber"))
{
pwinfo->gidnumber = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "gecos"))
{
pwinfo->gecos = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "homedirectory"))
{
pwinfo->homedirectory = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "loginshell"))
{
pwinfo->loginshell = safe_strdup(values[0]);
pwinfo->size += strlen(values[0]);
}
ldap_value_free(values);
}
}
if (check_pwinfo(pwinfo) == YP_TRUE)
{
val->valdat_len = pwinfo->size + MPWLINE_SIZE;
val->valdat_val = safe_malloc(val->valdat_len + 1);
sprintf(val->valdat_val, MPWLINE, pwinfo->uid, pwinfo->userpassword, pwinfo->uidnumber, pwinfo->gidnumber, pwinfo->gecos, pwinfo->homedirectory, pwinfo->loginshell);
rval = YP_TRUE;
} else {
rval = YP_NOKEY;
}
return (rval);
}
int assemble_group(valdat *val, LDAPMessage *group, struct gwinfo *gwinfo)
{
ypstat rval;
char *attr;
BerElement *ber = NULL;
rval = YP_YPERR;
fill_gwinfo(gwinfo);
for (attr = ldap_first_attribute (ldaprefs.ldap, group, &ber); attr; attr = ldap_next_attribute (ldaprefs.ldap, group, ber))
{
char **values;
values = ldap_get_values (ldaprefs.ldap, group, attr);
if (values)
{
if(!strcasecmp(attr, "cn"))
{
gwinfo->cn = safe_strdup(values[0]);
gwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "userpassword"))
{
gwinfo->userpassword = fix_password(values);
gwinfo->size += strlen(gwinfo->userpassword);
} else
if(!strcasecmp(attr, "gidnumber"))
{
gwinfo->gidnumber = safe_strdup(values[0]);
gwinfo->size += strlen(values[0]);
} else
if(!strcasecmp(attr, "memberUid"))
{
gwinfo->memberuid = safe_strdup(values[0]);
gwinfo->size += strlen(values[0]);
}
ldap_value_free(values);
}
}
if (check_gwinfo(gwinfo) == YP_TRUE)
{
val->valdat_len = gwinfo->size + GWLINE_SIZE;
val->valdat_val = safe_malloc(val->valdat_len + 1);
sprintf(val->valdat_val, GWLINE, gwinfo->cn, gwinfo->userpassword, gwinfo->gidnumber, gwinfo->memberuid);
rval = YP_TRUE;
} else {
rval = YP_NOKEY;
}
return (rval);
}
int assemble_nis(valdat *val, LDAPMessage *record, struct nisinfo *nisinfo)
{
ypstat rval;
char *attr;
BerElement *ber = NULL;
rval = YP_YPERR;
fill_nisinfo(nisinfo);
for (attr = ldap_first_attribute (ldaprefs.ldap, record, &ber); attr; attr = ldap_next_attribute (ldaprefs.ldap, record, ber))
{
char **values;
values = ldap_get_values (ldaprefs.ldap, record, attr);
if (values)
{
if(!strcasecmp(attr, "cn"))
{
nisinfo->cn = safe_strdup(values[0]);
} else
if(!strcasecmp(attr, "nismapentry"))
{
nisinfo->nismapentry = safe_strdup(values[0]);
} else
if(!strcasecmp(attr, "nismapname"))
{
nisinfo->nismapname = safe_strdup(values[0]);
}
ldap_value_free(values);
}
}
if (check_nisinfo(nisinfo) == YP_TRUE)
{
val->valdat_len = strlen(nisinfo->nismapentry);
val->valdat_val = safe_strdup(nisinfo->nismapentry);
rval = YP_TRUE;
} else {
rval = YP_NOKEY;
}
return (rval);
}
ypstat check_unique(struct mapcache *mapcache, char *key)
{
struct mapentry *mapentry_current;
ypstat rval;
rval = YP_YPERR;
if(mapcache != NULL)
{
mapentry_current = mapcache->mapentry;
for(mapentry_current = mapcache->mapentry; mapentry_current; mapentry_current = mapentry_current->next)
{
if (!strcmp(mapentry_current->key, key))
{
return (YP_TRUE);
}
}
rval = YP_NOKEY;
}
return (rval);
}
struct mapcache *create_cache (ypmaplist *maps)
{
LDAPMessage *ldapreturn, *record;
struct ypmaplist *maplist_current;
struct mapentry *mapentry_current;
struct mapcache *mapcache_current, *mapcache_head;
struct pwinfo *pwinfo;
struct gwinfo *gwinfo;
struct nisinfo *nisinfo;
char *base, *filter;
valdat *val;
int rval;
mapcache_current = mapcache_head = ldapreturn = record = NULL;
val = safe_malloc(sizeof(valdat));
for(maplist_current = maps; maplist_current; maplist_current = maplist_current->next)
{
mapcache_current = safe_malloc(sizeof(struct mapcache));
mapcache_current->map = (mapname *) safe_strdup(maplist_current->map);
mapcache_current->mapentry = NULL;
mapcache_current->sem = safe_malloc(sizeof(sem_t));
sem_init(mapcache_current->sem, 0, 1);
printf("Building cache for: %s\n", maplist_current->map);
if (!strcmp((char *) mapcache_current->map, "passwd.byname"))
{
/* XXX Add preferences for filter and basedn */
base = safe_malloc(strlen(ldaprefs.basedn) + strlen("ou=People,") + 1);
sprintf(base, "%s%s", "ou=People,", ldaprefs.basedn);
filter = safe_strdup("(objectClass=posixAccount)");
if(ldap_search_s(ldaprefs.ldap,
base,
LDAP_SCOPE_ONELEVEL,
filter,
user_attributes,
0,
&ldapreturn) != -1)
{
for (record = ldap_first_entry(ldaprefs.ldap, ldapreturn); record; record = ldap_next_entry(ldaprefs.ldap, record))
{
pwinfo = safe_malloc(sizeof(struct pwinfo));
rval = assemble_passwd(val, record, pwinfo);
if(rval == YP_TRUE);
{
if(check_unique(mapcache_current, pwinfo->uid) == YP_NOKEY)
{
mapentry_current = safe_malloc(sizeof(struct mapentry));
mapentry_current->key = safe_strdup(pwinfo->uid);
mapentry_current->val = val->valdat_val;
mapentry_current->next = mapcache_current->mapentry;
mapcache_current->mapentry = mapentry_current;
}
}
clean_pwinfo(pwinfo);
}
}
ldap_msgfree(ldapreturn);
free(filter);
free(base);
}
else if (!strcmp((char *) mapcache_current->map, "passwd.byuid"))
{
/* XXX Add preferences for filter and basedn */
base = safe_malloc(strlen(ldaprefs.basedn) + strlen("ou=People,") + 1);
sprintf(base, "%s%s", "ou=People,", ldaprefs.basedn);
filter = safe_strdup("(objectClass=posixAccount)");
if(ldap_search_s(ldaprefs.ldap,
base,
LDAP_SCOPE_ONELEVEL,
filter,
user_attributes,
0,
&ldapreturn) != -1)
{
for (record = ldap_first_entry(ldaprefs.ldap, ldapreturn); record; record = ldap_next_entry(ldaprefs.ldap, record))
{
pwinfo = safe_malloc(sizeof(struct pwinfo));
rval = assemble_passwd(val, record, pwinfo);
if(rval == YP_TRUE);
{
if(check_unique(mapcache_current, pwinfo->uidnumber) == YP_NOKEY)
{
mapentry_current = safe_malloc(sizeof(struct mapentry));
mapentry_current->key = safe_strdup(pwinfo->uidnumber);
mapentry_current->val = val->valdat_val;
mapentry_current->next = mapcache_current->mapentry;
mapcache_current->mapentry = mapentry_current;
}
}
clean_pwinfo(pwinfo);
}
}
ldap_msgfree(ldapreturn);
free(filter);
free(base);
}
else if (!strcmp((char *) mapcache_current->map, "group.byname"))
{
/* XXX Add preferences for filter and basedn */
base = safe_malloc(strlen(ldaprefs.basedn) + strlen("ou=Group,") + 1);
sprintf(base, "%s%s", "ou=Group,", ldaprefs.basedn);
filter = safe_strdup("(objectClass=posixGroup)");
if(ldap_search_s(ldaprefs.ldap,
base,
LDAP_SCOPE_ONELEVEL,
filter,
group_attributes,
0,
&ldapreturn) != -1)
{
for (record = ldap_first_entry(ldaprefs.ldap, ldapreturn); record; record = ldap_next_entry(ldaprefs.ldap, record))
{
gwinfo = safe_malloc(sizeof(struct gwinfo));
rval = assemble_group(val, record, gwinfo);
if(rval == YP_TRUE);
{
if(check_unique(mapcache_current, gwinfo->cn) == YP_NOKEY)
{
mapentry_current = safe_malloc(sizeof(struct mapentry));
mapentry_current->key = safe_strdup(gwinfo->cn);
mapentry_current->val = val->valdat_val;
mapentry_current->next = mapcache_current->mapentry;
mapcache_current->mapentry = mapentry_current;
}
}
clean_gwinfo(gwinfo);
}
}
ldap_msgfree(ldapreturn);
free(filter);
free(base);
}
else if (!strcmp((char *) mapcache_current->map, "group.bygid"))
{
/* XXX Add preferences for filter and basedn */
base = safe_malloc(strlen(ldaprefs.basedn) + strlen("ou=Group,") + 1);
sprintf(base, "%s%s", "ou=Group,", ldaprefs.basedn);
filter = safe_strdup("(objectClass=posixGroup)");
if(ldap_search_s(ldaprefs.ldap,
base,
LDAP_SCOPE_ONELEVEL,
filter,
group_attributes,
0,
&ldapreturn) != -1)
{
for (record = ldap_first_entry(ldaprefs.ldap, ldapreturn); record; record = ldap_next_entry(ldaprefs.ldap, record))
{
gwinfo = safe_malloc(sizeof(struct gwinfo));
rval = assemble_group(val, record, gwinfo);
if(rval == YP_TRUE);
{
if(check_unique(mapcache_current, gwinfo->cn) == YP_NOKEY)
{
mapentry_current = safe_malloc(sizeof(struct mapentry));
mapentry_current->key = safe_strdup(gwinfo->gidnumber);
mapentry_current->val = val->valdat_val;
mapentry_current->next = mapcache_current->mapentry;
mapcache_current->mapentry = mapentry_current;
}
}
clean_gwinfo(gwinfo);
}
}
ldap_msgfree(ldapreturn);
free(filter);
free(base);
} else {
/* XXX Add preferences for filter and basedn */
base = safe_malloc(strlen(ldaprefs.basedn) + strlen("ou=NisMapName,") + strlen((char *) mapcache_current->map) + 1);
sprintf(base, "nisMapName=%s,%s", (char *) mapcache_current->map, ldaprefs.basedn);
filter = safe_strdup("(objectClass=nisObject)");
if(ldap_search_s(ldaprefs.ldap,
base,
LDAP_SCOPE_ONELEVEL,
filter,
nis_attributes,
0,
&ldapreturn) != -1)
{
for (record = ldap_first_entry(ldaprefs.ldap, ldapreturn); record; record = ldap_next_entry(ldaprefs.ldap, record))
{
nisinfo = safe_malloc(sizeof(struct nisinfo));
rval = assemble_nis(val, record, nisinfo);
if(rval == YP_TRUE);
{
if(check_unique(mapcache_current, nisinfo->cn) == YP_NOKEY)
{
mapentry_current = safe_malloc(sizeof(struct mapentry));
mapentry_current->key = safe_strdup(nisinfo->cn);
mapentry_current->val = val->valdat_val;
mapentry_current->next = mapcache_current->mapentry;
mapcache_current->mapentry = mapentry_current;
}
}
clean_nisinfo(nisinfo);
}
}
ldap_msgfree(ldapreturn);
free(filter);
free(base);
}
mapcache_current->time = time(NULL);
mapcache_current->next = mapcache_head;
mapcache_head = mapcache_current;
}
return (mapcache_head);
}
void maintain_cache (void)
{
}
static struct mapcache *getcache(mapname *map)
{
struct mapcache *mapcache_current;
mapcache_current = ldaprefs.mapcache;
while(mapcache_current)
{
if (!strcmp((char *)mapcache_current->map, (char *)map))
{
return (mapcache_current);
}
mapcache_current = mapcache_current->next;
}
return (NULL);
}
ypstat yp_get_record(keydat *key, mapname *map, valdat *val)
{
struct mapcache *mapcache_current;
struct mapentry *mapentry_current;
ypstat rval;
char *tempkey;
tempkey = safe_malloc(key->keydat_len + 1);
bcopy(key->keydat_val, tempkey, key->keydat_len);
tempkey[key->keydat_len] = '\0';
rval = YP_YPERR;
mapcache_current = getcache(map);
if(mapcache_current != NULL)
{
if (!strcmp((char *)mapcache_current->map, (char *) map))
{
if(mapcache_current->mapentry == NULL)
{
free(tempkey);
return (YP_NOMAP);
}
mapentry_current = mapcache_current->mapentry;
while(mapentry_current)
{
if (!strcmp(mapentry_current->key, (char *)tempkey))
{
val->valdat_val = safe_strdup(mapentry_current->val);
val->valdat_len = strlen(mapentry_current->val);
key->keydat_val = safe_strdup(mapentry_current->key);
key->keydat_len = strlen(mapentry_current->key);
free(tempkey);
return (YP_TRUE);
}
mapentry_current = mapentry_current->next;
}
rval = YP_NOKEY;
}
} else {
rval = YP_NOMAP;
}
free(tempkey);
return (rval);
}
ypstat yp_first_record(keydat *key, mapname *map, valdat *val)
{
ypstat rval;
struct mapcache *mapcache_current;
rval = YP_YPERR;
mapcache_current = getcache(map);
if(mapcache_current != NULL)
{
if(mapcache_current->mapentry != NULL)
{
val->valdat_val = safe_strdup(mapcache_current->mapentry->val);
val->valdat_len = strlen(mapcache_current->mapentry->val);
key->keydat_val = safe_strdup(mapcache_current->mapentry->key);
key->keydat_len = strlen(mapcache_current->mapentry->key);
rval = YP_TRUE;
} else {
rval = YP_NOMAP;
}
} else {
rval = YP_NOMAP;
}
return (rval);
}
ypstat yp_next_record(keydat *key, mapname *map, valdat *val)
{
struct mapcache *mapcache_current;
struct mapentry *mapentry_current;
ypstat rval;
char *tempkey;
/* NIS clients will iterate through the entire map, calling only
* ypproc_nextbykey. Thus, the first call will have no key and
* a keylen of 0, so return the result of yp_first_record */
if (key->keydat_len == 0)
{
rval = yp_first_record(key, map, val);
return (rval);
}
tempkey = safe_malloc(key->keydat_len + 1);
bcopy(key->keydat_val, tempkey, key->keydat_len);
tempkey[key->keydat_len] = '\0';
rval = YP_YPERR;
mapcache_current = getcache(map);
if(mapcache_current != NULL)
{
if(mapcache_current->mapentry == NULL)
{
return (YP_NOMAP);
}
if (!strcmp((char *)mapcache_current->map, (char *) map))
{
mapentry_current = mapcache_current->mapentry;
while(mapentry_current)
{
if (!strcmp(mapentry_current->key, (char *)tempkey))
{
free(tempkey);
if (mapentry_current->next != NULL)
{
val->valdat_val = safe_strdup(mapentry_current->next->val);
val->valdat_len = strlen(mapentry_current->next->val);
key->keydat_val = safe_strdup(mapentry_current->next->key);
key->keydat_len = strlen(mapentry_current->next->key);
return (YP_TRUE);
} else {
key->keydat_len = 0;
return (YP_NOKEY);
}
}
mapentry_current = mapentry_current->next;
}
rval = YP_NOKEY;
}
} else {
rval = YP_NOMAP;
}
free(tempkey);
return (rval);
}
syntax highlighted by Code2HTML, v. 0.9.1