* nis/nss_nis/nis-netgrp.c: Remove locking by using data in struct
	__netgrent object passed in instead of global variables.
	Optimize.
	* nis/nss_nisplus/nisplus-netgrp.c: Remove locking by using data
	in struct __netgrent object passed in instead of global variables.
	* inet/netgroup.h (struct __netgrent): Add service_user field.
	Move cursor in anonymous union, add new field location to that
	union.
	* inet/getnetgrent_r.c: Extensive rewrite to really enable
	concurrent uset of set/get/endnetgrent and innetgr.
This commit is contained in:
Ulrich Drepper 2004-08-14 04:21:09 +00:00
parent a575320641
commit 8500b0caba
5 changed files with 152 additions and 195 deletions

View File

@ -1,8 +1,15 @@
2004-08-13 Ulrich Drepper <drepper@redhat.com> 2004-08-13 Ulrich Drepper <drepper@redhat.com>
* inet/getnetgrent_r.c (innetgr): We must get the lock used for * nis/nss_nis/nis-netgrp.c: Remove locking by using data in struct
the set/get/end interfaces since we call all these functions in __netgrent object passed in instead of global variables.
succession and must not be interrupted doing this. Optimize.
* nis/nss_nisplus/nisplus-netgrp.c: Remove locking by using data
in struct __netgrent object passed in instead of global variables.
* inet/netgroup.h (struct __netgrent): Add service_user field.
Move cursor in anonymous union, add new field location to that
union.
* inet/getnetgrent_r.c: Extensive rewrite to really enable
concurrent uset of set/get/endnetgrent and innetgr.
Reported by Chuck Simmons. Reported by Chuck Simmons.
* inet/netgroup.h (struct name_list): Replace name pointer with * inet/netgroup.h (struct name_list): Replace name pointer with

View File

@ -28,10 +28,6 @@
/* Protect above variable against multiple uses at the same time. */ /* Protect above variable against multiple uses at the same time. */
__libc_lock_define_initialized (static, lock) __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;
/* The whole information for the set/get/endnetgrent functions are /* The whole information for the set/get/endnetgrent functions are
kept in this structure. */ kept in this structure. */
static struct __netgrent dataset; static struct __netgrent dataset;
@ -45,7 +41,7 @@ extern int __nss_netgroup_lookup (service_user **nip, const char *name,
current location if it's not nil. Return nonzero if there are no current location if it's not nil. Return nonzero if there are no
services (left). */ services (left). */
static enum nss_status static enum nss_status
setup (void **fctp, const char *func_name, int all) setup (void **fctp, const char *func_name, int all, service_user **nipp)
{ {
/* Remember the first service_entry, it's always the same. */ /* Remember the first service_entry, it's always the same. */
static service_user *startp; static service_user *startp;
@ -53,19 +49,21 @@ setup (void **fctp, const char *func_name, int all)
if (startp == NULL) if (startp == NULL)
{ {
no_more = __nss_netgroup_lookup (&nip, func_name, fctp); /* Executing this more than once at the same time must yield the
startp = no_more ? (service_user *) -1 : nip; same result every time. So we need no locking. */
no_more = __nss_netgroup_lookup (nipp, func_name, fctp);
startp = no_more ? (service_user *) -1 : *nipp;
} }
else if (startp == (service_user *) -1) else if (startp == (service_user *) -1)
/* No services at all. */ /* No services at all. */
return 1; return 1;
else else
{ {
if (all || !nip) if (all || *nipp == NULL)
/* Reset to the beginning of the service list. */ /* Reset to the beginning of the service list. */
nip = startp; *nipp = startp;
/* Look up the first function. */ /* Look up the first function. */
no_more = __nss_lookup (&nip, func_name, fctp); no_more = __nss_lookup (nipp, func_name, fctp);
} }
return no_more; return no_more;
} }
@ -101,16 +99,15 @@ __internal_setnetgrent_reuse (const char *group, struct __netgrent *datap,
} fct; } fct;
enum nss_status status = NSS_STATUS_UNAVAIL; enum nss_status status = NSS_STATUS_UNAVAIL;
struct name_list *new_elem; struct name_list *new_elem;
int no_more;
/* Cycle through all the services and run their setnetgrent functions. */ /* Cycle through all the services and run their setnetgrent functions. */
no_more = setup (&fct.ptr, "setnetgrent", 1); int no_more = setup (&fct.ptr, "setnetgrent", 1, &datap->nip);
while (! no_more) while (! no_more)
{ {
/* Ignore status, we force check in `__nss_next'. */ /* Ignore status, we force check in `__nss_next'. */
status = (*fct.f) (group, datap); status = (*fct.f) (group, datap);
no_more = __nss_next (&nip, "setnetgrent", &fct.ptr, status, 0); no_more = __nss_next (&datap->nip, "setnetgrent", &fct.ptr, status, 0);
} }
/* Add the current group to the list of known groups. */ /* Add the current group to the list of known groups. */
@ -173,20 +170,19 @@ internal_endnetgrent (struct __netgrent *datap)
enum nss_status (*f) (struct __netgrent *); enum nss_status (*f) (struct __netgrent *);
void *ptr; void *ptr;
} fct; } fct;
int no_more;
/* Remember which was the last used service. */ /* Remember which was the last used service. */
old_nip = nip; old_nip = datap->nip;
/* Cycle through all the services and run their endnetgrent functions. */ /* Cycle through all the services and run their endnetgrent functions. */
no_more = setup (&fct.ptr, "endnetgrent", 1); int no_more = setup (&fct.ptr, "endnetgrent", 1, &datap->nip);
while (! no_more) while (! no_more)
{ {
/* Ignore status, we force check in `__nss_next'. */ /* Ignore status, we force check in `__nss_next'. */
(void) (*fct.f) (datap); (void) (*fct.f) (datap);
no_more = (nip == old_nip no_more = (datap->nip == old_nip
|| __nss_next (&nip, "endnetgrent", &fct.ptr, 0, 1)); || __nss_next (&datap->nip, "endnetgrent", &fct.ptr, 0, 1));
} }
/* Now free list of all netgroup names from last run. */ /* Now free list of all netgroup names from last run. */
@ -222,7 +218,6 @@ internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
enum nss_status (*f) (struct __netgrent *, char *, size_t, int *); enum nss_status (*f) (struct __netgrent *, char *, size_t, int *);
void *ptr; void *ptr;
} fct; } fct;
int no_more;
/* Initialize status to return if no more functions are found. */ /* Initialize status to return if no more functions are found. */
enum nss_status status = NSS_STATUS_NOTFOUND; enum nss_status status = NSS_STATUS_NOTFOUND;
@ -230,7 +225,7 @@ internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
/* Run through available functions, starting with the same function last /* Run through available functions, starting with the same function last
run. We will repeat each function as long as it succeeds, and then go run. We will repeat each function as long as it succeeds, and then go
on to the next service action. */ on to the next service action. */
no_more = setup (&fct.ptr, "getnetgrent_r", 0); int no_more = setup (&fct.ptr, "getnetgrent_r", 0, &datap->nip);
while (! no_more) while (! no_more)
{ {
status = (*fct.f) (datap, buffer, buflen, &errno); status = (*fct.f) (datap, buffer, buflen, &errno);
@ -284,7 +279,7 @@ internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
} }
} }
no_more = __nss_next (&nip, "getnetgrent_r", &fct.ptr, status, 0); no_more = __nss_next (&datap->nip, "getnetgrent_r", &fct.ptr, status, 0);
} }
if (status == NSS_STATUS_SUCCESS) if (status == NSS_STATUS_SUCCESS)
@ -337,14 +332,12 @@ innetgr (const char *netgroup, const char *host, const char *user,
int (*f) (struct __netgrent *, char *, size_t, int *); int (*f) (struct __netgrent *, char *, size_t, int *);
void *ptr; void *ptr;
} getfct; } getfct;
struct name_list *known = NULL; struct __netgrent entry;
struct name_list *needed = NULL;
int result = 0; int result = 0;
int no_more;
const char *current_group = netgroup; const char *current_group = netgroup;
int real_entry = 0; int real_entry = 0;
__libc_lock_lock (lock); memset (&entry, '\0', sizeof (entry));
/* Walk through the services until we found an answer or we shall /* Walk through the services until we found an answer or we shall
not work further. We can do some optimization here. Since all not work further. We can do some optimization here. Since all
@ -352,19 +345,14 @@ innetgr (const char *netgroup, const char *host, const char *user,
the work during one walk through the service list. */ the work during one walk through the service list. */
while (1) while (1)
{ {
no_more = setup (&setfct.ptr, "setnetgrent", 1); int no_more = setup (&setfct.ptr, "setnetgrent", 1, &entry.nip);
while (! no_more) while (! no_more)
{ {
enum nss_status status;
struct __netgrent entry;
/* Clear the space for the netgroup data. */
__bzero (&entry, sizeof (entry));
/* Open netgroup. */ /* Open netgroup. */
status = (*setfct.f) (current_group, &entry); enum nss_status status = (*setfct.f) (current_group, &entry);
if (status == NSS_STATUS_SUCCESS if (status == NSS_STATUS_SUCCESS
&& __nss_lookup (&nip, "getnetgrent_r", &getfct.ptr) == 0) && __nss_lookup (&entry.nip, "getnetgrent_r", &getfct.ptr) == 0)
{ {
char buffer[1024]; char buffer[1024];
@ -376,7 +364,8 @@ innetgr (const char *netgroup, const char *host, const char *user,
/* Make sure we haven't seen the name before. */ /* Make sure we haven't seen the name before. */
struct name_list *namep; struct name_list *namep;
for (namep = known; namep != NULL; namep = namep->next) for (namep = entry.known_groups; namep != NULL;
namep = namep->next)
if (strcmp (entry.val.group, namep->name) == 0) if (strcmp (entry.val.group, namep->name) == 0)
break; break;
if (namep == NULL if (namep == NULL
@ -393,9 +382,9 @@ innetgr (const char *netgroup, const char *host, const char *user,
break; break;
} }
namep->next = needed; namep->next = entry.needed_groups;
memcpy (namep->name, entry.val.group, group_len); memcpy (namep->name, entry.val.group, group_len);
needed = namep; entry.needed_groups = namep;
} }
} }
else else
@ -425,21 +414,21 @@ innetgr (const char *netgroup, const char *host, const char *user,
} }
/* Free all resources of the service. */ /* Free all resources of the service. */
if (__nss_lookup (&nip, "endnetgrent", &endfct.ptr) == 0) if (__nss_lookup (&entry.nip, "endnetgrent", &endfct.ptr) == 0)
(*endfct.f) (&entry); (*endfct.f) (&entry);
/* Look for the next service. */ /* Look for the next service. */
no_more = __nss_next (&nip, "setnetgrent", no_more = __nss_next (&entry.nip, "setnetgrent",
&setfct.ptr, status, 0); &setfct.ptr, status, 0);
} }
if (result == 0 && needed != NULL) if (result == 0 && entry.needed_groups != NULL)
{ {
struct name_list *tmp = needed; struct name_list *tmp = entry.needed_groups;
needed = tmp->next; entry.needed_groups = tmp->next;
tmp->next = known; tmp->next = entry.known_groups;
known = tmp; entry.known_groups = tmp;
current_group = known->name; current_group = entry.known_groups->name;
continue; continue;
} }
@ -447,22 +436,9 @@ innetgr (const char *netgroup, const char *host, const char *user,
break; break;
} }
__libc_lock_unlock (lock);
/* Free the memory. */ /* Free the memory. */
while (known != NULL) free_memory (&entry);
{
struct name_list *tmp = known;
known = known->next;
free (tmp);
}
while (needed != NULL)
{
struct name_list *tmp = needed;
needed = needed->next;
free (tmp);
}
return result == 1; return result;
} }
libc_hidden_def (innetgr) libc_hidden_def (innetgr)

View File

@ -20,6 +20,8 @@
#ifndef _NETGROUP_H #ifndef _NETGROUP_H
#define _NETGROUP_H 1 #define _NETGROUP_H 1
#include <nsswitch.h>
/* A netgroup can consist of names of other netgroups. We have to /* A netgroup can consist of names of other netgroups. We have to
track which netgroups were read and which still have to be read. */ track which netgroups were read and which still have to be read. */
struct name_list struct name_list
@ -51,11 +53,19 @@ struct __netgrent
functions. We must avoid global variables. */ functions. We must avoid global variables. */
char *data; char *data;
size_t data_size; size_t data_size;
char *cursor; union
{
char *cursor;
unsigned long int position;
};
int first; int first;
struct name_list *known_groups; struct name_list *known_groups;
struct name_list *needed_groups; struct name_list *needed_groups;
/* This handle for the NSS data base is shared between all
set/get/endXXXent functions. */
service_user *nip;
}; };

View File

@ -1,4 +1,5 @@
/* Copyright (C) 1996,1997,1999,2000,2002,2003 Free Software Foundation, Inc. /* Copyright (C) 1996,1997,1999,2000,2002,2003,2004
Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
@ -17,11 +18,12 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#include <nss.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <bits/libc-lock.h> #include <malloc.h>
#include <netdb.h> #include <netdb.h>
#include <nss.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -31,36 +33,28 @@
#include "nss-nis.h" #include "nss-nis.h"
/* Locks the static variables in this file. */
__libc_lock_define_initialized (static, lock)
static char *data;
static size_t data_size;
static char *cursor;
extern enum nss_status extern enum nss_status
_nss_netgroup_parseline (char **cursor, struct __netgrent *result, _nss_netgroup_parseline (char **cursor, struct __netgrent *netgrp,
char *buffer, size_t buflen, int *errnop); char *buffer, size_t buflen, int *errnop);
static void static void
internal_nis_endnetgrent (void) internal_nis_endnetgrent (struct __netgrent *netgrp)
{ {
if (data != NULL) if (netgrp->data != NULL)
{ {
free (data); free (netgrp->data);
data = NULL; netgrp->data = NULL;
data_size = 0; netgrp->data_size = 0;
cursor = NULL; netgrp->cursor = NULL;
} }
} }
enum nss_status enum nss_status
_nss_nis_setnetgrent (const char *group, struct __netgrent *dummy) _nss_nis_setnetgrent (const char *group, struct __netgrent *netgrp)
{ {
char *domain; char *domain;
char *result; int len;
int len, group_len;
enum nss_status status; enum nss_status status;
status = NSS_STATUS_SUCCESS; status = NSS_STATUS_SUCCESS;
@ -71,41 +65,32 @@ _nss_nis_setnetgrent (const char *group, struct __netgrent *dummy)
if (yp_get_default_domain (&domain)) if (yp_get_default_domain (&domain))
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
__libc_lock_lock (lock); internal_nis_endnetgrent (netgrp);
internal_nis_endnetgrent (); status = yperr2nss (yp_match (domain, "netgroup", group, strlen (group),
&netgrp->data, &len));
group_len = strlen (group);
status = yperr2nss (yp_match (domain, "netgroup", group, group_len,
&result, &len));
if (status == NSS_STATUS_SUCCESS) if (status == NSS_STATUS_SUCCESS)
{ {
if (len > 0 && (data = malloc (len + 1)) != NULL) /* Our implementation of yp_match already allocates a buffer
{ which is one byte larger than the value in LEN specifies
data_size = len; and the last byte is filled with NUL. So we can simply
cursor = strncpy (data, result, len + 1); use that buffer. */
data[len] = '\0'; assert (len > 0);
free (result); assert (malloc_usable_size (netgrp->data) >= len + 1);
} assert (netgrp->data[len] == '\0');
else
status = NSS_STATUS_NOTFOUND;
}
__libc_lock_unlock (lock); netgrp->data_size = len;
netgrp->cursor = netgrp->data;
}
return status; return status;
} }
enum nss_status enum nss_status
_nss_nis_endnetgrent (struct __netgrent *dummy) _nss_nis_endnetgrent (struct __netgrent *netgrp)
{ {
__libc_lock_lock (lock); internal_nis_endnetgrent (netgrp);
internal_nis_endnetgrent ();
__libc_lock_unlock (lock);
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
} }
@ -114,16 +99,9 @@ enum nss_status
_nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen, _nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen,
int *errnop) int *errnop)
{ {
enum nss_status status; if (result->cursor == NULL)
if (cursor == NULL)
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
__libc_lock_lock (lock); return _nss_netgroup_parseline (&result->cursor, result, buffer, buflen,
errnop);
status = _nss_netgroup_parseline (&cursor, result, buffer, buflen, errnop);
__libc_lock_unlock (lock);
return status;
} }

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1997, 2003 Free Software Foundation, Inc. /* Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
@ -23,51 +23,47 @@
#include <netdb.h> #include <netdb.h>
#include <string.h> #include <string.h>
#include <netgroup.h> #include <netgroup.h>
#include <bits/libc-lock.h>
#include <rpcsvc/nis.h> #include <rpcsvc/nis.h>
#include "nss-nisplus.h" #include "nss-nisplus.h"
__libc_lock_define_initialized (static, lock)
static nis_result *data = NULL;
static unsigned long data_size = 0;
static unsigned long position = 0;
#define NISENTRYVAL(idx,col,res) \ #define NISENTRYVAL(idx,col,res) \
((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val) ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
#define NISENTRYLEN(idx,col,res) \ #define NISENTRYLEN(idx,col,res) \
((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len) ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
static enum nss_status enum nss_status
_nss_nisplus_parse_netgroup (struct __netgrent *result, char *buffer, _nss_nisplus_getnetgrent_r (struct __netgrent *result, char *buffer,
size_t buflen, int *errnop) size_t buflen, int *errnop)
{ {
enum nss_status status; enum nss_status status;
/* Some sanity checks. */ /* Some sanity checks. */
if (data == NULL || data_size == 0) if (result->data == NULL || result->data_size == 0)
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
if (position == data_size) if (result->position == result->data_size)
return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN;
if (NISENTRYLEN (position, 1, data) > 0) unsigned int entrylen
= NISENTRYLEN (result->position, 1, (nis_result *) result->data);
if (entrylen > 0)
{ {
/* We have a list of other netgroups. */ /* We have a list of other netgroups. */
result->type = group_val; result->type = group_val;
if (NISENTRYLEN (position, 1, data) >= buflen) if (entrylen >= buflen)
{ {
*errnop = ERANGE; *errnop = ERANGE;
return NSS_STATUS_TRYAGAIN; return NSS_STATUS_TRYAGAIN;
} }
strncpy (buffer, NISENTRYVAL (position, 1, data), strncpy (buffer, NISENTRYVAL (result->position, 1,
NISENTRYLEN (position, 1, data)); (nis_result *) result->data),
buffer[NISENTRYLEN (position, 1, data)] = '\0'; entrylen);
buffer[entrylen] = '\0';
result->val.group = buffer; result->val.group = buffer;
++position; ++result->position;
result->first = 0; result->first = 0;
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
@ -75,8 +71,13 @@ _nss_nisplus_parse_netgroup (struct __netgrent *result, char *buffer,
/* Before we can copy the entry to the private buffer we have to make /* Before we can copy the entry to the private buffer we have to make
sure it is big enough. */ sure it is big enough. */
if (NISENTRYLEN (position, 2, data) + NISENTRYLEN (position, 3, data) + unsigned int hostlen
NISENTRYLEN (position, 4, data) + 6 > buflen) = NISENTRYLEN (result->position, 2, (nis_result *) result->data);
unsigned int userlen
= NISENTRYLEN (result->position, 3, (nis_result *) result->data);
unsigned int domainlen
= NISENTRYLEN (result->position, 4, (nis_result *) result->data);
if (hostlen + userlen + domainlen + 6 > buflen)
{ {
*errnop = ERANGE; *errnop = ERANGE;
status = NSS_STATUS_TRYAGAIN; status = NSS_STATUS_TRYAGAIN;
@ -87,40 +88,43 @@ _nss_nisplus_parse_netgroup (struct __netgrent *result, char *buffer,
result->type = triple_val; result->type = triple_val;
if (NISENTRYLEN (position, 2, data) == 0) if (hostlen == 0)
result->val.triple.host = NULL; result->val.triple.host = NULL;
else else
{ {
result->val.triple.host = cp; result->val.triple.host = cp;
cp = __stpncpy (cp, NISENTRYVAL (position, 2, data), cp = __stpncpy (cp, NISENTRYVAL (result->position, 2,
NISENTRYLEN (position, 2, data)); (nis_result *) result->data),
hostlen);
*cp++ = '\0'; *cp++ = '\0';
} }
if (NISENTRYLEN (position, 3, data) == 0) if (userlen == 0)
result->val.triple.user = NULL; result->val.triple.user = NULL;
else else
{ {
result->val.triple.user = cp; result->val.triple.user = cp;
cp = __stpncpy (cp, NISENTRYVAL (position, 3, data), cp = __stpncpy (cp, NISENTRYVAL (result->position, 3,
NISENTRYLEN (position, 3, data)); (nis_result *) result->data),
userlen);
*cp++ = '\0'; *cp++ = '\0';
} }
if (NISENTRYLEN (position, 4, data) == 0) if (domainlen == 0)
result->val.triple.domain = NULL; result->val.triple.domain = NULL;
else else
{ {
result->val.triple.domain = cp; result->val.triple.domain = cp;
cp = __stpncpy (cp, NISENTRYVAL (position, 4, data), cp = __stpncpy (cp, NISENTRYVAL (result->position, 4,
NISENTRYLEN (position, 4, data)); (nis_result *) result->data),
domainlen);
*cp = '\0'; *cp = '\0';
} }
status = NSS_STATUS_SUCCESS; status = NSS_STATUS_SUCCESS;
/* Remember where we stopped reading. */ /* Remember where we stopped reading. */
++position; ++result->position;
result->first = 0; result->first = 0;
} }
@ -128,8 +132,20 @@ _nss_nisplus_parse_netgroup (struct __netgrent *result, char *buffer,
return status; return status;
} }
static void
internal_endnetgrent (struct __netgrent *netgrp)
{
if (netgrp->data != NULL)
{
nis_freeresult ((nis_result *) netgrp->data);
netgrp->data = NULL;
netgrp->data_size = 0;
netgrp->position = 0;
}
}
enum nss_status enum nss_status
_nss_nisplus_setnetgrent (const char *group, struct __netgrent *dummy) _nss_nisplus_setnetgrent (const char *group, struct __netgrent *netgrp)
{ {
enum nss_status status; enum nss_status status;
char buf[strlen (group) + 30]; char buf[strlen (group) + 30];
@ -139,68 +155,38 @@ _nss_nisplus_setnetgrent (const char *group, struct __netgrent *dummy)
status = NSS_STATUS_SUCCESS; status = NSS_STATUS_SUCCESS;
__libc_lock_lock (lock); internal_endnetgrent (netgrp);
if (data != NULL)
{
nis_freeresult (data);
data = NULL;
data_size = 0;
position = 0;
}
sprintf (buf, "[name=%s],netgroup.org_dir", group); sprintf (buf, "[name=%s],netgroup.org_dir", group);
data = nis_list (buf, EXPAND_NAME, NULL, NULL); netgrp->data = (char *) nis_list (buf, EXPAND_NAME, NULL, NULL);
if (data == NULL) if (netgrp->data == NULL)
{ {
__set_errno (ENOMEM); __set_errno (ENOMEM);
status = NSS_STATUS_TRYAGAIN; status = NSS_STATUS_TRYAGAIN;
} }
else if (niserr2nss (data->status) != NSS_STATUS_SUCCESS) else if (niserr2nss (((nis_result *) netgrp->data)->status)
!= NSS_STATUS_SUCCESS)
{ {
status = niserr2nss (data->status); status = niserr2nss (((nis_result *) netgrp->data)->status);
nis_freeresult (data);
data = NULL; internal_endnetgrent (netgrp);
} }
else else
data_size = data->objects.objects_len; {
netgrp->data_size = ((nis_result *) netgrp->data)->objects.objects_len;
__libc_lock_unlock (lock); netgrp->position = 0;
netgrp->first = 1;
}
return status; return status;
} }
enum nss_status enum nss_status
_nss_nisplus_endnetgrent (struct __netgrent *dummy) _nss_nisplus_endnetgrent (struct __netgrent *netgrp)
{ {
__libc_lock_lock (lock); internal_endnetgrent (netgrp);
if (data != NULL)
{
nis_freeresult (data);
data = NULL;
data_size = 0;
position = 0;
}
__libc_lock_unlock (lock);
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
} }
enum nss_status
_nss_nisplus_getnetgrent_r (struct __netgrent *result,
char *buffer, size_t buflen, int *errnop)
{
enum nss_status status;
__libc_lock_lock (lock);
status = _nss_nisplus_parse_netgroup (result, buffer, buflen, errnop);
__libc_lock_unlock (lock);
return status;
}