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