1 /* $NetBSD: nsdispatch.c,v 1.2 1999/01/15 12:53:24 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998, 1999 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 #define _PATH_NS_CONF "/tmp/nsswitch.conf" 47 #include <nsswitch.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <unistd.h> 52 53 54 static int _nsmapsize = 0; 55 static ns_dbt *_nsmap = NULL; 56 57 /* 58 * size of dynamic array chunk for _nsmap and _nsmap[x].srclist 59 */ 60 #define NSELEMSPERCHUNK 8 61 62 63 int _nscmp __P((const void *, const void *)); 64 65 66 int 67 _nscmp(a, b) 68 const void *a; 69 const void *b; 70 { 71 return (strcasecmp(((ns_dbt *)a)->name, ((ns_dbt *)b)->name)); 72 } 73 74 75 void 76 _nsdbtaddsrc(dbt, src) 77 ns_dbt *dbt; 78 const ns_src *src; 79 { 80 if ((dbt->srclistsize % NSELEMSPERCHUNK) == 0) { 81 dbt->srclist = (ns_src *)realloc(dbt->srclist, 82 (dbt->srclistsize + NSELEMSPERCHUNK) * sizeof(ns_src)); 83 if (dbt->srclist == NULL) 84 err(1, "nsdispatch: memory allocation failure"); 85 } 86 memmove((void *)&dbt->srclist[dbt->srclistsize++], (void *)src, 87 sizeof(ns_src)); 88 } 89 90 91 void 92 _nsdbtdump(dbt) 93 const ns_dbt *dbt; 94 { 95 int i; 96 97 printf("%s (%d source%s):", dbt->name, dbt->srclistsize, 98 dbt->srclistsize == 1 ? "" : "s"); 99 for (i = 0; i < dbt->srclistsize; i++) { 100 printf(" %s", dbt->srclist[i].name); 101 if (!(dbt->srclist[i].flags & 102 (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) && 103 (dbt->srclist[i].flags & NS_SUCCESS)) 104 continue; 105 printf(" ["); 106 if (!(dbt->srclist[i].flags & NS_SUCCESS)) 107 printf(" SUCCESS=continue"); 108 if (dbt->srclist[i].flags & NS_UNAVAIL) 109 printf(" UNAVAIL=return"); 110 if (dbt->srclist[i].flags & NS_NOTFOUND) 111 printf(" NOTFOUND=return"); 112 if (dbt->srclist[i].flags & NS_TRYAGAIN) 113 printf(" TRYAGAIN=return"); 114 printf(" ]"); 115 } 116 printf("\n"); 117 } 118 119 120 const ns_dbt * 121 _nsdbtget(name) 122 const char *name; 123 { 124 static time_t confmod; 125 static ns_dbt dbt; 126 127 struct stat statbuf; 128 ns_dbt *ndbt; 129 130 extern FILE *_nsyyin; 131 extern int _nsyyparse __P((void)); 132 133 if (dbt.name == NULL) { /* construct dummy `files' entry */ 134 ns_src src; 135 136 src.name = NSSRC_FILES; 137 src.flags = NS_SUCCESS; 138 dbt.name = name; 139 _nsdbtaddsrc(&dbt, &src); 140 } 141 142 if (confmod) { 143 if (stat(_PATH_NS_CONF, &statbuf) == -1) 144 return (&dbt); 145 if (confmod < statbuf.st_mtime) { 146 int i, j; 147 148 for (i = 0; i < _nsmapsize; i++) { 149 for (j = 0; j < _nsmap[i].srclistsize; j++) { 150 if (_nsmap[i].srclist[j].name != NULL) 151 free((char *) 152 _nsmap[i].srclist[j].name); 153 } 154 if (_nsmap[i].srclist) 155 free(_nsmap[i].srclist); 156 if (_nsmap[i].name) 157 free((char *)_nsmap[i].name); 158 } 159 if (_nsmap) 160 free(_nsmap); 161 _nsmap = NULL; 162 _nsmapsize = 0; 163 confmod = 0; 164 } 165 } 166 if (!confmod) { 167 if (stat(_PATH_NS_CONF, &statbuf) == -1) 168 return (&dbt); 169 _nsyyin = fopen(_PATH_NS_CONF, "r"); 170 if (_nsyyin == NULL) 171 return (&dbt); 172 _nsyyparse(); 173 (void)fclose(_nsyyin); 174 qsort(_nsmap, _nsmapsize, sizeof(ns_dbt), _nscmp); 175 confmod = statbuf.st_mtime; 176 } 177 ndbt = bsearch(&dbt, _nsmap, _nsmapsize, sizeof(ns_dbt), _nscmp); 178 if (ndbt != NULL) 179 return (ndbt); 180 return (&dbt); 181 } 182 183 184 void 185 _nsdbtput(dbt) 186 const ns_dbt *dbt; 187 { 188 int i; 189 190 for (i = 0; i < _nsmapsize; i++) { 191 if (_nscmp(dbt, &_nsmap[i]) == 0) { 192 /* overwrite existing entry */ 193 if (_nsmap[i].srclist != NULL) 194 free(_nsmap[i].srclist); 195 memmove((void *)&_nsmap[i], (void *)dbt, 196 sizeof(ns_dbt)); 197 return; 198 } 199 } 200 201 if ((_nsmapsize % NSELEMSPERCHUNK) == 0) { 202 _nsmap = (ns_dbt *)realloc(_nsmap, 203 (_nsmapsize + NSELEMSPERCHUNK) * sizeof(ns_dbt)); 204 if (_nsmap == NULL) 205 err(1, "nsdispatch: memory allocation failure"); 206 } 207 memmove((void *)&_nsmap[_nsmapsize++], (void *)dbt, sizeof(ns_dbt)); 208 } 209 210 211 int 212 #if __STDC__ 213 nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, ...) 214 #else 215 nsdispatch(retval, disp_tab, database, va_alist) 216 void *retval; 217 const ns_dtab disp_tab[]; 218 const char *database; 219 va_dcl 220 #endif 221 { 222 va_list ap; 223 int i, curdisp, result; 224 const ns_dbt *dbt; 225 226 dbt = _nsdbtget(database); 227 result = 0; 228 229 #if _NS_DEBUG 230 _nsdumpdbt(dbt); 231 fprintf(stderr, "nsdispatch: %s\n", database); 232 #endif 233 for (i = 0; i < dbt->srclistsize; i++) { 234 #if _NS_DEBUG 235 fprintf(stderr, " source=%s", dbt->srclist[i]->source); 236 #endif 237 for (curdisp = 0; disp_tab[curdisp].src != NULL; curdisp++) 238 if (strcasecmp(disp_tab[curdisp].src, 239 dbt->srclist[i].name) == 0) 240 break; 241 result = 0; 242 if (disp_tab[curdisp].callback) { 243 #if __STDC__ 244 va_start(ap, database); 245 #else 246 va_start(ap); 247 #endif 248 result = disp_tab[curdisp].callback(retval, 249 disp_tab[curdisp].cb_data, ap); 250 va_end(ap); 251 #if _NS_DEBUG 252 fprintf(stderr, " result=%d (%d)", result, 253 (result & dbt->srclist[i].flags)); 254 #endif 255 if (result & dbt->srclist[i].flags) { 256 #if _NS_DEBUG 257 fprintf(stderr, " MATCH!\n"); 258 #endif 259 break; 260 } 261 } 262 #if _NS_DEBUG 263 fprintf(stderr, "\n"); 264 #endif 265 } 266 return (result ? result : NS_NOTFOUND); 267 } 268