diff options
Diffstat (limited to 'inet')
-rw-r--r-- | inet/getnetgrent_r.c | 65 |
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; } |