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