diff options
Diffstat (limited to 'inet')
-rw-r--r-- | inet/gethstent_r.c | 26 | ||||
-rw-r--r-- | inet/getnetgrent_r.c | 155 | ||||
-rw-r--r-- | inet/netgroup.h | 29 |
3 files changed, 131 insertions, 79 deletions
diff --git a/inet/gethstent_r.c b/inet/gethstent_r.c index f07601dfad..2c9f151a12 100644 --- a/inet/gethstent_r.c +++ b/inet/gethstent_r.c @@ -1,20 +1,20 @@ /* Copyright (C) 1996 Free Software Foundation, Inc. -This file is part of the GNU C Library. + This file is part of the GNU C Library. -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 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. + 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. */ + 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 <netdb.h> diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c index 7288dbeb4c..1848ad7f35 100644 --- a/inet/getnetgrent_r.c +++ b/inet/getnetgrent_r.c @@ -18,6 +18,7 @@ Boston, MA 02111-1307, USA. */ #include <libc-lock.h> #include <netdb.h> +#include <string.h> #include "netgroup.h" #include "nsswitch.h" @@ -28,18 +29,10 @@ __libc_lock_define_initialized (static, lock) /* This handle for the NSS data base is shared between all set/get/endXXXent functions. */ static service_user *nip; -/* Remember the first service_entry, it's always the same. */ -static service_user *startp; -/* A netgroup can consist of names of other netgroups. We have to - track which netgroups were read and which still have to be read. */ -struct name_list -{ - const char *name; - struct name_list *next; -}; -struct name_list *known_groups; -struct name_list *needed_groups; +/* The whole information for the set/get/endnetgrent functions are + kept in this structure. */ +static struct __netgrent dataset; /* The lookup function for the first entry of this service. */ @@ -52,7 +45,10 @@ extern int __nss_netgroup_lookup (service_user **nip, const char *name, static enum nss_status setup (void **fctp, const char *func_name, int all) { + /* Remember the first service_entry, it's always the same. */ + static service_user *startp = NULL; int no_more; + if (startp == NULL) { no_more = __nss_netgroup_lookup (&nip, func_name, fctp); @@ -74,29 +70,29 @@ setup (void **fctp, const char *func_name, int all) /* Free used memory. */ static void -free_memory (void) +free_memory (struct __netgrent *data) { - while (known_groups != NULL) + while (data->known_groups != NULL) { - struct name_list *tmp = known_groups; - known_groups = known_groups->next; + struct name_list *tmp = data->known_groups; + data->known_groups = data->known_groups->next; free (tmp->name); free (tmp); } - while (needed_groups != NULL) + while (data->needed_groups != NULL) { - struct name_list *tmp = needed_groups; - needed_groups = needed_groups->next; + struct name_list *tmp = data->needed_groups; + data->needed_groups = data->needed_groups->next; free (tmp->name); free (tmp); } } static int -internal_setnetgrent (const char *group) +__internal_setnetgrent_reuse (const char *group, struct __netgrent *datap) { - enum nss_status (*fct) (const char *); + enum nss_status (*fct) (const char *, struct __netgrent *); enum nss_status status = NSS_STATUS_UNAVAIL; struct name_list *new_elem; int no_more; @@ -106,7 +102,7 @@ internal_setnetgrent (const char *group) while (! no_more) { /* Ignore status, we force check in `__nss_next'. */ - status = (*fct) (group); + status = (*fct) (group, datap); no_more = __nss_next (&nip, "setnetgrent", (void **) &fct, status, 0); } @@ -121,24 +117,30 @@ internal_setnetgrent (const char *group) } else { - new_elem->next = known_groups; - known_groups = new_elem; + new_elem->next = datap->known_groups; + datap->known_groups = new_elem; } return status == NSS_STATUS_SUCCESS; } int +__internal_setnetgrent (const char *group, struct __netgrent *datap) +{ + /* Free list of all netgroup names from last run. */ + free_memory (datap); + + return __internal_setnetgrent_reuse (group, datap); +} + +int setnetgrent (const char *group) { int result; __libc_lock_lock (lock); - /* Free list of all netgroup names from last run. */ - free_memory (); - - result = internal_setnetgrent (group); + result = __internal_setnetgrent (group, &dataset); __libc_lock_unlock (lock); @@ -147,14 +149,12 @@ setnetgrent (const char *group) void -endnetgrent (void) +__internal_endnetgrent (struct __netgrent *datap) { service_user *old_nip; - enum nss_status (*fct) (void); + enum nss_status (*fct) (struct __netgrent *); int no_more; - __libc_lock_lock (lock); - /* Remember which was the last used service. */ old_nip = nip; @@ -163,66 +163,75 @@ endnetgrent (void) while (! no_more) { /* Ignore status, we force check in `__nss_next'. */ - (void) (*fct) (); + (void) (*fct) (datap); no_more = (nip == old_nip || __nss_next (&nip, "endnetgrent", (void **) &fct, 0, 1)); } /* Now free list of all netgroup names from last run. */ - free_memory (); + free_memory (datap); +} + + +void +endnetgrent (void) +{ + __libc_lock_lock (lock); + + __internal_endnetgrent (&dataset); __libc_lock_unlock (lock); } int -__getnetgrent_r (char **hostp, char **userp, char **domainp, - char *buffer, size_t buflen) +__internal_getnetgrent (char **hostp, char **userp, char **domainp, + struct __netgrent *datap, + char *buffer, size_t buflen) { enum nss_status (*fct) (struct __netgrent *, char *, int); - struct __netgrent result; int no_more; /* Initialize status to return if no more functions are found. */ enum nss_status status = NSS_STATUS_NOTFOUND; - __libc_lock_lock (lock); - /* 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. */ no_more = setup ((void **) &fct, "getnetgrent_r", 0); while (! no_more) { - status = (*fct) (&result, buffer, buflen); + status = (*fct) (datap, buffer, buflen); if (status == NSS_STATUS_RETURN) { /* This was the last one for this group. Look at next group if available. */ int found = 0; - while (needed_groups != NULL && ! found) + while (datap->needed_groups != NULL && ! found) { - struct name_list *tmp = needed_groups; - needed_groups = needed_groups->next; - tmp->next = known_groups; - known_groups = tmp; + struct name_list *tmp = datap->needed_groups; + datap->needed_groups = datap->needed_groups->next; + tmp->next = datap->known_groups; + datap->known_groups = tmp; - found = internal_setnetgrent (known_groups->name); + found = __internal_setnetgrent_reuse (datap->known_groups->name, + datap); } if (found) continue; } - else if (status == NSS_STATUS_SUCCESS && result.type == group_val) + else if (status == NSS_STATUS_SUCCESS && datap->type == group_val) { /* The last entry was a name of another netgroup. */ struct name_list *namep; /* Ignore if we've seen the name before. */ - for (namep = known_groups; namep != NULL; namep = namep->next) - if (strcmp (result.val.group, namep->name) == 0) + for (namep = datap->known_groups; namep != NULL; + namep = namep->next) + if (strcmp (datap->val.group, namep->name) == 0) break; if (namep != NULL) /* Really ignore. */ @@ -230,7 +239,7 @@ __getnetgrent_r (char **hostp, char **userp, char **domainp, namep = (struct name_list *) malloc (sizeof (struct name_list)); if (namep == NULL - || (namep->name = __strdup (result.val.group)) == NULL) + || (namep->name = __strdup (datap->val.group)) == NULL) { /* We are out of memory. */ if (namep != NULL) @@ -239,8 +248,8 @@ __getnetgrent_r (char **hostp, char **userp, char **domainp, } else { - namep->next = needed_groups; - needed_groups = namep; + namep->next = datap->needed_groups; + datap->needed_groups = namep; /* And get the next entry. */ continue; } @@ -251,14 +260,29 @@ __getnetgrent_r (char **hostp, char **userp, char **domainp, if (status == NSS_STATUS_SUCCESS) { - *hostp = result.val.triple.host; - *userp = result.val.triple.user; - *domainp = result.val.triple.domain; + *hostp = datap->val.triple.host; + *userp = datap->val.triple.user; + *domainp = datap->val.triple.domain; } + return status == NSS_STATUS_SUCCESS ? 1 : 0; +} + +/* The real entry point. */ +int +__getnetgrent_r (char **hostp, char **userp, char **domainp, + char *buffer, size_t buflen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = __internal_getnetgrent (hostp, userp, domainp, &dataset, + buffer, buflen); + __libc_lock_unlock (lock); - return status == NSS_STATUS_SUCCESS ? 1 : 0; + return status; } weak_alias (__getnetgrent_r, getnetgrent_r) @@ -267,18 +291,16 @@ int innetgr (const char *netgroup, const char *host, const char *user, const char *domain) { - int (*setfct) (const char *); - void (*endfct) (void); + int (*setfct) (const char *, struct __netgrent *); + void (*endfct) (struct __netgrent *); int (*getfct) (struct __netgrent *, char *, int); + struct name_list *known; + struct name_list *needed; int result = 0; int no_more; - struct name_list *known = NULL; - struct name_list *needed = NULL; const char *current_group = netgroup; int real_entry = 0; - __libc_lock_lock (lock); - /* Walk through the services until we found an answer or we shall not work further. We can do some optimization here. Since all services must provide the `setnetgrent' function we can do all @@ -289,14 +311,17 @@ innetgr (const char *netgroup, const char *host, const char *user, while (! no_more) { enum nss_status status; + struct __netgrent entry; + + /* Clear the space for the netgroup data. */ + bzero (&entry, sizeof (entry)); /* Open netgroup. */ - status = (*setfct) (current_group); + status = (*setfct) (current_group, &entry); if (status == NSS_STATUS_SUCCESS && __nss_lookup (&nip, "getnetgrent_r", (void **) &getfct) == 0) { char buffer[1024]; - struct __netgrent entry; while ((*getfct) (&entry, buffer, sizeof buffer) == NSS_STATUS_SUCCESS) @@ -356,7 +381,7 @@ innetgr (const char *netgroup, const char *host, const char *user, /* Free all resources of the service. */ if (__nss_lookup (&nip, "endnetgrent", (void **) &endfct) == 0) - (*endfct) (); + (*endfct) (&entry); /* Look for the next service. */ no_more = __nss_next (&nip, "setnetgrent", @@ -377,8 +402,6 @@ innetgr (const char *netgroup, const char *host, const char *user, break; } - __libc_lock_unlock (lock); - /* Free the memory. */ while (known != NULL) { diff --git a/inet/netgroup.h b/inet/netgroup.h index 746cd9eaad..d773d8a7ce 100644 --- a/inet/netgroup.h +++ b/inet/netgroup.h @@ -20,6 +20,16 @@ Boston, MA 02111-1307, USA. */ #ifndef _NETGROUP_H #define _NETGROUP_H 1 +/* A netgroup can consist of names of other netgroups. We have to + track which netgroups were read and which still have to be read. */ +struct name_list +{ + const char *name; + struct name_list *next; +}; + + +/* Dataset for iterating netgroups. */ struct __netgrent { enum { triple_val, group_val } type; @@ -36,6 +46,25 @@ struct __netgrent const char *group; } val; + + /* Room for the data kept between the calls to the netgroup + functions. We must avoid global variables. */ + char *data; + size_t data_size; + char *cursor; + int first; + + struct name_list *known_groups; + struct name_list *needed_groups; }; + +/* The internal netgroup handling functions might be called from outside. */ +extern int __internal_setnetgrent (const char *group, + struct __netgrent *datap); +extern void __internal_endnetgrent (struct __netgrent *datap); +extern int __internal_getnetgrent_r (char **hostp, char **userp, + char **domainp, struct __netgrent *datap, + char *buffer, size_t buflen); + #endif /* netgroup.h */ |