Blame grp/compat-initgroups.c

Packit 6c4009
/* Prototype for the setgrent functions we use here.  */
Packit 6c4009
typedef enum nss_status (*set_function) (void);
Packit 6c4009
Packit 6c4009
/* Prototype for the endgrent functions we use here.  */
Packit 6c4009
typedef enum nss_status (*end_function) (void);
Packit 6c4009
Packit 6c4009
/* Prototype for the setgrent functions we use here.  */
Packit 6c4009
typedef enum nss_status (*get_function) (struct group *, char *,
Packit 6c4009
					 size_t, int *);
Packit 6c4009
Packit 6c4009
Packit 6c4009
static enum nss_status
Packit 6c4009
compat_call (service_user *nip, const char *user, gid_t group, long int *start,
Packit 6c4009
	     long int *size, gid_t **groupsp, long int limit, int *errnop)
Packit 6c4009
{
Packit 6c4009
  struct group grpbuf;
Packit 6c4009
  enum nss_status status;
Packit 6c4009
  set_function setgrent_fct;
Packit 6c4009
  get_function getgrent_fct;
Packit 6c4009
  end_function endgrent_fct;
Packit 6c4009
  gid_t *groups = *groupsp;
Packit 6c4009
Packit 6c4009
  getgrent_fct = __nss_lookup_function (nip, "getgrent_r");
Packit 6c4009
  if (getgrent_fct == NULL)
Packit 6c4009
    return NSS_STATUS_UNAVAIL;
Packit 6c4009
Packit 6c4009
  setgrent_fct = __nss_lookup_function (nip, "setgrent");
Packit 6c4009
  if (setgrent_fct)
Packit 6c4009
    {
Packit 6c4009
      status = DL_CALL_FCT (setgrent_fct, ());
Packit 6c4009
      if (status != NSS_STATUS_SUCCESS)
Packit 6c4009
	return status;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  endgrent_fct = __nss_lookup_function (nip, "endgrent");
Packit 6c4009
Packit 6c4009
  struct scratch_buffer tmpbuf;
Packit 6c4009
  scratch_buffer_init (&tmpbuf);
Packit 6c4009
  enum nss_status result = NSS_STATUS_SUCCESS;
Packit 6c4009
Packit 6c4009
  do
Packit 6c4009
    {
Packit 6c4009
      while ((status = DL_CALL_FCT (getgrent_fct,
Packit 6c4009
				     (&grpbuf, tmpbuf.data, tmpbuf.length,
Packit 6c4009
				      errnop)),
Packit 6c4009
	      status == NSS_STATUS_TRYAGAIN)
Packit 6c4009
	     && *errnop == ERANGE)
Packit 6c4009
        {
Packit 6c4009
	  if (!scratch_buffer_grow (&tmpbuf))
Packit 6c4009
	    {
Packit 6c4009
	      result = NSS_STATUS_TRYAGAIN;
Packit 6c4009
	      goto done;
Packit 6c4009
	    }
Packit 6c4009
        }
Packit 6c4009
Packit 6c4009
      if (status != NSS_STATUS_SUCCESS)
Packit 6c4009
        goto done;
Packit 6c4009
Packit 6c4009
      if (grpbuf.gr_gid != group)
Packit 6c4009
        {
Packit 6c4009
          char **m;
Packit 6c4009
Packit 6c4009
          for (m = grpbuf.gr_mem; *m != NULL; ++m)
Packit 6c4009
            if (strcmp (*m, user) == 0)
Packit 6c4009
              {
Packit 6c4009
		/* Check whether the group is already on the list.  */
Packit 6c4009
		long int cnt;
Packit 6c4009
		for (cnt = 0; cnt < *start; ++cnt)
Packit 6c4009
		  if (groups[cnt] == grpbuf.gr_gid)
Packit 6c4009
		    break;
Packit 6c4009
Packit 6c4009
		if (cnt == *start)
Packit 6c4009
		  {
Packit 6c4009
		    /* Matches user and not yet on the list.  Insert
Packit 6c4009
		       this group.  */
Packit 6c4009
		    if (__glibc_unlikely (*start == *size))
Packit 6c4009
		      {
Packit 6c4009
			/* Need a bigger buffer.  */
Packit 6c4009
			gid_t *newgroups;
Packit 6c4009
			long int newsize;
Packit 6c4009
Packit 6c4009
			if (limit > 0 && *size == limit)
Packit 6c4009
			  /* We reached the maximum.  */
Packit 6c4009
			  goto done;
Packit 6c4009
Packit 6c4009
			if (limit <= 0)
Packit 6c4009
			  newsize = 2 * *size;
Packit 6c4009
			else
Packit 6c4009
			  newsize = MIN (limit, 2 * *size);
Packit 6c4009
Packit 6c4009
			newgroups = realloc (groups,
Packit 6c4009
					     newsize * sizeof (*groups));
Packit 6c4009
			if (newgroups == NULL)
Packit 6c4009
			  goto done;
Packit 6c4009
			*groupsp = groups = newgroups;
Packit 6c4009
			*size = newsize;
Packit 6c4009
		      }
Packit 6c4009
Packit 6c4009
		    groups[*start] = grpbuf.gr_gid;
Packit 6c4009
		    *start += 1;
Packit 6c4009
		  }
Packit 6c4009
Packit 6c4009
                break;
Packit 6c4009
              }
Packit 6c4009
        }
Packit 6c4009
    }
Packit 6c4009
  while (status == NSS_STATUS_SUCCESS);
Packit 6c4009
Packit 6c4009
 done:
Packit 6c4009
  scratch_buffer_free (&tmpbuf);
Packit 6c4009
Packit 6c4009
  if (endgrent_fct)
Packit 6c4009
    DL_CALL_FCT (endgrent_fct, ());
Packit 6c4009
Packit 6c4009
  return result;
Packit 6c4009
}