summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog43
-rw-r--r--db/Makefile18
-rw-r--r--grp/initgroups.c67
-rw-r--r--locale/programs/locale.c22
-rw-r--r--nss/XXX-lookup.c10
-rw-r--r--nss/file-lookup.c22
-rw-r--r--nss/host-lookup.c1
-rw-r--r--nss/network-lookup.c1
-rw-r--r--nss/nss_files/files-parse.c2
-rw-r--r--nss/nsswitch.c205
-rw-r--r--nss/nsswitch.h7
-rw-r--r--shlib-versions3
-rw-r--r--string/string.h2
-rw-r--r--sysdeps/generic/strncase.c5
14 files changed, 234 insertions, 174 deletions
diff --git a/ChangeLog b/ChangeLog
index c332444a1f..38048c962f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+Wed Jun 26 01:58:49 1996  Roland McGrath  <roland@delasyd.gnu.ai.mit.edu>
+
+	* nss/nss_files/files-parse.c (parse_list): Count null in EOL calc.
+
+	Move DB code into separate -ldb library.
+	* db/Makefile (extra-libs): New variable, list libdb.
+	(routines): Renamed to libdb-routines.
+	* shlib-versions: Add libdb=2.
+
+	* nss/network-lookup.c (DEFAULT_CONFIG): New macro.
+	* nss/host-lookup.c (DEFAULT_CONFIG): New macro.
+
+	* nss/nsswitch.c (nss_parse_service_list): Use __strncasecmp instead
+	of strncasecmp.  Extend syntax to grok [!foo=bar].
+
+	* sysdeps/generic/strncase.c: Define __strncasecmp with strncasecmp as
+	weak alias.
+	* string/string.h: Declare __strncasecmp.
+
+	* nss/nsswitch.c (nss_parse_file): Call __getline, not getline.
+	(service_alias): Variable removed.
+	(nss_parse_service_list): New function, broken out of nss_getline.
+	Remove alias conversion; we will just use symlinks.
+	(__nss_database_lookup): Take new string arg DEFCONFIG.
+	If no entry exists, make one with service list parsed from that.
+	* nss/nsswitch.h: Update protocol for __nss_database_lookup.
+	* nss/XXX-lookup.c (DEFAULT_CONFIG): New macro, set to 0 if undefined.
+	(DB_LOOKUP_FCT): Pass it to _nss_database_lookup.
+
+	* grp/initgroups.c: Rewritten using getgrent.  Handle unlimited group
+	list size.
+
+	* sunrpc/xdr.c (xdr_int): #if 0 out unresolved references in dead code.
+
+Wed Jun 26 01:56:50 1996  Ulrich Drepper  <drepper@cygnus.com>
+
+	* locale/programs/locale.c (long_options): Short form of
+	--version option is `-V'.
+	(main): Recognize `-V' as option, not `-v'.
+	Call `usage' instead of printing error message for illegal
+	option.
+	(usage): Document `-V'.
+
 Tue Jun 25 17:22:55 1996  Miles Bader  <miles@gnu.ai.mit.edu>
 
 	* sysdeps/mach/hurd/getcwd.c
diff --git a/db/Makefile b/db/Makefile
index 48e2570c6c..2c678dfaa6 100644
--- a/db/Makefile
+++ b/db/Makefile
@@ -8,14 +8,16 @@ subdir = db
 subdir-dirs = btree db hash mpool recno
 vpath %.c $(subdir-dirs)
 
-routines := bt_close bt_conv bt_debug bt_delete bt_get bt_open bt_overflow \
-	    bt_page bt_put bt_search bt_seq bt_split bt_utils		   \
-	    db								   \
-	    hash hash_bigkey hash_buf hash_func hash_log2 hash_page	   \
-	    ndbm							   \
-	    mpool							   \
-	    rec_close rec_delete rec_get rec_open rec_put rec_search	   \
-	    rec_seq rec_utils
+extra-libs := libdb
+libdb-routines := bt_close bt_conv bt_debug bt_delete bt_get \
+		  bt_open bt_overflow bt_page bt_put bt_search \
+		  bt_seq bt_split bt_utils \
+		  db \
+		  hash hash_bigkey hash_buf hash_func hash_log2 hash_page \
+		  ndbm \
+		  mpool \
+		  rec_close rec_delete rec_get rec_open rec_put rec_search \
+		  rec_seq rec_utils
 
 headers		:= db.h mpool.h ndbm.h
 distribute	:= compat.h					\
diff --git a/grp/initgroups.c b/grp/initgroups.c
index 5af1926742..a700557924 100644
--- a/grp/initgroups.c
+++ b/grp/initgroups.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1991, 1993 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 1991, 1993, 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
@@ -31,43 +31,66 @@ int
 DEFUN(initgroups, (user, group),
       CONST char *user AND gid_t group)
 {
-#ifdef NGROUPS_MAX
-#if NGROUPS_MAX == 0
+#if defined (NGROUPS_MAX) && NGROUPS_MAX == 0
+
+  /* No extra groups allowed.  */
   return 0;
+
 #else
-  static PTR info = NULL;
-  register FILE *stream;
-  register struct group *g;
-  gid_t groups[NGROUPS_MAX];
+
+  struct group *g;
   register size_t n;
+#ifdef NGROUPS_MAX
+  gid_t groups[NGROUPS_MAX];
+#else
+  long int limit = sysconf (_SC_NGROUPS_MAX);
+  gid_t *groups;
+  size_t ngroups;
 
-  if (info == NULL)
-    {
-      info = __grpalloc();
-      if (info == NULL)
-	return -1;
-    }
+  if (limit > 0)
+    ngroups = limit;
+  else
+    /* No fixed limit on groups.  Pick a starting buffer size.  */
+    ngroups = 16;
 
-  stream = __grpopen();
-  if (stream == NULL)
-    return -1;
+  groups = __alloca (ngroups * sizeof *groups);
+#endif
+
+  setgrent ();
 
   n = 0;
   groups[n++] = group;
 
-  while (n < NGROUPS_MAX && (g = __grpread(stream, info)) != NULL)
+  while ((g = getgrent ()) != NULL)
     if (g->gr_gid != group)
       {
 	register char **m;
 
 	for (m = g->gr_mem; *m != NULL; ++m)
-	  if (!strcmp(*m, user))
+	  if (!strcmp (*m, user))
+	    break;
+
+	if (*m == NULL)
+	  {
+	    /* Matched the user.  Insert this group.  */
+	    if (n == ngroups && limit <= 0)
+	      {
+		/* Need a bigger buffer.  */
+		groups = memcpy (__alloca (ngroups * 2 * sizeof *groups),
+				 groups, ngroups * sizeof *groups);
+		ngroups *= 2;
+	      }
+
 	    groups[n++] = g->gr_gid;
+
+	    if (n == limit)
+	      /* Can't take any more groups; stop searching.  */
+	      break;
+	  }
       }
 
-  return setgroups(n, groups);
-#endif
-#else
-  return 0;
+  endgrent ();
+
+  return setgroups (n, groups);
 #endif
 }
diff --git a/locale/programs/locale.c b/locale/programs/locale.c
index ef5d9ae825..5196fa51fe 100644
--- a/locale/programs/locale.c
+++ b/locale/programs/locale.c
@@ -49,7 +49,7 @@ static const struct option long_options[] =
   { "charmaps", no_argument, NULL, 'm' },
   { "help", no_argument, NULL, 'h' },
   { "keyword-name", no_argument, &show_keyword_name, 1 },
-  { "version", no_argument, NULL, 'v' },
+  { "version", no_argument, NULL, 'V' },
   { NULL, 0, NULL, 0 }
 };
 
@@ -130,7 +130,7 @@ main (int argc, char *argv[])
   int do_version = 0;
   int do_charmaps = 0;
 
-  /* Set initial values for global varaibles.  */
+  /* Set initial values for global variables.  */
   show_category_name = 0;
   show_keyword_name = 0;
 
@@ -142,7 +142,7 @@ main (int argc, char *argv[])
   /* Initialize the message catalog.  */
   textdomain (PACKAGE);
 
-  while ((optchar = getopt_long (argc, argv, "achkmv", long_options, NULL))
+  while ((optchar = getopt_long (argc, argv, "achkmV", long_options, NULL))
          != EOF)
     switch (optchar)
       {
@@ -163,12 +163,11 @@ main (int argc, char *argv[])
       case 'm':
 	do_charmaps = 1;
 	break;
-      case 'v':
+      case 'V':
 	do_version = 1;
 	break;
       default:
-	error (1, 0, gettext ("illegal option \"%s\""), optarg);
-	break;
+	usage (EXIT_FAILURE);
       }
 
   /* Version information is requested.  */
@@ -219,25 +218,24 @@ main (int argc, char *argv[])
 
 /* Display usage information and exit.  */
 static void
-usage(int status)
+usage (int status)
 {
   if (status != EXIT_SUCCESS)
     fprintf (stderr, gettext ("Try `%s --help' for more information.\n"),
              program_invocation_name);
   else
-    printf(gettext ("\
+    printf (gettext ("\
 Usage: %s [OPTION]... name\n\
 Mandatory arguments to long options are mandatory for short options too.\n\
   -h, --help            display this help and exit\n\
-  -v, --version         output version information and exit\n\
+  -V, --version         output version information and exit\n\
 \n\
   -a, --all-locales     write names of available locales\n\
   -m, --charmaps        write names of available charmaps\n\
 \n\
   -c, --category-name   write names of selected categories\n\
-  -k, --keyword-name    write names of selected keywords\n\
-\n\
-"), program_invocation_name);
+  -k, --keyword-name    write names of selected keywords\n"),
+	    program_invocation_name);
 
   exit (status);
 }
diff --git a/nss/XXX-lookup.c b/nss/XXX-lookup.c
index 1f8cbbf015..4a2d25cb42 100644
--- a/nss/XXX-lookup.c
+++ b/nss/XXX-lookup.c
@@ -25,6 +25,10 @@ Boston, MA 02111-1307, USA.  */
 |* DATABASE_NAME - name of the database the function accesses	   *|
 |*		   (e.g., hosts, servicess, ...)		   *|
 |* 								   *|
+|* One additional symbol may optionally be defined:		   *|
+|* 								   *|
+|* DEFAULT_CONFIG - string for default conf (e.g. "dns files")	   *|
+|* 								   *|
 \*******************************************************************/
 
 #define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
@@ -35,6 +39,9 @@ Boston, MA 02111-1307, USA.  */
 #define STRINGIFY1(Name) STRINGIFY2 (Name)
 #define STRINGIFY2(Name) #Name
 
+#ifndef DEFAULT_CONFIG
+#define DEFAULT_CONFIG 0
+#endif
 
 static service_user *database = NULL;
 
@@ -42,7 +49,8 @@ int
 DB_LOOKUP_FCT (service_user **ni, const char *fct_name, void **fctp)
 {
   if (database == NULL
-      && __nss_database_lookup (DATABASE_NAME_STRING, &database) < 0)
+      && __nss_database_lookup (DATABASE_NAME_STRING, DEFAULT_CONFIG,
+				&database) < 0)
     return -1;
 
   *ni = database;
diff --git a/nss/file-lookup.c b/nss/file-lookup.c
deleted file mode 100644
index d9f7c67320..0000000000
--- a/nss/file-lookup.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/* 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/host-lookup.c b/nss/host-lookup.c
index d9f7c67320..f511393372 100644
--- a/nss/host-lookup.c
+++ b/nss/host-lookup.c
@@ -18,5 +18,6 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #define DATABASE_NAME hosts
+#define DEFAULT_CONFIG "dns [!UNAVAIL=return] files"
 
 #include "XXX-lookup.c"
diff --git a/nss/network-lookup.c b/nss/network-lookup.c
index ab6e51f5c4..39a5ebd8c1 100644
--- a/nss/network-lookup.c
+++ b/nss/network-lookup.c
@@ -18,5 +18,6 @@ not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
 #define DATABASE_NAME networks
+#define DEFAULT_CONFIG "dns files"
 
 #include "XXX-lookup.c"
diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c
index ff67e974aa..de456995a2 100644
--- a/nss/nss_files/files-parse.c
+++ b/nss/nss_files/files-parse.c
@@ -107,7 +107,7 @@ 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');
+  eol = strchr (line, '\0') + 1;
   /* 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.  */
diff --git a/nss/nsswitch.c b/nss/nsswitch.c
index 2b3ae0bbe1..9b6c4eb12f 100644
--- a/nss/nsswitch.c
+++ b/nss/nsswitch.c
@@ -38,6 +38,7 @@ 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_user *nss_parse_service_list (const char *line);
 static service_library *nss_new_service (name_database *database,
 					 const char *name);
 
@@ -49,17 +50,6 @@ __libc_lock_define_initialized (static, lock);
 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;
 
@@ -84,8 +74,11 @@ nss_init (void)
 /* -1 == database not found
     0 == database entry pointer stored */
 int
-__nss_database_lookup (const char *database, service_user **ni)
+__nss_database_lookup (const char *database, const char *defconfig,
+		       service_user **ni)
 {
+  name_database_entry *entry;
+
   if (nss_initialized == 0)
     nss_init ();
 
@@ -94,7 +87,6 @@ __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;
 
       /* XXX Could use some faster mechanism here.  But each database is
 	 only requested once and so this might not be critical.  */
@@ -107,29 +99,17 @@ __nss_database_lookup (const char *database, service_user **ni)
     }
 
   /* No configuration data is available, either because nsswitch.conf
-     doesn't exist or because it doesn't have a line for this database.
-     Use a default equivalent to:
-     	database: compat [NOTFOUND=return] dns [NOTFOUND=return] files
-     */
-  {
-#define DEFAULT_SERVICE(name, next)					      \
-    static service_user default_##name =				      \
-      {									      \
-	#name,								      \
-	{								      \
-	  NSS_ACTION_CONTINUE,						      \
-	  NSS_ACTION_CONTINUE,						      \
-	  NSS_ACTION_RETURN,						      \
-	  NSS_ACTION_RETURN,						      \
-	},								      \
-	NULL, NULL,							      \
-	next								      \
-      }
-    DEFAULT_SERVICE (files, NULL);
-    DEFAULT_SERVICE (dns, &default_files);
-    DEFAULT_SERVICE (compat, &default_dns);
-    *ni = &default_compat;
-  }
+     doesn't exist or because it doesn't have a line for this database.  */
+  entry = malloc (sizeof *entry);
+  if (entry == NULL)
+    return -1;
+  entry->name = database;
+  /* DEFCONFIG specifies the default service list for this database,
+     or null to use the most common default.  */
+  entry->service = nss_parse_service_list (defconfig ?:
+					   "compat [NOTFOUND=return] files");
+
+  *ni = entry->service;
   return 0;
 }
 
@@ -246,9 +226,7 @@ nss_lookup_function (service_user *ni, const char *fct_name)
 
       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.  */
+	  /* Open and relocate the shared object.  */
 	  ni->library->lib_handle = _dl_open (shlib_name, RTLD_LAZY);
 	}
 
@@ -370,7 +348,7 @@ nss_parse_file (const char *fname)
       ssize_t n;
       char *cp;
 
-      n = getline (&line, &len, fp);
+      n = __getline (&line, &len, fp);
       if (n < 0)
 	break;
       if (line[n - 1] == '\n')
@@ -410,48 +388,16 @@ nss_parse_file (const char *fname)
 }
 
 
-static name_database_entry *
-nss_getline (char *line)
+/* Read the source names: `<source> ( "[" <status> "=" <action> "]" )*'.  */
+static service_user *
+nss_parse_service_list (const 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';
+  service_user *result = NULL, **nextp = &result;
 
-  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;
+      char *name;
 
       while (isspace (line[0]))
 	++line;
@@ -470,15 +416,6 @@ nss_getline (char *line)
       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);
@@ -507,8 +444,6 @@ nss_getline (char *line)
 
       if (line[0] == '[')
 	{
-	  int status;
-
 	  /* Read criterions.  */
 	  do
 	    ++line;
@@ -516,6 +451,14 @@ nss_getline (char *line)
 
 	  do
 	    {
+	      int not;
+	      enum nss_status status;
+	      lookup_actions action;
+
+	      /* Grok ! before name to mean all statii but that one.  */
+	      if (not = line[0] == '!')
+		++line;
+
 	      /* Read status name.  */
 	      name = line;
 	      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
@@ -525,18 +468,18 @@ nss_getline (char *line)
 	      /* Compare with known statii.  */
 	      if (line - name == 7)
 		{
-		  if (strncasecmp (name, "SUCCESS", 7) == 0)
+		  if (__strncasecmp (name, "SUCCESS", 7) == 0)
 		    status = NSS_STATUS_SUCCESS;
-		  else if (strncasecmp (name, "UNAVAIL", 7) == 0)
+		  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)
+		  if (__strncasecmp (name, "NOTFOUND", 8) == 0)
 		    status = NSS_STATUS_NOTFOUND;
-		  else if (strncasecmp (name, "TRYAGAIN", 8) == 0)
+		  else if (__strncasecmp (name, "TRYAGAIN", 8) == 0)
 		    status = NSS_STATUS_TRYAGAIN;
 		  else
 		    return result;
@@ -557,15 +500,29 @@ nss_getline (char *line)
 		     && line[0] != ']')
 		++line;
 
-	      if (line - name == 6 && strncasecmp (name, "RETURN", 6) == 0)
-		new_service->actions[2 + status] = NSS_ACTION_RETURN;
+	      if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0)
+		action = NSS_ACTION_RETURN;
 	      else if (line - name == 8
-		       && strncasecmp (name, "CONTINUE", 8) == 0)
-		new_service->actions[2 + status] = NSS_ACTION_CONTINUE;
+		       && __strncasecmp (name, "CONTINUE", 8) == 0)
+		action = NSS_ACTION_CONTINUE;
 	      else
 		return result;
 
-	      /* Match white spaces.  */
+	      if (not)
+		{
+		  /* Save the current action setting for this status,
+		     set them all to the given action, and reset this one.  */
+		  const lookup_actions save = new_service->actions[2 + status];
+		  new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action;
+		  new_service->actions[2 + NSS_STATUS_UNAVAIL] = action;
+		  new_service->actions[2 + NSS_STATUS_NOTFOUND] = action;
+		  new_service->actions[2 + NSS_STATUS_SUCCESS] = action;
+		  new_service->actions[2 + status] = save;
+		}
+	      else
+		new_service->actions[2 + status] = action;
+
+	      /* Skip white spaces.  */
 	      while (isspace (line[0]))
 		++line;
 	    }
@@ -575,14 +532,54 @@ nss_getline (char *line)
 	  ++line;
 	}
 
-      if (last == NULL)
-	result->service = new_service;
-      else
-	last->next = new_service;
-      last = new_service;
+      *nextp = new_service;
+      nextp = &new_service->next;
     }
-  /* NOTREACHED */
-  return NULL;
+}
+
+static name_database_entry *
+nss_getline (char *line)
+{
+  const char *name;
+  name_database_entry *result;
+
+  /* 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;
+
+  /* Save the database name.  */
+  {
+    const size_t len = strlen (name) + 1;
+    char *new = malloc (len);
+    if (new == NULL)
+      {
+	free (result);
+	return NULL;
+      }
+    result->name = memcpy (new, name, len);
+  }
+
+  /* Parse the list of services.  */
+  result->service = nss_parse_service_list (line);
+
+  result->next = NULL;
+  return result;
 }
 
 
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
index f597a58860..d95d43219e 100644
--- a/nss/nsswitch.h
+++ b/nss/nsswitch.h
@@ -108,9 +108,12 @@ typedef struct name_database
 
 /* Interface functions for NSS.  */
 
-/* Get the data structure representing the specified database.  More
+/* Get the data structure representing the specified database.
+   If there is no configuration for this database in the file,
+   parse a service list from DEFCONFIG and use that.  More
    than one function can use the database.  */
-int __nss_database_lookup (const char *database, service_user **ni);
+int __nss_database_lookup (const char *database, const char *defconfig,
+			   service_user **ni);
 
 
 /* Put first function with name FCT_NAME for SERVICE in FCTP.  The
diff --git a/shlib-versions b/shlib-versions
index 1bf19da1ec..075dab3c9a 100644
--- a/shlib-versions
+++ b/shlib-versions
@@ -40,3 +40,6 @@ alpha-*-linux*		libc=6
 # names given in /etc/nsswitch.conf.
 *-*-*			libnss_files=1
 *-*-*			libnss_dns=1
+
+# We use libdb.so.2 for the interface in version 1.85 of the Berkeley DB code.
+*-*-*			libdb=2
diff --git a/string/string.h b/string/string.h
index 755c631048..a5a6edd398 100644
--- a/string/string.h
+++ b/string/string.h
@@ -185,6 +185,8 @@ extern int __strcasecmp __P ((__const char *__s1, __const char *__s2));
 extern int strcasecmp __P ((__const char *__s1, __const char *__s2));
 
 /* Compare no more than N chars of S1 and S2, ignoring case.  */
+extern int __strncasecmp __P ((__const char *__s1, __const char *__s2,
+			       size_t __n));
 extern int strncasecmp __P ((__const char *__s1, __const char *__s2,
 			     size_t __n));
 
diff --git a/sysdeps/generic/strncase.c b/sysdeps/generic/strncase.c
index f589937fac..ffc50ff50f 100644
--- a/sysdeps/generic/strncase.c
+++ b/sysdeps/generic/strncase.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 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
@@ -25,7 +25,7 @@ Cambridge, MA 02139, USA.  */
    greater than zero if S1 is lexicographically less
    than, equal to or greater than S2.  */
 int
-DEFUN(strncasecmp, (s1, s2, n),
+DEFUN(__strncasecmp, (s1, s2, n),
       CONST char *s1 AND CONST char *s2 AND size_t n)
 {
   register CONST unsigned char *p1 = (CONST unsigned char *) s1;
@@ -45,3 +45,4 @@ DEFUN(strncasecmp, (s1, s2, n),
 
   return c1 - c2;
 }
+weak_alias (__strncasecmp, strncasecmp)