update from main archive 961001
authordrepper <drepper>
Wed, 2 Oct 1996 01:35:51 +0000 (01:35 +0000)
committerdrepper <drepper>
Wed, 2 Oct 1996 01:35:51 +0000 (01:35 +0000)
16 files changed:
manual/filesys.texi
misc/Makefile
nss/Makefile
nss/databases.def
nss/db-Makefile
nss/getXXent_r.c
nss/netgrp-lookup.c [new file with mode: 0644]
nss/nss.h
nss/nss_db/db-XXX.c
nss/nss_db/db-netgrp.c [new file with mode: 0644]
nss/nss_dns/dns-network.c
nss/nss_files/files-netgrp.c [new file with mode: 0644]
nss/nsswitch.c
nss/nsswitch.conf
nss/nsswitch.h
posix/unistd.h

index e269663..3132526 100644 (file)
@@ -327,6 +327,36 @@ conditions are defined for this function:
 @item EBADF
 The @var{dirstream} argument is not valid.
 @end table
+
+@code{readdir} is not thread safe.  Multiple threads using
+@code{readdir} on the same @var{dirstream} may overwrite the return
+value.  Use @code{readdir_r} when this is critical.
+@end deftypefun
+
+@comment dirent.h
+@comment GNU
+@deftypefun int readdir_r (DIR *@var{dirstream}, struct *@var{entry}, struct **@var{result})
+This function is the reentrant version of @code{reentrant}.  Like
+@code{readdir} it returns the next entry from the directory.  But to
+prevent conflicts for simultanously running threads the result is not
+stored in some internal memory.  Instead the argument @var{entry} has to
+point to a place where the result is stored.
+
+The return value is @code{0} in case the next entry was read
+successfully.  In this case a pointer to the result is returned in
+*@var{result}.  It is not required that *@var{result} is the same as
+@var{entry}.  If somethings goes wrong while exeucting @code{readdir_r}
+the function return @code{-1}.  The @code{errno} variable is set like
+described for @code{readdir}.
+
+@strong{Portability Note:} On some systems, @code{readdir_r} may not
+return a terminated string as the file name even if no @code{d_reclen}
+element is available in @code{struct dirent} and the file name as the
+maximal allowed size.  Modern systems all have the @code{d_reclen} field
+and on old systems multi threading is not critical.  In any case, there
+is no such problem with the @code{readdir} function so that even on
+systems without @code{d_reclen} field one could use multiple threads by
+using external locking.
 @end deftypefun
 
 @comment dirent.h
index e6ad0d0..343cc3e 100644 (file)
@@ -56,11 +56,6 @@ routines := brk sbrk sstk ioctl \
            hsearch hsearch_r tsearch lsearch \
            err error ustat \
            getsysstats
-
-ifneq (,$(filter %REENTRANT, $(defines)))
-routines += force-wrapper
-endif
-
 aux := init-misc
 distribute := bsd-compat.c
 extra-objs := bsd-compat.o
index b900e96..319bad5 100644 (file)
@@ -33,7 +33,7 @@ routines              = nsswitch $(addsuffix -lookup,$(databases))
 # Caution: if you add a database here, you must add its real name
 # in databases.def, too.
 databases              = proto service hosts network grp pwd rpc ethers \
-                         spwd
+                         spwd netgrp
 
 # Specify rules for the nss_* modules.  We have some services.
 services               := files dns db
index 98772ba..8a5ede2 100644 (file)
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA.  */
 DEFINE_DATABASE (ethers)
 DEFINE_DATABASE (group)
 DEFINE_DATABASE (hosts)
+DEFINE_DATABASE (netgroup)
 DEFINE_DATABASE (networks)
 DEFINE_DATABASE (passwd)
 DEFINE_DATABASE (protocols)
index 55edd66..756f4c6 100644 (file)
@@ -1,5 +1,5 @@
 DATABASES = $(wildcard /etc/passwd /etc/group /etc/ethers /etc/protocols \
-                      /etc/rpc /etc/services /etc/shadow)
+                      /etc/rpc /etc/services /etc/shadow /etc/netgroup)
 
 VAR_DB = /var/db
 
@@ -67,3 +67,11 @@ $(VAR_DB)/shadow.db: /etc/shadow
                 /^[^#]/ { printf ".%s ", $$1; print }' $^ | \
        $(MAKEDB) -o $@ -
        @echo "done."
+
+$(VAR_DB)/netgroup.db: /etc/netgroup
+       @echo -n "$(patsubst %.db,%,$(@F))... "
+       @$(AWK) '/^[^#]/ { end=sub(/\\/, " "); \
+                          gsub(/[ \t]+/, " "); \
+                          if(end == 1) printf "%s", $$0; else print }' $^ | \
+       $(MAKEDB) -o $@ -
+       @echo "done."
index ea391fe..6bff863 100644 (file)
@@ -136,7 +136,7 @@ SETFUNC_NAME (STAYOPEN)
 #ifdef NEED__RES
   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
     {
-      h_errno = NETDB_INTERNAL;
+      __set_h_errno (NETDB_INTERNAL);
       return NULL;
     }
 #endif /* need _res */
@@ -166,7 +166,7 @@ ENDFUNC_NAME (void)
 #ifdef NEED__RES
   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
     {
-      h_errno = NETDB_INTERNAL;
+      __set_h_errno (NETDB_INTERNAL);
       return NULL;
     }
 #endif /* need _res */
@@ -198,7 +198,7 @@ INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *result, char *buffer, int buflen
 #ifdef NEED__RES
   if ((_res.options & RES_INIT) == 0 && res_init () == -1)
     {
-      h_errno = NETDB_INTERNAL;
+      __set_h_errno (NETDB_INTERNAL);
       return NULL;
     }
 #endif /* need _res */
diff --git a/nss/netgrp-lookup.c b/nss/netgrp-lookup.c
new file mode 100644 (file)
index 0000000..b7ea374
--- /dev/null
@@ -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 netgroup
+
+#include "XXX-lookup.c"
index e9acb93..8246719 100644 (file)
--- a/nss/nss.h
+++ b/nss/nss.h
@@ -37,6 +37,7 @@ enum nss_status
   NSS_STATUS_UNAVAIL,
   NSS_STATUS_NOTFOUND,
   NSS_STATUS_SUCCESS,
+  NSS_STATUS_RETURN
 };
 
 
index e2bab51..0c41761 100644 (file)
@@ -56,10 +56,10 @@ static int keep_db;
 static unsigned int entidx;    /* Index for `getENTNAME'. */
 
 /* Open database file if not already opened.  */
-static int
+static enum nss_status
 internal_setent (int stayopen)
 {
-  int status = NSS_STATUS_SUCCESS;
+  enum nss_status status = NSS_STATUS_SUCCESS;
 
   if (db == NULL)
     {
@@ -78,10 +78,10 @@ internal_setent (int stayopen)
 
 
 /* Thread-safe, exported version of that.  */
-int
+enum nss_status
 CONCAT(_nss_db_set,ENTNAME) (int stayopen)
 {
-  int status;
+  enum nss_status status;
 
   __libc_lock_lock (lock);
 
@@ -109,7 +109,7 @@ internal_endent (void)
 
 
 /* Thread-safe, exported version of that.  */
-int
+enum nss_status
 CONCAT(_nss_db_end,ENTNAME) (void)
 {
   __libc_lock_lock (lock);
diff --git a/nss/nss_db/db-netgrp.c b/nss/nss_db/db-netgrp.c
new file mode 100644 (file)
index 0000000..441a0bd
--- /dev/null
@@ -0,0 +1,108 @@
+/* Netgroup file parser in nss_db modules.
+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 <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libc-lock.h>
+#include <paths.h>
+#include "nsswitch.h"
+#include "netgroup.h"
+
+
+#define DBFILE         _PATH_VARDB "netgroup.db"
+
+
+/* Locks the static variables in this file.  */
+__libc_lock_define_initialized (static, lock)
+\f
+/* Maintenance of the shared handle open on the database.  */
+static DB *db;
+static char *entry;
+static char *cursor;
+
+enum nss_status
+_nss_db_setnetgrent (const char *group)
+{
+  enum nss_status status = NSS_STATUS_SUCCESS;
+
+  __libc_lock_lock (lock);
+
+  /* Make sure the data base file is open.  */
+  if (db == NULL)
+    {
+      db = dbopen (DBFILE, O_RDONLY, 0, DB_BTREE, NULL);
+
+      if (db == NULL)
+       status = errno = EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+    }
+
+  if (status == NSS_STATUS_SUCCESS)
+    {
+      DBT key = { data: (void *) group, size: strlen (group) };
+      DBT value;
+
+      if ((*db->get) (db, &key, &value, 0) != 0)
+       status = NSS_STATUS_NOTFOUND;
+      else
+       cursor = entry = value.data;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return status;
+
+}
+
+
+enum nss_status
+_nss_db_endnetgrent (void)
+{
+  __libc_lock_lock (lock);
+
+  if (db != NULL)
+    {
+      (*db->close) (db);
+      db = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+extern enum nss_status _nss_netgroup_parseline (char **cursor,
+                                               struct __netgrent *result,
+                                               char *buffer, int buflen);
+
+enum nss_status
+_nss_db_getnetgrent_r (struct __netgrent *result, char *buffer, int buflen)
+{
+  int status;
+
+  __libc_lock_lock (lock);
+
+  status = _nss_netgroup_parseline (&cursor, result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
index 1b5d0ce..a2d9d28 100644 (file)
@@ -236,12 +236,12 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
        OSF/1 has a per-thread h_errno variable.  */
     if (header_pointer->aa != 0)
       {
-       h_errno = HOST_NOT_FOUND;
+       __set_h_errno (HOST_NOT_FOUND);
        return NSS_STATUS_NOTFOUND;
       }
     else
       {
-       h_errno = TRY_AGAIN;
+       __set_h_errno (TRY_AGAIN);
        return NSS_STATUS_TRYAGAIN;
       }
 
@@ -338,7 +338,6 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
       return NSS_STATUS_SUCCESS;
     }
 
-  /* XXX Really use global variable??? */
-  h_errno = TRY_AGAIN;
+  __set_h_errno (TRY_AGAIN);
   return NSS_STATUS_TRYAGAIN;
 }
diff --git a/nss/nss_files/files-netgrp.c b/nss/nss_files/files-netgrp.c
new file mode 100644 (file)
index 0000000..8af55f2
--- /dev/null
@@ -0,0 +1,262 @@
+/* Netgroup file parser in nss_files modules.
+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 <errno.h>
+#include <libc-lock.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "nsswitch.h"
+#include "netgroup.h"
+
+#define DATAFILE       "/etc/netgroup"
+
+
+/* Locks the static variables in this file.  */
+__libc_lock_define_initialized (static, lock)
+\f
+/* We share a single place where we store the data for the current
+   netgroup.  This buffer is allocated by `setnetgrent' and freed on
+   the next call of this function or when calling `endnetgrent'.  */
+static char *data;
+static size_t data_size;
+static char *cursor;
+static int first;
+
+
+#define EXPAND(needed)                                                       \
+  do                                                                         \
+    {                                                                        \
+      size_t old_cursor = cursor - data;                                     \
+                                                                             \
+      data_size += 512 > 2 * needed ? 512 : 2 * needed;                              \
+      data = realloc (data, data_size);                                              \
+                                                                             \
+      if (data == NULL)                                                              \
+       {                                                                     \
+         status = NSS_STATUS_UNAVAIL;                                        \
+         goto the_end;                                                       \
+       }                                                                     \
+                                                                             \
+      cursor = data + old_cursor;                                            \
+    }                                                                        \
+  while (0)
+
+
+enum nss_status
+_nss_files_setnetgrent (const char *group)
+{
+  FILE *fp;
+  enum nss_status status;
+
+  if (group[0] == '\0')
+    return NSS_STATUS_UNAVAIL;
+
+  __libc_lock_lock (lock);
+
+  /* Find the netgroups file and open it.  */
+  fp = fopen (DATAFILE, "r");
+  if (fp == NULL)
+    status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+  else
+    {
+      /* Read the file line by line and try to find the description
+        GROUP.  We must take care for long lines.  */
+      char *line = NULL;
+      size_t line_len = 0;
+      const ssize_t group_len = strlen (group);
+
+      status = NSS_STATUS_NOTFOUND;
+      cursor = data;
+
+      while (!feof (fp))
+       {
+         ssize_t curlen = getline (&line, &line_len, fp);
+         int found;
+
+         if (curlen < 0)
+           {
+             status = NSS_STATUS_NOTFOUND;
+             break;
+           }
+
+         found = (curlen > group_len && strncmp (line, group, group_len) == 0
+                  && isspace (line[group_len]));
+
+         /* Read the whole line (including continuation) and store it
+            if FOUND in nonzero.  Otherwise we don't need it.  */
+         if (found)
+           {
+             /* Store the data from the first line.  */
+             EXPAND (curlen - group_len);
+             memcpy (cursor, &line[group_len + 1], curlen - group_len);
+             cursor += (curlen - group_len) - 1;
+           }
+
+         while (line[curlen - 1] == '\n' && line[curlen - 2] == '\\')
+           {
+             /* Yes, we have a continuation line.  */
+             if (found)
+               /* Remove these characters from the stored line.  */
+               cursor -= 2;
+
+             /* Get netxt line.  */
+             curlen = getline (&line, &line_len, fp);
+             if (curlen <= 0)
+               break;
+
+             if (found)
+               {
+                 /* Make sure we have enough room.  */
+                 EXPAND (1 + curlen + 1);
+
+                 /* Add separator in case next line starts immediately.  */
+                 *cursor++ = ' ';
+
+                 /* Copy new line.  */
+                 memcpy (cursor, line, curlen + 1);
+                 cursor += curlen;
+               }
+           }
+
+         if (found)
+           {
+             /* Now we have read the line.  */
+             status = NSS_STATUS_SUCCESS;
+             cursor = data;
+             first = 1;
+             break;
+           }
+       }
+
+    the_end:
+      /* We don't need the file and the line buffer anymore.  */
+      free (line);
+      fclose (fp);
+    }
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
+
+
+int
+_nss_files_endnetgrent (void)
+{
+  __libc_lock_lock (lock);
+
+  /* Free allocated memory for data if some is present.  */
+  if (data != NULL)
+    {
+      free (data);
+      data = NULL;
+      data_size = 0;
+      cursor = NULL;
+    }
+
+  __libc_lock_unlock (lock);
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
+enum nss_status
+_nss_netgroup_parseline (char **cursor, struct __netgrent *result,
+                        char *buffer, int buflen)
+{
+  enum nss_status status;
+  const char *host, *user, *domain;
+  char *cp = *cursor;
+
+  /* First skip leading spaces.  */
+  while (isspace (*cp))
+    ++cp;
+
+  if (*cp != '(')
+    return first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN;
+
+  /* Match host name.  */
+  host = ++cp;
+  while (*cp != ',')
+    if (*cp++ == '\0')
+      return first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN;
+
+  /* Match user name.  */
+  user = ++cp;
+  while (*cp != ',')
+    if (*cp++ == '\0')
+      return first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN;
+
+  /* Match domain name.  */
+  domain = ++cp;
+  while (*cp != ')')
+    if (*cp++ == '\0')
+      return first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN;
+  ++cp;
+
+
+  /* When we got here we have found an entry.  Before we can copy it
+     to the private buffer we have to make sure it is big enough.  */
+  if (cp - host > buflen)
+    {
+      __set_errno (ERANGE);
+      status = NSS_STATUS_UNAVAIL;
+    }
+  else
+    {
+      memcpy (buffer, host, cp - host);
+
+      buffer[(user - host) - 1] = '\0';
+      result->host = *host == ',' ? NULL : buffer;
+
+      buffer[(domain - host) - 1] = '\0';
+      result->user = *user == ',' ? NULL : buffer + (user - host);
+
+      buffer[(cp - host) - 1] = '\0';
+      result->domain = *domain == ')' ? NULL : buffer + (domain - host);
+
+      status = NSS_STATUS_SUCCESS;
+
+      /* Rememember where we stopped reading.  */
+      *cursor = cp;
+
+      first = 0;
+    }
+
+  return status;
+}
+
+
+enum nss_status
+_nss_files_getnetgrent_r (struct __netgrent *result, char *buffer, int buflen)
+{
+  enum nss_status status;
+
+  __libc_lock_lock (lock);
+
+  status = _nss_netgroup_parseline (&cursor, result, buffer, buflen);
+
+  __libc_lock_unlock (lock);
+
+  return status;
+}
index f49ddb9..9f27ef8 100644 (file)
@@ -158,7 +158,7 @@ __nss_next (service_user **ni, const char *fct_name, void **fctp, int status,
   else
     {
       /* This is really only for debugging.  */
-       if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_SUCCESS)
+       if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN)
         __libc_fatal ("illegal status in " __FUNCTION__);
 
        if (nss_next_action (*ni, status) == NSS_ACTION_RETURN)
@@ -503,6 +503,7 @@ nss_parse_service_list (const char *line)
       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->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN;
       new_service->library = NULL;
       new_service->known = NULL;
       new_service->next = NULL;
index 08bd96e..63a7875 100644 (file)
@@ -14,3 +14,5 @@ protocols:    db files
 services:      db files
 ethers:                db files
 rpc:           db files
+
+netgroup:      db files
index 0c99f14..df4e0f7 100644 (file)
@@ -62,7 +62,7 @@ typedef struct service_user
   /* Name of the service (`files', `dns', `nis', ...).  */
   const char *name;
   /* Action according to result.  */
-  lookup_actions actions[4];
+  lookup_actions actions[5];
   /* Link to the underlying library object.  */
   service_library *library;
   /* Collection of known functions.  */
index 3b7cb0a..2147400 100644 (file)
@@ -128,7 +128,8 @@ __BEGIN_DECLS
 #include <gnu/types.h>
 
 #ifndef        ssize_t
-#define        ssize_t __ssize_t
+typedef __ssize_t ssize_t;
+#define        ssize_t ssize_t
 #endif
 
 #define        __need_size_t