summaryrefslogtreecommitdiff
path: root/nss
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1996-06-25 08:56:57 +0000
committerRoland McGrath <roland@gnu.org>1996-06-25 08:56:57 +0000
commit5f0e6fc702296840d2daa39f83f6cb1e40073d58 (patch)
tree6e6c29e50f713eac4c87b54a6e5730fa0dedb65a /nss
parent7f8116797fdb967571c00ec1d5b19d9d06813445 (diff)
Tue Jun 25 02:59:11 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>cvs/libc-960625
* malloc/malloc.h: Declare malloc_object_allocated_size, malloc_walk. * malloc/Makefile (dist-routines): Add malloc-size, malloc-walk. * malloc/malloc-size.c: New file. * malloc/malloc-walk.c: New file. * malloc/malloc-find.c (malloc_find_object_address): Return null if PTR is outside the heap. * elf/dl-load.c (_dl_map_object): If the requested name matches the soname of a loaded object, use that object. Mon Jun 24 19:57:01 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> * Makefile (subdirs): Add nss. * inet/Makefile (routines): Add getrpcent, getrpcbyname, getrpcbynumber, getrpcent_r, getrpcbyname_r, getrpcbynumber_r. * inet/getrpcbynumber_r.c: New file. * inet/getrpcbynumber.c: New file. * inet/getrpcbyname.c: New file. * inet/getrpcbyname_r.c: New file. * inet/getrpcent_r.c: New file. * inet/getrpcent.c: New file. * nss/rpc-lookup.c: New file. * nss/nss_files/files-rpc.c: New file. * nss/Makefile (routines): Add rpc-lookup. (libnss_files-routines): Add files-rpc. * sunrpc/Makefile (routines): Remove getrpcent. * sunrpc/getrpcent.c: File removed. * nss/getXXent_r.c (REENTRANT_GETNAME): Clear NO_MORE when NIP is non-null on entry. * Makeconfig (rpath-link): Add $(nssobjdir). (nssobjdir): New variable. * Makerules: Move shared library building before objects rules, so versions are known before extra-lib.mk gets included. * extra-lib.mk (lib-noranlib): Depend on the shared object too. * pwd/getpwuid.c: Rewritten using nss. * pwd/getpwnam.c: Likewise. * pwd/getpwent.c: Likewise. * grp/getgrnam.c: Likewise. * grp/getgrgid.c: Likewise. * grp/getgrent.c: Likewise. * pwd/Makefile (routines): Add getpwent_r, getpwnam_r, getpwuid_r. * pwd/getpwent_r.c: New file. * pwd/getpwnam_r.c: New file. * pwd/getpwuid_r.c: New file. * grp/Makefile (routines): Add getgrent_r, getgrgid_r, getgrnam_r. * grp/getgrnam_r.c: New file. * grp/getgrgid_r.c: New file. * grp/getgrent_r.c: New file. * grp/Makefile (routines): Remove grpopen, grpread. * pwd/Makefile (routines): Remove pwdopen, pwdread. * grp/grpopen.c, grp/grpread.c, pwd/pwdopen.c, pwd/pwdread.c: Removed. * pwd/fgetpwent.c: Rewritten using files-parse.c. * grp/fgetgrent.c: Likewise. * nss/Makefile (routines): Add grp-lookup and pwd-lookup. * nss/pwd-lookup.c, nss/grp-lookup.c: New files. * nss/nss_files/files-grp.c: New file. * nss/nss_files/files-pwd.c: New file. * nss/Makefile (subdir-dirs): New variable; use it in vpath. * nss/nss_files/files-parse.c: New file. * nss/nss_files/files-XXX.c: New file. * nss/nss_files/files-hosts.c, nss/nss_files/files-proto.c, nss/nss_files/files-service.c, nss/nss_files/files-network.c: Rewritten using them. * nss/Makefile (libnss_files-routines): Remove files-host. Add files-hosts, files-grp, files-pwd. * nss/nss_dns/dns-network.c: Don't include <pthread.h>. Mon Jun 24 22:39:12 1996 Richard Henderson <rth@tamu.edu> * sysdeps/alpha/dl-machine.h (ELF_MACHINE_RUNTIME_TRAMPOLINE): A .plt entry now loads the .rela.plt offset directly rather than making us calculate it. Sun Jun 23 15:24:05 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu> * time/Makefile ($(installed-localtime-file) rule): Do $(make-target-directory) first. * resolv.h: Fix wrapper for resolv/resolv.h. * configure.in (ld --no-whole-archive check): Use AC_TRY_COMMAND. Compile dummy file and pass -nostdlib -nostartfiles so as not to require installed libraries. * shlib-versions (*-*-*): Set libresolv=2, libnss_files=1, libnss_dns=1. Sun Jun 23 19:42:05 1996 Ulrich Drepper <drepper@cygnus.com> * resolv/netdb.h (_PATH_NSSWITCH_CONF): New macro. * inet/herrno.c: New file. * resolv/res_init.c: Remove res_hconf calls. * nss/Makefile, nss/XXX-lookup.c, nss/file-lookup.c, nss/getXXbyYY.c, nss/getXXbyYY_r.c, nss/getXXent.c, nss/getXXent_r.c, nss/host-lookup.c, nss/network-lookup.c, nss/nsswitch.c, nss/nsswitch.h, nss/proto-lookup.c, nss/service-lookup.c: New files. Implementation of name service switch, following the approach in Solaris. Interface specification and general structure inspired by Peter Eriksson <pen@lysator.liu.se>. * nss/nss_files/files-host.c, nss/nss_files/files-network.c, nss/nss_files/files-proto.c, nss/nss_files/files-service.c: Implementation of libnss_files.so module for file based databases in NSS service. * nss/nss_dns/dns-host.c, nss/nss_dns/dns-network.c: Implementation if libnss_dns.so module for DNS name lookup in NSS service. * inet/getproto.c, inet/getprtent.c, inet/getprtname.c, inet/getservent.c, inet/getsrvbynm.c, inet/getsrvbypt.c: Changed to serve as interface to NSS. * inet/gethstbyad.c, inet/gethstbyad_r.c, inet/gethstbynm.c, inet/gethstbynm2.c, inet/gethstbynm2_r.c, inet/gethstbynm_r.c, inet/gethstent.c, inet/gethstent_r.c, inet/getnetbynm.c, inet/getnetbynm_r.c, inet/getnetbypt.c, inet/getnetbypt_r.c, inet/getnetent.c, inet/getnetent_r.c, inet/getproto_r.c, inet/getprtent_r.c, inet/getprtname_r.c, inet/getservent_r.c, inet/getsrvbynm_r.c, inet/getsrvbypt_r.c: New files. Implement interfaces to NSS, including reentrant functions. * resolv/getnetbyaddr.c, resolv/getnetbyname.c, resolv/getnetent.c, resolv/sethostent.c: Removed: Obsoleted by NSS. * resolv/mapv4v6addr.h, resolv/mapv4v6hostent.h: Extracted from gethnamaddr.c. These private functions are now used in more than one file. * resolv/inet_pton.c, resolv/gethnamaddr.c: Updated to bind-4.9.4-T5B. Sat Jun 22 16:49:47 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * rpm/Makefile ($(config)): Make sure the word list in the for loop is syntactically non-empty.
Diffstat (limited to 'nss')
-rw-r--r--nss/Makefile57
-rw-r--r--nss/XXX-lookup.c51
-rw-r--r--nss/file-lookup.c22
-rw-r--r--nss/getXXbyYY.c71
-rw-r--r--nss/getXXbyYY_r.c129
-rw-r--r--nss/getXXent.c63
-rw-r--r--nss/getXXent_r.c222
-rw-r--r--nss/grp-lookup.c22
-rw-r--r--nss/host-lookup.c22
-rw-r--r--nss/network-lookup.c22
-rw-r--r--nss/nss_dns/dns-host.c611
-rw-r--r--nss/nss_dns/dns-network.c338
-rw-r--r--nss/nss_files/files-XXX.c221
-rw-r--r--nss/nss_files/files-grp.c49
-rw-r--r--nss/nss_files/files-hosts.c111
-rw-r--r--nss/nss_files/files-network.c54
-rw-r--r--nss/nss_files/files-parse.c171
-rw-r--r--nss/nss_files/files-proto.c48
-rw-r--r--nss/nss_files/files-pwd.c54
-rw-r--r--nss/nss_files/files-rpc.c48
-rw-r--r--nss/nss_files/files-service.c51
-rw-r--r--nss/nsswitch.c588
-rw-r--r--nss/nsswitch.h138
-rw-r--r--nss/proto-lookup.c22
-rw-r--r--nss/pwd-lookup.c22
-rw-r--r--nss/rpc-lookup.c22
-rw-r--r--nss/service-lookup.c22
27 files changed, 3251 insertions, 0 deletions
diff --git a/nss/Makefile b/nss/Makefile
new file mode 100644
index 0000000000..91c4ef7380
--- /dev/null
+++ b/nss/Makefile
@@ -0,0 +1,57 @@
+# Copyright (C) 1996 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#
+# Makefile for name service switch.
+#
+subdir := nss
+
+distribute := nsswitch.h XXX-lookup.c getXXbyYY.c getXXbyYY_r.c \
+ getXXent.c getXXent_r.c
+
+# This is the trivial part which goes into libc itself.
+routines := nsswitch \
+ $(addsuffix -lookup,proto service host network \
+ grp pwd rpc)
+
+
+# Specify rules for the nss_* modules. We have some services.
+services := files dns
+
+extra-libs = $(services:%=libnss_%)
+
+# The sources are found in the appropriate subdir.
+subdir-dirs = nss_files nss_dns
+vpath %.c $(subdir-dirs)
+
+
+libnss_files-routines := files-proto files-service files-network \
+ files-hosts files-grp files-pwd files-rpc
+distribute += files-XXX.c files-parse.c
+
+libnss_dns-routines := dns-host dns-network
+
+libnss_files-inhibit-o = $(filter-out .so,$(object-suffixes))
+libnss_dns-inhibit-o = $(filter-out .so,$(object-suffixes))
+
+
+include ../Rules
+
+
+resobjdir := $(firstword $(objdir) $(patsubst ../$(subdir),.,$(..)resolv))
+LDLIBS-nss_dns.so = -L$(resobjdir) -Wl,-rpath-link=$(resobjdir) -lresolv
diff --git a/nss/XXX-lookup.c b/nss/XXX-lookup.c
new file mode 100644
index 0000000000..1f8cbbf015
--- /dev/null
+++ b/nss/XXX-lookup.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "nsswitch.h"
+
+/*******************************************************************\
+|* Here we assume one symbol to be defined: *|
+|* *|
+|* DATABASE_NAME - name of the database the function accesses *|
+|* (e.g., hosts, servicess, ...) *|
+|* *|
+\*******************************************************************/
+
+#define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
+#define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
+#define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
+
+#define DATABASE_NAME_STRING STRINGIFY1 (DATABASE_NAME)
+#define STRINGIFY1(Name) STRINGIFY2 (Name)
+#define STRINGIFY2(Name) #Name
+
+
+static service_user *database = NULL;
+
+int
+DB_LOOKUP_FCT (service_user **ni, const char *fct_name, void **fctp)
+{
+ if (database == NULL
+ && __nss_database_lookup (DATABASE_NAME_STRING, &database) < 0)
+ return -1;
+
+ *ni = database;
+
+ return __nss_lookup (ni, fct_name, fctp);
+}
diff --git a/nss/file-lookup.c b/nss/file-lookup.c
new file mode 100644
index 0000000000..d9f7c67320
--- /dev/null
+++ b/nss/file-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME hosts
+
+#include "XXX-lookup.c"
diff --git a/nss/getXXbyYY.c b/nss/getXXbyYY.c
new file mode 100644
index 0000000000..5eb9ee9c87
--- /dev/null
+++ b/nss/getXXbyYY.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "../nss/nsswitch.h"
+
+/*******************************************************************\
+|* Here we assume several symbols to be defined: *|
+|* *|
+|* LOOKUP_TYPE - the return type of the function *|
+|* *|
+|* FUNCTION_NAME - name of the non-reentrant function *|
+|* *|
+|* DATABASE_NAME - name of the database the function accesses *|
+|* (e.g., host, services, ...) *|
+|* *|
+|* ADD_PARAMS - additional parameter, can vary in number *|
+|* *|
+|* ADD_VARIABLES - names of additional parameter *|
+|* *|
+|* BUFLEN - length of buffer allocated for the non *|
+|* reentrant version *|
+|* *|
+|* Optionally the following vars can be defined: *|
+|* *|
+|* NEED_H_ERRNO - an extra parameter will be passed to point to *|
+|* the global `h_errno' variable. *|
+|* *|
+\*******************************************************************/
+
+/* To make the real sources a bit prettier. */
+#define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
+#define APPEND_R(name) APPEND_R1 (name)
+#define APPEND_R1(name) name##_r
+
+/* Sometimes we need to store error codes in the `h_errno' variable. */
+#ifdef NEED_H_ERRNO
+# define H_ERRNO_PARM , int *h_errnop
+# define H_ERRNO_VAR , &h_errno
+#else
+# define H_ERRNO_PARM
+# define H_ERRNO_VAR
+#endif
+
+
+/* Prototype for reentrant version we use here. */
+extern LOOKUP_TYPE *REENTRANT_NAME (ADD_PARAMS, LOOKUP_TYPE *result,
+ char *buffer, int buflen H_ERRNO_PARM);
+
+LOOKUP_TYPE *
+FUNCTION_NAME (ADD_PARAMS)
+{
+ static LOOKUP_TYPE result;
+ static char buffer[BUFLEN];
+
+ return REENTRANT_NAME (ADD_VARIABLES, &result, buffer, BUFLEN H_ERRNO_VAR);
+}
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
new file mode 100644
index 0000000000..42092361be
--- /dev/null
+++ b/nss/getXXbyYY_r.c
@@ -0,0 +1,129 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "nsswitch.h"
+
+/*******************************************************************\
+|* Here we assume several symbols to be defined: *|
+|* *|
+|* LOOKUP_TYPE - the return type of the function *|
+|* *|
+|* FUNCTION_NAME - name of the non-reentrant function *|
+|* *|
+|* DATABASE_NAME - name of the database the function accesses *|
+|* (e.g., host, services, ...) *|
+|* *|
+|* ADD_PARAMS - additional parameter, can vary in number *|
+|* *|
+|* ADD_VARIABLES - names of additional parameter *|
+|* *|
+|* Optionally the following vars can be defined: *|
+|* *|
+|* NEED_H_ERRNO - an extra parameter will be passed to point to *|
+|* the global `h_errno' variable. *|
+|* *|
+|* NEED__RES - the global _res variable might be used so we *|
+|* will have to initialize it if necessary *|
+|* *|
+\*******************************************************************/
+
+/* To make the real sources a bit prettier. */
+#define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
+#define APPEND_R(name) APPEND_R1 (name)
+#define APPEND_R1(name) name##_r
+
+#define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME)
+#define REENTRANT_NAME_STRING STRINGIZE (REENTRANT_NAME)
+#define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
+#define STRINGIZE(name) STRINGIZE1 (name)
+#define STRINGIZE1(name) #name
+
+#define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
+#define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
+#define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
+
+/* Sometimes we need to store error codes in the `h_errno' variable. */
+#ifdef NEED_H_ERRNO
+# define H_ERRNO_PARM , int *h_errnop
+# define H_ERRNO_VAR , h_errnop
+#else
+# define H_ERRNO_PARM
+# define H_ERRNO_VAR
+#endif
+
+
+/* Type of the lookup function we need here. */
+typedef int (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *, int
+ H_ERRNO_PARM);
+
+/* Some usages of this file might use this variable. */
+extern struct __res_state _res;
+
+/* The lookup function for the first entry of this service. */
+extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp);
+
+
+
+LOOKUP_TYPE *
+REENTRANT_NAME (ADD_PARAMS, LOOKUP_TYPE *result, char *buffer, int buflen
+ H_ERRNO_PARM)
+{
+ static service_user *startp = NULL;
+ static lookup_function start_fct;
+ service_user *nip;
+ lookup_function fct;
+ int no_more;
+ enum nss_status status = NSS_STATUS_UNAVAIL;
+
+ if (startp == NULL)
+ {
+ no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING, (void **) &fct);
+ if (no_more)
+ startp = (service_user *) -1;
+ else
+ {
+ startp = nip;
+ start_fct = fct;
+
+#ifdef NEED__RES
+ /* The resolver code will really be used so we have to
+ initialize it. */
+ if ((_res.options & RES_INIT) == 0 && res_init () == -1)
+ {
+ h_errno = NETDB_INTERNAL;
+ return NULL;
+ }
+#endif /* need _res */
+ }
+ }
+ else
+ {
+ fct = start_fct;
+ no_more = (nip = startp) == (service_user *) -1;
+ }
+
+ while (no_more == 0)
+ {
+ status = (*fct) (ADD_VARIABLES, result, buffer, buflen H_ERRNO_VAR);
+
+ no_more = __nss_next (&nip, REENTRANT_NAME_STRING, &fct, status, 0);
+ }
+
+ return status == NSS_STATUS_SUCCESS ? result : NULL;
+}
diff --git a/nss/getXXent.c b/nss/getXXent.c
new file mode 100644
index 0000000000..da3712c70f
--- /dev/null
+++ b/nss/getXXent.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "nsswitch.h"
+
+/*******************************************************************\
+|* Here we assume several symbols to be defined: *|
+|* *|
+|* LOOKUP_TYPE - the return type of the function *|
+|* *|
+|* GETFUNC_NAME - name of the non-reentrant getXXXent function *|
+|* *|
+|* BUFLEN - size of static buffer *|
+|* *|
+|* Optionally the following vars can be defined: *|
+|* *|
+|* NEED_H_ERRNO - an extra parameter will be passed to point to *|
+|* the global `h_errno' variable. *|
+|* *|
+\*******************************************************************/
+
+/* To make the real sources a bit prettier. */
+#define REENTRANT_GETNAME APPEND_R (GETFUNC_NAME)
+#define APPEND_R(name) APPEND_R1 (name)
+#define APPEND_R1(name) name##_r
+
+/* Sometimes we need to store error codes in the `h_errno' variable. */
+#ifdef NEED_H_ERRNO
+# define H_ERRNO_PARM , int *h_errnop
+# define H_ERRNO_VAR , &h_errno
+#else
+# define H_ERRNO_PARM
+# define H_ERRNO_VAR
+#endif
+
+/* Prototype of the reentrant version. */
+LOOKUP_TYPE *REENTRANT_GETNAME (LOOKUP_TYPE *result, char *buffer,
+ int buflen H_ERRNO_PARM);
+
+
+LOOKUP_TYPE *
+GETFUNC_NAME (void)
+{
+ static char buffer[BUFLEN];
+ LOOKUP_TYPE result;
+
+ return REENTRANT_GETNAME (&result, buffer, BUFLEN H_ERRNO_VAR);
+}
diff --git a/nss/getXXent_r.c b/nss/getXXent_r.c
new file mode 100644
index 0000000000..3d1e9593e6
--- /dev/null
+++ b/nss/getXXent_r.c
@@ -0,0 +1,222 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <libc-lock.h>
+
+#include "nsswitch.h"
+
+/*******************************************************************\
+|* Here we assume several symbols to be defined: *|
+|* *|
+|* LOOKUP_TYPE - the return type of the function *|
+|* *|
+|* SETFUNC_NAME - name of the non-reentrant setXXXent function *|
+|* *|
+|* GETFUNC_NAME - name of the non-reentrant getXXXent function *|
+|* *|
+|* ENDFUNC_NAME - name of the non-reentrant endXXXent function *|
+|* *|
+|* DATABASE_NAME - name of the database the function accesses *|
+|* (e.g., host, services, ...) *|
+|* *|
+|* Optionally the following vars can be defined: *|
+|* *|
+|* STAYOPEN - variable declaration for setXXXent function *|
+|* *|
+|* STAYOPEN_VAR - variable name for setXXXent function *|
+|* *|
+|* NEED_H_ERRNO - an extra parameter will be passed to point to *|
+|* the global `h_errno' variable. *|
+|* *|
+\*******************************************************************/
+
+/* To make the real sources a bit prettier. */
+#define REENTRANT_GETNAME APPEND_R (GETFUNC_NAME)
+#define APPEND_R(name) APPEND_R1 (name)
+#define APPEND_R1(name) name##_r
+
+#define SETFUNC_NAME_STRING STRINGIZE (SETFUNC_NAME)
+#define GETFUNC_NAME_STRING STRINGIZE (GETFUNC_NAME)
+#define ENDFUNC_NAME_STRING STRINGIZE (ENDFUNC_NAME)
+#define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
+#define STRINGIZE(name) STRINGIZE1 (name)
+#define STRINGIZE1(name) #name
+
+#define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
+#define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
+#define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
+
+/* Sometimes we need to store error codes in the `h_errno' variable. */
+#ifdef NEED_H_ERRNO
+# define H_ERRNO_PARM , int *h_errnop
+# define H_ERRNO_VAR , &h_errno
+#else
+# define H_ERRNO_PARM
+# define H_ERRNO_VAR
+#endif
+
+/* Some databases take the `stayopen' flag. */
+#ifndef STAYOPEN
+#define STAYOPEN void
+#define STAYOPEN_VAR
+#endif
+
+/* Prototype for the setXXXent functions we use here. */
+typedef int (*set_function) (STAYOPEN);
+
+/* Prototype for the endXXXent functions we use here. */
+typedef int (*end_function) (void);
+
+/* Prototype for the setXXXent functions we use here. */
+typedef int (*get_function) (LOOKUP_TYPE *, char *, int H_ERRNO_PARM);
+
+
+/* This handle for the NSS data base is shared between all
+ set/get/endXXXent functions. */
+static service_user *nip;
+/* Remember the first service_entry, it's always the same. */
+static service_user *startp;
+
+/* Protect above variable against multiple uses at the same time. */
+__libc_lock_define_initialized (static, lock);
+
+/* The lookup function for the first entry of this service. */
+extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp);
+
+
+void
+APPEND_R (SETFUNC_NAME) (STAYOPEN)
+{
+ set_function fct;
+ int no_more;
+
+#ifdef NEED__RES
+ if ((_res.options & RES_INIT) == 0 && res_init () == -1)
+ {
+ h_errno = NETDB_INTERNAL;
+ return NULL;
+ }
+#endif /* need _res */
+
+ __libc_lock_lock (lock);
+
+ if (startp == NULL)
+ {
+ no_more = DB_LOOKUP_FCT (&nip, SETFUNC_NAME_STRING, (void **) &fct);
+ startp = no_more == 0 ? (service_user *) -1 : nip;
+ }
+ else
+ no_more = (nip = startp) != (service_user *) -1;
+
+ /* Cycle through all the services and run their setXXent functions. */
+ while (! no_more)
+ {
+ /* Ignore status, we force check in __NSS_NEXT. */
+ (void) (*fct) (STAYOPEN_VAR);
+
+ no_more = __nss_next (&nip, SETFUNC_NAME_STRING, (void **) &fct, 0, 1);
+ }
+
+ __libc_lock_unlock (lock);
+}
+
+
+void
+APPEND_R (ENDFUNC_NAME) (void)
+{
+ end_function fct;
+ int no_more;
+
+#ifdef NEED__RES
+ if ((_res.options & RES_INIT) == 0 && res_init () == -1)
+ {
+ h_errno = NETDB_INTERNAL;
+ return NULL;
+ }
+#endif /* need _res */
+
+ __libc_lock_lock (lock);
+
+ if (startp == NULL)
+ {
+ no_more = DB_LOOKUP_FCT (&nip, SETFUNC_NAME_STRING, (void **) &fct);
+ startp = no_more == 0 ? (service_user *) -1 : nip;
+ }
+ else
+ no_more = (nip = startp) != (service_user *) -1;
+
+ /* Cycle through all the services and run their endXXent functions. */
+ while (no_more == 0)
+ {
+ /* Ignore status, we force check in __NSS_NEXT. */
+ (void) (*fct) ();
+
+ no_more = __nss_next (&nip, ENDFUNC_NAME_STRING, (void **) &fct, 0, 1);
+ }
+
+ __libc_lock_unlock (lock);
+}
+
+
+LOOKUP_TYPE *
+REENTRANT_GETNAME (LOOKUP_TYPE *result, char *buffer, int buflen H_ERRNO_PARM)
+{
+ get_function fct;
+ int no_more;
+ enum nss_status status = NSS_STATUS_NOTFOUND;
+
+#ifdef NEED__RES
+ if ((_res.options & RES_INIT) == 0 && res_init () == -1)
+ {
+ h_errno = NETDB_INTERNAL;
+ return NULL;
+ }
+#endif /* need _res */
+
+ __libc_lock_lock (lock);
+
+ if (nip)
+ /* Continuing a walk-through started before. */
+ no_more = 0;
+ else
+ {
+ if (startp == NULL)
+ {
+ no_more = DB_LOOKUP_FCT (&nip, SETFUNC_NAME_STRING, (void **) &fct);
+ startp = no_more == 0 ? (service_user *) -1 : nip;
+ }
+ else
+ no_more = (nip = startp) != (service_user *) -1;
+
+ if (no_more != 0)
+ status = NSS_STATUS_UNAVAIL;
+ }
+
+ while (no_more == 0)
+ {
+ status = (*fct) (result, buffer, buflen H_ERRNO_VAR);
+
+ no_more = __nss_next (&nip, GETFUNC_NAME_STRING, (void **) &fct,
+ status, 0);
+ }
+
+ __libc_lock_unlock (lock);
+
+ return status == NSS_STATUS_SUCCESS ? result : NULL;
+}
diff --git a/nss/grp-lookup.c b/nss/grp-lookup.c
new file mode 100644
index 0000000000..ce3753c665
--- /dev/null
+++ b/nss/grp-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME group
+
+#include "XXX-lookup.c"
diff --git a/nss/host-lookup.c b/nss/host-lookup.c
new file mode 100644
index 0000000000..d9f7c67320
--- /dev/null
+++ b/nss/host-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME hosts
+
+#include "XXX-lookup.c"
diff --git a/nss/network-lookup.c b/nss/network-lookup.c
new file mode 100644
index 0000000000..ab6e51f5c4
--- /dev/null
+++ b/nss/network-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME networks
+
+#include "XXX-lookup.c"
diff --git a/nss/nss_dns/dns-host.c b/nss/nss_dns/dns-host.c
new file mode 100644
index 0000000000..eaa9e81218
--- /dev/null
+++ b/nss/nss_dns/dns-host.c
@@ -0,0 +1,611 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Parts of this file are plain copies of the file `getnetnamadr.c' from
+ the bind package and it has the following copyright. */
+
+/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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 University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/syslog.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#include "nsswitch.h"
+
+/* Get implementation for some internal functions. */
+#include "../resolv/mapv4v6addr.h"
+#include "../resolv/mapv4v6hostent.h"
+
+/* Maximum number of aliases we allow. */
+#define MAX_NR_ALIASES 48
+#define MAX_NR_ADDRS 48
+
+#if PACKETSZ > 1024
+# define MAXPACKET PACKETSZ
+#else
+# define MAXPACKET 1024
+#endif
+
+static const char AskedForGot[] = "\
+gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+
+
+/* We need this time later. */
+typedef union querybuf
+{
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+
+static enum nss_status getanswer_r (const querybuf *answer, int anslen,
+ const char *qname, int qtype,
+ struct hostent *result,
+ char *buffer, int buflen, int *h_errnop);
+
+enum nss_status
+_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
+ char *buffer, int buflen, int *h_errnop)
+{
+ struct host_data
+ {
+ char *aliases[MAX_NR_ALIASES];
+ unsigned char host_addr[16]; /* IPv4 or IPv6 */
+ char *h_addr_ptrs[MAX_NR_ADDRS + 1];
+ char linebuffer[0];
+ } *host_data = (struct host_data *) buffer;
+ int linebuflen = buflen - offsetof (struct host_data, linebuffer);
+ querybuf host_buffer;
+ int size, type, n;
+ const char *cp;
+
+ switch (af) {
+ case AF_INET:
+ size = INADDRSZ;
+ type = T_A;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ type = T_AAAA;
+ break;
+ default:
+ *h_errnop = NETDB_INTERNAL;
+ errno = EAFNOSUPPORT;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ result->h_addrtype = af;
+ result->h_length = size;
+
+ /*
+ * if there aren't any dots, it could be a user-level alias.
+ * this is also done in res_query() since we are not the only
+ * function that looks up host names.
+ */
+ if (strchr (name, '.') == NULL && (cp = __hostalias (name)) != NULL)
+ name = cp;
+
+ /*
+ * disallow names consisting only of digits/dots, unless
+ * they end in a dot.
+ */
+ if (isdigit (name[0]))
+ for (cp = name;; ++cp)
+ {
+ if (*cp == '\0')
+ {
+ char *bp;
+
+ if (*--cp == '.')
+ break;
+ /*
+ * All-numeric, no dot at the end. Fake up a hostent
+ * as if we'd actually done a lookup.
+ */
+ if (inet_pton (af, name, host_data->host_addr) <= 0)
+ {
+ *h_errnop = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ bp = __stpncpy (host_data->linebuffer, name, linebuflen);
+ host_data->linebuffer[linebuflen - 1] = '\0';
+ linebuflen -= bp - host_data->linebuffer;
+
+ result->h_name = host_data->linebuffer;
+ result->h_aliases = host_data->aliases;
+ host_data->aliases[0] = NULL;
+ host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
+ host_data->h_addr_ptrs[1] = NULL;
+ result->h_addr_list = host_data->h_addr_ptrs;
+
+ if (_res.options & RES_USE_INET6)
+ map_v4v6_hostent (result, &bp, &linebuflen);
+ *h_errnop = NETDB_SUCCESS;
+ return NSS_STATUS_SUCCESS;
+ }
+ if (!isdigit (*cp) && *cp != '.')
+ break;
+ }
+
+ n = res_search (name, C_IN, type, host_buffer.buf, sizeof (host_buffer));
+ if (n < 0)
+ return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+
+ return getanswer_r (&host_buffer, n, name, type, result, buffer, buflen,
+ h_errnop);
+}
+
+
+enum nss_status
+_nss_dns_gethostbyname_r (const char *name, struct hostent *result,
+ char *buffer, int buflen, int *h_errnop)
+{
+ enum nss_status status = NSS_STATUS_NOTFOUND;
+
+ if (_res.options & RES_USE_INET6)
+ status = _nss_dns_gethostbyname2_r (name, AF_INET6, result, buffer,
+ buflen, h_errnop);
+ if (status == NSS_STATUS_NOTFOUND)
+ status = _nss_dns_gethostbyname2_r (name, AF_INET, result, buffer,
+ buflen, h_errnop);
+
+ return status;
+}
+
+
+enum nss_status
+_nss_dns_gethostbyaddr_r (const char *addr, int len, int af,
+ struct hostent *result, char *buffer, int buflen,
+ int *h_errnop)
+{
+ static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
+ static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
+ const u_char *uaddr = (const u_char *)addr;
+ struct host_data
+ {
+ char *aliases[MAX_NR_ALIASES];
+ unsigned char host_addr[16]; /* IPv4 or IPv6 */
+ char *h_addr_ptrs[MAX_NR_ADDRS + 1];
+ char linebuffer[0];
+ } *host_data = (struct host_data *) buffer;
+ querybuf host_buffer;
+ char qbuf[MAXDNAME+1], *qp;
+ int size, n, status;
+
+ if (af == AF_INET6 && len == IN6ADDRSZ &&
+ (bcmp (uaddr, mapped, sizeof mapped) == 0
+ || bcmp (uaddr, tunnelled, sizeof tunnelled) == 0))
+ {
+ /* Unmap. */
+ addr += sizeof mapped;
+ uaddr += sizeof mapped;
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+
+ switch (af)
+ {
+ case AF_INET:
+ size = INADDRSZ;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
+ if (size != len)
+ {
+ errno = EAFNOSUPPORT;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ switch (af)
+ {
+ case AF_INET:
+ sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff),
+ (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
+ break;
+ case AF_INET6:
+ qp = qbuf;
+ for (n = IN6ADDRSZ - 1; n >= 0; n--)
+ qp += sprintf (qp, "%x.%x.", uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
+ strcpy(qp, "ip6.int");
+ break;
+ default:
+ /* Cannot happen. */
+ }
+
+ n = res_query (qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
+ sizeof host_buffer);
+ if (n < 0)
+ return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+
+ status = getanswer_r (&host_buffer, n, qbuf, T_PTR, result, buffer, buflen,
+ h_errnop);
+ if (status != NSS_STATUS_SUCCESS)
+ return status;
+
+#ifdef SUNSECURITY
+ This is not implemented because it is not possible to use the current
+ source from bind in a multi-threaded program.
+#endif
+
+ result->h_addrtype = af;
+ result->h_length = len;
+ bcopy (addr, host_data->host_addr, len);
+ host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
+ host_data->h_addr_ptrs[1] = NULL;
+ if (af == AF_INET && (_res.options & RES_USE_INET6))
+ {
+ map_v4v6_address ((char *) host_data->host_addr,
+ (char *) host_data->host_addr);
+ result->h_addrtype = AF_INET6;
+ result->h_length = IN6ADDRSZ;
+ }
+ *h_errnop = NETDB_SUCCESS;
+ return NSS_STATUS_SUCCESS;
+}
+
+
+static enum nss_status
+getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
+ struct hostent *result, char *buffer, int buflen, int *h_errnop)
+{
+ struct host_data
+ {
+ char *aliases[MAX_NR_ALIASES];
+ unsigned char host_addr[16]; /* IPv4 or IPv6 */
+ char *h_addr_ptrs[MAX_NR_ADDRS + 1];
+ char linebuffer[0];
+ } *host_data = (struct host_data *) buffer;
+ int linebuflen = buflen - offsetof (struct host_data, linebuffer);
+ register const HEADER *hp;
+ const u_char *end_of_message, *cp;
+ int n, ancount, qdcount;
+ int haveanswer, had_error;
+ char *bp, **ap, **hap;
+ char tbuf[MAXDNAME+1];
+ const char *tname;
+ int (*name_ok) __P ((const char *));
+
+ tname = qname;
+ result->h_name = NULL;
+ end_of_message = answer->buf + anslen;
+ switch (qtype)
+ {
+ case T_A:
+ case T_AAAA:
+ name_ok = res_hnok;
+ break;
+ case T_PTR:
+ name_ok = res_dnok;
+ break;
+ default:
+ return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
+ }
+
+ /*
+ * find first satisfactory answer
+ */
+ hp = &answer->hdr;
+ bp = host_data->linebuffer;
+ ancount = ntohs (hp->ancount);
+ qdcount = ntohs (hp->qdcount);
+ cp = answer->buf + HFIXEDSZ;
+ if (qdcount != 1)
+ {
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+ if (n < 0 || (*name_ok) (bp) == 0)
+ {
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_UNAVAIL;
+ }
+ cp += n + QFIXEDSZ;
+
+ if (qtype == T_A || qtype == T_AAAA)
+ {
+ /* res_send() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = strlen (bp) + 1; /* for the \0 */
+ result->h_name = bp;
+ bp += n;
+ linebuflen -= n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = result->h_name;
+ }
+
+ ap = host_data->aliases;
+ *ap = NULL;
+ result->h_aliases = host_data->aliases;
+ hap = host_data->h_addr_ptrs;
+ *hap = NULL;
+ result->h_addr_list = host_data->h_addr_ptrs;
+ haveanswer = 0;
+ had_error = 0;
+
+ while (ancount-- > 0 && cp < end_of_message && had_error == 0)
+ {
+ int type, class;
+
+ n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+ if (n < 0 || (*name_ok) (bp) == 0)
+ {
+ ++had_error;
+ continue;
+ }
+ cp += n; /* name */
+ type = _getshort (cp);
+ cp += INT16SZ; /* type */
+ class = _getshort(cp);
+ cp += INT16SZ + INT32SZ; /* class, TTL */
+ n = _getshort(cp);
+ cp += INT16SZ; /* len */
+ if (class != C_IN)
+ {
+ /* XXX - debug? syslog? */
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+
+ if ((qtype ==T_A || qtype == T_AAAA) && type == T_CNAME)
+ {
+ if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
+ continue;
+ n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
+ if (n < 0 || (*name_ok) (tbuf) == 0)
+ {
+ ++had_error;
+ continue;
+ }
+ cp += n;
+ /* Store alias. */
+ *ap++ = bp;
+ n = strlen (bp) + 1; /* For the \0. */
+ bp += n;
+ linebuflen -= n;
+ /* Get canonical name. */
+ n = strlen (tbuf) + 1; /* For the \0. */
+ if (n > buflen)
+ {
+ ++had_error;
+ continue;
+ }
+ strcpy (bp, tbuf);
+ result->h_name = bp;
+ bp += n;
+ linebuflen -= n;
+ continue;
+ }
+
+ if (qtype == T_PTR && type == T_CNAME)
+ {
+ n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
+ if (n < 0 || res_hnok (tbuf) == 0)
+ {
+ ++had_error;
+ continue;
+ }
+ cp += n;
+ /* Get canonical name. */
+ n = strlen (tbuf) + 1; /* For the \0. */
+ if (n > buflen)
+ {
+ ++had_error;
+ continue;
+ }
+ strcpy (bp, tbuf);
+ tname = bp;
+ bp += n;
+ linebuflen -= n;
+ continue;
+ }
+ if (type != qtype)
+ {
+ syslog (LOG_NOTICE | LOG_AUTH,
+ "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+ qname, p_class (C_IN), p_type (qtype), p_type (type));
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+
+ switch (type)
+ {
+ case T_PTR:
+ if (strcasecmp (tname, bp) != 0)
+ {
+ syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+ if (n < 0 || res_hnok (bp) == 0)
+ {
+ ++had_error;
+ break;
+ }
+#if MULTI_PTRS_ARE_ALIASES
+ cp += n;
+ if (haveanswer == 0)
+ result->h_name = bp;
+ else if (ap < &host_data->aliases[MAXALIASES-1])
+ *ap++ = bp;
+ else
+ n = -1;
+ if (n != -1)
+ {
+ n = strlen (bp) + 1; /* for the \0 */
+ bp += n;
+ linebuflen -= n;
+ }
+ break;
+#else
+ result->h_name = bp;
+ if (_res.options & RES_USE_INET6)
+ {
+ n = strlen (bp) + 1; /* for the \0 */
+ bp += n;
+ linebuflen -= n;
+ map_v4v6_hostent (result, &bp, &linebuflen);
+ }
+ *h_errnop = NETDB_SUCCESS;
+ return NSS_STATUS_SUCCESS;
+#endif
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp (result->h_name, bp) != 0)
+ {
+ syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (haveanswer)
+ {
+ if (n != result->h_length)
+ {
+ cp += n;
+ continue;
+ }
+ }
+ else
+ {
+ register int nn;
+
+ result->h_name = bp;
+ nn = strlen (bp) + 1; /* for the \0 */
+ bp += nn;
+ linebuflen -= nn;
+ }
+
+ bp += sizeof (align) - ((u_long) bp % sizeof (align));
+
+ if (n >= linebuflen)
+ {
+ ++had_error;
+ continue;
+ }
+ if (hap >= &host_data->h_addr_ptrs[MAX_NR_ADDRS-1])
+ {
+ cp += n;
+ continue;
+ }
+ bcopy (cp, *hap++ = bp, n);
+ bp += n;
+ cp += n;
+ linebuflen -= n;
+ break;
+ default:
+ abort ();
+ }
+ if (had_error == 0)
+ ++haveanswer;
+ }
+
+ if (haveanswer > 0)
+ {
+ *ap = NULL;
+ *hap = NULL;
+#if defined(RESOLVSORT)
+ /*
+ * Note: we sort even if host can take only one address
+ * in its return structures - should give it the "best"
+ * address in that case, not some random one
+ */
+ if (_res.nsort && haveanswer > 1 && qtype == T_A)
+ addrsort (host_data->h_addr_ptrs, haveanswer);
+#endif /*RESOLVSORT*/
+
+ if (result->h_name == NULL)
+ {
+ n = strlen (qname) + 1; /* For the \0. */
+ if (n > linebuflen)
+ goto try_again;
+ strcpy (bp, qname);
+ result->h_name = bp;
+ bp += n;
+ linebuflen -= n;
+ }
+
+ if (_res.options & RES_USE_INET6)
+ map_v4v6_hostent (result, &bp, &linebuflen);
+ *h_errnop = NETDB_SUCCESS;
+ return NSS_STATUS_SUCCESS;
+ }
+try_again:
+ *h_errnop = TRY_AGAIN;
+ return NSS_STATUS_TRYAGAIN;
+}
diff --git a/nss/nss_dns/dns-network.c b/nss/nss_dns/dns-network.c
new file mode 100644
index 0000000000..b714128f1d
--- /dev/null
+++ b/nss/nss_dns/dns-network.c
@@ -0,0 +1,338 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Parts of this file are plain copies of the file `getnetnamadr.c' from
+ the bind package and it has the following copyright. */
+
+/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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 University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nsswitch.h"
+#include <arpa/inet.h>
+
+/* Maximum number of aliases we allow. */
+#define MAX_NR_ALIASES 48
+
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+
+typedef enum
+{
+ BYADDR,
+ BYNAME
+} lookup_method;
+
+
+/* We need this time later. */
+typedef union querybuf
+{
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+
+/* Protortypes for local functions. */
+static int getanswer_r (const querybuf *answer, int anslen,
+ struct netent *result, char *buffer, int buflen,
+ lookup_method net_i);
+
+
+int
+_nss_dns_getnetbyname_r (const char *name, struct netent *result,
+ char *buffer, int buflen)
+{
+ /* Return entry for network with NAME. */
+ querybuf net_buffer;
+ int anslen;
+ char *qbuf;
+
+ qbuf = strdupa (name);
+ anslen = res_search (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
+ sizeof (querybuf));
+ if (anslen < 0)
+ /* Nothing found. */
+ return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+
+ return getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYNAME);
+}
+
+
+int
+_nss_dns_getnetbyaddr_r (long net, int type, struct netent *result,
+ char *buffer, int buflen)
+{
+ /* Return entry for network with NAME. */
+ int status;
+ querybuf net_buffer;
+ unsigned int net_bytes[4];
+ char qbuf[MAXDNAME];
+ int cnt, anslen;
+ u_int32_t net2;
+
+ /* No net address lookup for IPv6 yet. */
+ if (type != AF_INET)
+ return NSS_STATUS_UNAVAIL;
+
+ net2 = (u_int32_t) net;
+ for (cnt = 4; net2 != 0; net2 >>= 8)
+ net_bytes[--cnt] = net2 & 0xff;
+
+ switch (cnt)
+ {
+ case 3:
+ /* Class A network. */
+ sprintf (qbuf, "0.0.0.%u.in-addr.arpa", net_bytes[3]);
+ break;
+ case 2:
+ /* Class B network. */
+ sprintf (qbuf, "0.0.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2]);
+ break;
+ case 1:
+ /* Class C network. */
+ sprintf (qbuf, "0.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
+ net_bytes[1]);
+ break;
+ case 0:
+ /* Class D - E network. */
+ sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
+ net_bytes[1], net_bytes[0]);
+ break;
+ }
+
+ anslen = res_query (qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
+ sizeof (querybuf));
+ if (anslen < 0)
+ /* Nothing found. */
+ return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+
+ status = getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYADDR);
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ /* Strip trailing zeros. */
+ unsigned int u_net = net; /* Maybe net should be unsigned? */
+
+ while ((u_net & 0xff) == 0 && u_net != 0)
+ u_net >>= 8;
+ result->n_net = u_net;
+ }
+
+ return status;
+}
+
+
+#undef offsetof
+#define offsetof(Type, Member) ((size_t) &((Type *) NULL)->Member)
+
+static int
+getanswer_r (const querybuf *answer, int anslen, struct netent *result,
+ char *buffer, int buflen, lookup_method net_i)
+{
+ /*
+ * Find first satisfactory answer
+ *
+ * answer --> +------------+ ( MESSAGE )
+ * | Header |
+ * +------------+
+ * | Question | the question for the name server
+ * +------------+
+ * | Answer | RRs answering the question
+ * +------------+
+ * | Authority | RRs pointing toward an authority
+ * | Additional | RRs holding additional information
+ * +------------+
+ */
+ struct net_data
+ {
+ char *aliases[MAX_NR_ALIASES];
+ char linebuffer[0];
+ } *net_data = (struct net_data *) buffer;
+ int linebuflen = buflen - offsetof (struct net_data, linebuffer);
+ const char *end_of_message = &answer->buf[anslen];
+ const HEADER *header_pointer = &answer->hdr;
+ /* #/records in the answer section. */
+ int answer_count = ntohs (header_pointer->ancount);
+ /* #/entries in the question section. */
+ int question_count = ntohs (header_pointer->qdcount);
+ char *bp = net_data->linebuffer;
+ const char *cp = &answer->buf[HFIXEDSZ];
+ char **alias_pointer;
+ int have_answer;
+ char *ans;
+
+ if (question_count == 0)
+ /* FIXME: the Sun version uses for host name lookup an additional
+ parameter for pointing to h_errno. this is missing here.
+ OSF/1 has a per-thread h_errno variable. */
+ if (header_pointer->aa != 0)
+ {
+ h_errno = HOST_NOT_FOUND;
+ return NSS_STATUS_NOTFOUND;
+ }
+ else
+ {
+ h_errno = TRY_AGAIN;
+ return NSS_STATUS_TRYAGAIN;
+ }
+
+ /* Skip the question part. */
+ while (question_count-- > 0)
+ cp += __dn_skipname (cp, end_of_message) + QFIXEDSZ;
+
+ alias_pointer = result->n_aliases = &net_data->aliases[0];
+ *alias_pointer = NULL;
+ have_answer = 0;
+ ans = NULL;
+
+ while (--answer_count >= 0 && cp < end_of_message)
+ {
+ int n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+ int type, class;
+
+ if (n < 0 || res_dnok (bp) == 0)
+ break;
+ cp += n;
+ ans = strdupa (bp);
+ GETSHORT (type, cp);
+ GETSHORT (class, cp);
+ cp += INT32SZ; /* TTL */
+ GETSHORT (n, cp);
+
+ if (class == C_IN && type == T_PTR)
+ {
+ n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
+ if (n < 0 || !res_hnok (bp))
+ {
+ /* XXX What does this mean? The original form from bind
+ returns NULL. Incrementing cp has no effect in any case.
+ What should I return here. ??? */
+ cp += n;
+ return NSS_STATUS_UNAVAIL;
+ }
+ cp += n;
+ *alias_pointer++ = bp;
+ bp += strlen (bp) + 1;
+ result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
+ ++have_answer;
+ }
+ }
+
+ if (have_answer)
+ {
+ char *tmp;
+ int len;
+ char *in, *cp, *rp, *wp;
+ int cnt, first_flag;
+
+ *alias_pointer = NULL;
+ switch (net_i)
+ {
+ case BYADDR:
+ result->n_name = result->n_aliases[0];
+ result->n_net = 0L;
+ break;
+ case BYNAME:
+ len = strlen (result->n_aliases[0]);
+ tmp = (char *) alloca (len + 1);
+ tmp[len] = 0;
+ wp = &tmp[len - 1];
+
+ rp = in = result->n_aliases[0];
+ result->n_name = ans;
+
+ first_flag = 1;
+ for (cnt = 0; cnt < 4; ++cnt)
+ {
+ char *startp;
+
+ startp = rp;
+ while (*rp != '.')
+ ++rp;
+ if (rp - startp > 1 || *startp != '0' || !first_flag)
+ {
+ first_flag = 0;
+ if (cnt > 0)
+ *wp-- = '.';
+ cp = rp;
+ while (cp > startp)
+ *wp-- = *--cp;
+ }
+ in = rp + 1;
+ }
+
+ result->n_net = inet_network (wp);
+ break;
+ }
+
+ ++result->n_aliases;
+ return NSS_STATUS_SUCCESS;
+ }
+
+ /* XXX Really use global variable??? */
+ h_errno = TRY_AGAIN;
+ return NSS_STATUS_TRYAGAIN;
+}
diff --git a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c
new file mode 100644
index 0000000000..40bb7df81e
--- /dev/null
+++ b/nss/nss_files/files-XXX.c
@@ -0,0 +1,221 @@
+/* Common code for file-based databases in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <libc-lock.h>
+#include "nsswitch.h"
+
+/* These symbols are defined by the including source file:
+
+ ENTNAME -- database name of the structure and functions (hostent, pwent).
+ STRUCTURE -- struct name, define only if not ENTNAME (passwd, group).
+ DATAFILE -- string of the database file's name.
+
+ NEED_H_ERRNO - defined iff an arg `int *herrnop' is used.
+ MIDLINE_COMMENTS - defined iff # before \n terminates a database line.
+*/
+
+#define ENTNAME_r CONCAT(ENTNAME,_r)
+
+#ifdef NEED_H_ERRNO
+#define H_ERRNO_PROTO , int *herrnop
+#define H_ERRNO_ARG , herrnop
+#define H_ERRNO_SET(val) (*herrnop = (val))
+#else
+#define H_ERRNO_PROTO
+#define H_ERRNO_ARG
+#define H_ERRNO_SET(val) ((void) 0)
+#endif
+
+/* Locks the static variables in this file. */
+__libc_lock_define_initialized (static, lock);
+
+/* Maintenance of the shared stream open on the database file. */
+
+static FILE *stream;
+static int keep_stream;
+
+/* Open database file if not already opened. */
+static int
+internal_setent (int stayopen)
+{
+ int status = NSS_STATUS_SUCCESS;
+
+ if (stream == NULL)
+ {
+ stream = fopen (DATAFILE, "r");
+
+ if (stream == NULL)
+ status = NSS_STATUS_UNAVAIL;
+ }
+ else
+ rewind (stream);
+
+ /* Remember STAYOPEN flag. */
+ if (stream != NULL)
+ keep_stream |= stayopen;
+
+ return status;
+}
+
+
+/* Thread-safe, exported version of that. */
+int
+CONCAT(_nss_files_set,ENTNAME) (int stayopen)
+{
+ int status;
+
+ __libc_lock_lock (lock);
+
+ status = internal_setent (stayopen);
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+
+/* Close the database file. */
+static void
+internal_endent (void)
+{
+ if (stream != NULL)
+ {
+ fclose (stream);
+ stream = NULL;
+ }
+
+ /* Reset STAYOPEN flag. */
+ keep_stream = 0;
+}
+
+
+/* Thread-safe, exported version of that. */
+int
+CONCAT(_nss_files_end,ENTNAME) (void)
+{
+ __libc_lock_lock (lock);
+
+ internal_endent ();
+
+ __libc_lock_unlock (lock);
+
+ return NSS_STATUS_SUCCESS;
+}
+
+/* Parsing the database file into `struct STRUCTURE' data structures. */
+
+static enum nss_status
+internal_getent (struct STRUCTURE *result,
+ char *buffer, int buflen H_ERRNO_PROTO)
+{
+ char *p;
+ struct parser_data *data = (void *) buffer;
+ int linebuflen = buffer + buflen - data->linebuffer;
+
+ /* Someone called internal_setent before calling us, so if the
+ stream is not open now the file could not be opened. */
+ if (stream == NULL)
+ {
+ H_ERRNO_SET (NETDB_INTERNAL);
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ if (buflen < sizeof *data + 1)
+ {
+ errno = ERANGE;
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ do
+ {
+ p = fgets (data->linebuffer, linebuflen, stream);
+ if (p == NULL)
+ {
+ /* End of file or read error. */
+ H_ERRNO_SET (HOST_NOT_FOUND);
+ return NSS_STATUS_NOTFOUND;
+ }
+
+ /* Skip leading blanks. */
+ while (isspace (*p))
+ ++p;
+ } while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
+ /* Parse the line. If it is invalid, loop to
+ get the next line of the file to parse. */
+ ! parse_line (p, result, data, buflen));
+
+ /* Filled in RESULT with the next entry from the database file. */
+ return NSS_STATUS_SUCCESS;
+}
+
+
+/* Return the next entry from the database file, doing locking. */
+int
+CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result,
+ char *buffer, int buflen H_ERRNO_PROTO)
+{
+ /* Return next entry in host file. */
+ int status;
+
+ __libc_lock_lock (lock);
+
+ status = internal_getent (result, buffer, buflen H_ERRNO_ARG);
+
+ __libc_lock_unlock (lock);
+
+ return status;
+}
+
+/* Macro for defining lookup functions for this file-based database.
+
+ NAME is the name of the lookup; e.g. `hostbyname'.
+
+ PROTO describes the arguments for the lookup key;
+ e.g. `const char *hostname'.
+
+ BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result'
+ to the lookup key arguments and does `break;' if they match. */
+
+#define DB_LOOKUP(name, break_if_match, proto...) \
+enum nss_status \
+_nss_files_get##name##_r (proto, \
+ struct STRUCTURE *result, \
+ char *buffer, int buflen H_ERRNO_PROTO) \
+{ \
+ enum nss_status status; \
+ \
+ __libc_lock_lock (lock); \
+ \
+ /* Reset file pointer to beginning or open file. */ \
+ internal_setent (keep_stream); \
+ \
+ while ((status = internal_getent (result, buffer, buflen H_ERRNO_ARG)) \
+ == NSS_STATUS_SUCCESS) \
+ { break_if_match } \
+ \
+ if (! keep_stream) \
+ internal_endent (); \
+ \
+ __libc_lock_unlock (lock); \
+ \
+ return status; \
+}
diff --git a/nss/nss_files/files-grp.c b/nss/nss_files/files-grp.c
new file mode 100644
index 0000000000..6d528a6df2
--- /dev/null
+++ b/nss/nss_files/files-grp.c
@@ -0,0 +1,49 @@
+/* Group file parser in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <grp.h>
+
+#define STRUCTURE group
+#define ENTNAME grent
+#define DATAFILE "/etc/group"
+struct grent_data {};
+
+#define TRAILING_LIST_MEMBER gr_mem
+#define TRAILING_LIST_SEPARATOR_P(c) ((c) == ',')
+#include "files-parse.c"
+LINE_PARSER
+(
+ STRING_FIELD (result->gr_name, ISCOLON, 0);
+ STRING_FIELD (result->gr_passwd, ISCOLON, 0);
+ INT_FIELD (result->gr_gid, ISCOLON, 0, 10,);
+)
+
+#include "files-XXX.c"
+
+DB_LOOKUP (grnam,
+ {
+ if (! strcmp (name, result->gr_name))
+ break;
+ }, const char *name)
+
+DB_LOOKUP (grgid,
+ {
+ if (result->gr_gid == gid)
+ break;
+ }, gid_t gid)
diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c
new file mode 100644
index 0000000000..dad818c941
--- /dev/null
+++ b/nss/nss_files/files-hosts.c
@@ -0,0 +1,111 @@
+/* Hosts file parser in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+
+
+/* Get implementation for some internal functions. */
+#include "../resolv/mapv4v6addr.h"
+#include "../resolv/mapv4v6hostent.h"
+
+
+#define ENTNAME hostent
+#define DATAFILE _PATH_HOSTS
+
+struct hostent_data
+ {
+ unsigned char host_addr[16]; /* IPv4 or IPv6 address. */
+ char *h_addr_ptrs[2]; /* Points to that and null terminator. */
+ };
+
+#define TRAILING_LIST_MEMBER h_aliases
+#define TRAILING_LIST_SEPARATOR_P isspace
+#include "files-parse.c"
+LINE_PARSER
+({
+ char *addr;
+
+ STRING_FIELD (addr, isspace, 1);
+
+ /* Parse address. */
+ if ((_res.options & RES_USE_INET6)
+ && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
+ {
+ result->h_addrtype = AF_INET6;
+ result->h_length = IN6ADDRSZ;
+ }
+ else if (inet_pton (AF_INET, addr, entdata->host_addr) > 0)
+ {
+ if (_res.options & RES_USE_INET6)
+ {
+ map_v4v6_address ((char *) entdata->host_addr,
+ (char *) entdata->host_addr);
+ result->h_addrtype = AF_INET6;
+ result->h_length = IN6ADDRSZ;
+ }
+ else
+ {
+ result->h_addrtype = AF_INET;
+ result->h_length = INADDRSZ;
+ }
+ }
+ else
+ /* Illegal address: ignore line. */
+ return 0;
+
+ /* Store a pointer to the addressin the expected form. */
+ entdata->h_addr_ptrs[0] = entdata->host_addr;
+ entdata->h_addr_ptrs[1] = NULL;
+ result->h_addr_list = entdata->h_addr_ptrs;
+
+ /* If we need the host entry in IPv6 form change it now. */
+ if (_res.options & RES_USE_INET6)
+ {
+ char *bufptr = data->linebuffer;
+ int buflen = (char *) data + datalen - bufptr;
+ map_v4v6_hostent (result, &bufptr, &buflen);
+ }
+
+ STRING_FIELD (result->h_name, isspace, 1);
+})
+
+#include "files-XXX.c"
+
+DB_LOOKUP (hostbyname,
+ {
+ char **ap;
+ if (! strcmp (name, result->h_name))
+ break;
+ for (ap = result->h_aliases; *ap; ++ap)
+ if (! strcmp (name, *ap))
+ break;
+ if (*ap)
+ break;
+ }, const char *name)
+
+DB_LOOKUP (hostbyaddr,
+ {
+ if (result->h_addrtype == type && result->h_length == len &&
+ ! memcmp (addr, result->h_addr_list[0], len))
+ break;
+ }, const char *addr, int len, int type)
diff --git a/nss/nss_files/files-network.c b/nss/nss_files/files-network.c
new file mode 100644
index 0000000000..504c420b04
--- /dev/null
+++ b/nss/nss_files/files-network.c
@@ -0,0 +1,54 @@
+/* Networks file parser in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#define ENTNAME netent
+#define DATAFILE _PATH_NETWORKS
+
+struct netent_data {};
+
+#define TRAILING_LIST_MEMBER n_aliases
+#define TRAILING_LIST_SEPARATOR_P isspace
+#include "files-parse.c"
+LINE_PARSER
+({
+ char *addr;
+
+ STRING_FIELD (result->n_name, isspace, 1);
+
+ STRING_FIELD (addr, isspace, 1);
+ result->n_net = inet_network (addr);
+
+})
+
+#include "files-XXX.c"
+
+DB_LOOKUP (netbyname,
+ LOOKUP_NAME (n_name, n_aliases),
+ const char *name)
+
+DB_LOOKUP (netbyaddr,
+ {
+ if (result->n_addrtype == type && result->n_net == net)
+ /* Bingo! */
+ break;
+ }, int type, unsigned long int net)
diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c
new file mode 100644
index 0000000000..a93bee1ab3
--- /dev/null
+++ b/nss/nss_files/files-parse.c
@@ -0,0 +1,171 @@
+/* Common code for file-based database parsers in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#define CONCAT(a,b) CONCAT1(a,b)
+#define CONCAT1(a,b) a##b
+
+#ifndef STRUCTURE
+#define STRUCTURE ENTNAME
+#endif
+
+
+struct parser_data
+ {
+ struct CONCAT(ENTNAME,_data) entdata;
+ char linebuffer[0];
+ };
+
+#define LINE_PARSER(BODY) \
+static inline int \
+parse_line (char *line, struct STRUCTURE *result, \
+ struct parser_data *data, int datalen) \
+{ \
+ struct CONCAT(ENTNAME,_data) *const entdata __attribute__ ((unused)) \
+ = &data->entdata; \
+ BODY; \
+ TRAILING_LIST_PARSER; \
+ return 1; \
+}
+
+
+/* Comments can come mid-line; trim the line at the first # seen. */
+#define MIDLINE_COMMENTS \
+ { \
+ char *p = strchr (line, '#'); \
+ if (p) \
+ *p = '\0'; \
+ }
+
+#define STRING_FIELD(variable, terminator_p, swallow) \
+ { \
+ variable = line; \
+ while (!terminator_p (*line)) \
+ if (*++line == '\0') \
+ return 0; \
+ *line = '\0'; \
+ do \
+ ++line; \
+ while (swallow && terminator_p (*line)); \
+ }
+
+#define INT_FIELD(variable, terminator_p, swallow, base, convert) \
+ { \
+ char *endp; \
+ variable = convert (strtol (line, &endp, base)); \
+ if (endp == line) \
+ return 0; \
+ else if (terminator_p (*endp)) \
+ do \
+ ++endp; \
+ while (swallow && terminator_p (*endp)); \
+ else if (*endp != '\0') \
+ return 0; \
+ line = endp; \
+ }
+
+#define ISCOLON(c) ((c) == ':')
+
+
+#ifndef TRAILING_LIST_MEMBER
+#define TRAILING_LIST_PARSER /* Nothing to do. */
+#else
+
+#define TRAILING_LIST_PARSER \
+{ \
+ char **list = parse_list (line, data, datalen); \
+ if (list) \
+ result->TRAILING_LIST_MEMBER = list; \
+ else \
+ return 0; \
+}
+
+static inline char **
+parse_list (char *line, struct parser_data *data, int datalen)
+{
+ char *eol, **list, **p;
+
+ /* Find the end of the line buffer. */
+ eol = strchr (line, '\0');
+ /* Adjust the pointer so it is aligned for storing pointers. */
+ eol += (eol - (char *) 0) % __alignof__ (char *);
+ /* We will start the storage here for the vector of pointers. */
+ list = (char **) eol;
+
+ p = list;
+ while (1)
+ {
+ char *elt;
+
+ if ((char *) &p[1] - (char *) data > datalen)
+ {
+ /* We cannot fit another pointer in the buffer. */
+ errno = ERANGE;
+ return NULL;
+ }
+ if (*line == '\0')
+ break;
+
+ elt = line;
+ while (1)
+ {
+ if (TRAILING_LIST_SEPARATOR_P (*line))
+ {
+ *p++ = elt;
+ *line = '\0';
+ do
+ ++line;
+ while (TRAILING_LIST_SEPARATOR_P (*line));
+ }
+ else if (*line == '\0' || *line == '\n')
+ {
+ /* End of the line. */
+ if (line > elt)
+ /* Last element. */
+ *p++ = elt;
+ *line = '\0';
+ break;
+ }
+ else
+ ++line;
+ }
+ }
+ *p = NULL;
+
+ return list;
+}
+
+#define LOOKUP_NAME(nameelt, aliaselt) \
+{ \
+ char **ap; \
+ if (! strcmp (name, result->nameelt)) \
+ break; \
+ for (ap = result->aliaselt; *ap; ++ap) \
+ if (! strcmp (name, *ap)) \
+ break; \
+ if (*ap) \
+ break; \
+}
+
+#endif
diff --git a/nss/nss_files/files-proto.c b/nss/nss_files/files-proto.c
new file mode 100644
index 0000000000..d67f8db8f6
--- /dev/null
+++ b/nss/nss_files/files-proto.c
@@ -0,0 +1,48 @@
+/* Protocols file parser in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <netdb.h>
+
+
+#define ENTNAME protoent
+#define DATAFILE _PATH_PROTOCOLS
+
+struct protoent_data {};
+
+#define TRAILING_LIST_MEMBER p_aliases
+#define TRAILING_LIST_SEPARATOR_P isspace
+#include "files-parse.c"
+LINE_PARSER
+(
+ MIDLINE_COMMENTS;
+ STRING_FIELD (result->p_name, isspace, 1);
+ INT_FIELD (result->p_proto, isspace, 1, 10,);
+ )
+
+#include "files-XXX.c"
+
+DB_LOOKUP (protobyname,
+ LOOKUP_NAME (p_name, p_aliases),
+ const char *name)
+
+DB_LOOKUP (protobynumber,
+ {
+ if (result->p_proto == proto)
+ break;
+ }, int proto)
diff --git a/nss/nss_files/files-pwd.c b/nss/nss_files/files-pwd.c
new file mode 100644
index 0000000000..4b6a4b737f
--- /dev/null
+++ b/nss/nss_files/files-pwd.c
@@ -0,0 +1,54 @@
+/* User file parser in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <pwd.h>
+
+#define STRUCTURE passwd
+#define ENTNAME pwent
+#define DATAFILE "/etc/passwd"
+struct pwent_data {};
+
+#include "files-parse.c"
+LINE_PARSER
+({
+ STRING_FIELD (result->pw_name, ISCOLON, 0);
+ STRING_FIELD (result->pw_passwd, ISCOLON, 0);
+ INT_FIELD (result->pw_uid, ISCOLON, 0, 10,);
+ INT_FIELD (result->pw_gid, ISCOLON, 0, 10,);
+ STRING_FIELD (result->pw_gecos, ISCOLON, 0);
+ STRING_FIELD (result->pw_dir, ISCOLON, 0);
+ result->pw_shell = line;
+ line = strchr (line, '\n');
+ if (line)
+ *line = '\0';
+})
+
+#include "files-XXX.c"
+
+DB_LOOKUP (pwnam,
+ {
+ if (! strcmp (name, result->pw_name))
+ break;
+ }, const char *name)
+
+DB_LOOKUP (pwuid,
+ {
+ if (result->pw_uid == uid)
+ break;
+ }, uid_t uid)
diff --git a/nss/nss_files/files-rpc.c b/nss/nss_files/files-rpc.c
new file mode 100644
index 0000000000..fef0ff88b1
--- /dev/null
+++ b/nss/nss_files/files-rpc.c
@@ -0,0 +1,48 @@
+/* SunRPC program number file parser in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <rpc/netdb.h>
+
+
+#define ENTNAME rpcent
+#define DATAFILE "/etc/rpc"
+
+struct rpcent_data {};
+
+#define TRAILING_LIST_MEMBER r_aliases
+#define TRAILING_LIST_SEPARATOR_P isspace
+#include "files-parse.c"
+LINE_PARSER
+(
+ MIDLINE_COMMENTS;
+ STRING_FIELD (result->r_name, isspace, 1);
+ INT_FIELD (result->r_number, isspace, 1, 10,);
+ )
+
+#include "files-XXX.c"
+
+DB_LOOKUP (rpcbyname,
+ LOOKUP_NAME (r_name, r_aliases),
+ const char *name)
+
+DB_LOOKUP (rpcbynumber,
+ {
+ if (result->r_number == number)
+ break;
+ }, int number)
diff --git a/nss/nss_files/files-service.c b/nss/nss_files/files-service.c
new file mode 100644
index 0000000000..3bcb48787a
--- /dev/null
+++ b/nss/nss_files/files-service.c
@@ -0,0 +1,51 @@
+/* Services file parser in nss_files module.
+Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+
+#define ENTNAME servent
+#define DATAFILE _PATH_SERVICES
+
+struct servent_data {};
+
+#define TRAILING_LIST_MEMBER s_aliases
+#define TRAILING_LIST_SEPARATOR_P isspace
+#include "files-parse.c"
+#define ISSLASH(c) ((c) == '/')
+LINE_PARSER
+(
+ MIDLINE_COMMENTS;
+ STRING_FIELD (result->s_name, isspace, 1);
+ INT_FIELD (result->s_port, ISSLASH, 10, 0, htons);
+ STRING_FIELD (result->s_proto, isspace, 1);
+ )
+
+#include "files-XXX.c"
+
+DB_LOOKUP (servbyname,
+ LOOKUP_NAME (s_name, s_aliases),
+ const char *name)
+
+DB_LOOKUP (servbyport,
+ {
+ if (result->s_port == port)
+ break;
+ }, int port)
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
new file mode 100644
index 0000000000..4c2ccf692f
--- /dev/null
+++ b/nss/nsswitch.c
@@ -0,0 +1,588 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <ctype.h>
+#include <dlfcn.h>
+#include <netdb.h>
+#include <libc-lock.h>
+#include <search.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nsswitch.h"
+#include "../elf/link.h" /* We need some help from ld.so. */
+
+/* Prototypes for the local functions. */
+static void nss_init (void);
+static void *nss_lookup_function (service_user *ni, const char *fct_name);
+static int nss_find_entry (struct entry **knownp, const char *key,
+ void **valp);
+static void nss_insert_entry (struct entry **knownp, const char *key,
+ void *val);
+static name_database *nss_parse_file (const char *fname);
+static name_database_entry *nss_getline (char *line);
+static service_library *nss_new_service (name_database *database,
+ const char *name);
+
+
+__libc_lock_define_initialized (static, lock);
+
+
+/* Global variable. */
+struct __res_state _res;
+
+
+/* Known aliases for service names. */
+static struct {
+ const char *alias;
+ const char *value;
+} service_alias[] =
+{
+ { "nis+", "nisplus" },
+ { "yp", "nis" }
+};
+
+
+/* Nonzero if the sevices are already initialized. */
+static int nss_initialized;
+
+
+/* The root of the whole data base. */
+static name_database *service_table;
+
+
+static void
+nss_init (void)
+{
+ /* Prevent multiple threads to change the service table. */
+ __libc_lock_lock (lock);
+
+ if (service_table == NULL)
+ service_table = nss_parse_file (_PATH_NSSWITCH_CONF);
+
+ __libc_lock_unlock (lock);
+}
+
+
+/* -1 == database not found
+ 0 == database entry pointer stored */
+int
+__nss_database_lookup (const char *database, service_user **ni)
+{
+ /* Return first `service_user' entry for DATABASE.
+ XXX Will use perfect hashing function for known databases. */
+ name_database_entry *entry;
+
+ /* Test whether configuration data is available. */
+ if (service_table == NULL)
+ {
+ if (nss_initialized == 0)
+ nss_init ();
+
+ if (service_table == NULL)
+ return -1;
+ }
+
+ /* XXX Could use some faster mechanism here. But each database is
+ only requested once and so this might not be critical. */
+ for (entry = service_table->entry; entry != NULL; entry = entry->next)
+ if (strcmp (database, entry->name) == 0)
+ break;
+
+ if (entry == NULL || (*ni = entry->service) == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+/* -1 == not found
+ 0 == adjusted for next function */
+int
+__nss_lookup (service_user **ni, const char *fct_name, void **fctp)
+{
+ *fctp = nss_lookup_function (*ni, fct_name);
+
+ while (*fctp == NULL
+ && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE
+ && (*ni)->next != NULL)
+ {
+ *ni = (*ni)->next;
+
+ *fctp = nss_lookup_function (*ni, fct_name);
+ }
+
+ return *fctp != NULL ? 0 : -1;
+}
+
+
+/* -1 == not found
+ 0 == adjusted for next function
+ 1 == finished */
+int
+__nss_next (service_user **ni, const char *fct_name, void **fctp, int status,
+ int all_values)
+{
+ if (all_values)
+ {
+ if (nss_next_action (*ni, NSS_STATUS_TRYAGAIN) == NSS_ACTION_RETURN
+ && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_RETURN
+ && nss_next_action (*ni, NSS_STATUS_NOTFOUND) == NSS_ACTION_RETURN
+ && nss_next_action (*ni, NSS_STATUS_SUCCESS) == NSS_ACTION_RETURN)
+ return 1;
+ }
+ else
+ {
+ /* This is really only for debugging. */
+ if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_SUCCESS)
+ __libc_fatal ("illegal status in " __FUNCTION__);
+
+ if (nss_next_action (*ni, status) == NSS_ACTION_RETURN)
+ return 1;
+ }
+
+ if ((*ni)->next == NULL)
+ return -1;
+
+ do
+ {
+ *ni = (*ni)->next;
+
+ *fctp = nss_lookup_function (*ni, fct_name);
+ }
+ while (*fctp == NULL
+ && nss_next_action (*ni, NSS_STATUS_UNAVAIL) == NSS_ACTION_CONTINUE
+ && (*ni)->next != NULL);
+
+ return *fctp != NULL ? 0 : -1;
+}
+
+
+static int
+nss_dlerror_run (void (*operate) (void))
+{
+ const char *last_errstring = NULL;
+ const char *last_object_name = NULL;
+
+ (void) _dl_catch_error (&last_errstring, &last_object_name, operate);
+
+ return last_errstring != NULL;
+}
+
+
+static void *
+nss_lookup_function (service_user *ni, const char *fct_name)
+{
+ void *result;
+
+ /* Determine whether current function is loaded. */
+ if (nss_find_entry (&ni->known, fct_name, &result) >= 0)
+ return result;
+
+ /* If we failed to allocate the needed data structures for the
+ service return an error. This should only happen when we are out
+ of memory. */
+ if (ni->library == NULL)
+ return NULL;
+
+ /* We now modify global data. Protect it. */
+ __libc_lock_lock (lock);
+
+ if (ni->library->lib_handle == NULL)
+ {
+ /* Load the shared library. */
+ size_t shlen = (7 + strlen (ni->library->name) + 3
+ + sizeof (NSS_SHLIB_REVISION));
+ char shlib_name[shlen];
+
+ void do_open (void)
+ {
+ /* The used function is found in GNU ld.so. XXX The first
+ argument to _dl_open used to be `_dl_loaded'. But this
+ does (currently) not work. */
+ ni->library->lib_handle = _dl_open (shlib_name, RTLD_LAZY);
+ }
+
+ /* Construct name. */
+ __stpcpy (__stpcpy (__stpcpy (shlib_name, "libnss_"), ni->library->name),
+ ".so" NSS_SHLIB_REVISION);
+
+ if (nss_dlerror_run (do_open) != 0)
+ /* Failed to load the library. */
+ ni->library->lib_handle = (void *) -1;
+ }
+
+ if (ni->library->lib_handle == (void *) -1)
+ /* Library not found => function not found. */
+ result = NULL;
+ else
+ {
+ /* Get the desired function. Again, GNU ld.so magic ahead. */
+ size_t namlen = (5 + strlen (ni->library->name) + 1
+ + strlen (fct_name) + 1);
+ char name[namlen];
+ struct link_map *map = ni->library->lib_handle;
+ Elf32_Addr loadbase;
+ const Elf32_Sym *ref = NULL;
+ void get_sym (void)
+ {
+ struct link_map *scope[2] = { map, NULL };
+ loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0);
+ }
+
+ __stpcpy (__stpcpy (__stpcpy (__stpcpy (name, "_nss_"),
+ ni->library->name),
+ "_"),
+ fct_name);
+
+ result = (nss_dlerror_run (get_sym)
+ ? NULL : (void *) (loadbase + ref->st_value));
+ }
+
+ /* Remember function pointer for the usage. */
+ nss_insert_entry (&ni->known, fct_name, result);
+
+ /* Remove the lock. */
+ __libc_lock_unlock (lock);
+
+ return result;
+}
+
+
+static int
+known_compare (const void *p1, const void *p2)
+{
+ known_function *v1 = (known_function *) p1;
+ known_function *v2 = (known_function *) p2;
+
+ return strcmp (v1->fct_name, v2->fct_name);
+}
+
+
+static int
+nss_find_entry (struct entry **knownp, const char *key, void **valp)
+{
+ known_function looking_for = { fct_name: key };
+ struct entry **found;
+
+ found = __tfind (&looking_for, (const void **) knownp, known_compare);
+
+ if (found == NULL)
+ return -1;
+
+ *valp = ((known_function *) (*found)->key)->fct_ptr;
+
+ return 0;
+}
+
+
+static void
+nss_insert_entry (struct entry **knownp, const char *key, void *val)
+{
+ known_function *to_insert;
+
+ to_insert = (known_function *) malloc (sizeof (known_function));
+ if (to_insert == NULL)
+ return;
+
+ to_insert->fct_name = key;
+ to_insert->fct_ptr = val;
+
+ __tsearch (to_insert, (void **) knownp, known_compare);
+}
+
+
+static name_database *
+nss_parse_file (const char *fname)
+{
+ FILE *fp;
+ name_database *result;
+ name_database_entry *last;
+ char *line;
+ size_t len;
+
+ /* Open the configuration file. */
+ fp = fopen (fname, "r");
+ if (fp == NULL)
+ return NULL;
+
+ result = (name_database *) malloc (sizeof (name_database));
+ if (result == NULL)
+ return NULL;
+
+ result->entry = NULL;
+ result->library = NULL;
+ last = NULL;
+ line = NULL;
+ len = 0;
+ do
+ {
+ name_database_entry *this;
+ ssize_t n;
+ char *cp;
+
+ n = getline (&line, &len, fp);
+ if (n < 0)
+ break;
+ if (line[n - 1] == '\n')
+ line[n - 1] = '\0';
+
+ /* Because the file format does not know any form of quoting we
+ can search forward for the next '#' character and if found
+ make it terminating the line. */
+ cp = strchr (line, '#');
+ if (cp != NULL)
+ *cp = '\0';
+
+ /* If the line is blank it is ignored. */
+ if (line[0] == '\0')
+ continue;
+
+ /* Each line completely specifies the actions for a database. */
+ this = nss_getline (line);
+ if (this != NULL)
+ {
+ if (last != NULL)
+ last->next = this;
+ else
+ result->entry = this;
+
+ last = this;
+ }
+ }
+ while (!feof (fp));
+
+ /* Free the buffer. */
+ free (line);
+ /* Close configuration file. */
+ fclose (fp);
+
+ /* Now create for each service we could use an entry in LIBRARY list. */
+ for (last = result->entry; last != NULL; last = last->next)
+ {
+ service_user *runp;
+
+ for (runp = last->service; runp != NULL; runp = runp->next)
+ runp->library = nss_new_service (result, runp->name);
+ }
+
+ return result;
+}
+
+
+static name_database_entry *
+nss_getline (char *line)
+{
+ const char *name;
+ name_database_entry *result;
+ service_user *last;
+
+ /* Ignore leading white spaces. ATTENTION: this is different from
+ what is implemented in Solaris. The Solaris man page says a line
+ beginning with a white space character is ignored. We regard
+ this as just another misfeature in Solaris. */
+ while (isspace (line[0]))
+ ++line;
+
+ /* Recognize `<database> ":"'. */
+ name = line;
+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != ':')
+ ++line;
+ if (line[0] == '\0' || name == line)
+ /* Syntax error. */
+ return NULL;
+ *line++ = '\0';
+
+ result = (name_database_entry *) malloc (sizeof (name_database_entry));
+ if (result == NULL)
+ return NULL;
+
+ result->name = strdup (name);
+ if (result->name == NULL)
+ {
+ free (result);
+ return NULL;
+ }
+ result->service = NULL;
+ result->next = NULL;
+ last = NULL;
+
+ /* Read the source names: `<source> ( "[" <status> "=" <action> "]" )*'. */
+ while (1)
+ {
+ service_user *new_service;
+ size_t n;
+
+ while (isspace (line[0]))
+ ++line;
+ if (line[0] == '\0')
+ /* No source specified. */
+ return result;
+
+ /* Read <source> identifier. */
+ name = line;
+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[')
+ ++line;
+ if (name == line)
+ return result;
+
+
+ new_service = (service_user *) malloc (sizeof (service_user));
+ if (new_service == NULL)
+ return result;
+
+ /* Test whether the source name is one of the aliases. */
+ for (n = 0; n < sizeof (service_alias) / sizeof (service_alias[0]); ++n)
+ if (strncmp (service_alias[n].alias, name, line - name) == 0
+ && service_alias[n].alias[line - name] == '\0')
+ break;
+
+ if (n < sizeof (service_alias) / sizeof (service_alias[0]))
+ new_service->name = service_alias[n].value;
+ else
+ {
+ char *source = (char *) malloc (line - name + 1);
+ if (source == NULL)
+ {
+ free (new_service);
+ return result;
+ }
+ memcpy (source, name, line - name);
+ source[line - name] = '\0';
+
+ new_service->name = source;
+ }
+
+ /* Set default actions. */
+ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE;
+ new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE;
+ new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE;
+ new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN;
+ new_service->library = NULL;
+ new_service->known = NULL;
+ new_service->next = NULL;
+
+ while (isspace (line[0]))
+ ++line;
+
+ if (line[0] == '[')
+ {
+ int status;
+
+ /* Read criterions. */
+ do
+ ++line;
+ while (line[0] != '\0' && isspace (line[0]));
+
+ do
+ {
+ /* Read status name. */
+ name = line;
+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
+ && line[0] != ']')
+ ++line;
+
+ /* Compare with known statii. */
+ if (line - name == 7)
+ {
+ if (strncasecmp (name, "SUCCESS", 7) == 0)
+ status = NSS_STATUS_SUCCESS;
+ else if (strncasecmp (name, "UNAVAIL", 7) == 0)
+ status = NSS_STATUS_UNAVAIL;
+ else
+ return result;
+ }
+ else if (line - name == 8)
+ {
+ if (strncasecmp (name, "NOTFOUND", 8) == 0)
+ status = NSS_STATUS_NOTFOUND;
+ else if (strncasecmp (name, "TRYAGAIN", 8) == 0)
+ status = NSS_STATUS_TRYAGAIN;
+ else
+ return result;
+ }
+ else
+ return result;
+
+ while (isspace (line[0]))
+ ++line;
+ if (line[0] != '=')
+ return result;
+ do
+ ++line;
+ while (isspace (line[0]));
+
+ name = line;
+ while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
+ && line[0] != ']')
+ ++line;
+
+ if (line - name == 6 && strncasecmp (name, "RETURN", 6) == 0)
+ new_service->actions[2 + status] = NSS_ACTION_RETURN;
+ else if (line - name == 8
+ && strncasecmp (name, "CONTINUE", 8) == 0)
+ new_service->actions[2 + status] = NSS_ACTION_CONTINUE;
+ else
+ return result;
+
+ /* Match white spaces. */
+ while (isspace (line[0]))
+ ++line;
+ }
+ while (line[0] != ']');
+
+ /* Skip the ']'. */
+ ++line;
+ }
+
+ if (last == NULL)
+ result->service = new_service;
+ else
+ last->next = new_service;
+ last = new_service;
+ }
+ /* NOTREACHED */
+ return NULL;
+}
+
+
+static service_library *
+nss_new_service (name_database *database, const char *name)
+{
+ service_library **currentp = &database->library;
+
+ while (*currentp != NULL)
+ {
+ if (strcmp ((*currentp)->name, name) == 0)
+ return *currentp;
+ currentp = &(*currentp)->next;
+ }
+
+ /* We have to add the new service. */
+ *currentp = (service_library *) malloc (sizeof (service_library));
+ if (*currentp == NULL)
+ return NULL;
+
+ (*currentp)->name = name;
+ (*currentp)->lib_handle = NULL;
+ (*currentp)->next = NULL;
+
+ return *currentp;
+}
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
new file mode 100644
index 0000000000..f597a58860
--- /dev/null
+++ b/nss/nsswitch.h
@@ -0,0 +1,138 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef _NSSWITCH_H
+#define _NSSWITCH_H 1
+
+/* This is an *internal* header. */
+
+#include <arpa/nameser.h>
+#include <netinet/in.h>
+#include <resolv.h>
+#include <search.h>
+
+
+/* Revision number of NSS interface (must be a string). */
+#define NSS_SHLIB_REVISION ".1"
+
+
+/* Possible results of lookup using a nss_* function. */
+enum nss_status
+{
+ NSS_STATUS_TRYAGAIN = -2,
+ NSS_STATUS_UNAVAIL,
+ NSS_STATUS_NOTFOUND,
+ NSS_STATUS_SUCCESS,
+};
+
+
+/* Actions performed after lookup finished. */
+typedef enum
+{
+ NSS_ACTION_CONTINUE,
+ NSS_ACTION_RETURN
+} lookup_actions;
+
+
+typedef struct service_library
+{
+ /* Name of service (`files', `dns', `nis', ...). */
+ const char *name;
+ /* Pointer to the loaded shared library. */
+ void *lib_handle;
+ /* And the link to the next entry. */
+ struct service_library *next;
+} service_library;
+
+
+/* For mappng a function name to a function pointer. */
+typedef struct
+{
+ const char *fct_name;
+ void *fct_ptr;
+} known_function;
+
+
+typedef struct service_user
+{
+ /* Name of the service (`files', `dns', `nis', ...). */
+ const char *name;
+ /* Action according to result. */
+ lookup_actions actions[4];
+ /* Link to the underlying library object. */
+ service_library *library;
+ /* Collection of known functions. */
+ struct entry *known;
+ /* And the link to the next entry. */
+ struct service_user *next;
+} service_user;
+
+/* To access the action based on the status value use this macro. */
+#define nss_next_action(ni, status) ((ni)->actions[2 + status])
+
+
+typedef struct name_database_entry
+{
+ /* Name of the database. */
+ const char *name;
+ /* List of service to be used. */
+ service_user *service;
+ /* And the link to the next entry. */
+ struct name_database_entry *next;
+} name_database_entry;
+
+
+typedef struct name_database
+{
+ /* List of all known databases. */
+ name_database_entry *entry;
+ /* List of libraries with service implementation. */
+ service_library *library;
+} name_database;
+
+
+/* Interface functions for NSS. */
+
+/* Get the data structure representing the specified database. More
+ than one function can use the database. */
+int __nss_database_lookup (const char *database, service_user **ni);
+
+
+/* Put first function with name FCT_NAME for SERVICE in FCTP. The
+ position is remembered in NI. The function returns a value < 0 if
+ an error occured or no such function exists. */
+int __nss_lookup (service_user **ni, const char *fct_name, void **fctp);
+
+/* Determine the next step in the lookup process according to the
+ result STATUS of the call to the last function returned by
+ `__nss_lookup' or `__nss_next'. NI specifies the last function
+ examined. The function return a value > 0 if the process should
+ stop with the last result of the last function call to be the
+ result of the entire lookup. The returned valie is 0 if there is
+ another function to use and < 0 if an error occured.
+
+ If ALL_VALUES is nonzero, the return value will not be > 0 as long as
+ there is a possibility the lookup process can ever use following
+ services. In other words, only if all four lookup results have
+ the action RETURN associated the lookup process stops before the
+ natural end. */
+int __nss_next (service_user **ni, const char *fct_name, void **fctp,
+ int status, int all_values);
+
+
+#endif /* nsswitch.h */
diff --git a/nss/proto-lookup.c b/nss/proto-lookup.c
new file mode 100644
index 0000000000..f27ff591d9
--- /dev/null
+++ b/nss/proto-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME protocols
+
+#include "XXX-lookup.c"
diff --git a/nss/pwd-lookup.c b/nss/pwd-lookup.c
new file mode 100644
index 0000000000..e792560bad
--- /dev/null
+++ b/nss/pwd-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME passwd
+
+#include "XXX-lookup.c"
diff --git a/nss/rpc-lookup.c b/nss/rpc-lookup.c
new file mode 100644
index 0000000000..f49359ad2b
--- /dev/null
+++ b/nss/rpc-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME rpc
+
+#include "XXX-lookup.c"
diff --git a/nss/service-lookup.c b/nss/service-lookup.c
new file mode 100644
index 0000000000..c1a3256add
--- /dev/null
+++ b/nss/service-lookup.c
@@ -0,0 +1,22 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define DATABASE_NAME services
+
+#include "XXX-lookup.c"