diff options
Diffstat (limited to 'inet/getnetgrent_r.c')
-rw-r--r-- | inet/getnetgrent_r.c | 133 |
1 files changed, 64 insertions, 69 deletions
diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c index 97b2b809f0..640210ab2e 100644 --- a/inet/getnetgrent_r.c +++ b/inet/getnetgrent_r.c @@ -1,5 +1,4 @@ -/* Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004, 2005 - Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,1998,1999,2002,2004 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 @@ -17,7 +16,6 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include <assert.h> #include <bits/libc-lock.h> #include <errno.h> #include <netdb.h> @@ -35,13 +33,15 @@ __libc_lock_define_initialized (static, lock) static struct __netgrent dataset; /* The lookup function for the first entry of this service. */ -extern int __nss_netgroup_lookup (service_user **nipp, const char *name, +extern int __nss_netgroup_lookup (service_user **nip, const char *name, void **fctp) internal_function; -/* Set up NIP to run through the services. Return nonzero if there are no + +/* Set up NIP to run through the services. If ALL is zero, use NIP's + current location if it's not nil. Return nonzero if there are no services (left). */ -static int -setup (void **fctp, service_user **nipp) +static enum nss_status +setup (void **fctp, const char *func_name, int all, service_user **nipp) { /* Remember the first service_entry, it's always the same. */ static service_user *startp; @@ -51,7 +51,7 @@ setup (void **fctp, service_user **nipp) { /* Executing this more than once at the same time must yield the same result every time. So we need no locking. */ - no_more = __nss_netgroup_lookup (nipp, "setnetgrent", fctp); + no_more = __nss_netgroup_lookup (nipp, func_name, fctp); startp = no_more ? (service_user *) -1 : *nipp; } else if (startp == (service_user *) -1) @@ -59,10 +59,11 @@ setup (void **fctp, service_user **nipp) return 1; else { - /* Reset to the beginning of the service list. */ - *nipp = startp; + if (all || *nipp == NULL) + /* Reset to the beginning of the service list. */ + *nipp = startp; /* Look up the first function. */ - no_more = __nss_lookup (nipp, "setnetgrent", fctp); + no_more = __nss_lookup (nipp, func_name, fctp); } return no_more; } @@ -86,20 +87,6 @@ free_memory (struct __netgrent *data) } } -static void -endnetgrent_hook (struct __netgrent *datap) -{ - enum nss_status (*endfct) (struct __netgrent *); - - if (datap->nip == NULL) - return; - - endfct = __nss_lookup_function (datap->nip, "endnetgrent"); - if (endfct != NULL) - (void) (*endfct) (datap); - datap->nip = NULL; -} - static int internal_function __internal_setnetgrent_reuse (const char *group, struct __netgrent *datap, @@ -113,29 +100,14 @@ __internal_setnetgrent_reuse (const char *group, struct __netgrent *datap, enum nss_status status = NSS_STATUS_UNAVAIL; struct name_list *new_elem; - /* Free data from previous service. */ - endnetgrent_hook (datap); - /* Cycle through all the services and run their setnetgrent functions. */ - int no_more = setup (&fct.ptr, &datap->nip); + int no_more = setup (&fct.ptr, "setnetgrent", 1, &datap->nip); while (! no_more) { - assert (datap->data == NULL); - /* Ignore status, we force check in `__nss_next'. */ status = (*fct.f) (group, datap); - service_user *old_nip = datap->nip; no_more = __nss_next (&datap->nip, "setnetgrent", &fct.ptr, status, 0); - - if (status == NSS_STATUS_SUCCESS && ! no_more) - { - enum nss_status (*endfct) (struct __netgrent *); - - endfct = __nss_lookup_function (old_nip, "endnetgrent"); - if (endfct != NULL) - (void) (*endfct) (datap); - } } /* Add the current group to the list of known groups. */ @@ -185,13 +157,34 @@ setnetgrent (const char *group) return result; } + void internal_endnetgrent (struct __netgrent *datap); libc_hidden_proto (internal_endnetgrent) void internal_endnetgrent (struct __netgrent *datap) { - endnetgrent_hook (datap); + service_user *old_nip; + union + { + enum nss_status (*f) (struct __netgrent *); + void *ptr; + } fct; + + /* Remember which was the last used service. */ + old_nip = datap->nip; + + /* Cycle through all the services and run their endnetgrent functions. */ + int no_more = setup (&fct.ptr, "endnetgrent", 1, &datap->nip); + while (! no_more) + { + /* Ignore status, we force check in `__nss_next'. */ + (void) (*fct.f) (datap); + + no_more = (datap->nip == old_nip + || __nss_next (&datap->nip, "endnetgrent", &fct.ptr, 0, 1)); + } + /* Now free list of all netgroup names from last run. */ free_memory (datap); } @@ -220,7 +213,11 @@ internal_getnetgrent_r (char **hostp, char **userp, char **domainp, struct __netgrent *datap, char *buffer, size_t buflen, int *errnop) { - enum nss_status (*fct) (struct __netgrent *, char *, size_t, int *); + union + { + enum nss_status (*f) (struct __netgrent *, char *, size_t, int *); + void *ptr; + } fct; /* Initialize status to return if no more functions are found. */ enum nss_status status = NSS_STATUS_NOTFOUND; @@ -228,12 +225,10 @@ 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 = setup (&fct.ptr, "getnetgrent_r", 0, &datap->nip); while (! no_more) { - status = (*fct) (datap, buffer, buflen, &errno); + status = (*fct.f) (datap, buffer, buflen, &errno); if (status == NSS_STATUS_RETURN) { @@ -251,12 +246,8 @@ internal_getnetgrent_r (char **hostp, char **userp, char **domainp, datap, errnop); } - if (found && datap->nip != NULL) - { - fct = __nss_lookup_function (datap->nip, "getnetgrent_r"); - if (fct != NULL) - continue; - } + if (found) + continue; } else if (status == NSS_STATUS_SUCCESS && datap->type == group_val) { @@ -288,7 +279,7 @@ internal_getnetgrent_r (char **hostp, char **userp, char **domainp, } } - break; + no_more = __nss_next (&datap->nip, "getnetgrent_r", &fct.ptr, status, 0); } if (status == NSS_STATUS_SUCCESS) @@ -331,8 +322,16 @@ innetgr (const char *netgroup, const char *host, const char *user, int (*f) (const char *, struct __netgrent *); void *ptr; } setfct; - void (*endfct) (struct __netgrent *); - int (*getfct) (struct __netgrent *, char *, size_t, int *); + union + { + void (*f) (struct __netgrent *); + void *ptr; + } endfct; + union + { + int (*f) (struct __netgrent *, char *, size_t, int *); + void *ptr; + } getfct; struct __netgrent entry; int result = 0; const char *current_group = netgroup; @@ -346,21 +345,18 @@ innetgr (const char *netgroup, const char *host, const char *user, the work during one walk through the service list. */ while (1) { - int no_more = setup (&setfct.ptr, &entry.nip); + int no_more = setup (&setfct.ptr, "setnetgrent", 1, &entry.nip); while (! no_more) { - assert (entry.data == NULL); - /* Open netgroup. */ enum nss_status status = (*setfct.f) (current_group, &entry); if (status == NSS_STATUS_SUCCESS - && (getfct = __nss_lookup_function (entry.nip, "getnetgrent_r")) - != NULL) + && __nss_lookup (&entry.nip, "getnetgrent_r", &getfct.ptr) == 0) { char buffer[1024]; - while ((*getfct) (&entry, buffer, sizeof buffer, &errno) + while ((*getfct.f) (&entry, buffer, sizeof buffer, &errno) == NSS_STATUS_SUCCESS) { if (entry.type == group_val) @@ -409,18 +405,17 @@ innetgr (const char *netgroup, const char *host, const char *user, } } + if (result != 0) + break; + /* If we found one service which does know the given netgroup we don't try further. */ status = NSS_STATUS_RETURN; } /* Free all resources of the service. */ - endfct = __nss_lookup_function (entry.nip, "endnetgrent"); - if (endfct != NULL) - (*endfct) (&entry); - - if (result != 0) - break; + if (__nss_lookup (&entry.nip, "endnetgrent", &endfct.ptr) == 0) + (*endfct.f) (&entry); /* Look for the next service. */ no_more = __nss_next (&entry.nip, "setnetgrent", @@ -444,6 +439,6 @@ innetgr (const char *netgroup, const char *host, const char *user, /* Free the memory. */ free_memory (&entry); - return result == 1; + return result; } libc_hidden_def (innetgr) |