Blame inet/getnetgrent_r.c

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