summary refs log tree commit diff
path: root/inet
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-10-07 10:06:31 -0400
committerUlrich Drepper <drepper@gmail.com>2011-10-07 10:06:31 -0400
commit684ae515993269277448150a1ca70db3b94aa5bd (patch)
tree493609057fdfc4aa2dd41f8d6e0c2047616b5d9c /inet
parent21fd49a9ef9c21cd2c87d0facf9f53bedb5cea20 (diff)
downloadglibc-684ae515993269277448150a1ca70db3b94aa5bd.tar.gz
glibc-684ae515993269277448150a1ca70db3b94aa5bd.tar.xz
glibc-684ae515993269277448150a1ca70db3b94aa5bd.zip
Implement caching of nscd
Diffstat (limited to 'inet')
-rw-r--r--inet/getnetgrent_r.c65
1 files changed, 60 insertions, 5 deletions
diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c
index 6aaba7b030..87903877bf 100644
--- a/inet/getnetgrent_r.c
+++ b/inet/getnetgrent_r.c
@@ -28,6 +28,7 @@
 #include "netgroup.h"
 #include "nsswitch.h"
 #include <sysdep.h>
+#include <nscd/nscd_proto.h>
 
 
 /* Protect above variable against multiple uses at the same time.  */
@@ -101,7 +102,7 @@ endnetgrent_hook (struct __netgrent *datap)
 {
   enum nss_status (*endfct) (struct __netgrent *);
 
-  if (datap->nip == NULL)
+  if (datap->nip == NULL || datap->nip == (service_user *) -1l)
     return;
 
   endfct = __nss_lookup_function (datap->nip, "endnetgrent");
@@ -189,8 +190,21 @@ setnetgrent (const char *group)
 
   __libc_lock_lock (lock);
 
+  if (__nss_not_use_nscd_netgroup > 0
+      && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY)
+    __nss_not_use_nscd_netgroup = 0;
+
+  if (!__nss_not_use_nscd_netgroup
+      && !__nss_database_custom[NSS_DBSIDX_netgroup])
+    {
+      result = __nscd_setnetgrent (group, &dataset);
+      if (result >= 0)
+	goto out;
+    }
+
   result = internal_setnetgrent (group, &dataset);
 
+ out:
   __libc_lock_unlock (lock);
 
   return result;
@@ -226,6 +240,26 @@ int internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
 			    char *buffer, size_t buflen, int *errnop);
 libc_hidden_proto (internal_getnetgrent_r)
 
+
+static enum nss_status
+nscd_getnetgrent (struct __netgrent *datap, char *buffer, size_t buflen,
+		  int *errnop)
+{
+  if (datap->cursor >= datap->data + datap->data_size)
+    return NSS_STATUS_UNAVAIL;
+
+  datap->type = triple_val;
+  datap->val.triple.host = datap->cursor;
+  datap->cursor = (char *) rawmemchr (datap->cursor, '\0') + 1;
+  datap->val.triple.user = datap->cursor;
+  datap->cursor = (char *) rawmemchr (datap->cursor, '\0') + 1;
+  datap->val.triple.domain = datap->cursor;
+  datap->cursor = (char *) rawmemchr (datap->cursor, '\0') + 1;
+
+  return NSS_STATUS_SUCCESS;
+}
+
+
 int
 internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
 			  struct __netgrent *datap,
@@ -239,9 +273,18 @@ internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
   /* Run through available functions, starting with the same function last
      run.  We will repeat each function as long as it succeeds, and then go
      on to the next service action.  */
-  int no_more = (datap->nip == NULL
-		 || (fct = __nss_lookup_function (datap->nip, "getnetgrent_r"))
-		    == NULL);
+  int no_more = datap->nip == NULL;
+  if (! no_more)
+    {
+      if (datap->nip == (service_user *) -1l)
+	fct = nscd_getnetgrent;
+      else
+	{
+	  fct = __nss_lookup_function (datap->nip, "getnetgrent_r");
+	  no_more = fct == NULL;
+	}
+    }
+
   while (! no_more)
     {
       status = DL_CALL_FCT (*fct, (datap, buffer, buflen, &errno));
@@ -342,6 +385,18 @@ int
 innetgr (const char *netgroup, const char *host, const char *user,
 	 const char *domain)
 {
+  if (__nss_not_use_nscd_netgroup > 0
+      && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY)
+    __nss_not_use_nscd_netgroup = 0;
+
+  if (!__nss_not_use_nscd_netgroup
+      && !__nss_database_custom[NSS_DBSIDX_netgroup])
+    {
+      int result = __nscd_innetgr (netgroup, host, user, domain);
+      if (result >= 0)
+	return result;
+    }
+
   union
   {
     enum nss_status (*f) (const char *, struct __netgrent *);
@@ -453,7 +508,7 @@ innetgr (const char *netgroup, const char *host, const char *user,
 	  entry.needed_groups = tmp->next;
 	  tmp->next = entry.known_groups;
 	  entry.known_groups = tmp;
-	  current_group = entry.known_groups->name;
+	  current_group = tmp->name;
 	  continue;
 	}