Home | History | Annotate | Line # | Download | only in net
nsdispatch.c revision 1.1.2.1
      1 /*-
      2  * Copyright 1995,1996 Luke Mewburn <lm (at) werj.com.au>.  All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  * 3. All advertising materials mentioning features or use of this software
     13  *    must display the following acknowledgement:
     14  * 	This product includes software developed by Luke Mewburn.
     15  * 4. The name of the author may not be used to endorse or promote products
     16  *    derived from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     24  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     26  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
     27  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include <sys/types.h>
     31 #include <sys/param.h>
     32 #include <sys/stat.h>
     33 
     34 #include <fcntl.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #include <unistd.h>
     39 
     40 #include "nsswitch.h"
     41 
     42 static int	  _nsmapsize = 0;
     43 static ns_DBT	 *_nsmap = NULL;
     44 /*
     45  * number of ns_DBT per chunk in _nsmap. calculated along the lines of
     46  *	NSELEMSPERCHUNK * sizeof(ns_DBT) < (1024 - some slop)
     47  * this is to help power of 2 mallocs which are really wasteful if the
     48  * amount just overflows a power of 2 boundary.
     49  */
     50 #define NSELEMSPERCHUNK		17
     51 
     52 int
     53 _nscmp(const void *a, const void *b)
     54 {
     55     return strncmp(((ns_DBT*)a)->name, ((ns_DBT *)b)->name, NS_MAXDBLEN);
     56 } /* _nscmp */
     57 
     58 void
     59 __nsdbput(dbt)
     60 	const ns_DBT *dbt;
     61 {
     62 	int	i;
     63 
     64 	for (i = 0; i < _nsmapsize; i++) {
     65 		if (_nscmp(dbt, &_nsmap[i]) == 0) {
     66 			memmove((void *)&_nsmap[i], (void *)dbt,
     67 				sizeof(ns_DBT));
     68 			return;
     69 		}
     70 	}
     71 
     72 	if ((_nsmapsize % NSELEMSPERCHUNK) == 0) {
     73 		_nsmap = realloc(_nsmap,
     74 			    (_nsmapsize + NSELEMSPERCHUNK) * sizeof(ns_DBT));
     75 		if (_nsmap == NULL)
     76 			_err(1, "nsdispatch: %m");
     77 
     78 	}
     79 	memmove((void *)&_nsmap[_nsmapsize++], (void *)dbt, sizeof(ns_DBT));
     80 } /* __nsdbput */
     81 
     82 
     83 /*
     84  * __nsdbget --
     85  *	args: ns_DBT *dbt
     86  *	modifies: dbt
     87  *	looks for the element in dbt->name and finds from there
     88  *
     89  */
     90 void
     91 __nsdbget(dbt)
     92 	ns_DBT *dbt;
     93 {
     94 #ifdef NSLINEAR		/* XXX: just to compare linear vs bsearch */
     95 	int	i;
     96 	for (i = 0; i < _nsmapsize; i++) {
     97 		if (_nscmp(dbt, &_nsmap[i]) == 0) {
     98 			memmove((void *)dbt, (void *)&_nsmap[i],
     99 				sizeof(ns_DBT));
    100 			return;
    101 		}
    102 	}
    103 #else
    104 	ns_DBT *e;
    105 	e = bsearch(dbt, _nsmap, _nsmapsize, sizeof(ns_DBT), _nscmp);
    106 	if (e != NULL)
    107 		memmove((void *)dbt, (void *)e, sizeof(ns_DBT));
    108 #endif
    109 } /* __nsdbget */
    110 
    111 
    112 void
    113 _nsdumpdbt(dbt)
    114 	const ns_DBT *dbt;
    115 {
    116 	int i;
    117 	printf("%s:\n", dbt->name);
    118 	for (i = 0; i < dbt->size; i++) {
    119 		int source = (dbt->map[i] & NS_SOURCEMASK);
    120 		int status = (dbt->map[i] & NS_STATUSMASK);
    121 
    122 		printf("  %2d: [%x] ", i, dbt->map[i]);
    123 		if (!dbt->map[i]) {
    124 		    printf(" (empty)\n");
    125 		    continue;
    126 		}
    127 		switch(source) {
    128 		case NS_FILES:		printf(" files"); break;
    129 		case NS_DNS:		printf(" dns"); break;
    130 		case NS_NIS:		printf(" nis"); break;
    131 		case NS_NISPLUS:	printf(" nisplus"); break;
    132 		case NS_COMPAT:		printf(" compat"); break;
    133 		default:		printf(" BADSOURCE(%x)", source); break;
    134 		}
    135 
    136 		if (!(status & NS_SUCCESS))
    137 			printf(" SUCCESS=continue");
    138 		if (status & NS_UNAVAIL)
    139 			printf(" UNAVAIL=return");
    140 		if (status & NS_NOTFOUND)
    141 			printf(" NOTFOUND=return");
    142 		if (status & NS_TRYAGAIN)
    143 			printf(" TRYAGAIN=return");
    144 		printf("\n");
    145 	}
    146 } /* nsdumpdbt */
    147 
    148 
    149 void
    150 _nsgetdbt(src, dbt)
    151 	const char	*src;
    152 	ns_DBT		*dbt;
    153 {
    154 	static time_t	 confmod;
    155 	struct stat	 statbuf;
    156 
    157 	extern FILE 	*_nsyyin;
    158 	extern int	_nsyyparse();
    159 
    160 	strncpy(dbt->name, src, NS_MAXDBLEN);
    161 	dbt->name[NS_MAXDBLEN - 1] = '\0';
    162 	dbt->size = 1;
    163 	dbt->map[0] = NS_DEFAULTMAP;		/* default to 'files' */
    164 
    165 	if (confmod) {
    166 		if (stat(_PATH_NS_CONF, &statbuf) == -1)
    167 			return;
    168 		if (confmod < statbuf.st_mtime) {
    169 			free(_nsmap);
    170 			_nsmap = NULL;
    171 			_nsmapsize = 0;
    172 			confmod = 0;
    173 		}
    174 	}
    175 	if (!confmod) {
    176 		if (stat(_PATH_NS_CONF, &statbuf) == -1)
    177 			return;
    178 		_nsyyin = fopen(_PATH_NS_CONF, "r");
    179 		if (_nsyyin == NULL)
    180 			return;
    181 		_nsyyparse();
    182 #ifndef NSLINEAR
    183 		qsort(_nsmap, _nsmapsize, sizeof(ns_DBT), _nscmp);
    184 #endif
    185 		(void)fclose(_nsyyin);
    186 		confmod = statbuf.st_mtime;
    187 	}
    188 	__nsdbget(dbt);
    189 } /* nsgetdbt */
    190 
    191 
    192 int
    193 #if __STDC__
    194 nsdispatch(void *retval, ns_dtab disp_tab, const char *database, ...)
    195 #else
    196 nsdispatch(retval, disp_tab, database, va_alist)
    197 	void		*retval;
    198 	ns_dtab		disp_tab;
    199 	const char	*database;
    200 	va_dcl
    201 #endif
    202 {
    203 	va_list	ap;
    204 	int	curdisp, result = 0;
    205 	ns_DBT	dbt;
    206 
    207 	_nsgetdbt(database, &dbt);
    208 
    209 #if NSDEBUG
    210 	_nsdumpdbt(&dbt);
    211 	fprintf(stderr, "nsdispatch: %s\n", database);
    212 #endif
    213 	for (curdisp = 0; curdisp < dbt.size; curdisp++) {
    214 		int source = (dbt.map[curdisp] & NS_SOURCEMASK);
    215 #if NSDEBUG
    216 		fprintf(stderr, "    %2d: source=%d", curdisp, source);
    217 #endif
    218 		if (source < 0 || source >= NS_MAXSOURCE)
    219 			continue;
    220 
    221 		result = 0;
    222 		if (disp_tab[source].cb) {
    223 #if __STDC__
    224 			va_start(ap, database);
    225 #else
    226 			va_start(ap);
    227 #endif
    228 			result = disp_tab[source].cb(retval,
    229 						disp_tab[source].cb_data, ap);
    230 			va_end(ap);
    231 #if NSDEBUG
    232 			fprintf(stderr, " result=%d (%d)", result,
    233 			    (result & (dbt.map[curdisp] & NS_STATUSMASK)));
    234 #endif
    235 			if (result & (dbt.map[curdisp] & NS_STATUSMASK)) {
    236 #if NSDEBUG
    237 				fprintf(stderr, " MATCH!\n");
    238 #endif
    239 				break;
    240 			}
    241 		}
    242 #if NSDEBUG
    243 		fprintf(stderr, "\n");
    244 #endif
    245 	}
    246 	return (result ? result : NS_NOTFOUND);
    247 } /* nsdispatch */
    248