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