1778c7b1cSBill Paul /* 2778c7b1cSBill Paul * Copyright (c) 1995 3778c7b1cSBill Paul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4778c7b1cSBill Paul * 5778c7b1cSBill Paul * Redistribution and use in source and binary forms, with or without 6778c7b1cSBill Paul * modification, are permitted provided that the following conditions 7778c7b1cSBill Paul * are met: 8778c7b1cSBill Paul * 1. Redistributions of source code must retain the above copyright 9778c7b1cSBill Paul * notice, this list of conditions and the following disclaimer. 10778c7b1cSBill Paul * 2. Redistributions in binary form must reproduce the above copyright 11778c7b1cSBill Paul * notice, this list of conditions and the following disclaimer in the 12778c7b1cSBill Paul * documentation and/or other materials provided with the distribution. 13778c7b1cSBill Paul * 3. All advertising materials mentioning features or use of this software 14778c7b1cSBill Paul * must display the following acknowledgement: 15778c7b1cSBill Paul * This product includes software developed by Bill Paul. 16778c7b1cSBill Paul * 4. Neither the name of the author nor the names of any co-contributors 17778c7b1cSBill Paul * may be used to endorse or promote products derived from this software 18778c7b1cSBill Paul * without specific prior written permission. 19778c7b1cSBill Paul * 20778c7b1cSBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21778c7b1cSBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22778c7b1cSBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23778c7b1cSBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24778c7b1cSBill Paul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25778c7b1cSBill Paul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26778c7b1cSBill Paul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27778c7b1cSBill Paul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28778c7b1cSBill Paul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29778c7b1cSBill Paul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30778c7b1cSBill Paul * SUCH DAMAGE. 31778c7b1cSBill Paul * 321fbdac93SBill Paul * $Id: yp_dblookup.c,v 1.9 1996/05/01 02:33:52 wpaul Exp $ 33778c7b1cSBill Paul * 34778c7b1cSBill Paul */ 35778c7b1cSBill Paul #include <stdio.h> 36778c7b1cSBill Paul #include <stdlib.h> 37778c7b1cSBill Paul #include <fcntl.h> 38778c7b1cSBill Paul #include <string.h> 39778c7b1cSBill Paul #include <limits.h> 40778c7b1cSBill Paul #include <unistd.h> 41778c7b1cSBill Paul #include <db.h> 42778c7b1cSBill Paul #include <sys/stat.h> 43b2264be8SBill Paul #include <sys/param.h> 44778c7b1cSBill Paul #include <errno.h> 45778c7b1cSBill Paul #include <paths.h> 46b2264be8SBill Paul #include <rpcsvc/yp.h> 47778c7b1cSBill Paul #include "yp_extern.h" 48778c7b1cSBill Paul 491fbdac93SBill Paul #ifndef lint 501fbdac93SBill Paul static const char rcsid[] = "$Id: yp_dblookup.c,v 1.9 1996/05/01 02:33:52 wpaul Exp $"; 511fbdac93SBill Paul #endif 521fbdac93SBill Paul 5377732bc5SBill Paul int ypdb_debug = 0; 54778c7b1cSBill Paul int yp_errno = YP_TRUE; 55778c7b1cSBill Paul 56778c7b1cSBill Paul #define PERM_SECURE (S_IRUSR|S_IWUSR) 57778c7b1cSBill Paul HASHINFO openinfo = { 58778c7b1cSBill Paul 4096, /* bsize */ 59778c7b1cSBill Paul 32, /* ffactor */ 60b2264be8SBill Paul 512, /* nelem */ 61b2264be8SBill Paul 2048 * 512, /* cachesize */ 62778c7b1cSBill Paul NULL, /* hash */ 63778c7b1cSBill Paul 0, /* lorder */ 64778c7b1cSBill Paul }; 65778c7b1cSBill Paul 66b2264be8SBill Paul #ifdef DB_CACHE 67b2264be8SBill Paul #define MAXDBS 20 68b2264be8SBill Paul #define LASTDB (MAXDBS - 1) 69b2264be8SBill Paul 70b2264be8SBill Paul struct dbent { 71b2264be8SBill Paul DB *dbp; 72b2264be8SBill Paul char *name; 73b2264be8SBill Paul char *key; 74b2264be8SBill Paul int size; 75b2264be8SBill Paul }; 76b2264be8SBill Paul 77b2264be8SBill Paul static struct dbent *dbs[MAXDBS]; 78b2264be8SBill Paul static int numdbs = 0; 79b2264be8SBill Paul 80778c7b1cSBill Paul /* 81b2264be8SBill Paul * Make sure all the DB entries are NULL to start with. 82b2264be8SBill Paul */ 83b2264be8SBill Paul void yp_init_dbs() 84b2264be8SBill Paul { 85b2264be8SBill Paul register int i; 86b2264be8SBill Paul 87b2264be8SBill Paul for (i = 0; i < MAXDBS; i++); 88b2264be8SBill Paul dbs[i] = NULL; 89b2264be8SBill Paul return; 90b2264be8SBill Paul } 91b2264be8SBill Paul 921fbdac93SBill Paul /* 931fbdac93SBill Paul * Zorch a single entry in the dbent table and release 941fbdac93SBill Paul * all its resources. 951fbdac93SBill Paul */ 961fbdac93SBill Paul static __inline void yp_flush(i) 97b2264be8SBill Paul register int i; 98b2264be8SBill Paul { 99b2264be8SBill Paul (void)(dbs[i]->dbp->close)(dbs[i]->dbp); 100b2264be8SBill Paul dbs[i]->dbp = NULL; 101b2264be8SBill Paul free(dbs[i]->name); 102b2264be8SBill Paul dbs[i]->name = NULL; 103b2264be8SBill Paul dbs[i]->key = NULL; 104b2264be8SBill Paul dbs[i]->size = 0; 105b2264be8SBill Paul free(dbs[i]); 106b2264be8SBill Paul dbs[i] = NULL; 107b2264be8SBill Paul numdbs--; 108b2264be8SBill Paul } 109b2264be8SBill Paul 110b2264be8SBill Paul /* 111b2264be8SBill Paul * Close all databases and erase all database names. 112b2264be8SBill Paul */ 113b2264be8SBill Paul void yp_flush_all() 114b2264be8SBill Paul { 115b2264be8SBill Paul register int i; 116b2264be8SBill Paul 117b2264be8SBill Paul for (i = 0; i < MAXDBS; i++) { 118b2264be8SBill Paul if (dbs[i] != NULL && dbs[i]->dbp != NULL) { 119b2264be8SBill Paul yp_flush(i); 120b2264be8SBill Paul } 121b2264be8SBill Paul } 122b2264be8SBill Paul } 123b2264be8SBill Paul 124b2264be8SBill Paul 125b2264be8SBill Paul /* 126b2264be8SBill Paul * Add a DB handle and database name to the cache. We only maintain 127b2264be8SBill Paul * fixed number of entries in the cache, so if we're asked to store 128b2264be8SBill Paul * a new entry when all our slots are already filled, we have to kick 129b2264be8SBill Paul * out the entry in the last slot to make room. 130b2264be8SBill Paul */ 1311fbdac93SBill Paul static __inline void yp_add_db(dbp, name, size) 132b2264be8SBill Paul DB *dbp; 133b2264be8SBill Paul char *name; 134b2264be8SBill Paul int size; 135b2264be8SBill Paul { 136b2264be8SBill Paul register int i; 137b2264be8SBill Paul register struct dbent *tmp; 138b2264be8SBill Paul 139b2264be8SBill Paul tmp = dbs[LASTDB]; 140b2264be8SBill Paul 141b2264be8SBill Paul /* Rotate */ 142b2264be8SBill Paul for (i = LASTDB; i > 0; i--) 143b2264be8SBill Paul dbs[i] = dbs[i - 1]; 144b2264be8SBill Paul 145b2264be8SBill Paul dbs[0] = tmp; 146b2264be8SBill Paul 147b2264be8SBill Paul if (dbs[0]) { 148b2264be8SBill Paul if (ypdb_debug) 149b2264be8SBill Paul yp_error("table overflow -- releasing last slot"); 150b2264be8SBill Paul yp_flush(0); 151b2264be8SBill Paul } 152b2264be8SBill Paul 153b2264be8SBill Paul /* 1541fbdac93SBill Paul * Allocate a new entry. 155b2264be8SBill Paul */ 156b2264be8SBill Paul if (dbs[0] == NULL) { 157b2264be8SBill Paul dbs[0] = (struct dbent *)malloc(sizeof(struct dbent)); 158b2264be8SBill Paul bzero((char *)dbs[0], sizeof(struct dbent)); 159b2264be8SBill Paul } 160b2264be8SBill Paul 161b2264be8SBill Paul numdbs++; 162b2264be8SBill Paul dbs[0]->dbp = dbp; 163b2264be8SBill Paul dbs[0]->name = strdup(name); 164b2264be8SBill Paul dbs[0]->size = size; 165b2264be8SBill Paul return; 166b2264be8SBill Paul } 167b2264be8SBill Paul 168b2264be8SBill Paul /* 169b2264be8SBill Paul * Search the list for a database matching 'name.' If we find it, 170b2264be8SBill Paul * move it to the head of the list and return its DB handle. If 171b2264be8SBill Paul * not, just fail: yp_open_db_cache() will subsequently try to open 172b2264be8SBill Paul * the database itself and call yp_add_db() to add it to the 173b2264be8SBill Paul * list. 174b2264be8SBill Paul * 175b2264be8SBill Paul * The search works like this: 176b2264be8SBill Paul * 177b2264be8SBill Paul * - The caller specifies the name of a database to locate. We try to 178b2264be8SBill Paul * find an entry in our list with a matching name. 179b2264be8SBill Paul * 180b2264be8SBill Paul * - If the caller doesn't specify a key or size, we assume that the 181b2264be8SBill Paul * first entry that we encounter with a matching name is returned. 182b2264be8SBill Paul * This will result in matches regardless of the pointer index. 183b2264be8SBill Paul * 184b2264be8SBill Paul * - If the caller also specifies a key and length, we check name 185b2264be8SBill Paul * matches to see if their saved key indexes and lengths also match. 186b2264be8SBill Paul * This lets us return a DB handle that's already positioned at the 187b2264be8SBill Paul * correct location within a database. 188b2264be8SBill Paul * 189b2264be8SBill Paul * - Once we have a match, it gets migrated to the top of the list 190b2264be8SBill Paul * array so that it will be easier to find if another request for 191b2264be8SBill Paul * the same database comes in later. 192b2264be8SBill Paul */ 1931fbdac93SBill Paul static __inline DB *yp_find_db(name, key, size) 194b2264be8SBill Paul char *name; 195b2264be8SBill Paul char *key; 1961fbdac93SBill Paul int size; 197b2264be8SBill Paul { 198b2264be8SBill Paul register int i, j; 199b2264be8SBill Paul register struct dbent *tmp; 200b2264be8SBill Paul 201b2264be8SBill Paul for (i = 0; i < numdbs; i++) { 202b2264be8SBill Paul if (dbs[i]->name != NULL && !strcmp(dbs[i]->name, name)) { 203b2264be8SBill Paul if (size) { 204b2264be8SBill Paul if (size != dbs[i]->size || 205b2264be8SBill Paul strncmp(dbs[i]->key, key, size)) 206b2264be8SBill Paul continue; 207b2264be8SBill Paul } else { 208b2264be8SBill Paul if (dbs[i]->size) { 209b2264be8SBill Paul continue; 210b2264be8SBill Paul } 211b2264be8SBill Paul } 212b2264be8SBill Paul if (i > 0) { 213b2264be8SBill Paul tmp = dbs[i]; 214b2264be8SBill Paul for (j = i; j > 0; j--) 215b2264be8SBill Paul dbs[j] = dbs[j - 1]; 216b2264be8SBill Paul dbs[0] = tmp; 217b2264be8SBill Paul } 218b2264be8SBill Paul return(dbs[0]->dbp); 219b2264be8SBill Paul } 220b2264be8SBill Paul } 221b2264be8SBill Paul return(NULL); 222b2264be8SBill Paul } 223b2264be8SBill Paul 224b2264be8SBill Paul /* 225b2264be8SBill Paul * Open a DB database and cache the handle for later use. We first 226b2264be8SBill Paul * check the cache to see if the required database is already open. 227b2264be8SBill Paul * If so, we fetch the handle from the cache. If not, we try to open 228b2264be8SBill Paul * the database and save the handle in the cache for later use. 229b2264be8SBill Paul */ 230b2264be8SBill Paul DB *yp_open_db_cache(domain, map, key, size) 231b2264be8SBill Paul const char *domain; 232b2264be8SBill Paul const char *map; 233b2264be8SBill Paul const char *key; 234b2264be8SBill Paul const int size; 235b2264be8SBill Paul { 236b2264be8SBill Paul DB *dbp = NULL; 237b2264be8SBill Paul char buf[MAXPATHLEN + 2]; 238b2264be8SBill Paul 2391fbdac93SBill Paul strcpy(buf, domain); 2401fbdac93SBill Paul strcat(buf, "/"); 2411fbdac93SBill Paul strcat(buf, map); 242b2264be8SBill Paul 243b2264be8SBill Paul if ((dbp = yp_find_db((char *)&buf, key, size)) != NULL) { 244b2264be8SBill Paul return(dbp); 245b2264be8SBill Paul } else { 246b2264be8SBill Paul if ((dbp = yp_open_db(domain, map)) != NULL) 247b2264be8SBill Paul yp_add_db(dbp, (char *)&buf, size); 248b2264be8SBill Paul } 249b2264be8SBill Paul 250b2264be8SBill Paul return (dbp); 251b2264be8SBill Paul } 252b2264be8SBill Paul #endif 253b2264be8SBill Paul 254b2264be8SBill Paul /* 255b2264be8SBill Paul * Open a DB database. 256778c7b1cSBill Paul */ 257778c7b1cSBill Paul DB *yp_open_db(domain, map) 258778c7b1cSBill Paul const char *domain; 259778c7b1cSBill Paul const char *map; 260778c7b1cSBill Paul { 261b2264be8SBill Paul DB *dbp = NULL; 262b2264be8SBill Paul char buf[MAXPATHLEN + 2]; 263778c7b1cSBill Paul 264778c7b1cSBill Paul yp_errno = YP_TRUE; 265778c7b1cSBill Paul 266778c7b1cSBill Paul if (map[0] == '.' || strchr(map, '/')) { 267778c7b1cSBill Paul yp_errno = YP_BADARGS; 268778c7b1cSBill Paul return (NULL); 269778c7b1cSBill Paul } 270778c7b1cSBill Paul 271b2264be8SBill Paul #ifdef DB_CACHE 272b2264be8SBill Paul if (yp_validdomain(domain)) { 273b2264be8SBill Paul yp_errno = YP_NODOM; 274b2264be8SBill Paul return(NULL); 275b2264be8SBill Paul } 276b2264be8SBill Paul #endif 277778c7b1cSBill Paul snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); 278778c7b1cSBill Paul 279b2264be8SBill Paul #ifdef DB_CACHE 280b2264be8SBill Paul again: 281b2264be8SBill Paul #endif 282b2264be8SBill Paul dbp = dbopen(buf,O_RDONLY, PERM_SECURE, DB_HASH, NULL); 283778c7b1cSBill Paul 284778c7b1cSBill Paul if (dbp == NULL) { 285778c7b1cSBill Paul switch(errno) { 286b2264be8SBill Paul #ifdef DB_CACHE 287b2264be8SBill Paul case ENFILE: 288b2264be8SBill Paul /* 289b2264be8SBill Paul * We ran out of file descriptors. Nuke an 290b2264be8SBill Paul * open one and try again. 291b2264be8SBill Paul */ 292b2264be8SBill Paul yp_error("ran out of file descriptors"); 293b2264be8SBill Paul yp_flush(numdbs - 1); 294b2264be8SBill Paul goto again; 295b2264be8SBill Paul break; 296b2264be8SBill Paul #endif 297778c7b1cSBill Paul case ENOENT: 298778c7b1cSBill Paul yp_errno = YP_NOMAP; 299778c7b1cSBill Paul break; 300778c7b1cSBill Paul case EFTYPE: 301778c7b1cSBill Paul yp_errno = YP_BADDB; 302778c7b1cSBill Paul break; 303778c7b1cSBill Paul default: 304778c7b1cSBill Paul yp_errno = YP_YPERR; 305778c7b1cSBill Paul break; 306778c7b1cSBill Paul } 307778c7b1cSBill Paul } 308778c7b1cSBill Paul 309778c7b1cSBill Paul return (dbp); 310778c7b1cSBill Paul } 311778c7b1cSBill Paul 312778c7b1cSBill Paul /* 313778c7b1cSBill Paul * Database access routines. 314778c7b1cSBill Paul * 315778c7b1cSBill Paul * - yp_get_record(): retrieve an arbitrary key/data pair given one key 316778c7b1cSBill Paul * to match against. 317778c7b1cSBill Paul * 318778c7b1cSBill Paul * - yp_first_record(): retrieve first key/data base in a database. 319778c7b1cSBill Paul * 320778c7b1cSBill Paul * - yp_next_record(): retrieve key/data pair that sequentially follows 321778c7b1cSBill Paul * the supplied key value in the database. 322778c7b1cSBill Paul */ 323778c7b1cSBill Paul 324778c7b1cSBill Paul int yp_get_record(domain,map,key,data,allow) 325778c7b1cSBill Paul const char *domain; 326778c7b1cSBill Paul const char *map; 327778c7b1cSBill Paul const DBT *key; 328778c7b1cSBill Paul DBT *data; 329778c7b1cSBill Paul int allow; 330778c7b1cSBill Paul { 331778c7b1cSBill Paul DB *dbp; 332b2264be8SBill Paul int rval = 0; 333778c7b1cSBill Paul 33477732bc5SBill Paul if (ypdb_debug) 335778c7b1cSBill Paul yp_error("Looking up key [%.*s] in map [%s]", 336778c7b1cSBill Paul key->size, key->data, map); 337778c7b1cSBill Paul 338778c7b1cSBill Paul /* 339778c7b1cSBill Paul * Avoid passing back magic "YP_*" entries unless 340778c7b1cSBill Paul * the caller specifically requested them by setting 341778c7b1cSBill Paul * the 'allow' flag. 342778c7b1cSBill Paul */ 343778c7b1cSBill Paul if (!allow && !strncmp(key->data, "YP_", 3)) 344778c7b1cSBill Paul return(YP_NOKEY); 345778c7b1cSBill Paul 346b2264be8SBill Paul #ifdef DB_CACHE 347b2264be8SBill Paul if ((dbp = yp_open_db_cache(domain, map, NULL, 0)) == NULL) { 348b2264be8SBill Paul #else 349778c7b1cSBill Paul if ((dbp = yp_open_db(domain, map)) == NULL) { 350b2264be8SBill Paul #endif 351778c7b1cSBill Paul return(yp_errno); 352778c7b1cSBill Paul } 353778c7b1cSBill Paul 354920491cfSBill Paul if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) { 355b2264be8SBill Paul #ifdef DB_CACHE 356b2264be8SBill Paul dbs[0]->size = 0; 357b2264be8SBill Paul #else 358778c7b1cSBill Paul (void)(dbp->close)(dbp); 359b2264be8SBill Paul #endif 360920491cfSBill Paul if (rval == 1) 361778c7b1cSBill Paul return(YP_NOKEY); 362920491cfSBill Paul else 363920491cfSBill Paul return(YP_BADDB); 364778c7b1cSBill Paul } 365778c7b1cSBill Paul 36677732bc5SBill Paul if (ypdb_debug) 367778c7b1cSBill Paul yp_error("Result of lookup: key: [%.*s] data: [%.*s]", 368778c7b1cSBill Paul key->size, key->data, data->size, data->data); 369778c7b1cSBill Paul 370b2264be8SBill Paul #ifdef DB_CACHE 371b2264be8SBill Paul if (dbs[0]->size) { 372b2264be8SBill Paul dbs[0]->key = key->data; 373b2264be8SBill Paul dbs[0]->size = key->size; 374b2264be8SBill Paul } 375b2264be8SBill Paul #else 376b2264be8SBill Paul (void)(dbp->close)(dbp); 377b2264be8SBill Paul #endif 378b2264be8SBill Paul 379778c7b1cSBill Paul return(YP_TRUE); 380778c7b1cSBill Paul } 381778c7b1cSBill Paul 382b2264be8SBill Paul int yp_first_record(dbp,key,data,allow) 383778c7b1cSBill Paul const DB *dbp; 384778c7b1cSBill Paul DBT *key; 385778c7b1cSBill Paul DBT *data; 386b2264be8SBill Paul int allow; 387778c7b1cSBill Paul { 388920491cfSBill Paul int rval; 389778c7b1cSBill Paul 39077732bc5SBill Paul if (ypdb_debug) 391778c7b1cSBill Paul yp_error("Retrieving first key in map."); 392778c7b1cSBill Paul 393920491cfSBill Paul if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) { 394b2264be8SBill Paul #ifdef DB_CACHE 395b2264be8SBill Paul dbs[0]->size = 0; 396b2264be8SBill Paul #endif 397920491cfSBill Paul if (rval == 1) 398920491cfSBill Paul return(YP_NOKEY); 399920491cfSBill Paul else 400778c7b1cSBill Paul return(YP_BADDB); 401920491cfSBill Paul } 402778c7b1cSBill Paul 403778c7b1cSBill Paul /* Avoid passing back magic "YP_*" records. */ 404b2264be8SBill Paul while (!strncmp(key->data, "YP_", 3) && !allow) { 405920491cfSBill Paul if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) { 406b2264be8SBill Paul #ifdef DB_CACHE 407b2264be8SBill Paul dbs[0]->size = 0; 408b2264be8SBill Paul #endif 409920491cfSBill Paul if (rval == 1) 410920491cfSBill Paul return(YP_NOKEY); 411920491cfSBill Paul else 412778c7b1cSBill Paul return(YP_BADDB); 413778c7b1cSBill Paul } 414920491cfSBill Paul } 415778c7b1cSBill Paul 41677732bc5SBill Paul if (ypdb_debug) 417778c7b1cSBill Paul yp_error("Result of lookup: key: [%.*s] data: [%.*s]", 418778c7b1cSBill Paul key->size, key->data, data->size, data->data); 419778c7b1cSBill Paul 420b2264be8SBill Paul #ifdef DB_CACHE 421b2264be8SBill Paul if (dbs[0]->size) { 422b2264be8SBill Paul dbs[0]->key = key->data; 423b2264be8SBill Paul dbs[0]->size = key->size; 424b2264be8SBill Paul } 425b2264be8SBill Paul #endif 426b2264be8SBill Paul 427778c7b1cSBill Paul return(YP_TRUE); 428778c7b1cSBill Paul } 429778c7b1cSBill Paul 430b2264be8SBill Paul int yp_next_record(dbp,key,data,all,allow) 431778c7b1cSBill Paul const DB *dbp; 432778c7b1cSBill Paul DBT *key; 433778c7b1cSBill Paul DBT *data; 434778c7b1cSBill Paul int all; 435b2264be8SBill Paul int allow; 436778c7b1cSBill Paul { 437b2264be8SBill Paul static DBT lkey = { NULL, 0 }; 438b2264be8SBill Paul static DBT ldata = { NULL, 0 }; 439920491cfSBill Paul int rval; 440778c7b1cSBill Paul 441920491cfSBill Paul if (key == NULL || key->data == NULL) { 442b2264be8SBill Paul rval = yp_first_record(dbp,key,data,allow); 443920491cfSBill Paul if (rval == YP_NOKEY) 444920491cfSBill Paul return(YP_NOMORE); 445920491cfSBill Paul else 446920491cfSBill Paul return(rval); 447920491cfSBill Paul } 448778c7b1cSBill Paul 44977732bc5SBill Paul if (ypdb_debug) 450778c7b1cSBill Paul yp_error("Retreiving next key, previous was: [%.*s]", 451778c7b1cSBill Paul key->size, key->data); 452778c7b1cSBill Paul 453778c7b1cSBill Paul if (!all) { 454b2264be8SBill Paul #ifndef DB_CACHE 455b2264be8SBill Paul if (key->size != lkey.size || 456b2264be8SBill Paul strncmp(key->data, lkey.data, key->size)) { 457b2264be8SBill Paul #else 458b2264be8SBill Paul if (!dbs[0]->size) { 459b2264be8SBill Paul #endif 460778c7b1cSBill Paul (dbp->seq)(dbp,&lkey,&ldata,R_FIRST); 461b2264be8SBill Paul while(strncmp((char *)key->data,lkey.data, 462b2264be8SBill Paul (int)key->size) || key->size != lkey.size) 463778c7b1cSBill Paul (dbp->seq)(dbp,&lkey,&ldata,R_NEXT); 464778c7b1cSBill Paul } 465b2264be8SBill Paul } 466778c7b1cSBill Paul 467b2264be8SBill Paul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 468b2264be8SBill Paul #ifdef DB_CACHE 469b2264be8SBill Paul dbs[0]->size = 0; 470b2264be8SBill Paul #endif 471778c7b1cSBill Paul return(YP_NOMORE); 472b2264be8SBill Paul } 473778c7b1cSBill Paul 474778c7b1cSBill Paul /* Avoid passing back magic "YP_*" records. */ 475b2264be8SBill Paul while (!strncmp(key->data, "YP_", 3) && !allow) 476b2264be8SBill Paul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 477b2264be8SBill Paul #ifdef DB_CACHE 478b2264be8SBill Paul dbs[0]->size = 0; 479b2264be8SBill Paul #endif 480778c7b1cSBill Paul return(YP_NOMORE); 481b2264be8SBill Paul } 482778c7b1cSBill Paul 48377732bc5SBill Paul if (ypdb_debug) 484778c7b1cSBill Paul yp_error("Result of lookup: key: [%.*s] data: [%.*s]", 485778c7b1cSBill Paul key->size, key->data, data->size, data->data); 486778c7b1cSBill Paul 487b2264be8SBill Paul #ifdef DB_CACHE 488b2264be8SBill Paul if (dbs[0]->size) { 489b2264be8SBill Paul dbs[0]->key = key->data; 490b2264be8SBill Paul dbs[0]->size = key->size; 491b2264be8SBill Paul } 492b2264be8SBill Paul #else 493b2264be8SBill Paul lkey.data = key->data; 494b2264be8SBill Paul lkey.size = key->size; 495b2264be8SBill Paul #endif 496b2264be8SBill Paul 497778c7b1cSBill Paul return(YP_TRUE); 498778c7b1cSBill Paul } 499