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 * 321130b656SJordan K. Hubbard * $FreeBSD$ 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 501130b656SJordan K. Hubbard static const char rcsid[] = "$FreeBSD$"; 511fbdac93SBill Paul #endif 521fbdac93SBill Paul 5377732bc5SBill Paul int ypdb_debug = 0; 54180807d2SBill Paul enum ypstat 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 */ 60b3e93234SBill Paul 256, /* nelem */ 61b2264be8SBill Paul 2048 * 512, /* cachesize */ 62778c7b1cSBill Paul NULL, /* hash */ 63778c7b1cSBill Paul 0, /* lorder */ 64778c7b1cSBill Paul }; 65778c7b1cSBill Paul 66b2264be8SBill Paul #ifdef DB_CACHE 6779acf67fSBill Paul #include <sys/queue.h> 6879acf67fSBill Paul 6979acf67fSBill Paul #ifndef MAXDBS 70b2264be8SBill Paul #define MAXDBS 20 7179acf67fSBill Paul #endif 7279acf67fSBill Paul 7379acf67fSBill Paul static int numdbs = 0; 74b2264be8SBill Paul 75b2264be8SBill Paul struct dbent { 76b2264be8SBill Paul DB *dbp; 77b2264be8SBill Paul char *name; 78b2264be8SBill Paul char *key; 79b2264be8SBill Paul int size; 8044519760SBill Paul int flags; 81b2264be8SBill Paul }; 82b2264be8SBill Paul 8379acf67fSBill Paul static CIRCLEQ_HEAD(circlehead, circleq_entry) qhead; 8479acf67fSBill Paul 8579acf67fSBill Paul struct circleq_entry { 8679acf67fSBill Paul struct dbent *dbptr; 8779acf67fSBill Paul CIRCLEQ_ENTRY(circleq_entry) links; 8879acf67fSBill Paul }; 89b2264be8SBill Paul 90778c7b1cSBill Paul /* 9179acf67fSBill Paul * Initialize the circular queue. 92b2264be8SBill Paul */ 93b2264be8SBill Paul void yp_init_dbs() 94b2264be8SBill Paul { 9579acf67fSBill Paul CIRCLEQ_INIT(&qhead); 96b2264be8SBill Paul return; 97b2264be8SBill Paul } 98b2264be8SBill Paul 991fbdac93SBill Paul /* 10079acf67fSBill Paul * Dynamically allocate an entry for the circular queue. 10179acf67fSBill Paul * Return a NULL pointer on failure. 1021fbdac93SBill Paul */ 10379acf67fSBill Paul static struct circleq_entry *yp_malloc_qent() 104b2264be8SBill Paul { 10579acf67fSBill Paul register struct circleq_entry *q; 10679acf67fSBill Paul 10779acf67fSBill Paul q = (struct circleq_entry *)malloc(sizeof(struct circleq_entry)); 10879acf67fSBill Paul if (q == NULL) { 10979acf67fSBill Paul yp_error("failed to malloc() circleq entry: %s", 11079acf67fSBill Paul strerror(errno)); 11179acf67fSBill Paul return(NULL); 11279acf67fSBill Paul } 11379acf67fSBill Paul bzero((char *)q, sizeof(struct circleq_entry)); 11479acf67fSBill Paul q->dbptr = (struct dbent *)malloc(sizeof(struct dbent)); 11579acf67fSBill Paul if (q->dbptr == NULL) { 11679acf67fSBill Paul yp_error("failed to malloc() circleq entry: %s", 11779acf67fSBill Paul strerror(errno)); 11879acf67fSBill Paul free(q); 11979acf67fSBill Paul return(NULL); 12079acf67fSBill Paul } 12179acf67fSBill Paul bzero((char *)q->dbptr, sizeof(struct dbent)); 12279acf67fSBill Paul 12379acf67fSBill Paul return(q); 124b2264be8SBill Paul } 125b2264be8SBill Paul 126b2264be8SBill Paul /* 12779acf67fSBill Paul * Free a previously allocated circular queue 12879acf67fSBill Paul * entry. 12979acf67fSBill Paul */ 13079acf67fSBill Paul static void yp_free_qent(q) 13179acf67fSBill Paul struct circleq_entry *q; 13279acf67fSBill Paul { 13379acf67fSBill Paul /* 13479acf67fSBill Paul * First, close the database. In theory, this is also 13579acf67fSBill Paul * supposed to free the resources allocated by the DB 13679acf67fSBill Paul * package, including the memory pointed to by q->dbptr->key. 13779acf67fSBill Paul * This means we don't have to free q->dbptr->key here. 13879acf67fSBill Paul */ 13979acf67fSBill Paul if (q->dbptr->dbp) { 14079acf67fSBill Paul (void)(q->dbptr->dbp->close)(q->dbptr->dbp); 14179acf67fSBill Paul q->dbptr->dbp = NULL; 14279acf67fSBill Paul } 14379acf67fSBill Paul /* 14479acf67fSBill Paul * Then free the database name, which was strdup()'ed. 14579acf67fSBill Paul */ 14679acf67fSBill Paul free(q->dbptr->name); 14779acf67fSBill Paul 14879acf67fSBill Paul /* 14979acf67fSBill Paul * Free the rest of the dbent struct. 15079acf67fSBill Paul */ 15179acf67fSBill Paul free(q->dbptr); 15279acf67fSBill Paul q->dbptr = NULL; 15379acf67fSBill Paul 15479acf67fSBill Paul /* 15579acf67fSBill Paul * Free the circleq struct. 15679acf67fSBill Paul */ 15779acf67fSBill Paul free(q); 15879acf67fSBill Paul q = NULL; 15979acf67fSBill Paul 16079acf67fSBill Paul return; 16179acf67fSBill Paul } 16279acf67fSBill Paul 16379acf67fSBill Paul /* 16479acf67fSBill Paul * Zorch a single entry in the dbent queue and release 16579acf67fSBill Paul * all its resources. (This always removes the last entry 16679acf67fSBill Paul * in the queue.) 16779acf67fSBill Paul */ 16879acf67fSBill Paul static void yp_flush() 16979acf67fSBill Paul { 17079acf67fSBill Paul register struct circleq_entry *qptr; 17179acf67fSBill Paul 17279acf67fSBill Paul qptr = qhead.cqh_last; 17379acf67fSBill Paul CIRCLEQ_REMOVE(&qhead, qptr, links); 17479acf67fSBill Paul yp_free_qent(qptr); 17579acf67fSBill Paul numdbs--; 17679acf67fSBill Paul 17779acf67fSBill Paul return; 17879acf67fSBill Paul } 17979acf67fSBill Paul 18079acf67fSBill Paul /* 18179acf67fSBill Paul * Close all databases, erase all database names and empty the queue. 182b2264be8SBill Paul */ 183b2264be8SBill Paul void yp_flush_all() 184b2264be8SBill Paul { 18579acf67fSBill Paul register struct circleq_entry *qptr; 186b2264be8SBill Paul 18779acf67fSBill Paul while(qhead.cqh_first != (void *)&qhead) { 18879acf67fSBill Paul qptr = qhead.cqh_first; /* save this */ 18979acf67fSBill Paul CIRCLEQ_REMOVE(&qhead, qhead.cqh_first, links); 19079acf67fSBill Paul yp_free_qent(qptr); 191b2264be8SBill Paul } 19279acf67fSBill Paul numdbs = 0; 19379acf67fSBill Paul 19479acf67fSBill Paul return; 195b2264be8SBill Paul } 196b2264be8SBill Paul 19744519760SBill Paul static char *inter_string = "YP_INTERDOMAIN"; 19844519760SBill Paul static char *secure_string = "YP_SECURE"; 19944519760SBill Paul static int inter_sz = sizeof("YP_INTERDOMAIN") - 1; 20044519760SBill Paul static int secure_sz = sizeof("YP_SECURE") - 1; 20144519760SBill Paul 20244519760SBill Paul static int yp_setflags(dbp) 20344519760SBill Paul DB *dbp; 20444519760SBill Paul { 20544519760SBill Paul DBT key = { NULL, 0 }, data = { NULL, 0 }; 20644519760SBill Paul int flags = 0; 20744519760SBill Paul 20844519760SBill Paul key.data = inter_string; 20944519760SBill Paul key.size = inter_sz; 21044519760SBill Paul 21144519760SBill Paul if (!(dbp->get)(dbp, &key, &data, 0)) 21244519760SBill Paul flags |= YP_INTERDOMAIN; 21344519760SBill Paul 21444519760SBill Paul key.data = secure_string; 21544519760SBill Paul key.size = secure_sz; 21644519760SBill Paul 21744519760SBill Paul if (!(dbp->get)(dbp, &key, &data, 0)) 21844519760SBill Paul flags |= YP_SECURE; 21944519760SBill Paul 22044519760SBill Paul return(flags); 22144519760SBill Paul } 22244519760SBill Paul 22344519760SBill Paul int yp_testflag(map, domain, flag) 22444519760SBill Paul char *map; 22544519760SBill Paul char *domain; 22644519760SBill Paul int flag; 22744519760SBill Paul { 22844519760SBill Paul char buf[MAXPATHLEN + 2]; 22944519760SBill Paul register struct circleq_entry *qptr; 23044519760SBill Paul 23144519760SBill Paul if (map == NULL || domain == NULL) 23244519760SBill Paul return(0); 23344519760SBill Paul 23444519760SBill Paul strcpy(buf, domain); 23544519760SBill Paul strcat(buf, "/"); 23644519760SBill Paul strcat(buf, map); 23744519760SBill Paul 23844519760SBill Paul for (qptr = qhead.cqh_first; qptr != (void *)&qhead; 23944519760SBill Paul qptr = qptr->links.cqe_next) { 24044519760SBill Paul if (!strcmp(qptr->dbptr->name, buf)) { 24144519760SBill Paul if (qptr->dbptr->flags & flag) 24244519760SBill Paul return(1); 24344519760SBill Paul else 24444519760SBill Paul return(0); 24544519760SBill Paul } 24644519760SBill Paul } 24744519760SBill Paul 24844519760SBill Paul if (yp_open_db_cache(domain, map, NULL, 0) == NULL) 24944519760SBill Paul return(0); 25044519760SBill Paul 25144519760SBill Paul if (qhead.cqh_first->dbptr->flags & flag) 25244519760SBill Paul return(1); 25344519760SBill Paul 25444519760SBill Paul return(0); 25544519760SBill Paul } 256b2264be8SBill Paul 257b2264be8SBill Paul /* 258b2264be8SBill Paul * Add a DB handle and database name to the cache. We only maintain 259b2264be8SBill Paul * fixed number of entries in the cache, so if we're asked to store 260b2264be8SBill Paul * a new entry when all our slots are already filled, we have to kick 261b2264be8SBill Paul * out the entry in the last slot to make room. 262b2264be8SBill Paul */ 26379acf67fSBill Paul static int yp_cache_db(dbp, name, size) 264b2264be8SBill Paul DB *dbp; 265b2264be8SBill Paul char *name; 266b2264be8SBill Paul int size; 267b2264be8SBill Paul { 26879acf67fSBill Paul register struct circleq_entry *qptr; 269b2264be8SBill Paul 27079acf67fSBill Paul if (numdbs == MAXDBS) { 271b2264be8SBill Paul if (ypdb_debug) 27279acf67fSBill Paul yp_error("queue overflow -- releasing last slot"); 27379acf67fSBill Paul yp_flush(); 274b2264be8SBill Paul } 275b2264be8SBill Paul 276b2264be8SBill Paul /* 27779acf67fSBill Paul * Allocate a new queue entry. 278b2264be8SBill Paul */ 27979acf67fSBill Paul 28079acf67fSBill Paul if ((qptr = yp_malloc_qent()) == NULL) { 28179acf67fSBill Paul yp_error("failed to allocate a new cache entry"); 28279acf67fSBill Paul return(1); 283b2264be8SBill Paul } 284b2264be8SBill Paul 28579acf67fSBill Paul qptr->dbptr->dbp = dbp; 28679acf67fSBill Paul qptr->dbptr->name = strdup(name); 28779acf67fSBill Paul qptr->dbptr->size = size; 28879acf67fSBill Paul qptr->dbptr->key = NULL; 28979acf67fSBill Paul 29044519760SBill Paul qptr->dbptr->flags = yp_setflags(dbp); 29144519760SBill Paul 29279acf67fSBill Paul CIRCLEQ_INSERT_HEAD(&qhead, qptr, links); 293b2264be8SBill Paul numdbs++; 29479acf67fSBill Paul 29579acf67fSBill Paul return(0); 296b2264be8SBill Paul } 297b2264be8SBill Paul 298b2264be8SBill Paul /* 299b2264be8SBill Paul * Search the list for a database matching 'name.' If we find it, 300b2264be8SBill Paul * move it to the head of the list and return its DB handle. If 301b2264be8SBill Paul * not, just fail: yp_open_db_cache() will subsequently try to open 30279acf67fSBill Paul * the database itself and call yp_cache_db() to add it to the 303b2264be8SBill Paul * list. 304b2264be8SBill Paul * 305b2264be8SBill Paul * The search works like this: 306b2264be8SBill Paul * 307b2264be8SBill Paul * - The caller specifies the name of a database to locate. We try to 30879acf67fSBill Paul * find an entry in our queue with a matching name. 309b2264be8SBill Paul * 310b2264be8SBill Paul * - If the caller doesn't specify a key or size, we assume that the 311b2264be8SBill Paul * first entry that we encounter with a matching name is returned. 31279acf67fSBill Paul * This will result in matches regardless of the key/size values 31379acf67fSBill Paul * stored in the queue entry. 314b2264be8SBill Paul * 31579acf67fSBill Paul * - If the caller also specifies a key and length, we check to see 31679acf67fSBill Paul * if the key and length saved in the queue entry also matches. 317b2264be8SBill Paul * This lets us return a DB handle that's already positioned at the 318b2264be8SBill Paul * correct location within a database. 319b2264be8SBill Paul * 32079acf67fSBill Paul * - Once we have a match, it gets migrated to the top of the queue 32179acf67fSBill Paul * so that it will be easier to find if another request for 322b2264be8SBill Paul * the same database comes in later. 323b2264be8SBill Paul */ 324b3e93234SBill Paul static DB *yp_find_db(name, key, size) 325b2264be8SBill Paul char *name; 326b2264be8SBill Paul char *key; 3271fbdac93SBill Paul int size; 328b2264be8SBill Paul { 32979acf67fSBill Paul register struct circleq_entry *qptr; 330b2264be8SBill Paul 33179acf67fSBill Paul for (qptr = qhead.cqh_first; qptr != (void *)&qhead; 33279acf67fSBill Paul qptr = qptr->links.cqe_next) { 33379acf67fSBill Paul if (!strcmp(qptr->dbptr->name, name)) { 334b2264be8SBill Paul if (size) { 33579acf67fSBill Paul if (size != qptr->dbptr->size || 33679acf67fSBill Paul strncmp(qptr->dbptr->key, key, size)) 337b2264be8SBill Paul continue; 338b2264be8SBill Paul } else { 33979acf67fSBill Paul if (qptr->dbptr->size) 340b2264be8SBill Paul continue; 341b2264be8SBill Paul } 34279acf67fSBill Paul if (qptr != qhead.cqh_first) { 34379acf67fSBill Paul CIRCLEQ_REMOVE(&qhead, qptr, links); 34479acf67fSBill Paul CIRCLEQ_INSERT_HEAD(&qhead, qptr, links); 345b2264be8SBill Paul } 34679acf67fSBill Paul return(qptr->dbptr->dbp); 347b2264be8SBill Paul } 348b2264be8SBill Paul } 349b3e93234SBill Paul 350b2264be8SBill Paul return(NULL); 351b2264be8SBill Paul } 352b2264be8SBill Paul 353b2264be8SBill Paul /* 354b2264be8SBill Paul * Open a DB database and cache the handle for later use. We first 355b2264be8SBill Paul * check the cache to see if the required database is already open. 356b2264be8SBill Paul * If so, we fetch the handle from the cache. If not, we try to open 357b2264be8SBill Paul * the database and save the handle in the cache for later use. 358b2264be8SBill Paul */ 359b2264be8SBill Paul DB *yp_open_db_cache(domain, map, key, size) 360b2264be8SBill Paul const char *domain; 361b2264be8SBill Paul const char *map; 362b2264be8SBill Paul const char *key; 363b2264be8SBill Paul const int size; 364b2264be8SBill Paul { 365b2264be8SBill Paul DB *dbp = NULL; 366b2264be8SBill Paul char buf[MAXPATHLEN + 2]; 367b3e93234SBill Paul /* 368b3e93234SBill Paul snprintf(buf, sizeof(buf), "%s/%s", domain, map); 369b3e93234SBill Paul */ 37079acf67fSBill Paul yp_errno = YP_TRUE; 371b2264be8SBill Paul 3721fbdac93SBill Paul strcpy(buf, domain); 3731fbdac93SBill Paul strcat(buf, "/"); 3741fbdac93SBill Paul strcat(buf, map); 375b2264be8SBill Paul 376b2264be8SBill Paul if ((dbp = yp_find_db((char *)&buf, key, size)) != NULL) { 377b2264be8SBill Paul return(dbp); 378b2264be8SBill Paul } else { 37979acf67fSBill Paul if ((dbp = yp_open_db(domain, map)) != NULL) { 38079acf67fSBill Paul if (yp_cache_db(dbp, (char *)&buf, size)) { 38179acf67fSBill Paul (void)(dbp->close)(dbp); 38279acf67fSBill Paul yp_errno = YP_YPERR; 38379acf67fSBill Paul return(NULL); 38479acf67fSBill Paul } 38579acf67fSBill Paul } 386b2264be8SBill Paul } 387b2264be8SBill Paul 388b2264be8SBill Paul return (dbp); 389b2264be8SBill Paul } 390b2264be8SBill Paul #endif 391b2264be8SBill Paul 392b2264be8SBill Paul /* 393b2264be8SBill Paul * Open a DB database. 394778c7b1cSBill Paul */ 395778c7b1cSBill Paul DB *yp_open_db(domain, map) 396778c7b1cSBill Paul const char *domain; 397778c7b1cSBill Paul const char *map; 398778c7b1cSBill Paul { 399b2264be8SBill Paul DB *dbp = NULL; 400b2264be8SBill Paul char buf[MAXPATHLEN + 2]; 401778c7b1cSBill Paul 402778c7b1cSBill Paul yp_errno = YP_TRUE; 403778c7b1cSBill Paul 404778c7b1cSBill Paul if (map[0] == '.' || strchr(map, '/')) { 405778c7b1cSBill Paul yp_errno = YP_BADARGS; 406778c7b1cSBill Paul return (NULL); 407778c7b1cSBill Paul } 408778c7b1cSBill Paul 409b2264be8SBill Paul #ifdef DB_CACHE 410b2264be8SBill Paul if (yp_validdomain(domain)) { 411b2264be8SBill Paul yp_errno = YP_NODOM; 412b2264be8SBill Paul return(NULL); 413b2264be8SBill Paul } 414b2264be8SBill Paul #endif 415778c7b1cSBill Paul snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); 416778c7b1cSBill Paul 417b2264be8SBill Paul #ifdef DB_CACHE 418b2264be8SBill Paul again: 419b2264be8SBill Paul #endif 420b2264be8SBill Paul dbp = dbopen(buf,O_RDONLY, PERM_SECURE, DB_HASH, NULL); 421778c7b1cSBill Paul 422778c7b1cSBill Paul if (dbp == NULL) { 423778c7b1cSBill Paul switch(errno) { 424b2264be8SBill Paul #ifdef DB_CACHE 425b2264be8SBill Paul case ENFILE: 426b2264be8SBill Paul /* 427b2264be8SBill Paul * We ran out of file descriptors. Nuke an 428b2264be8SBill Paul * open one and try again. 429b2264be8SBill Paul */ 430b2264be8SBill Paul yp_error("ran out of file descriptors"); 43179acf67fSBill Paul yp_flush(); 432b2264be8SBill Paul goto again; 433b2264be8SBill Paul break; 434b2264be8SBill Paul #endif 435778c7b1cSBill Paul case ENOENT: 436778c7b1cSBill Paul yp_errno = YP_NOMAP; 437778c7b1cSBill Paul break; 438778c7b1cSBill Paul case EFTYPE: 439778c7b1cSBill Paul yp_errno = YP_BADDB; 440778c7b1cSBill Paul break; 441778c7b1cSBill Paul default: 442778c7b1cSBill Paul yp_errno = YP_YPERR; 443778c7b1cSBill Paul break; 444778c7b1cSBill Paul } 445778c7b1cSBill Paul } 446778c7b1cSBill Paul 447778c7b1cSBill Paul return (dbp); 448778c7b1cSBill Paul } 449778c7b1cSBill Paul 450778c7b1cSBill Paul /* 451778c7b1cSBill Paul * Database access routines. 452778c7b1cSBill Paul * 453778c7b1cSBill Paul * - yp_get_record(): retrieve an arbitrary key/data pair given one key 454778c7b1cSBill Paul * to match against. 455778c7b1cSBill Paul * 456778c7b1cSBill Paul * - yp_first_record(): retrieve first key/data base in a database. 457778c7b1cSBill Paul * 458778c7b1cSBill Paul * - yp_next_record(): retrieve key/data pair that sequentially follows 459778c7b1cSBill Paul * the supplied key value in the database. 460778c7b1cSBill Paul */ 461778c7b1cSBill Paul 462180807d2SBill Paul #ifdef DB_CACHE 463180807d2SBill Paul int yp_get_record(dbp,key,data,allow) 464180807d2SBill Paul DB *dbp; 465180807d2SBill Paul #else 466778c7b1cSBill Paul int yp_get_record(domain,map,key,data,allow) 467778c7b1cSBill Paul const char *domain; 468778c7b1cSBill Paul const char *map; 469180807d2SBill Paul #endif 470778c7b1cSBill Paul const DBT *key; 471778c7b1cSBill Paul DBT *data; 472778c7b1cSBill Paul int allow; 473778c7b1cSBill Paul { 474180807d2SBill Paul #ifndef DB_CACHE 475778c7b1cSBill Paul DB *dbp; 476180807d2SBill Paul #endif 477b2264be8SBill Paul int rval = 0; 47879acf67fSBill Paul #ifndef DB_CACHE 47979acf67fSBill Paul static unsigned char buf[YPMAXRECORD]; 48079acf67fSBill Paul #endif 481778c7b1cSBill Paul 48277732bc5SBill Paul if (ypdb_debug) 483180807d2SBill Paul yp_error("Looking up key [%.*s]", 484180807d2SBill Paul key->size, key->data); 485778c7b1cSBill Paul 486778c7b1cSBill Paul /* 487778c7b1cSBill Paul * Avoid passing back magic "YP_*" entries unless 488778c7b1cSBill Paul * the caller specifically requested them by setting 489778c7b1cSBill Paul * the 'allow' flag. 490778c7b1cSBill Paul */ 491778c7b1cSBill Paul if (!allow && !strncmp(key->data, "YP_", 3)) 492778c7b1cSBill Paul return(YP_NOKEY); 493778c7b1cSBill Paul 494180807d2SBill Paul #ifndef DB_CACHE 495778c7b1cSBill Paul if ((dbp = yp_open_db(domain, map)) == NULL) { 496778c7b1cSBill Paul return(yp_errno); 497778c7b1cSBill Paul } 498180807d2SBill Paul #endif 499778c7b1cSBill Paul 500920491cfSBill Paul if ((rval = (dbp->get)(dbp, key, data, 0)) != 0) { 501b2264be8SBill Paul #ifdef DB_CACHE 50279acf67fSBill Paul qhead.cqh_first->dbptr->size = 0; 503b2264be8SBill Paul #else 504778c7b1cSBill Paul (void)(dbp->close)(dbp); 505b2264be8SBill Paul #endif 506920491cfSBill Paul if (rval == 1) 507778c7b1cSBill Paul return(YP_NOKEY); 508920491cfSBill Paul else 509920491cfSBill Paul return(YP_BADDB); 510778c7b1cSBill Paul } 511778c7b1cSBill Paul 51277732bc5SBill Paul if (ypdb_debug) 513778c7b1cSBill Paul yp_error("Result of lookup: key: [%.*s] data: [%.*s]", 514778c7b1cSBill Paul key->size, key->data, data->size, data->data); 515778c7b1cSBill Paul 516b2264be8SBill Paul #ifdef DB_CACHE 51779acf67fSBill Paul if (qhead.cqh_first->dbptr->size) { 51879acf67fSBill Paul qhead.cqh_first->dbptr->key = key->data; 51979acf67fSBill Paul qhead.cqh_first->dbptr->size = key->size; 520b2264be8SBill Paul } 521b2264be8SBill Paul #else 52279acf67fSBill Paul bcopy((char *)data->data, (char *)&buf, data->size); 52379acf67fSBill Paul data->data = (void *)&buf; 524b2264be8SBill Paul (void)(dbp->close)(dbp); 525b2264be8SBill Paul #endif 526b2264be8SBill Paul 527778c7b1cSBill Paul return(YP_TRUE); 528778c7b1cSBill Paul } 529778c7b1cSBill Paul 530b2264be8SBill Paul int yp_first_record(dbp,key,data,allow) 531778c7b1cSBill Paul const DB *dbp; 532778c7b1cSBill Paul DBT *key; 533778c7b1cSBill Paul DBT *data; 534b2264be8SBill Paul int allow; 535778c7b1cSBill Paul { 536920491cfSBill Paul int rval; 53779acf67fSBill Paul #ifndef DB_CACHE 53879acf67fSBill Paul static unsigned char buf[YPMAXRECORD]; 53979acf67fSBill Paul #endif 540778c7b1cSBill Paul 54177732bc5SBill Paul if (ypdb_debug) 542778c7b1cSBill Paul yp_error("Retrieving first key in map."); 543778c7b1cSBill Paul 544920491cfSBill Paul if ((rval = (dbp->seq)(dbp,key,data,R_FIRST)) != 0) { 545b2264be8SBill Paul #ifdef DB_CACHE 54679acf67fSBill Paul qhead.cqh_first->dbptr->size = 0; 547b2264be8SBill Paul #endif 548920491cfSBill Paul if (rval == 1) 549920491cfSBill Paul return(YP_NOKEY); 550920491cfSBill Paul else 551778c7b1cSBill Paul return(YP_BADDB); 552920491cfSBill Paul } 553778c7b1cSBill Paul 554778c7b1cSBill Paul /* Avoid passing back magic "YP_*" records. */ 555b2264be8SBill Paul while (!strncmp(key->data, "YP_", 3) && !allow) { 556920491cfSBill Paul if ((rval = (dbp->seq)(dbp,key,data,R_NEXT)) != 0) { 557b2264be8SBill Paul #ifdef DB_CACHE 55879acf67fSBill Paul qhead.cqh_first->dbptr->size = 0; 559b2264be8SBill Paul #endif 560920491cfSBill Paul if (rval == 1) 561920491cfSBill Paul return(YP_NOKEY); 562920491cfSBill Paul else 563778c7b1cSBill Paul return(YP_BADDB); 564778c7b1cSBill Paul } 565920491cfSBill Paul } 566778c7b1cSBill Paul 56777732bc5SBill Paul if (ypdb_debug) 568778c7b1cSBill Paul yp_error("Result of lookup: key: [%.*s] data: [%.*s]", 569778c7b1cSBill Paul key->size, key->data, data->size, data->data); 570778c7b1cSBill Paul 571b2264be8SBill Paul #ifdef DB_CACHE 57279acf67fSBill Paul if (qhead.cqh_first->dbptr->size) { 57379acf67fSBill Paul qhead.cqh_first->dbptr->key = key->data; 57479acf67fSBill Paul qhead.cqh_first->dbptr->size = key->size; 575b2264be8SBill Paul } 57679acf67fSBill Paul #else 57779acf67fSBill Paul bcopy((char *)data->data, (char *)&buf, data->size); 57879acf67fSBill Paul data->data = (void *)&buf; 579b2264be8SBill Paul #endif 580b2264be8SBill Paul 581778c7b1cSBill Paul return(YP_TRUE); 582778c7b1cSBill Paul } 583778c7b1cSBill Paul 584b2264be8SBill Paul int yp_next_record(dbp,key,data,all,allow) 585778c7b1cSBill Paul const DB *dbp; 586778c7b1cSBill Paul DBT *key; 587778c7b1cSBill Paul DBT *data; 588778c7b1cSBill Paul int all; 589b2264be8SBill Paul int allow; 590778c7b1cSBill Paul { 591b2264be8SBill Paul static DBT lkey = { NULL, 0 }; 592b2264be8SBill Paul static DBT ldata = { NULL, 0 }; 593920491cfSBill Paul int rval; 59479acf67fSBill Paul #ifndef DB_CACHE 59579acf67fSBill Paul static unsigned char keybuf[YPMAXRECORD]; 59679acf67fSBill Paul static unsigned char datbuf[YPMAXRECORD]; 59779acf67fSBill Paul #endif 598778c7b1cSBill Paul 599180807d2SBill Paul if (key == NULL || !key->size || key->data == NULL) { 600b2264be8SBill Paul rval = yp_first_record(dbp,key,data,allow); 601920491cfSBill Paul if (rval == YP_NOKEY) 602920491cfSBill Paul return(YP_NOMORE); 603559605f1SBill Paul else { 604559605f1SBill Paul #ifdef DB_CACHE 605559605f1SBill Paul qhead.cqh_first->dbptr->key = key->data; 606559605f1SBill Paul qhead.cqh_first->dbptr->size = key->size; 607559605f1SBill Paul #endif 608920491cfSBill Paul return(rval); 609920491cfSBill Paul } 610559605f1SBill Paul } 611778c7b1cSBill Paul 61277732bc5SBill Paul if (ypdb_debug) 613778c7b1cSBill Paul yp_error("Retreiving next key, previous was: [%.*s]", 614778c7b1cSBill Paul key->size, key->data); 615778c7b1cSBill Paul 616778c7b1cSBill Paul if (!all) { 617b3e93234SBill Paul #ifdef DB_CACHE 61879acf67fSBill Paul if (qhead.cqh_first->dbptr->key == NULL) { 619b2264be8SBill Paul #endif 620778c7b1cSBill Paul (dbp->seq)(dbp,&lkey,&ldata,R_FIRST); 621b2264be8SBill Paul while(strncmp((char *)key->data,lkey.data, 622b2264be8SBill Paul (int)key->size) || key->size != lkey.size) 623b3e93234SBill Paul if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) { 624b3e93234SBill Paul #ifdef DB_CACHE 62579acf67fSBill Paul qhead.cqh_first->dbptr->size = 0; 626b3e93234SBill Paul #endif 627b3e93234SBill Paul return(YP_NOKEY); 628778c7b1cSBill Paul } 629b3e93234SBill Paul 630b3e93234SBill Paul #ifdef DB_CACHE 631b3e93234SBill Paul } 632b3e93234SBill Paul #endif 633b2264be8SBill Paul } 634778c7b1cSBill Paul 635b2264be8SBill Paul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 636b2264be8SBill Paul #ifdef DB_CACHE 63779acf67fSBill Paul qhead.cqh_first->dbptr->size = 0; 638b2264be8SBill Paul #endif 639778c7b1cSBill Paul return(YP_NOMORE); 640b2264be8SBill Paul } 641778c7b1cSBill Paul 642778c7b1cSBill Paul /* Avoid passing back magic "YP_*" records. */ 643b2264be8SBill Paul while (!strncmp(key->data, "YP_", 3) && !allow) 644b2264be8SBill Paul if ((dbp->seq)(dbp,key,data,R_NEXT)) { 645b2264be8SBill Paul #ifdef DB_CACHE 64679acf67fSBill Paul qhead.cqh_first->dbptr->size = 0; 647b2264be8SBill Paul #endif 648778c7b1cSBill Paul return(YP_NOMORE); 649b2264be8SBill Paul } 650778c7b1cSBill Paul 65177732bc5SBill Paul if (ypdb_debug) 652778c7b1cSBill Paul yp_error("Result of lookup: key: [%.*s] data: [%.*s]", 653778c7b1cSBill Paul key->size, key->data, data->size, data->data); 654778c7b1cSBill Paul 655b2264be8SBill Paul #ifdef DB_CACHE 65679acf67fSBill Paul if (qhead.cqh_first->dbptr->size) { 65779acf67fSBill Paul qhead.cqh_first->dbptr->key = key->data; 65879acf67fSBill Paul qhead.cqh_first->dbptr->size = key->size; 659b2264be8SBill Paul } 660b2264be8SBill Paul #else 66179acf67fSBill Paul bcopy((char *)key->data, (char *)&keybuf, key->size); 66279acf67fSBill Paul lkey.data = (void *)&keybuf; 663b2264be8SBill Paul lkey.size = key->size; 66479acf67fSBill Paul bcopy((char *)data->data, (char *)&datbuf, data->size); 66579acf67fSBill Paul data->data = (void *)&datbuf; 666b2264be8SBill Paul #endif 667b2264be8SBill Paul 668778c7b1cSBill Paul return(YP_TRUE); 669778c7b1cSBill Paul } 670180807d2SBill Paul 671180807d2SBill Paul #ifdef DB_CACHE 672180807d2SBill Paul /* 673180807d2SBill Paul * Database glue functions. 674180807d2SBill Paul */ 675180807d2SBill Paul 676180807d2SBill Paul static DB *yp_currmap_db = NULL; 677180807d2SBill Paul static int yp_allow_db = 0; 678180807d2SBill Paul 679180807d2SBill Paul ypstat yp_select_map(map, domain, key, allow) 680180807d2SBill Paul char *map; 681180807d2SBill Paul char *domain; 682180807d2SBill Paul keydat *key; 683180807d2SBill Paul int allow; 684180807d2SBill Paul { 685180807d2SBill Paul yp_currmap_db = yp_open_db_cache(domain, map, key->keydat_val, 686180807d2SBill Paul key->keydat_len); 687180807d2SBill Paul 688180807d2SBill Paul yp_allow_db = allow; 689180807d2SBill Paul return(yp_errno); 690180807d2SBill Paul } 691180807d2SBill Paul 692180807d2SBill Paul ypstat yp_getbykey(key, val) 693180807d2SBill Paul keydat *key; 694180807d2SBill Paul valdat *val; 695180807d2SBill Paul { 696180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 697180807d2SBill Paul ypstat rval; 698180807d2SBill Paul 699180807d2SBill Paul db_key.data = key->keydat_val; 700180807d2SBill Paul db_key.size = key->keydat_len; 701180807d2SBill Paul 702180807d2SBill Paul rval = yp_get_record(yp_currmap_db, 703180807d2SBill Paul &db_key, &db_val, yp_allow_db); 704180807d2SBill Paul 705180807d2SBill Paul if (rval == YP_TRUE) { 706180807d2SBill Paul val->valdat_val = db_val.data; 707180807d2SBill Paul val->valdat_len = db_val.size; 708180807d2SBill Paul } 709180807d2SBill Paul 710180807d2SBill Paul return(rval); 711180807d2SBill Paul } 712180807d2SBill Paul 713180807d2SBill Paul ypstat yp_firstbykey(key, val) 714180807d2SBill Paul keydat *key; 715180807d2SBill Paul valdat *val; 716180807d2SBill Paul { 717180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 718180807d2SBill Paul ypstat rval; 719180807d2SBill Paul 720180807d2SBill Paul rval = yp_first_record(yp_currmap_db, &db_key, &db_val, yp_allow_db); 721180807d2SBill Paul 722180807d2SBill Paul if (rval == YP_TRUE) { 723180807d2SBill Paul key->keydat_val = db_key.data; 724180807d2SBill Paul key->keydat_len = db_key.size; 725180807d2SBill Paul val->valdat_val = db_val.data; 726180807d2SBill Paul val->valdat_len = db_val.size; 727180807d2SBill Paul } 728180807d2SBill Paul 729180807d2SBill Paul return(rval); 730180807d2SBill Paul } 731180807d2SBill Paul 732180807d2SBill Paul ypstat yp_nextbykey(key, val) 733180807d2SBill Paul keydat *key; 734180807d2SBill Paul valdat *val; 735180807d2SBill Paul { 736180807d2SBill Paul DBT db_key = { NULL, 0 }, db_val = { NULL, 0 }; 737180807d2SBill Paul ypstat rval; 738180807d2SBill Paul 739180807d2SBill Paul db_key.data = key->keydat_val; 740180807d2SBill Paul db_key.size = key->keydat_len; 741180807d2SBill Paul 742180807d2SBill Paul rval = yp_next_record(yp_currmap_db, &db_key, &db_val, 0, yp_allow_db); 743180807d2SBill Paul 744180807d2SBill Paul if (rval == YP_TRUE) { 745180807d2SBill Paul key->keydat_val = db_key.data; 746180807d2SBill Paul key->keydat_len = db_key.size; 747180807d2SBill Paul val->valdat_val = db_val.data; 748180807d2SBill Paul val->valdat_len = db_val.size; 749180807d2SBill Paul } 750180807d2SBill Paul 751180807d2SBill Paul return(rval); 752180807d2SBill Paul } 753180807d2SBill Paul #endif 754