112891Swpaul/* 212891Swpaul * Copyright (c) 1995 312891Swpaul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 412891Swpaul * 512891Swpaul * Redistribution and use in source and binary forms, with or without 612891Swpaul * modification, are permitted provided that the following conditions 712891Swpaul * are met: 812891Swpaul * 1. Redistributions of source code must retain the above copyright 912891Swpaul * notice, this list of conditions and the following disclaimer. 1012891Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1112891Swpaul * notice, this list of conditions and the following disclaimer in the 1212891Swpaul * documentation and/or other materials provided with the distribution. 1312891Swpaul * 3. All advertising materials mentioning features or use of this software 1412891Swpaul * must display the following acknowledgement: 1512891Swpaul * This product includes software developed by Bill Paul. 1612891Swpaul * 4. Neither the name of the author nor the names of any co-contributors 1712891Swpaul * may be used to endorse or promote products derived from this software 1812891Swpaul * without specific prior written permission. 1912891Swpaul * 2012891Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2112891Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2212891Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2312891Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2412891Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2512891Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2612891Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2712891Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2812891Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2912891Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3012891Swpaul * SUCH DAMAGE. 3112891Swpaul */ 3230827Scharnier 33114601Sobrien#include <sys/cdefs.h> 34114601Sobrien__FBSDID("$FreeBSD$"); 3530827Scharnier 3630827Scharnier#include <db.h> 3730827Scharnier#include <errno.h> 3830827Scharnier#include <fcntl.h> 3930827Scharnier#include <limits.h> 4030827Scharnier#include <paths.h> 4112891Swpaul#include <stdio.h> 4212891Swpaul#include <stdlib.h> 4312891Swpaul#include <string.h> 4412891Swpaul#include <unistd.h> 4512891Swpaul#include <sys/stat.h> 4615426Swpaul#include <sys/param.h> 4715426Swpaul#include <rpcsvc/yp.h> 4812891Swpaul#include "yp_extern.h" 4912891Swpaul 5012997Swpaulint ypdb_debug = 0; 5120818Swpaulenum ypstat yp_errno = YP_TRUE; 5212891Swpaul 5312891Swpaul#define PERM_SECURE (S_IRUSR|S_IWUSR) 5412891SwpaulHASHINFO openinfo = { 5512891Swpaul 4096, /* bsize */ 5612891Swpaul 32, /* ffactor */ 5716118Swpaul 256, /* nelem */ 5815426Swpaul 2048 * 512, /* cachesize */ 5912891Swpaul NULL, /* hash */ 6012891Swpaul 0, /* lorder */ 6112891Swpaul}; 6212891Swpaul 6315426Swpaul#ifdef DB_CACHE 6416999Swpaul#include <sys/queue.h> 6516999Swpaul 6616999Swpaul#ifndef MAXDBS 6715426Swpaul#define MAXDBS 20 6816999Swpaul#endif 6915426Swpaul 7016999Swpaulstatic int numdbs = 0; 7116999Swpaul 7215426Swpaulstruct dbent { 7315426Swpaul DB *dbp; 7415426Swpaul char *name; 7515426Swpaul char *key; 7615426Swpaul int size; 7719161Swpaul int flags; 7815426Swpaul}; 7915426Swpaul 8070493Sphkstatic TAILQ_HEAD(circlehead, circleq_entry) qhead; 8115426Swpaul 8216999Swpaulstruct circleq_entry { 8316999Swpaul struct dbent *dbptr; 8470493Sphk TAILQ_ENTRY(circleq_entry) links; 8516999Swpaul}; 8616999Swpaul 8712891Swpaul/* 8816999Swpaul * Initialize the circular queue. 8912891Swpaul */ 9090298Sdesvoid 9190298Sdesyp_init_dbs(void) 9215426Swpaul{ 9370493Sphk TAILQ_INIT(&qhead); 9416999Swpaul return; 9516999Swpaul} 9615426Swpaul 9716999Swpaul/* 9816999Swpaul * Dynamically allocate an entry for the circular queue. 9916999Swpaul * Return a NULL pointer on failure. 10016999Swpaul */ 10190298Sdesstatic struct circleq_entry * 10290298Sdesyp_malloc_qent(void) 10316999Swpaul{ 10416999Swpaul register struct circleq_entry *q; 10516999Swpaul 10616999Swpaul q = (struct circleq_entry *)malloc(sizeof(struct circleq_entry)); 10716999Swpaul if (q == NULL) { 10830827Scharnier yp_error("failed to malloc() circleq entry"); 10916999Swpaul return(NULL); 11016999Swpaul } 11116999Swpaul bzero((char *)q, sizeof(struct circleq_entry)); 11216999Swpaul q->dbptr = (struct dbent *)malloc(sizeof(struct dbent)); 11316999Swpaul if (q->dbptr == NULL) { 11430827Scharnier yp_error("failed to malloc() circleq entry"); 11516999Swpaul free(q); 11616999Swpaul return(NULL); 11716999Swpaul } 11816999Swpaul bzero((char *)q->dbptr, sizeof(struct dbent)); 11916999Swpaul 12016999Swpaul return(q); 12116999Swpaul} 12216999Swpaul 12316999Swpaul/* 12416999Swpaul * Free a previously allocated circular queue 12516999Swpaul * entry. 12616999Swpaul */ 12790298Sdesstatic void 12890298Sdesyp_free_qent(struct circleq_entry *q) 12916999Swpaul{ 13016999Swpaul /* 13116999Swpaul * First, close the database. In theory, this is also 13216999Swpaul * supposed to free the resources allocated by the DB 13316999Swpaul * package, including the memory pointed to by q->dbptr->key. 13416999Swpaul * This means we don't have to free q->dbptr->key here. 13516999Swpaul */ 13616999Swpaul if (q->dbptr->dbp) { 13716999Swpaul (void)(q->dbptr->dbp->close)(q->dbptr->dbp); 13816999Swpaul q->dbptr->dbp = NULL; 13916999Swpaul } 14016999Swpaul /* 14116999Swpaul * Then free the database name, which was strdup()'ed. 14216999Swpaul */ 14316999Swpaul free(q->dbptr->name); 14416999Swpaul 14516999Swpaul /* 14616999Swpaul * Free the rest of the dbent struct. 14716999Swpaul */ 14816999Swpaul free(q->dbptr); 14916999Swpaul q->dbptr = NULL; 15016999Swpaul 15116999Swpaul /* 15216999Swpaul * Free the circleq struct. 15316999Swpaul */ 15416999Swpaul free(q); 15516999Swpaul q = NULL; 15616999Swpaul 15715426Swpaul return; 15815426Swpaul} 15915426Swpaul 16016044Swpaul/* 16116999Swpaul * Zorch a single entry in the dbent queue and release 16216999Swpaul * all its resources. (This always removes the last entry 16316999Swpaul * in the queue.) 16416044Swpaul */ 16590298Sdesstatic void 16690298Sdesyp_flush(void) 16715426Swpaul{ 16816999Swpaul register struct circleq_entry *qptr; 16916999Swpaul 17070493Sphk qptr = TAILQ_LAST(&qhead, circlehead); 17170493Sphk TAILQ_REMOVE(&qhead, qptr, links); 17216999Swpaul yp_free_qent(qptr); 17315426Swpaul numdbs--; 17416999Swpaul 17516999Swpaul return; 17615426Swpaul} 17715426Swpaul 17815426Swpaul/* 17916999Swpaul * Close all databases, erase all database names and empty the queue. 18015426Swpaul */ 18190298Sdesvoid 18290298Sdesyp_flush_all(void) 18315426Swpaul{ 18416999Swpaul register struct circleq_entry *qptr; 18515426Swpaul 18690297Sdes while (!TAILQ_EMPTY(&qhead)) { 18770493Sphk qptr = TAILQ_FIRST(&qhead); /* save this */ 18870493Sphk TAILQ_REMOVE(&qhead, qptr, links); 18990297Sdes yp_free_qent(qptr); 19015426Swpaul } 19116999Swpaul numdbs = 0; 19216999Swpaul 19316999Swpaul return; 19415426Swpaul} 19515426Swpaul 19619161Swpaulstatic char *inter_string = "YP_INTERDOMAIN"; 19719161Swpaulstatic char *secure_string = "YP_SECURE"; 19819161Swpaulstatic int inter_sz = sizeof("YP_INTERDOMAIN") - 1; 19919161Swpaulstatic int secure_sz = sizeof("YP_SECURE") - 1; 20015426Swpaul 20190298Sdesstatic int 20290298Sdesyp_setflags(DB *dbp) 20319161Swpaul{ 20419161Swpaul DBT key = { NULL, 0 }, data = { NULL, 0 }; 20519161Swpaul int flags = 0; 20619161Swpaul 20719161Swpaul key.data = inter_string; 20819161Swpaul key.size = inter_sz; 20919161Swpaul 21019161Swpaul if (!(dbp->get)(dbp, &key, &data, 0)) 21119161Swpaul flags |= YP_INTERDOMAIN; 21219161Swpaul 21319161Swpaul key.data = secure_string; 21419161Swpaul key.size = secure_sz; 21519161Swpaul 21619161Swpaul if (!(dbp->get)(dbp, &key, &data, 0)) 21719161Swpaul flags |= YP_SECURE; 21819161Swpaul 21919161Swpaul return(flags); 22019161Swpaul} 22119161Swpaul 22290298Sdesint 22390298Sdesyp_testflag(char *map, char *domain, int flag) 22419161Swpaul{ 22519161Swpaul char buf[MAXPATHLEN + 2]; 22619161Swpaul register struct circleq_entry *qptr; 22719161Swpaul 22819161Swpaul if (map == NULL || domain == NULL) 22919161Swpaul return(0); 23019161Swpaul 23119161Swpaul strcpy(buf, domain); 23219161Swpaul strcat(buf, "/"); 23319161Swpaul strcat(buf, map); 23419161Swpaul 23570493Sphk TAILQ_FOREACH(qptr, &qhead, links) { 23619161Swpaul if (!strcmp(qptr->dbptr->name, buf)) { 23719161Swpaul if (qptr->dbptr->flags & flag) 23819161Swpaul return(1); 23919161Swpaul else 24019161Swpaul return(0); 24119161Swpaul } 24219161Swpaul } 24319161Swpaul 24419161Swpaul if (yp_open_db_cache(domain, map, NULL, 0) == NULL) 24519161Swpaul return(0); 24619161Swpaul 24770493Sphk if (TAILQ_FIRST(&qhead)->dbptr->flags & flag) 24819161Swpaul return(1); 24919161Swpaul 25019161Swpaul return(0); 25119161Swpaul} 25219161Swpaul 25315426Swpaul/* 25415426Swpaul * Add a DB handle and database name to the cache. We only maintain 25515426Swpaul * fixed number of entries in the cache, so if we're asked to store 25615426Swpaul * a new entry when all our slots are already filled, we have to kick 25715426Swpaul * out the entry in the last slot to make room. 25815426Swpaul */ 25990298Sdesstatic int 26090298Sdesyp_cache_db(DB *dbp, char *name, int size) 26115426Swpaul{ 26216999Swpaul register struct circleq_entry *qptr; 26315426Swpaul 26416999Swpaul if (numdbs == MAXDBS) { 26515426Swpaul if (ypdb_debug) 26616999Swpaul yp_error("queue overflow -- releasing last slot"); 26716999Swpaul yp_flush(); 26815426Swpaul } 26915426Swpaul 27015426Swpaul /* 27116999Swpaul * Allocate a new queue entry. 27215426Swpaul */ 27316999Swpaul 27416999Swpaul if ((qptr = yp_malloc_qent()) == NULL) { 27516999Swpaul yp_error("failed to allocate a new cache entry"); 27616999Swpaul return(1); 27715426Swpaul } 27815426Swpaul 27916999Swpaul qptr->dbptr->dbp = dbp; 28016999Swpaul qptr->dbptr->name = strdup(name); 28116999Swpaul qptr->dbptr->size = size; 28216999Swpaul qptr->dbptr->key = NULL; 28316999Swpaul 28419161Swpaul qptr->dbptr->flags = yp_setflags(dbp); 28519161Swpaul 28670493Sphk TAILQ_INSERT_HEAD(&qhead, qptr, links); 28715426Swpaul numdbs++; 28816999Swpaul 28916999Swpaul return(0); 29015426Swpaul} 29115426Swpaul 29215426Swpaul/* 29315426Swpaul * Search the list for a database matching 'name.' If we find it, 29415426Swpaul * move it to the head of the list and return its DB handle. If 29515426Swpaul * not, just fail: yp_open_db_cache() will subsequently try to open 29616999Swpaul * the database itself and call yp_cache_db() to add it to the 29715426Swpaul * list. 29815426Swpaul * 29915426Swpaul * The search works like this: 30015426Swpaul * 30115426Swpaul * - The caller specifies the name of a database to locate. We try to 30216999Swpaul * find an entry in our queue with a matching name. 30315426Swpaul * 30415426Swpaul * - If the caller doesn't specify a key or size, we assume that the 30515426Swpaul * first entry that we encounter with a matching name is returned. 30616999Swpaul * This will result in matches regardless of the key/size values 30716999Swpaul * stored in the queue entry. 30815426Swpaul * 30916999Swpaul * - If the caller also specifies a key and length, we check to see 31016999Swpaul * if the key and length saved in the queue entry also matches. 31115426Swpaul * This lets us return a DB handle that's already positioned at the 31215426Swpaul * correct location within a database. 31315426Swpaul * 31416999Swpaul * - Once we have a match, it gets migrated to the top of the queue 31516999Swpaul * so that it will be easier to find if another request for 31615426Swpaul * the same database comes in later. 31715426Swpaul */ 31890298Sdesstatic DB * 31995658Sdesyp_find_db(const char *name, const char *key, int size) 32015426Swpaul{ 32116999Swpaul register struct circleq_entry *qptr; 32215426Swpaul 32370493Sphk TAILQ_FOREACH(qptr, &qhead, links) { 32416999Swpaul if (!strcmp(qptr->dbptr->name, name)) { 32515426Swpaul if (size) { 32616999Swpaul if (size != qptr->dbptr->size || 32716999Swpaul strncmp(qptr->dbptr->key, key, size)) 32815426Swpaul continue; 32915426Swpaul } else { 33016999Swpaul if (qptr->dbptr->size) 33115426Swpaul continue; 33215426Swpaul } 33370493Sphk if (qptr != TAILQ_FIRST(&qhead)) { 33470493Sphk TAILQ_REMOVE(&qhead, qptr, links); 33570493Sphk TAILQ_INSERT_HEAD(&qhead, qptr, links); 33615426Swpaul } 33716999Swpaul return(qptr->dbptr->dbp); 33815426Swpaul } 33915426Swpaul } 34016118Swpaul 34115426Swpaul return(NULL); 34215426Swpaul} 34315426Swpaul 34415426Swpaul/* 34515426Swpaul * Open a DB database and cache the handle for later use. We first 34615426Swpaul * check the cache to see if the required database is already open. 34715426Swpaul * If so, we fetch the handle from the cache. If not, we try to open 34815426Swpaul * the database and save the handle in the cache for later use. 34915426Swpaul */ 35090298SdesDB * 35190298Sdesyp_open_db_cache(const char *domain, const char *map, const char *key, 35290298Sdes const int size) 35315426Swpaul{ 35415426Swpaul DB *dbp = NULL; 35515426Swpaul char buf[MAXPATHLEN + 2]; 35616118Swpaul/* 35716118Swpaul snprintf(buf, sizeof(buf), "%s/%s", domain, map); 35816118Swpaul*/ 35916999Swpaul yp_errno = YP_TRUE; 36015426Swpaul 36116044Swpaul strcpy(buf, domain); 36216044Swpaul strcat(buf, "/"); 36316044Swpaul strcat(buf, map); 36415426Swpaul 36595658Sdes if ((dbp = yp_find_db(buf, key, size)) != NULL) { 36615426Swpaul return(dbp); 36715426Swpaul } else { 36816999Swpaul if ((dbp = yp_open_db(domain, map)) != NULL) { 36995658Sdes if (yp_cache_db(dbp, buf, size)) { 37016999Swpaul (void)(dbp->close)(dbp); 37116999Swpaul yp_errno = YP_YPERR; 37216999Swpaul return(NULL); 37316999Swpaul } 37416999Swpaul } 37515426Swpaul } 37615426Swpaul 37715426Swpaul return (dbp); 37815426Swpaul} 37915426Swpaul#endif 38015426Swpaul 38115426Swpaul/* 38215426Swpaul * Open a DB database. 38315426Swpaul */ 38490298SdesDB * 38590298Sdesyp_open_db(const char *domain, const char *map) 38612891Swpaul{ 38715426Swpaul DB *dbp = NULL; 38815426Swpaul char buf[MAXPATHLEN + 2]; 38912891Swpaul 39012891Swpaul yp_errno = YP_TRUE; 39112891Swpaul 39212891Swpaul if (map[0] == '.' || strchr(map, '/')) { 39312891Swpaul yp_errno = YP_BADARGS; 39412891Swpaul return (NULL); 39512891Swpaul } 39612891Swpaul 39715426Swpaul#ifdef DB_CACHE 39815426Swpaul if (yp_validdomain(domain)) { 39915426Swpaul yp_errno = YP_NODOM; 40015426Swpaul return(NULL); 40115426Swpaul } 40215426Swpaul#endif 40312891Swpaul snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); 40412891Swpaul 40515426Swpaul#ifdef DB_CACHE 40615426Swpaulagain: 40715426Swpaul#endif 40815426Swpaul dbp = dbopen(buf,O_RDONLY, PERM_SECURE, DB_HASH, NULL); 40912891Swpaul 41012891Swpaul if (dbp == NULL) { 41190297Sdes switch (errno) { 41215426Swpaul#ifdef DB_CACHE 41315426Swpaul case ENFILE: 41415426Swpaul /* 41515426Swpaul * We ran out of file descriptors. Nuke an 41615426Swpaul * open one and try again. 41715426Swpaul */ 41815426Swpaul yp_error("ran out of file descriptors"); 41916999Swpaul yp_flush(); 42015426Swpaul goto again; 42115426Swpaul break; 42215426Swpaul#endif 42312891Swpaul case ENOENT: 42412891Swpaul yp_errno = YP_NOMAP; 42512891Swpaul break; 42612891Swpaul case EFTYPE: 42712891Swpaul yp_errno = YP_BADDB; 42812891Swpaul break; 42912891Swpaul default: 43012891Swpaul yp_errno = YP_YPERR; 43112891Swpaul break; 43212891Swpaul } 43312891Swpaul } 43412891Swpaul 43512891Swpaul return (dbp); 43612891Swpaul} 43712891Swpaul 43812891Swpaul/* 43912891Swpaul * Database access routines. 44012891Swpaul * 44112891Swpaul * - yp_get_record(): retrieve an arbitrary key/data pair given one key 44212891Swpaul * to match against. 44312891Swpaul * 44412891Swpaul * - yp_first_record(): retrieve first key/data base in a database. 44590297Sdes * 44612891Swpaul * - yp_next_record(): retrieve key/data pair that sequentially follows 44712891Swpaul * the supplied key value in the database. 44812891Swpaul */ 44912891Swpaul 45020818Swpaul#ifdef DB_CACHE 45190298Sdesint 45290298Sdesyp_get_record(DB *dbp, const DBT *key, DBT *data, int allow) 45320818Swpaul#else 45490298Sdesint 45590298Sdesyp_get_record(const char *domain, const char *map, 45690298Sdes const DBT *key, DBT *data, int allow) 45720818Swpaul#endif 45812891Swpaul{ 45920818Swpaul#ifndef DB_CACHE 46012891Swpaul DB *dbp; 46120818Swpaul#endif 46215426Swpaul int rval = 0; 46316999Swpaul#ifndef DB_CACHE 46416999Swpaul static unsigned char buf[YPMAXRECORD]; 46516999Swpaul#endif 46612891Swpaul 46712997Swpaul if (ypdb_debug) 46830827Scharnier yp_error("looking up key [%.*s]", 46996221Sdes (int)key->size, (char *)key->data); 47012891Swpaul 47112891Swpaul /* 47212891Swpaul * Avoid passing back magic "YP_*" entries unless 47312891Swpaul * the caller specifically requested them by setting 47412891Swpaul * the 'allow' flag. 47512891Swpaul */ 47612891Swpaul if (!allow && !strncmp(key->data, "YP_", 3)) 47712891Swpaul return(YP_NOKEY); 47812891Swpaul 47920818Swpaul#ifndef DB_CACHE 48012891Swpaul if ((dbp = yp_open_db(domain, map)) == NULL) { 48112891Swpaul return(yp_errno); 48212891Swpaul } 48320818Swpaul#endif 48412891Swpaul 48515426Swpaul if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) { 48615426Swpaul#ifdef DB_CACHE 48770493Sphk TAILQ_FIRST(&qhead)->dbptr->size = 0; 48815426Swpaul#else 48912891Swpaul (void)(dbp->close)(dbp); 49015426Swpaul#endif 49113896Swpaul if (rval == 1) 49213896Swpaul return(YP_NOKEY); 49313896Swpaul else 49413896Swpaul return(YP_BADDB); 49512891Swpaul } 49612891Swpaul 49712997Swpaul if (ypdb_debug) 49830827Scharnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 49996221Sdes (int)key->size, (char *)key->data, 50096221Sdes (int)data->size, (char *)data->data); 50112891Swpaul 50215426Swpaul#ifdef DB_CACHE 50370493Sphk if (TAILQ_FIRST(&qhead)->dbptr->size) { 50470493Sphk TAILQ_FIRST(&qhead)->dbptr->key = ""; 50570493Sphk TAILQ_FIRST(&qhead)->dbptr->size = 0; 50615426Swpaul } 50715426Swpaul#else 50895658Sdes bcopy(data->data, &buf, data->size); 50995658Sdes data->data = &buf; 51015426Swpaul (void)(dbp->close)(dbp); 51115426Swpaul#endif 51215426Swpaul 51312891Swpaul return(YP_TRUE); 51412891Swpaul} 51512891Swpaul 51690298Sdesint 51790298Sdesyp_first_record(const DB *dbp, DBT *key, DBT *data, int allow) 51812891Swpaul{ 51913896Swpaul int rval; 52016999Swpaul#ifndef DB_CACHE 52116999Swpaul static unsigned char buf[YPMAXRECORD]; 52216999Swpaul#endif 52312891Swpaul 52412997Swpaul if (ypdb_debug) 52530827Scharnier yp_error("retrieving first key in map"); 52612891Swpaul 52713896Swpaul if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) { 52815426Swpaul#ifdef DB_CACHE 52970493Sphk TAILQ_FIRST(&qhead)->dbptr->size = 0; 53015426Swpaul#endif 53113896Swpaul if (rval == 1) 53213896Swpaul return(YP_NOKEY); 53390297Sdes else 53413896Swpaul return(YP_BADDB); 53513896Swpaul } 53612891Swpaul 53712891Swpaul /* Avoid passing back magic "YP_*" records. */ 53815426Swpaul while (!strncmp(key->data, "YP_", 3) && !allow) { 53913896Swpaul if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) { 54015426Swpaul#ifdef DB_CACHE 54170493Sphk TAILQ_FIRST(&qhead)->dbptr->size = 0; 54215426Swpaul#endif 54313896Swpaul if (rval == 1) 54413896Swpaul return(YP_NOKEY); 54513896Swpaul else 54613896Swpaul return(YP_BADDB); 54713896Swpaul } 54812891Swpaul } 54912891Swpaul 55012997Swpaul if (ypdb_debug) 55130827Scharnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 55296221Sdes (int)key->size, (char *)key->data, 55396221Sdes (int)data->size, (char *)data->data); 55412891Swpaul 55515426Swpaul#ifdef DB_CACHE 55670493Sphk if (TAILQ_FIRST(&qhead)->dbptr->size) { 55770493Sphk TAILQ_FIRST(&qhead)->dbptr->key = key->data; 55870493Sphk TAILQ_FIRST(&qhead)->dbptr->size = key->size; 55915426Swpaul } 56016999Swpaul#else 56195658Sdes bcopy(data->data, &buf, data->size); 56295658Sdes data->data = &buf; 56315426Swpaul#endif 56415426Swpaul 56512891Swpaul return(YP_TRUE); 56612891Swpaul} 56712891Swpaul 56890298Sdesint 56990298Sdesyp_next_record(const DB *dbp, DBT *key, DBT *data, int all, int allow) 57012891Swpaul{ 57115426Swpaul static DBT lkey = { NULL, 0 }; 57215426Swpaul static DBT ldata = { NULL, 0 }; 57313896Swpaul int rval; 57416999Swpaul#ifndef DB_CACHE 57516999Swpaul static unsigned char keybuf[YPMAXRECORD]; 57616999Swpaul static unsigned char datbuf[YPMAXRECORD]; 57716999Swpaul#endif 57812891Swpaul 57920818Swpaul if (key == NULL || !key->size || key->data == NULL) { 58015426Swpaul rval = yp_first_record(dbp,key,data,allow); 58113896Swpaul if (rval == YP_NOKEY) 58213896Swpaul return(YP_NOMORE); 58321882Swpaul else { 58421882Swpaul#ifdef DB_CACHE 58570493Sphk TAILQ_FIRST(&qhead)->dbptr->key = key->data; 58670493Sphk TAILQ_FIRST(&qhead)->dbptr->size = key->size; 58721882Swpaul#endif 58813896Swpaul return(rval); 58921882Swpaul } 59013896Swpaul } 59112891Swpaul 59212997Swpaul if (ypdb_debug) 59330827Scharnier yp_error("retrieving next key, previous was: [%.*s]", 59496221Sdes (int)key->size, (char *)key->data); 59512891Swpaul 59612891Swpaul if (!all) { 59716118Swpaul#ifdef DB_CACHE 59870493Sphk if (TAILQ_FIRST(&qhead)->dbptr->key == NULL) { 59915426Swpaul#endif 60015426Swpaul (dbp->seq)(dbp,&lkey,&ldata,R_FIRST); 60145671Swpaul while (key->size != lkey.size || 60295658Sdes strncmp(key->data, lkey.data, 60345671Swpaul (int)key->size)) 60416118Swpaul if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) { 60516118Swpaul#ifdef DB_CACHE 60670493Sphk TAILQ_FIRST(&qhead)->dbptr->size = 0; 60716118Swpaul#endif 60816118Swpaul return(YP_NOKEY); 60916118Swpaul } 61016118Swpaul 61190297Sdes#ifdef DB_CACHE 61215426Swpaul } 61316118Swpaul#endif 61412891Swpaul } 61512891Swpaul 61615426Swpaul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 61715426Swpaul#ifdef DB_CACHE 61870493Sphk TAILQ_FIRST(&qhead)->dbptr->size = 0; 61915426Swpaul#endif 62012891Swpaul return(YP_NOMORE); 62115426Swpaul } 62212891Swpaul 62312891Swpaul /* Avoid passing back magic "YP_*" records. */ 62415426Swpaul while (!strncmp(key->data, "YP_", 3) && !allow) 62515426Swpaul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 62615426Swpaul#ifdef DB_CACHE 62770493Sphk TAILQ_FIRST(&qhead)->dbptr->size = 0; 62815426Swpaul#endif 62912891Swpaul return(YP_NOMORE); 63015426Swpaul } 63112891Swpaul 63212997Swpaul if (ypdb_debug) 63330827Scharnier yp_error("result of lookup: key: [%.*s] data: [%.*s]", 63496221Sdes (int)key->size, (char *)key->data, 63596221Sdes (int)data->size, (char *)data->data); 63612891Swpaul 63715426Swpaul#ifdef DB_CACHE 63870493Sphk if (TAILQ_FIRST(&qhead)->dbptr->size) { 63970493Sphk TAILQ_FIRST(&qhead)->dbptr->key = key->data; 64070493Sphk TAILQ_FIRST(&qhead)->dbptr->size = key->size; 64115426Swpaul } 64215426Swpaul#else 64395658Sdes bcopy(key->data, &keybuf, key->size); 64495658Sdes lkey.data = &keybuf; 64515426Swpaul lkey.size = key->size; 64695658Sdes bcopy(data->data, &datbuf, data->size); 64795658Sdes data->data = &datbuf; 64815426Swpaul#endif 64915426Swpaul 65012891Swpaul return(YP_TRUE); 65112891Swpaul} 65220818Swpaul 65320818Swpaul#ifdef DB_CACHE 65420818Swpaul/* 65520818Swpaul * Database glue functions. 65620818Swpaul */ 65720818Swpaul 65820818Swpaulstatic DB *yp_currmap_db = NULL; 65920818Swpaulstatic int yp_allow_db = 0; 66020818Swpaul 66190298Sdesypstat 66290298Sdesyp_select_map(char *map, char *domain, keydat *key, int allow) 66320818Swpaul{ 66433250Swpaul if (key == NULL) 66533250Swpaul yp_currmap_db = yp_open_db_cache(domain, map, NULL, 0); 66633250Swpaul else 66733250Swpaul yp_currmap_db = yp_open_db_cache(domain, map, 66833250Swpaul key->keydat_val, 66933250Swpaul key->keydat_len); 67020818Swpaul 67120818Swpaul yp_allow_db = allow; 67220818Swpaul return(yp_errno); 67320818Swpaul} 67420818Swpaul 67590298Sdesypstat 67690298Sdesyp_getbykey(keydat *key, valdat *val) 67720818Swpaul{ 67820818Swpaul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 67920818Swpaul ypstat rval; 68020818Swpaul 68120818Swpaul db_key.data = key->keydat_val; 68220818Swpaul db_key.size = key->keydat_len; 68320818Swpaul 68420818Swpaul rval = yp_get_record(yp_currmap_db, 68520818Swpaul &db_key, &db_val, yp_allow_db); 68620818Swpaul 68720818Swpaul if (rval == YP_TRUE) { 68820818Swpaul val->valdat_val = db_val.data; 68920818Swpaul val->valdat_len = db_val.size; 69020818Swpaul } 69120818Swpaul 69220818Swpaul return(rval); 69320818Swpaul} 69420818Swpaul 69590298Sdesypstat 69690298Sdesyp_firstbykey(keydat *key, valdat *val) 69720818Swpaul{ 69820818Swpaul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 69920818Swpaul ypstat rval; 70020818Swpaul 70120818Swpaul rval = yp_first_record(yp_currmap_db, &db_key, &db_val, yp_allow_db); 70220818Swpaul 70320818Swpaul if (rval == YP_TRUE) { 70420818Swpaul key->keydat_val = db_key.data; 70520818Swpaul key->keydat_len = db_key.size; 70620818Swpaul val->valdat_val = db_val.data; 70720818Swpaul val->valdat_len = db_val.size; 70820818Swpaul } 70920818Swpaul 71020818Swpaul return(rval); 71120818Swpaul} 71220818Swpaul 71390298Sdesypstat 71490298Sdesyp_nextbykey(keydat *key, valdat *val) 71520818Swpaul{ 71620818Swpaul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 71720818Swpaul ypstat rval; 71820818Swpaul 71920818Swpaul db_key.data = key->keydat_val; 72020818Swpaul db_key.size = key->keydat_len; 72120818Swpaul 72220818Swpaul rval = yp_next_record(yp_currmap_db, &db_key, &db_val, 0, yp_allow_db); 72320818Swpaul 72420818Swpaul if (rval == YP_TRUE) { 72520818Swpaul key->keydat_val = db_key.data; 72620818Swpaul key->keydat_len = db_key.size; 72720818Swpaul val->valdat_val = db_val.data; 72820818Swpaul val->valdat_len = db_val.size; 72920818Swpaul } 73020818Swpaul 73120818Swpaul return(rval); 73220818Swpaul} 73320818Swpaul#endif 734