diff options
author | nectar <nectar@FreeBSD.org> | 2000-09-06 18:16:48 +0000 |
---|---|---|
committer | nectar <nectar@FreeBSD.org> | 2000-09-06 18:16:48 +0000 |
commit | 748554442d0ac4467fdac2ce9d42006588fd4481 (patch) | |
tree | aed2ddbcac97f46f60ee9c2063a3345553f6a1ee /lib/libc/net/nsdispatch.c | |
parent | 59ffb36b778f8e629622726f6bd32dfa4fda7e35 (diff) | |
download | FreeBSD-src-748554442d0ac4467fdac2ce9d42006588fd4481.zip FreeBSD-src-748554442d0ac4467fdac2ce9d42006588fd4481.tar.gz |
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
Diffstat (limited to 'lib/libc/net/nsdispatch.c')
-rw-r--r-- | lib/libc/net/nsdispatch.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c new file mode 100644 index 0000000..311b89d --- /dev/null +++ b/lib/libc/net/nsdispatch.c @@ -0,0 +1,270 @@ +/* $NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +static char *rcsid = + "$FreeBSD$"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> + +#include <err.h> +#include <fcntl.h> +#define _NS_PRIVATE +#include <nsswitch.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* + * default sourcelist: `files' + */ +const ns_src __nsdefaultsrc[] = { + { NSSRC_FILES, NS_SUCCESS }, + { 0 }, +}; + + +static int _nsmapsize = 0; +static ns_dbt *_nsmap = NULL; + +/* + * size of dynamic array chunk for _nsmap and _nsmap[x].srclist + */ +#define NSELEMSPERCHUNK 8 + + +int _nscmp __P((const void *, const void *)); + + +int +_nscmp(a, b) + const void *a; + const void *b; +{ + return (strcasecmp(((const ns_dbt *)a)->name, + ((const ns_dbt *)b)->name)); +} + + +void +_nsdbtaddsrc(dbt, src) + ns_dbt *dbt; + const ns_src *src; +{ + if ((dbt->srclistsize % NSELEMSPERCHUNK) == 0) { + dbt->srclist = (ns_src *)realloc(dbt->srclist, + (dbt->srclistsize + NSELEMSPERCHUNK) * sizeof(ns_src)); + if (dbt->srclist == NULL) + err(1, "nsdispatch: memory allocation failure"); + } + memmove(&dbt->srclist[dbt->srclistsize++], src, sizeof(ns_src)); +} + + +void +_nsdbtdump(dbt) + const ns_dbt *dbt; +{ + int i; + + printf("%s (%d source%s):", dbt->name, dbt->srclistsize, + dbt->srclistsize == 1 ? "" : "s"); + for (i = 0; i < dbt->srclistsize; i++) { + printf(" %s", dbt->srclist[i].name); + if (!(dbt->srclist[i].flags & + (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) && + (dbt->srclist[i].flags & NS_SUCCESS)) + continue; + printf(" ["); + if (!(dbt->srclist[i].flags & NS_SUCCESS)) + printf(" SUCCESS=continue"); + if (dbt->srclist[i].flags & NS_UNAVAIL) + printf(" UNAVAIL=return"); + if (dbt->srclist[i].flags & NS_NOTFOUND) + printf(" NOTFOUND=return"); + if (dbt->srclist[i].flags & NS_TRYAGAIN) + printf(" TRYAGAIN=return"); + printf(" ]"); + } + printf("\n"); +} + + +const ns_dbt * +_nsdbtget(name) + const char *name; +{ + static time_t confmod; + + struct stat statbuf; + ns_dbt dbt; + + extern FILE *_nsyyin; + extern int _nsyyparse __P((void)); + + dbt.name = name; + + if (confmod) { + if (stat(_PATH_NS_CONF, &statbuf) == -1) + return (NULL); + if (confmod < statbuf.st_mtime) { + int i, j; + + for (i = 0; i < _nsmapsize; i++) { + for (j = 0; j < _nsmap[i].srclistsize; j++) { + if (_nsmap[i].srclist[j].name != NULL) { + /*LINTED const cast*/ + free((void *) + _nsmap[i].srclist[j].name); + } + } + if (_nsmap[i].srclist) + free(_nsmap[i].srclist); + if (_nsmap[i].name) { + /*LINTED const cast*/ + free((void *)_nsmap[i].name); + } + } + if (_nsmap) + free(_nsmap); + _nsmap = NULL; + _nsmapsize = 0; + confmod = 0; + } + } + if (!confmod) { + if (stat(_PATH_NS_CONF, &statbuf) == -1) + return (NULL); + _nsyyin = fopen(_PATH_NS_CONF, "r"); + if (_nsyyin == NULL) + return (NULL); + _nsyyparse(); + (void)fclose(_nsyyin); + qsort(_nsmap, (size_t)_nsmapsize, sizeof(ns_dbt), _nscmp); + confmod = statbuf.st_mtime; + } + return (bsearch(&dbt, _nsmap, (size_t)_nsmapsize, sizeof(ns_dbt), + _nscmp)); +} + + +void +_nsdbtput(dbt) + const ns_dbt *dbt; +{ + int i; + + for (i = 0; i < _nsmapsize; i++) { + if (_nscmp(dbt, &_nsmap[i]) == 0) { + /* overwrite existing entry */ + if (_nsmap[i].srclist != NULL) + free(_nsmap[i].srclist); + memmove(&_nsmap[i], dbt, sizeof(ns_dbt)); + return; + } + } + + if ((_nsmapsize % NSELEMSPERCHUNK) == 0) { + _nsmap = (ns_dbt *)realloc(_nsmap, + (_nsmapsize + NSELEMSPERCHUNK) * sizeof(ns_dbt)); + if (_nsmap == NULL) + err(1, "nsdispatch: memory allocation failure"); + } + memmove(&_nsmap[_nsmapsize++], dbt, sizeof(ns_dbt)); +} + + +int +#if __STDC__ +nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, + const char *method, const ns_src defaults[], ...) +#else +nsdispatch(retval, disp_tab, database, method, defaults, va_alist) + void *retval; + const ns_dtab disp_tab[]; + const char *database; + const char *method; + const ns_src defaults[]; + va_dcl +#endif +{ + va_list ap; + int i, curdisp, result; + const ns_dbt *dbt; + const ns_src *srclist; + int srclistsize; + + dbt = _nsdbtget(database); + if (dbt != NULL) { + srclist = dbt->srclist; + srclistsize = dbt->srclistsize; + } else { + srclist = defaults; + srclistsize = 0; + while (srclist[srclistsize].name != NULL) + srclistsize++; + } + result = 0; + + for (i = 0; i < srclistsize; i++) { + for (curdisp = 0; disp_tab[curdisp].src != NULL; curdisp++) + if (strcasecmp(disp_tab[curdisp].src, + srclist[i].name) == 0) + break; + result = 0; + if (disp_tab[curdisp].callback) { +#if __STDC__ + va_start(ap, defaults); +#else + va_start(ap); +#endif + result = disp_tab[curdisp].callback(retval, + disp_tab[curdisp].cb_data, ap); + va_end(ap); + if (result & srclist[i].flags) { + break; + } + } + } + return (result ? result : NS_NOTFOUND); +} |