xref: /freebsd/usr.sbin/ypserv/yp_dblookup.c (revision 1fbdac93d98e19ba0c459e3a2c782dcf764ef05a)
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