Blame inet/getnetgrent_r.c

Packit 6c4009
/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <assert.h>
Packit 6c4009
#include <atomic.h>
Packit 6c4009
#include <libc-lock.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <netdb.h>
Packit 6c4009
#include <stdbool.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include "netgroup.h"
Packit 6c4009
#include "nsswitch.h"
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <nscd/nscd_proto.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Protect above variable against multiple uses at the same time.  */
Packit 6c4009
__libc_lock_define_initialized (static, lock)
Packit 6c4009
Packit 6c4009
/* The whole information for the set/get/endnetgrent functions are
Packit 6c4009
   kept in this structure.  */
Packit 6c4009
static struct __netgrent dataset;
Packit 6c4009
Packit 6c4009
/* Set up NIP to run through the services.  Return nonzero if there are no
Packit 6c4009
   services (left).  */
Packit 6c4009
static int
Packit 6c4009
setup (void **fctp, service_user **nipp)
Packit 6c4009
{
Packit 6c4009
  /* Remember the first service_entry, it's always the same.  */
Packit 6c4009
  static bool startp_initialized;
Packit 6c4009
  static service_user *startp;
Packit 6c4009
  int no_more;
Packit 6c4009
Packit 6c4009
  if (!startp_initialized)
Packit 6c4009
    {
Packit 6c4009
      /* Executing this more than once at the same time must yield the
Packit 6c4009
	 same result every time.  So we need no locking.  */
Packit 6c4009
      no_more = __nss_netgroup_lookup2 (nipp, "setnetgrent", NULL, fctp);
Packit 6c4009
      startp = no_more ? (service_user *) -1 : *nipp;
Packit 6c4009
#ifdef PTR_MANGLE
Packit 6c4009
      PTR_MANGLE (startp);
Packit 6c4009
#endif
Packit 6c4009
      atomic_write_barrier ();
Packit 6c4009
      startp_initialized = true;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      service_user *nip = startp;
Packit 6c4009
#ifdef PTR_DEMANGLE
Packit 6c4009
      PTR_DEMANGLE (nip);
Packit 6c4009
#endif
Packit 6c4009
      if (nip == (service_user *) -1)
Packit 6c4009
	/* No services at all.  */
Packit 6c4009
	return 1;
Packit 6c4009
Packit 6c4009
      /* Reset to the beginning of the service list.  */
Packit 6c4009
      *nipp = nip;
Packit 6c4009
      /* Look up the first function.  */
Packit 6c4009
      no_more = __nss_lookup (nipp, "setnetgrent", NULL, fctp);
Packit 6c4009
    }
Packit 6c4009
  return no_more;
Packit 6c4009
}
Packit 6c4009

Packit 6c4009
/* Free used memory.  */
Packit 6c4009
static void
Packit 6c4009
free_memory (struct __netgrent *data)
Packit 6c4009
{
Packit 6c4009
  while (data->known_groups != NULL)
Packit 6c4009
    {
Packit 6c4009
      struct name_list *tmp = data->known_groups;
Packit 6c4009
      data->known_groups = data->known_groups->next;
Packit 6c4009
      free (tmp);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  while (data->needed_groups != NULL)
Packit 6c4009
    {
Packit 6c4009
      struct name_list *tmp = data->needed_groups;
Packit 6c4009
      data->needed_groups = data->needed_groups->next;
Packit 6c4009
      free (tmp);
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009

Packit 6c4009
static void
Packit 6c4009
endnetgrent_hook (struct __netgrent *datap)
Packit 6c4009
{
Packit 6c4009
  enum nss_status (*endfct) (struct __netgrent *);
Packit 6c4009
Packit 6c4009
  if (datap->nip == NULL || datap->nip == (service_user *) -1l)
Packit 6c4009
    return;
Packit 6c4009
Packit 6c4009
  endfct = __nss_lookup_function (datap->nip, "endnetgrent");
Packit 6c4009
  if (endfct != NULL)
Packit 6c4009
    (void) (*endfct) (datap);
Packit 6c4009
  datap->nip = NULL;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
__internal_setnetgrent_reuse (const char *group, struct __netgrent *datap,
Packit 6c4009
			      int *errnop)
Packit 6c4009
{
Packit 6c4009
  union
Packit 6c4009
  {
Packit 6c4009
    enum nss_status (*f) (const char *, struct __netgrent *);
Packit 6c4009
    void *ptr;
Packit 6c4009
  } fct;
Packit 6c4009
  enum nss_status status = NSS_STATUS_UNAVAIL;
Packit 6c4009
  struct name_list *new_elem;
Packit 6c4009
Packit 6c4009
  /* Free data from previous service.  */
Packit 6c4009
  endnetgrent_hook (datap);
Packit 6c4009
Packit 6c4009
  /* Cycle through all the services and run their setnetgrent functions.  */
Packit 6c4009
  int no_more = setup (&fct.ptr, &datap->nip);
Packit 6c4009
  while (! no_more)
Packit 6c4009
    {
Packit 6c4009
      assert (datap->data == NULL);
Packit 6c4009
Packit 6c4009
      /* Ignore status, we force check in `__nss_next2'.  */
Packit 6c4009
      status = DL_CALL_FCT (*fct.f, (group, datap));
Packit 6c4009
Packit 6c4009
      service_user *old_nip = datap->nip;
Packit 6c4009
      no_more = __nss_next2 (&datap->nip, "setnetgrent", NULL, &fct.ptr,
Packit 6c4009
			     status, 0);
Packit 6c4009
Packit 6c4009
      if (status == NSS_STATUS_SUCCESS && ! no_more)
Packit 6c4009
	{
Packit 6c4009
	  enum nss_status (*endfct) (struct __netgrent *);
Packit 6c4009
Packit 6c4009
	  endfct = __nss_lookup_function (old_nip, "endnetgrent");
Packit 6c4009
	  if (endfct != NULL)
Packit 6c4009
	    (void) DL_CALL_FCT (*endfct, (datap));
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Add the current group to the list of known groups.  */
Packit 6c4009
  size_t group_len = strlen (group) + 1;
Packit 6c4009
  new_elem = (struct name_list *) malloc (sizeof (struct name_list)
Packit 6c4009
					  + group_len);
Packit 6c4009
  if (new_elem == NULL)
Packit 6c4009
    {
Packit 6c4009
      *errnop = errno;
Packit 6c4009
      status = NSS_STATUS_TRYAGAIN;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      new_elem->next = datap->known_groups;
Packit 6c4009
      memcpy (new_elem->name, group, group_len);
Packit 6c4009
      datap->known_groups = new_elem;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return status == NSS_STATUS_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
__internal_setnetgrent (const char *group, struct __netgrent *datap)
Packit 6c4009
{
Packit 6c4009
  /* Free list of all netgroup names from last run.  */
Packit 6c4009
  free_memory (datap);
Packit 6c4009
Packit 6c4009
  return __internal_setnetgrent_reuse (group, datap, &errno);
Packit 6c4009
}
Packit 6c4009
libc_hidden_def (__internal_setnetgrent)
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
nscd_setnetgrent (const char *group)
Packit 6c4009
{
Packit 6c4009
#ifdef USE_NSCD
Packit 6c4009
  if (__nss_not_use_nscd_netgroup > 0
Packit 6c4009
      && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY)
Packit 6c4009
    __nss_not_use_nscd_netgroup = 0;
Packit 6c4009
Packit 6c4009
  if (!__nss_not_use_nscd_netgroup
Packit 6c4009
      && !__nss_database_custom[NSS_DBSIDX_netgroup])
Packit 6c4009
    return __nscd_setnetgrent (group, &dataset);
Packit 6c4009
#endif
Packit 6c4009
  return -1;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
setnetgrent (const char *group)
Packit 6c4009
{
Packit 6c4009
  int result;
Packit 6c4009
Packit 6c4009
  __libc_lock_lock (lock);
Packit 6c4009
Packit 6c4009
  result = nscd_setnetgrent (group);
Packit 6c4009
  if (result < 0)
Packit 6c4009
    result = __internal_setnetgrent (group, &dataset);
Packit 6c4009
Packit 6c4009
  __libc_lock_unlock (lock);
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
__internal_endnetgrent (struct __netgrent *datap)
Packit 6c4009
{
Packit 6c4009
  endnetgrent_hook (datap);
Packit 6c4009
  /* Now free list of all netgroup names from last run.  */
Packit 6c4009
  free_memory (datap);
Packit 6c4009
}
Packit 6c4009
libc_hidden_def (__internal_endnetgrent)
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
endnetgrent (void)
Packit 6c4009
{
Packit 6c4009
  __libc_lock_lock (lock);
Packit 6c4009
Packit 6c4009
  __internal_endnetgrent (&dataset);
Packit 6c4009
Packit 6c4009
  __libc_lock_unlock (lock);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#ifdef USE_NSCD
Packit 6c4009
static const char *
Packit 6c4009
get_nonempty_val (const char *in)
Packit 6c4009
{
Packit 6c4009
  if (*in == '\0')
Packit 6c4009
    return NULL;
Packit 6c4009
  return in;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static enum nss_status
Packit 6c4009
nscd_getnetgrent (struct __netgrent *datap, char *buffer, size_t buflen,
Packit 6c4009
		  int *errnop)
Packit 6c4009
{
Packit 6c4009
  if (datap->cursor >= datap->data + datap->data_size)
Packit 6c4009
    return NSS_STATUS_UNAVAIL;
Packit 6c4009
Packit 6c4009
  datap->type = triple_val;
Packit 6c4009
  datap->val.triple.host = get_nonempty_val (datap->cursor);
Packit 6c4009
  datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1;
Packit 6c4009
  datap->val.triple.user = get_nonempty_val (datap->cursor);
Packit 6c4009
  datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1;
Packit 6c4009
  datap->val.triple.domain = get_nonempty_val (datap->cursor);
Packit 6c4009
  datap->cursor = (char *) __rawmemchr (datap->cursor, '\0') + 1;
Packit 6c4009
Packit 6c4009
  return NSS_STATUS_SUCCESS;
Packit 6c4009
}
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
__internal_getnetgrent_r (char **hostp, char **userp, char **domainp,
Packit 6c4009
			  struct __netgrent *datap,
Packit 6c4009
			  char *buffer, size_t buflen, int *errnop)
Packit 6c4009
{
Packit 6c4009
  enum nss_status (*fct) (struct __netgrent *, char *, size_t, int *);
Packit 6c4009
Packit 6c4009
  /* Initialize status to return if no more functions are found.  */
Packit 6c4009
  enum nss_status status = NSS_STATUS_NOTFOUND;
Packit 6c4009
Packit 6c4009
  /* Run through available functions, starting with the same function last
Packit 6c4009
     run.  We will repeat each function as long as it succeeds, and then go
Packit 6c4009
     on to the next service action.  */
Packit 6c4009
  int no_more = datap->nip == NULL;
Packit 6c4009
  if (! no_more)
Packit 6c4009
    {
Packit 6c4009
#ifdef USE_NSCD
Packit 6c4009
      /* This bogus function pointer is a special marker left by
Packit 6c4009
	 __nscd_setnetgrent to tell us to use the data it left
Packit 6c4009
	 before considering any modules.  */
Packit 6c4009
      if (datap->nip == (service_user *) -1l)
Packit 6c4009
	fct = nscd_getnetgrent;
Packit 6c4009
      else
Packit 6c4009
#endif
Packit 6c4009
	{
Packit 6c4009
	  fct = __nss_lookup_function (datap->nip, "getnetgrent_r");
Packit 6c4009
	  no_more = fct == NULL;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      while (! no_more)
Packit 6c4009
	{
Packit 6c4009
	  status = DL_CALL_FCT (*fct, (datap, buffer, buflen, &errno));
Packit 6c4009
Packit 6c4009
	  if (status == NSS_STATUS_RETURN
Packit 6c4009
	      /* The service returned a NOTFOUND, but there are more groups that
Packit 6c4009
		 we need to resolve before we give up.  */
Packit 6c4009
	      || (status == NSS_STATUS_NOTFOUND && datap->needed_groups != NULL))
Packit 6c4009
	    {
Packit 6c4009
	      /* This was the last one for this group.  Look at next group
Packit 6c4009
		 if available.  */
Packit 6c4009
	      int found = 0;
Packit 6c4009
	      while (datap->needed_groups != NULL && ! found)
Packit 6c4009
		{
Packit 6c4009
		  struct name_list *tmp = datap->needed_groups;
Packit 6c4009
		  datap->needed_groups = datap->needed_groups->next;
Packit 6c4009
		  tmp->next = datap->known_groups;
Packit 6c4009
		  datap->known_groups = tmp;
Packit 6c4009
Packit 6c4009
		  found = __internal_setnetgrent_reuse (datap->known_groups->name,
Packit 6c4009
							datap, errnop);
Packit 6c4009
		}
Packit 6c4009
Packit 6c4009
	      if (found && datap->nip != NULL)
Packit 6c4009
		{
Packit 6c4009
		  fct = __nss_lookup_function (datap->nip, "getnetgrent_r");
Packit 6c4009
		  if (fct != NULL)
Packit 6c4009
		    continue;
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	  else if (status == NSS_STATUS_SUCCESS && datap->type == group_val)
Packit 6c4009
	    {
Packit 6c4009
	      /* The last entry was a name of another netgroup.  */
Packit 6c4009
	      struct name_list *namep;
Packit 6c4009
Packit 6c4009
	      /* Ignore if we've seen the name before.  */
Packit 6c4009
	      for (namep = datap->known_groups; namep != NULL;
Packit 6c4009
		   namep = namep->next)
Packit 6c4009
		if (strcmp (datap->val.group, namep->name) == 0)
Packit 6c4009
		  break;
Packit 6c4009
	      if (namep == NULL)
Packit 6c4009
		for (namep = datap->needed_groups; namep != NULL;
Packit 6c4009
		     namep = namep->next)
Packit 6c4009
		  if (strcmp (datap->val.group, namep->name) == 0)
Packit 6c4009
		    break;
Packit 6c4009
	      if (namep != NULL)
Packit 6c4009
		/* Really ignore.  */
Packit 6c4009
		continue;
Packit 6c4009
Packit 6c4009
	      size_t group_len = strlen (datap->val.group) + 1;
Packit 6c4009
	      namep = (struct name_list *) malloc (sizeof (struct name_list)
Packit 6c4009
						  + group_len);
Packit 6c4009
	      if (namep == NULL)
Packit 6c4009
		/* We are out of memory.  */
Packit 6c4009
		status = NSS_STATUS_RETURN;
Packit 6c4009
	      else
Packit 6c4009
		{
Packit 6c4009
		  namep->next = datap->needed_groups;
Packit 6c4009
		  memcpy (namep->name, datap->val.group, group_len);
Packit 6c4009
		  datap->needed_groups = namep;
Packit 6c4009
		  /* And get the next entry.  */
Packit 6c4009
		  continue;
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	  break;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (status == NSS_STATUS_SUCCESS)
Packit 6c4009
    {
Packit 6c4009
      *hostp = (char *) datap->val.triple.host;
Packit 6c4009
      *userp = (char *) datap->val.triple.user;
Packit 6c4009
      *domainp = (char *) datap->val.triple.domain;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return status == NSS_STATUS_SUCCESS ? 1 : 0;
Packit 6c4009
}
Packit 6c4009
libc_hidden_def (__internal_getnetgrent_r)
Packit 6c4009
Packit 6c4009
/* The real entry point.  */
Packit 6c4009
int
Packit 6c4009
__getnetgrent_r (char **hostp, char **userp, char **domainp,
Packit 6c4009
		 char *buffer, size_t buflen)
Packit 6c4009
{
Packit 6c4009
  enum nss_status status;
Packit 6c4009
Packit 6c4009
  __libc_lock_lock (lock);
Packit 6c4009
Packit 6c4009
  status = __internal_getnetgrent_r (hostp, userp, domainp, &dataset,
Packit 6c4009
				     buffer, buflen, &errno);
Packit 6c4009
Packit 6c4009
  __libc_lock_unlock (lock);
Packit 6c4009
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
weak_alias (__getnetgrent_r, getnetgrent_r)
Packit 6c4009

Packit 6c4009
/* Test whether given (host,user,domain) triple is in NETGROUP.  */
Packit 6c4009
int
Packit 6c4009
innetgr (const char *netgroup, const char *host, const char *user,
Packit 6c4009
	 const char *domain)
Packit 6c4009
{
Packit 6c4009
#ifdef USE_NSCD
Packit 6c4009
  if (__nss_not_use_nscd_netgroup > 0
Packit 6c4009
      && ++__nss_not_use_nscd_netgroup > NSS_NSCD_RETRY)
Packit 6c4009
    __nss_not_use_nscd_netgroup = 0;
Packit 6c4009
Packit 6c4009
  if (!__nss_not_use_nscd_netgroup
Packit 6c4009
      && !__nss_database_custom[NSS_DBSIDX_netgroup])
Packit 6c4009
    {
Packit 6c4009
      int result = __nscd_innetgr (netgroup, host, user, domain);
Packit 6c4009
      if (result >= 0)
Packit 6c4009
	return result;
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  union
Packit 6c4009
  {
Packit 6c4009
    enum nss_status (*f) (const char *, struct __netgrent *);
Packit 6c4009
    void *ptr;
Packit 6c4009
  } setfct;
Packit 6c4009
  void (*endfct) (struct __netgrent *);
Packit 6c4009
  int (*getfct) (struct __netgrent *, char *, size_t, int *);
Packit 6c4009
  struct __netgrent entry;
Packit 6c4009
  int result = 0;
Packit 6c4009
  const char *current_group = netgroup;
Packit 6c4009
Packit 6c4009
  memset (&entry, '\0', sizeof (entry));
Packit 6c4009
Packit 6c4009
  /* Walk through the services until we found an answer or we shall
Packit 6c4009
     not work further.  We can do some optimization here.  Since all
Packit 6c4009
     services must provide the `setnetgrent' function we can do all
Packit 6c4009
     the work during one walk through the service list.  */
Packit 6c4009
  while (1)
Packit 6c4009
    {
Packit 6c4009
      int no_more = setup (&setfct.ptr, &entry.nip);
Packit 6c4009
      while (! no_more)
Packit 6c4009
	{
Packit 6c4009
	  assert (entry.data == NULL);
Packit 6c4009
Packit 6c4009
	  /* Open netgroup.  */
Packit 6c4009
	  enum nss_status status = DL_CALL_FCT (*setfct.f,
Packit 6c4009
						(current_group, &entry));
Packit 6c4009
Packit 6c4009
	  if (status == NSS_STATUS_SUCCESS
Packit 6c4009
	      && (getfct = __nss_lookup_function (entry.nip, "getnetgrent_r"))
Packit 6c4009
		 != NULL)
Packit 6c4009
	    {
Packit 6c4009
	      char buffer[1024];
Packit 6c4009
Packit 6c4009
	      while (DL_CALL_FCT (*getfct,
Packit 6c4009
				  (&entry, buffer, sizeof buffer, &errno))
Packit 6c4009
		     == NSS_STATUS_SUCCESS)
Packit 6c4009
		{
Packit 6c4009
		  if (entry.type == group_val)
Packit 6c4009
		    {
Packit 6c4009
		      /* Make sure we haven't seen the name before.  */
Packit 6c4009
		      struct name_list *namep;
Packit 6c4009
Packit 6c4009
		      for (namep = entry.known_groups; namep != NULL;
Packit 6c4009
			   namep = namep->next)
Packit 6c4009
			if (strcmp (entry.val.group, namep->name) == 0)
Packit 6c4009
			  break;
Packit 6c4009
		      if (namep == NULL)
Packit 6c4009
			for (namep = entry.needed_groups; namep != NULL;
Packit 6c4009
			     namep = namep->next)
Packit 6c4009
			  if (strcmp (entry.val.group, namep->name) == 0)
Packit 6c4009
			    break;
Packit 6c4009
		      if (namep == NULL
Packit 6c4009
			  && strcmp (netgroup, entry.val.group) != 0)
Packit 6c4009
			{
Packit 6c4009
			  size_t group_len = strlen (entry.val.group) + 1;
Packit 6c4009
			  namep =
Packit 6c4009
			    (struct name_list *) malloc (sizeof (*namep)
Packit 6c4009
							 + group_len);
Packit 6c4009
			  if (namep == NULL)
Packit 6c4009
			    {
Packit 6c4009
			      /* Out of memory, simply return.  */
Packit 6c4009
			      result = -1;
Packit 6c4009
			      break;
Packit 6c4009
			    }
Packit 6c4009
Packit 6c4009
			  namep->next = entry.needed_groups;
Packit 6c4009
			  memcpy (namep->name, entry.val.group, group_len);
Packit 6c4009
			  entry.needed_groups = namep;
Packit 6c4009
			}
Packit 6c4009
		    }
Packit 6c4009
		  else
Packit 6c4009
		    {
Packit 6c4009
		      if ((entry.val.triple.host == NULL || host == NULL
Packit 6c4009
			   || __strcasecmp (entry.val.triple.host, host) == 0)
Packit 6c4009
			  && (entry.val.triple.user == NULL || user == NULL
Packit 6c4009
			      || strcmp (entry.val.triple.user, user) == 0)
Packit 6c4009
			  && (entry.val.triple.domain == NULL || domain == NULL
Packit 6c4009
			      || __strcasecmp (entry.val.triple.domain,
Packit 6c4009
					       domain) == 0))
Packit 6c4009
			{
Packit 6c4009
			  result = 1;
Packit 6c4009
			  break;
Packit 6c4009
			}
Packit 6c4009
		    }
Packit 6c4009
		}
Packit 6c4009
Packit 6c4009
	      /* If we found one service which does know the given
Packit 6c4009
		 netgroup we don't try further.  */
Packit 6c4009
	      status = NSS_STATUS_RETURN;
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
	  /* Free all resources of the service.  */
Packit 6c4009
	  endfct = __nss_lookup_function (entry.nip, "endnetgrent");
Packit 6c4009
	  if (endfct != NULL)
Packit 6c4009
	    DL_CALL_FCT (*endfct, (&entry));
Packit 6c4009
Packit 6c4009
	  if (result != 0)
Packit 6c4009
	    break;
Packit 6c4009
Packit 6c4009
	  /* Look for the next service.  */
Packit 6c4009
	  no_more = __nss_next2 (&entry.nip, "setnetgrent", NULL,
Packit 6c4009
				 &setfct.ptr, status, 0);
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (result == 0 && entry.needed_groups != NULL)
Packit 6c4009
	{
Packit 6c4009
	  struct name_list *tmp = entry.needed_groups;
Packit 6c4009
	  entry.needed_groups = tmp->next;
Packit 6c4009
	  tmp->next = entry.known_groups;
Packit 6c4009
	  entry.known_groups = tmp;
Packit 6c4009
	  current_group = tmp->name;
Packit 6c4009
	  continue;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      /* No way out.  */
Packit 6c4009
      break;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Free the memory.  */
Packit 6c4009
  free_memory (&entry);
Packit 6c4009
Packit 6c4009
  return result == 1;
Packit 6c4009
}
Packit 6c4009
libc_hidden_def (innetgr)