[rtems-libbsd commit] nsdispatch.c: New file added along with required dependencies

Joel Sherrill joel at rtems.org
Wed Sep 12 22:07:22 UTC 2012


Module:    rtems-libbsd
Branch:    master
Commit:    c52d92245af983204feadd0248c0fc668765e73d
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=c52d92245af983204feadd0248c0fc668765e73d

Author:    Joel Sherrill <joel.sherrill at oarcorp.com>
Date:      Wed Sep 12 17:09:48 2012 -0500

nsdispatch.c: New file added along with required dependencies

This file uses dynamic loading and is using some magic for
statically linked modules included in it. These modules may
or may not show up magically in an RTEMS executable. This will
eventually have to be investigated and resolved.

---

 .gitignore                                    |    3 +
 freebsd-userspace/Makefile                    |   22 +-
 freebsd-userspace/lib/libc/net/nsdispatch.c   |  778 +++++++++++++++++++++++++
 freebsd-userspace/lib/libc/net/nslexer.l      |  119 ++++
 freebsd-userspace/lib/libc/net/nsparser.h     |   14 +
 freebsd-userspace/lib/libc/net/nsparser.y     |  184 ++++++
 freebsd-userspace/lib/libc/net/nss_backends.h |   43 ++
 7 files changed, 1162 insertions(+), 1 deletions(-)

diff --git a/.gitignore b/.gitignore
index 885ff5d..e106e7f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,3 +57,6 @@ rtemsbsd/sparc64/include/freebsd/machine/legacyvar.h
 rtemsbsd/sparc64/include/freebsd/machine/pci_cfgreg.h
 rtemsbsd/v850/include/freebsd/machine/legacyvar.h
 rtemsbsd/v850/include/freebsd/machine/pci_cfgreg.h
+freebsd-userspace/lib/libc/net/nslexer.c
+freebsd-userspace/lib/libc/net/nsparser.c
+freebsd-userspace/lib/libc/net/nsparser.i
diff --git a/freebsd-userspace/Makefile b/freebsd-userspace/Makefile
index 7055f0a..b06cffe 100644
--- a/freebsd-userspace/Makefile
+++ b/freebsd-userspace/Makefile
@@ -13,6 +13,8 @@ CFLAGS += -Isys
 CFLAGS += -Ilocal 
 # XXX hack to find rpc
 CFLAGS += -I../services/librpc/include 
+# nsparser needs this
+CFLAGS += -Ilib/libc/net
 
 CFLAGS += -I$(INSTALL_BASE)/include
 
@@ -57,6 +59,8 @@ C_FILES += lib/libc/net/getproto.c
 C_FILES += lib/libc/net/getprotoent.c
 C_FILES += lib/libc/net/getprotoname.c
 C_FILES += lib/libc/net/getservent.c
+C_FILES += lib/libc/net/nsdispatch.c
+C_FILES += lib/libc/net/nslexer.c
 C_FILES += lib/libc/gen/err.c
 C_FILES += lib/libc/gen/gethostname.c
 C_FILES += lib/libc/nameser/ns_name.c
@@ -204,6 +208,11 @@ C_D_FILES = $(C_FILES:%.c=%.d)
 LIB = libbsdc.a
 GEN_FILES = include/rpc/rpcb_prot.h
 GEN_FILES += commands/sbin/route/keywords.h
+GEN_FILES += lib/libc/net/nslexer.c
+GEN_FILES += lib/libc/net/nsparser.c
+
+EXTRA_CLEAN = lib/libc/net/nsparser.i
+
 all: $(LIB)
 
 $(LIB): $(GEN_FILES) $(C_O_FILES)
@@ -223,6 +232,17 @@ commands/sbin/route/keywords.h: commands/sbin/route/keywords
 	    > commands/sbin/route/keywords.h
 	rm -f _keywords.tmp
 
+YFLAGS+=-p_nsyy
+LFLAGS+=-P_nsyy
+
+lib/libc/net/nslexer.c: lib/libc/net/nslexer.l
+	${LEX} ${LFLAGS} -t $^ | \
+		sed -e '/YY_BUF_SIZE/s/16384/1024/' >$@
+
+lib/libc/net/nsparser.c: lib/libc/net/nsparser.y
+	yacc -d ${YFLAGS} -o lib/libc/net/nsparser.i $^
+	cat lib/libc/net/nsparser.i | \
+		sed -e '/YY_BUF_SIZE/s/16384/1024/' >$@
 install: $(LIB)
 	install -d $(INSTALL_BASE)/include
 	cd include; for i in `find . -name '*.h'` ; do \
@@ -236,7 +256,7 @@ install: $(LIB)
 	install -c -m 644 $(LIB) $(INSTALL_BASE)
 
 clean:
-	rm -f $(LIB) $(C_O_FILES) $(C_D_FILES) $(GEN_FILES)
+	rm -f $(LIB) $(C_O_FILES) $(C_D_FILES) $(GEN_FILES) $(CLEAN_FILES)
 
 -include $(C_D_FILES)
 
diff --git a/freebsd-userspace/lib/libc/net/nsdispatch.c b/freebsd-userspace/lib/libc/net/nsdispatch.c
new file mode 100644
index 0000000..dcd7438
--- /dev/null
+++ b/freebsd-userspace/lib/libc/net/nsdispatch.c
@@ -0,0 +1,778 @@
+#include "port_before.h"
+
+/*	$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.
+ */
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#ifndef __rtems__
+#include <dlfcn.h>
+#else
+#include <stdint.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "nss_tls.h"
+#include "libc_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+enum _nss_constants {
+	/* Number of elements allocated when we grow a vector */
+	ELEMSPERCHUNK =	8
+};
+
+/*
+ * Global NSS data structures are mostly read-only, but we update
+ * them when we read or re-read the nsswitch.conf.
+ */
+static	pthread_rwlock_t	nss_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/*
+ * Runtime determination of whether we are dynamically linked or not.
+ */
+extern	int		_DYNAMIC __attribute__ ((weak));
+#define	is_dynamic()	(&_DYNAMIC != NULL)
+
+/*
+ * default sourcelist: `files'
+ */
+const ns_src __nsdefaultsrc[] = {
+	{ NSSRC_FILES, NS_SUCCESS },
+	{ 0 },
+};
+
+/* Database, source mappings. */
+static	unsigned int		 _nsmapsize;
+static	ns_dbt			*_nsmap = NULL;
+
+/* NSS modules. */
+static	unsigned int		 _nsmodsize;
+static	ns_mod			*_nsmod;
+
+/* Placeholder for builtin modules' dlopen `handle'. */
+static	int			 __nss_builtin_handle;
+static	void			*nss_builtin_handle = &__nss_builtin_handle;
+
+#ifdef NS_CACHING
+/*
+ * Cache lookup cycle prevention function - if !NULL then no cache lookups
+ * will be made
+ */
+static	void			*nss_cache_cycle_prevention_func = NULL;
+#endif
+
+/*
+ * When this is set to 1, nsdispatch won't use nsswitch.conf
+ * but will consult the 'defaults' source list only.
+ * NOTE: nested fallbacks (when nsdispatch calls fallback functions,
+ *     which in turn calls nsdispatch, which should call fallback
+ *     function) are not supported
+ */
+struct fb_state {
+	int	fb_dispatch;
+};
+static	void	fb_endstate(void *);
+NSS_TLS_HANDLING(fb);
+
+/*
+ * Attempt to spew relatively uniform messages to syslog.
+ */
+#define nss_log(level, fmt, ...) \
+	syslog((level), "NSSWITCH(%s): " fmt, __func__, __VA_ARGS__)
+#define nss_log_simple(level, s) \
+	syslog((level), "NSSWITCH(%s): " s, __func__)
+
+/*
+ * Dynamically growable arrays are used for lists of databases, sources,
+ * and modules.  The following `vector' interface is used to isolate the
+ * common operations.
+ */
+typedef	int	(*vector_comparison)(const void *, const void *);
+typedef	void	(*vector_free_elem)(void *);
+static	void	  vector_sort(void *, unsigned int, size_t,
+		    vector_comparison);
+static	void	  vector_free(void *, unsigned int *, size_t,
+		    vector_free_elem);
+static	void	 *vector_ref(unsigned int, void *, unsigned int, size_t);
+static	void	 *vector_search(const void *, void *, unsigned int, size_t,
+		    vector_comparison);
+static	void	 *vector_append(const void *, void *, unsigned int *, size_t);
+
+
+/*
+ * Internal interfaces.
+ */
+static	int	 string_compare(const void *, const void *);
+static	int	 mtab_compare(const void *, const void *);
+static	int	 nss_configure(void);
+static	void	 ns_dbt_free(ns_dbt *);
+static	void	 ns_mod_free(ns_mod *);
+static	void	 ns_src_free(ns_src **, int);
+static	void	 nss_load_builtin_modules(void);
+static	void	 nss_load_module(const char *, nss_module_register_fn);
+static	void	 nss_atexit(void);
+/* nsparser */
+extern	FILE	*_nsyyin;
+
+
+/*
+ * The vector operations
+ */
+static void
+vector_sort(void *vec, unsigned int count, size_t esize,
+    vector_comparison comparison)
+{
+	qsort(vec, count, esize, comparison);
+}
+
+
+static void *
+vector_search(const void *key, void *vec, unsigned int count, size_t esize,
+    vector_comparison comparison)
+{
+	return (bsearch(key, vec, count, esize, comparison));
+}
+
+
+static void *
+vector_append(const void *elem, void *vec, unsigned int *count, size_t esize)
+{
+	void	*p;
+
+	if ((*count % ELEMSPERCHUNK) == 0) {
+		p = realloc(vec, (*count + ELEMSPERCHUNK) * esize);
+		if (p == NULL) {
+			nss_log_simple(LOG_ERR, "memory allocation failure");
+			return (vec);
+		}
+		vec = p;
+	}
+	memmove((void *)(((uintptr_t)vec) + (*count * esize)), elem, esize);
+	(*count)++;
+	return (vec);
+}
+
+
+static void *
+vector_ref(unsigned int i, void *vec, unsigned int count, size_t esize)
+{
+	if (i < count)
+		return (void *)((uintptr_t)vec + (i * esize));
+	else
+		return (NULL);
+}
+
+
+#define VECTOR_FREE(v, c, s, f) \
+	do { vector_free(v, c, s, f); v = NULL; } while (0)
+static void
+vector_free(void *vec, unsigned int *count, size_t esize,
+    vector_free_elem free_elem)
+{
+	unsigned int	 i;
+	void		*elem;
+
+	for (i = 0; i < *count; i++) {
+		elem = vector_ref(i, vec, *count, esize);
+		if (elem != NULL)
+			free_elem(elem);
+	}
+	free(vec);
+	*count = 0;
+}
+
+/*
+ * Comparison functions for vector_search.
+ */
+static int
+string_compare(const void *a, const void *b)
+{
+      return (strcasecmp(*(const char * const *)a, *(const char * const *)b));
+}
+
+
+static int
+mtab_compare(const void *a, const void *b)
+{
+      int     cmp;
+
+      cmp = strcmp(((const ns_mtab *)a)->name, ((const ns_mtab *)b)->name);
+      if (cmp != 0)
+	      return (cmp);
+      else
+	      return (strcmp(((const ns_mtab *)a)->database,
+		  ((const ns_mtab *)b)->database));
+}
+
+/*
+ * NSS nsmap management.
+ */
+void
+_nsdbtaddsrc(ns_dbt *dbt, const ns_src *src)
+{
+	const ns_mod	*modp;
+
+	dbt->srclist = vector_append(src, dbt->srclist, &dbt->srclistsize,
+	    sizeof(*src));
+	modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod),
+	    string_compare);
+	if (modp == NULL)
+		nss_load_module(src->name, NULL);
+}
+
+
+#ifdef _NSS_DEBUG
+void
+_nsdbtdump(const ns_dbt *dbt)
+{
+	int i;
+
+	printf("%s (%d source%s):", dbt->name, dbt->srclistsize,
+	    dbt->srclistsize == 1 ? "" : "s");
+	for (i = 0; i < (int)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");
+}
+#endif
+
+
+/*
+ * The first time nsdispatch is called (during a process's lifetime,
+ * or after nsswitch.conf has been updated), nss_configure will
+ * prepare global data needed by NSS.
+ */
+static int
+nss_configure(void)
+{
+	static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER;
+	static time_t	 confmod;
+	struct stat	 statbuf;
+	int		 result, isthreaded;
+	const char	*path;
+#ifdef NS_CACHING
+	void		*handle;
+#endif
+
+	result = 0;
+	isthreaded = __isthreaded;
+#if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT)
+	/* NOTE WELL:  THIS IS A SECURITY HOLE. This must only be built
+	 * for debugging purposes and MUST NEVER be used in production.
+	 */
+	path = getenv("NSSWITCH_CONF");
+	if (path == NULL)
+#endif
+	path = _PATH_NS_CONF;
+	if (stat(path, &statbuf) != 0)
+		return (0);
+	if (statbuf.st_mtime <= confmod)
+		return (0);
+	if (isthreaded) {
+	    result = _pthread_mutex_trylock(&conf_lock);
+	    if (result != 0)
+		    return (0);
+	    (void)_pthread_rwlock_unlock(&nss_lock);
+	    result = _pthread_rwlock_wrlock(&nss_lock);
+	    if (result != 0)
+		    goto fin2;
+	}
+	_nsyyin = fopen(path, "r");
+	if (_nsyyin == NULL)
+		goto fin;
+	VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
+	    (vector_free_elem)ns_dbt_free);
+	VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
+	    (vector_free_elem)ns_mod_free);
+	nss_load_builtin_modules();
+	_nsyyparse();
+	(void)fclose(_nsyyin);
+	vector_sort(_nsmap, _nsmapsize, sizeof(*_nsmap), string_compare);
+	if (confmod == 0)
+		(void)atexit(nss_atexit);
+	confmod = statbuf.st_mtime;
+
+#ifdef NS_CACHING
+	handle = libc_dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+	if (handle != NULL) {
+		nss_cache_cycle_prevention_func = dlsym(handle,
+			"_nss_cache_cycle_prevention_function");
+		dlclose(handle);
+	}
+#endif
+fin:
+	if (isthreaded) {
+	    (void)_pthread_rwlock_unlock(&nss_lock);
+	    if (result == 0)
+		    result = _pthread_rwlock_rdlock(&nss_lock);
+	}
+fin2:
+	if (isthreaded)
+		(void)_pthread_mutex_unlock(&conf_lock);
+	return (result);
+}
+
+
+void
+_nsdbtput(const ns_dbt *dbt)
+{
+	unsigned int	 i;
+	ns_dbt		*p;
+
+	for (i = 0; i < _nsmapsize; i++) {
+		p = vector_ref(i, _nsmap, _nsmapsize, sizeof(*_nsmap));
+		if (string_compare(&dbt->name, &p->name) == 0) {
+			/* overwrite existing entry */
+			if (p->srclist != NULL)
+				ns_src_free(&p->srclist, p->srclistsize);
+			memmove(p, dbt, sizeof(*dbt));
+			return;
+		}
+	}
+	_nsmap = vector_append(dbt, _nsmap, &_nsmapsize, sizeof(*_nsmap));
+}
+
+
+static void
+ns_dbt_free(ns_dbt *dbt)
+{
+	ns_src_free(&dbt->srclist, dbt->srclistsize);
+	if (dbt->name)
+		free((void *)dbt->name);
+}
+
+
+static void
+ns_src_free(ns_src **src, int srclistsize)
+{
+	int	i;
+
+	for (i = 0; i < srclistsize; i++)
+		if ((*src)[i].name != NULL)
+			/* This one was allocated by nslexer. You'll just
+			 * have to trust me.
+			 */
+			free((void *)((*src)[i].name));
+	free(*src);
+	*src = NULL;
+}
+
+
+
+/*
+ * NSS module management.
+ */
+/* The built-in NSS modules are all loaded at once. */
+#define NSS_BACKEND(name, reg) \
+ns_mtab	*reg(unsigned int *, nss_module_unregister_fn *);
+#include "nss_backends.h"
+#undef NSS_BACKEND
+
+static void
+nss_load_builtin_modules(void)
+{
+#define NSS_BACKEND(name, reg) nss_load_module(#name, reg);
+#include "nss_backends.h"
+#undef NSS_BACKEND
+}
+
+
+/* Load a built-in or dynamically linked module.  If the `reg_fn'
+ * argument is non-NULL, assume a built-in module and use reg_fn to
+ * register it.  Otherwise, search for a dynamic NSS module.
+ */
+static void
+nss_load_module(const char *source, nss_module_register_fn reg_fn)
+{
+	char		 buf[PATH_MAX];
+	ns_mod		 mod;
+	nss_module_register_fn fn;
+
+	memset(&mod, 0, sizeof(mod));
+	mod.name = strdup(source);
+	if (mod.name == NULL) {
+		nss_log_simple(LOG_ERR, "memory allocation failure");
+		return;
+	}
+	if (reg_fn != NULL) {
+		/* The placeholder is required, as a NULL handle
+		 * represents an invalid module.
+		 */
+		mod.handle = nss_builtin_handle;
+		fn = reg_fn;
+	} else if (!is_dynamic())
+		goto fin;
+#ifndef __rtems__
+	else {
+		if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name,
+		    NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf))
+			goto fin;
+		mod.handle = libc_dlopen(buf, RTLD_LOCAL|RTLD_LAZY);
+		if (mod.handle == NULL) {
+#ifdef _NSS_DEBUG
+			/* This gets pretty annoying since the built-in
+			 * sources aren't modules yet.
+			 */
+			nss_log(LOG_DEBUG, "%s, %s", mod.name, dlerror());
+#endif
+			goto fin;
+		}
+		fn = (nss_module_register_fn)dlfunc(mod.handle,
+		    "nss_module_register");
+		if (fn == NULL) {
+			(void)dlclose(mod.handle);
+			mod.handle = NULL;
+			nss_log(LOG_ERR, "%s, %s", mod.name, dlerror());
+			goto fin;
+		}
+	}
+#endif
+	mod.mtab = fn(mod.name, &mod.mtabsize, &mod.unregister);
+	if (mod.mtab == NULL || mod.mtabsize == 0) {
+#ifndef __rtems__
+		if (mod.handle != nss_builtin_handle)
+			(void)dlclose(mod.handle);
+#endif
+		mod.handle = NULL;
+		nss_log(LOG_ERR, "%s, registration failed", mod.name);
+		goto fin;
+	}
+	if (mod.mtabsize > 1)
+		qsort(mod.mtab, mod.mtabsize, sizeof(mod.mtab[0]),
+		    mtab_compare);
+fin:
+	_nsmod = vector_append(&mod, _nsmod, &_nsmodsize, sizeof(*_nsmod));
+	vector_sort(_nsmod, _nsmodsize, sizeof(*_nsmod), string_compare);
+}
+
+
+
+static void
+ns_mod_free(ns_mod *mod)
+{
+
+	free(mod->name);
+	if (mod->handle == NULL)
+		return;
+	if (mod->unregister != NULL)
+		mod->unregister(mod->mtab, mod->mtabsize);
+#ifndef __rtems__
+	if (mod->handle != nss_builtin_handle)
+		(void)dlclose(mod->handle);
+#endif
+}
+
+
+
+/*
+ * Cleanup
+ */
+static void
+nss_atexit(void)
+{
+	int isthreaded;
+
+	isthreaded = __isthreaded;
+	if (isthreaded)
+		(void)_pthread_rwlock_wrlock(&nss_lock);
+	VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
+	    (vector_free_elem)ns_dbt_free);
+	VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
+	    (vector_free_elem)ns_mod_free);
+	if (isthreaded)
+		(void)_pthread_rwlock_unlock(&nss_lock);
+}
+
+
+
+/*
+ * Finally, the actual implementation.
+ */
+static nss_method
+nss_method_lookup(const char *source, const char *database,
+    const char *method, const ns_dtab disp_tab[], void **mdata)
+{
+	ns_mod	*mod;
+	ns_mtab	*match, key;
+	int	 i;
+
+	if (disp_tab != NULL)
+		for (i = 0; disp_tab[i].src != NULL; i++)
+			if (strcasecmp(source, disp_tab[i].src) == 0) {
+				*mdata = disp_tab[i].mdata;
+				return (disp_tab[i].method);
+			}
+	mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod),
+	    string_compare);
+	if (mod != NULL && mod->handle != NULL) {
+		key.database = database;
+		key.name = method;
+		match = bsearch(&key, mod->mtab, mod->mtabsize,
+		    sizeof(mod->mtab[0]), mtab_compare);
+		if (match != NULL) {
+			*mdata = match->mdata;
+			return (match->method);
+		}
+	}
+
+	*mdata = NULL;
+	return (NULL);
+}
+
+static void
+fb_endstate(void *p)
+{
+	free(p);
+}
+
+__weak_reference(_nsdispatch, nsdispatch);
+
+int
+_nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
+	    const char *method_name, const ns_src defaults[], ...)
+{
+	va_list		 ap;
+	const ns_dbt	*dbt;
+	const ns_src	*srclist;
+	nss_method	 method, fb_method;
+	void		*mdata;
+	int		 isthreaded, serrno, i, result, srclistsize;
+	struct fb_state	*st;
+
+#ifdef NS_CACHING
+	nss_cache_data	 cache_data;
+	nss_cache_data	*cache_data_p;
+	int		 cache_flag;
+#endif
+	
+	dbt = NULL;
+	fb_method = NULL;
+
+	isthreaded = __isthreaded;
+	serrno = errno;
+	if (isthreaded) {
+		result = _pthread_rwlock_rdlock(&nss_lock);
+		if (result != 0) {
+			result = NS_UNAVAIL;
+			goto fin;
+		}
+	}
+
+	result = fb_getstate(&st);
+	if (result != 0) {
+		result = NS_UNAVAIL;
+		goto fin;
+	}
+
+	result = nss_configure();
+	if (result != 0) {
+		result = NS_UNAVAIL;
+		goto fin;
+	}
+	if (st->fb_dispatch == 0) {
+		dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap),
+		    string_compare);
+		fb_method = nss_method_lookup(NSSRC_FALLBACK, database,
+		    method_name, disp_tab, &mdata);
+	}
+
+	if (dbt != NULL) {
+		srclist = dbt->srclist;
+		srclistsize = dbt->srclistsize;
+	} else {
+		srclist = defaults;
+		srclistsize = 0;
+		while (srclist[srclistsize].name != NULL)
+			srclistsize++;
+	}
+
+#ifdef NS_CACHING
+	cache_data_p = NULL;
+	cache_flag = 0;
+#endif
+	for (i = 0; i < srclistsize; i++) {
+		result = NS_NOTFOUND;
+		method = nss_method_lookup(srclist[i].name, database,
+		    method_name, disp_tab, &mdata);
+
+		if (method != NULL) {
+#ifdef NS_CACHING
+			if (strcmp(srclist[i].name, NSSRC_CACHE) == 0 &&
+			    nss_cache_cycle_prevention_func == NULL) {
+#ifdef NS_STRICT_LIBC_EID_CHECKING
+				if (issetugid() != 0)
+					continue;
+#endif
+				cache_flag = 1;
+
+				memset(&cache_data, 0, sizeof(nss_cache_data));
+				cache_data.info = (nss_cache_info const *)mdata;
+				cache_data_p = &cache_data;
+
+				va_start(ap, defaults);
+				if (cache_data.info->id_func != NULL)
+					result = __nss_common_cache_read(retval,
+					    cache_data_p, ap);
+				else if (cache_data.info->marshal_func != NULL)
+					result = __nss_mp_cache_read(retval,
+					    cache_data_p, ap);
+				else
+					result = __nss_mp_cache_end(retval,
+					    cache_data_p, ap);
+				va_end(ap);
+			} else {
+				cache_flag = 0;
+				errno = 0;
+				va_start(ap, defaults);
+				result = method(retval, mdata, ap);
+				va_end(ap);
+			}
+#else /* NS_CACHING */
+			errno = 0;
+			va_start(ap, defaults);
+			result = method(retval, mdata, ap);
+			va_end(ap);
+#endif /* NS_CACHING */
+
+			if (result & (srclist[i].flags))
+				break;
+		} else {
+			if (fb_method != NULL) {
+				st->fb_dispatch = 1;
+				va_start(ap, defaults);
+				result = fb_method(retval,
+				    (void *)srclist[i].name, ap);
+				va_end(ap);
+				st->fb_dispatch = 0;
+			} else
+				nss_log(LOG_DEBUG, "%s, %s, %s, not found, "
+				    "and no fallback provided",
+				    srclist[i].name, database, method_name);
+		}
+	}
+
+#ifdef NS_CACHING
+	if (cache_data_p != NULL &&
+	    (result & (NS_NOTFOUND | NS_SUCCESS)) && cache_flag == 0) {
+		va_start(ap, defaults);
+		if (result == NS_SUCCESS) {
+			if (cache_data.info->id_func != NULL)
+				__nss_common_cache_write(retval, cache_data_p,
+				    ap);
+			else if (cache_data.info->marshal_func != NULL)
+				__nss_mp_cache_write(retval, cache_data_p, ap);
+		} else if (result == NS_NOTFOUND) {
+			if (cache_data.info->id_func == NULL) {
+				if (cache_data.info->marshal_func != NULL)
+					__nss_mp_cache_write_submit(retval,
+					    cache_data_p, ap);
+			} else
+				__nss_common_cache_write_negative(cache_data_p);
+		}
+		va_end(ap);
+	}
+#endif /* NS_CACHING */
+
+	if (isthreaded)
+		(void)_pthread_rwlock_unlock(&nss_lock);
+fin:
+	errno = serrno;
+	return (result);
+}
diff --git a/freebsd-userspace/lib/libc/net/nslexer.l b/freebsd-userspace/lib/libc/net/nslexer.l
new file mode 100644
index 0000000..34c79d9
--- /dev/null
+++ b/freebsd-userspace/lib/libc/net/nslexer.l
@@ -0,0 +1,119 @@
+%{
+/*	$NetBSD: nslexer.l,v 1.3 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 "namespace.h"
+#include <ctype.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+#include "nsparser.h"
+
+#define YY_NO_UNPUT
+
+%}
+
+%option yylineno
+
+BLANK		[ \t]
+CR		\n
+STRING		[a-zA-Z][a-zA-Z0-9_]*
+
+%%
+
+{BLANK}+	;			/* skip whitespace */
+
+#.*		;			/* skip comments */
+
+\\{CR}		;			/* allow continuation */
+
+{CR}		return NL;
+
+[sS][uU][cC][cC][eE][sS][sS]		return SUCCESS;
+[uU][nN][aA][vV][aA][iI][lL]		return UNAVAIL;
+[nN][oO][tT][fF][oO][uU][nN][dD]	return NOTFOUND;
+[tT][rR][yY][aA][gG][aA][iI][nN]	return TRYAGAIN;
+
+[rR][eE][tT][uU][rR][nN]		return RETURN;
+[cC][oO][nN][tT][iI][nN][uU][eE]	return CONTINUE;
+
+{STRING}	{
+			char *p;
+			int i;
+
+			if ((p = strdup(yytext)) == NULL) {
+				syslog(LOG_ERR,
+			       "NSSWITCH(nslexer): memory allocation failure");
+				return ERRORTOKEN;
+			}
+			for (i = 0; i < strlen(p); i++) {
+				if (isupper((unsigned char)p[i]))
+					p[i] = tolower((unsigned char)p[i]);
+			}
+			_nsyylval.str = p;
+			return STRING;
+		}
+
+.		return yytext[0];
+
+%%
+
+#undef _nsyywrap
+int
+_nsyywrap()
+{
+	return 1;
+} /* _nsyywrap */
+
+void
+_nsyyerror(msg)
+	const char *msg;
+{
+
+	 syslog(LOG_ERR, "NSSWITCH(nslexer): %s line %d: %s at '%s'",
+	     _PATH_NS_CONF, yylineno, msg, yytext);
+} /* _nsyyerror */
diff --git a/freebsd-userspace/lib/libc/net/nsparser.h b/freebsd-userspace/lib/libc/net/nsparser.h
new file mode 100644
index 0000000..96fd9a8
--- /dev/null
+++ b/freebsd-userspace/lib/libc/net/nsparser.h
@@ -0,0 +1,14 @@
+#define NL 257
+#define SUCCESS 258
+#define UNAVAIL 259
+#define NOTFOUND 260
+#define TRYAGAIN 261
+#define RETURN 262
+#define CONTINUE 263
+#define ERRORTOKEN 264
+#define STRING 265
+typedef union {
+	char *str;
+	int   mapval;
+} YYSTYPE;
+extern YYSTYPE _nsyylval;
diff --git a/freebsd-userspace/lib/libc/net/nsparser.y b/freebsd-userspace/lib/libc/net/nsparser.y
new file mode 100644
index 0000000..730458a
--- /dev/null
+++ b/freebsd-userspace/lib/libc/net/nsparser.y
@@ -0,0 +1,184 @@
+%{
+/*	$NetBSD: nsparser.y,v 1.3 1999/01/25 00:16:18 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>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+static	void	_nsaddsrctomap(const char *);
+
+static	ns_dbt		curdbt;
+static	ns_src		cursrc;
+%}
+
+%union {
+	char *str;
+	int   mapval;
+}
+
+%token	NL
+%token	SUCCESS UNAVAIL NOTFOUND TRYAGAIN
+%token	RETURN CONTINUE
+%token  ERRORTOKEN
+%token	<str> STRING
+
+%type	<mapval> Status Action
+
+%%
+
+File
+	:	/* empty */
+	| Lines
+	;
+
+Lines
+	: Entry
+	| Lines Entry
+	;
+
+Entry
+	: NL
+	| Database ':' NL
+		{
+			free((char*)curdbt.name);
+		}
+	| Database ':' Srclist NL
+		{
+			_nsdbtput(&curdbt);
+		}
+	| error NL
+		{
+			yyerrok;
+		}
+	;
+
+Database
+	: STRING
+		{
+			curdbt.name = yylval.str;
+			curdbt.srclist = NULL;
+			curdbt.srclistsize = 0;
+		}
+	;
+
+Srclist
+	: Item
+	| Srclist Item
+	;
+
+Item
+	: STRING
+		{
+			cursrc.flags = NS_TERMINATE;
+			_nsaddsrctomap($1);
+		}
+	| STRING '[' { cursrc.flags = NS_SUCCESS; } Criteria ']'
+		{
+			_nsaddsrctomap($1);
+		}
+	;
+
+Criteria
+	: Criterion
+	| Criteria Criterion
+	;
+
+Criterion
+	: Status '=' Action
+		{
+			if ($3)	     /* if action == RETURN set RETURN bit */
+				cursrc.flags |= $1;  
+			else	     /* else unset it */
+				cursrc.flags &= ~$1;
+		}
+	;
+
+Status
+	: SUCCESS	{ $$ = NS_SUCCESS; }
+	| UNAVAIL	{ $$ = NS_UNAVAIL; }
+	| NOTFOUND	{ $$ = NS_NOTFOUND; }
+	| TRYAGAIN	{ $$ = NS_TRYAGAIN; }
+	;
+
+Action
+	: RETURN	{ $$ = NS_ACTION_RETURN; }
+	| CONTINUE	{ $$ = NS_ACTION_CONTINUE; }
+	;
+
+%%
+
+static void
+_nsaddsrctomap(elem)
+	const char *elem;
+{
+	int		i, lineno;
+	extern int	_nsyylineno;
+	extern char *	_nsyytext;
+
+	lineno = _nsyylineno - (*_nsyytext == '\n' ? 1 : 0);
+	if (curdbt.srclistsize > 0) {
+		if (((strcasecmp(elem, NSSRC_COMPAT) == 0) &&
+		    (strcasecmp(curdbt.srclist[0].name, NSSRC_CACHE) != 0)) ||
+		    (strcasecmp(curdbt.srclist[0].name, NSSRC_COMPAT) == 0)) {
+			syslog(LOG_ERR,
+	    "NSSWITCH(nsparser): %s line %d: 'compat' used with sources, other than 'cache'",
+			    _PATH_NS_CONF, lineno);
+			free((void*)elem);
+			return;
+		}
+	}
+	for (i = 0; i < curdbt.srclistsize; i++) {
+		if (strcasecmp(curdbt.srclist[i].name, elem) == 0) {
+			syslog(LOG_ERR,
+		       "NSSWITCH(nsparser): %s line %d: duplicate source '%s'",
+			    _PATH_NS_CONF, lineno, elem);
+			free((void*)elem);
+			return;
+		}
+	}
+	cursrc.name = elem;
+	_nsdbtaddsrc(&curdbt, &cursrc);
+}
diff --git a/freebsd-userspace/lib/libc/net/nss_backends.h b/freebsd-userspace/lib/libc/net/nss_backends.h
new file mode 100644
index 0000000..9bea37b
--- /dev/null
+++ b/freebsd-userspace/lib/libc/net/nss_backends.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+/*
+ * Eventually, the implementations of existing built-in NSS functions
+ * may be moved into NSS modules and live here.
+ */
+#if 0
+NSS_BACKEND(	files,	_files_nss_module_register	)
+NSS_BACKEND(	dns,	_dns_nss_module_register	)
+NSS_BACKEND(	nis,	_nis_nss_module_register	)
+NSS_BACKEND(	compat,	_compat_nss_module_register	)
+#endif




More information about the vc mailing list