Back to index

glibc  2.9
Typedefs | Functions
compat-initgroups.c File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef enum nss_status(* set_function )(void)
typedef enum nss_status(* end_function )(void)
typedef enum nss_status(* get_function )(struct group *, char *, size_t, int *)

Functions

static enum nss_status compat_call (service_user *nip, const char *user, gid_t group, long int *start, long int *size, gid_t **groupsp, long int limit, int *errnop)

Typedef Documentation

typedef enum nss_status(* end_function)(void)

Definition at line 5 of file compat-initgroups.c.

typedef enum nss_status(* get_function)(struct group *, char *, size_t, int *)

Definition at line 8 of file compat-initgroups.c.

typedef enum nss_status(* set_function)(void)

Definition at line 2 of file compat-initgroups.c.


Function Documentation

static enum nss_status compat_call ( service_user nip,
const char *  user,
gid_t  group,
long int start,
long int size,
gid_t **  groupsp,
long int  limit,
int errnop 
) [static]

Definition at line 12 of file compat-initgroups.c.

{
  struct group grpbuf;
  size_t buflen = __sysconf (_SC_GETGR_R_SIZE_MAX);
  char *tmpbuf;
  enum nss_status status;
  set_function setgrent_fct;
  get_function getgrent_fct;
  end_function endgrent_fct;
  gid_t *groups = *groupsp;

  getgrent_fct = __nss_lookup_function (nip, "getgrent_r");
  if (getgrent_fct == NULL)
    return NSS_STATUS_UNAVAIL;

  setgrent_fct = __nss_lookup_function (nip, "setgrent");
  if (setgrent_fct)
    {
      status = DL_CALL_FCT (setgrent_fct, ());
      if (status != NSS_STATUS_SUCCESS)
       return status;
    }

  endgrent_fct = __nss_lookup_function (nip, "endgrent");

  tmpbuf = __alloca (buflen);

  do
    {
      while ((status = DL_CALL_FCT (getgrent_fct,
                                 (&grpbuf, tmpbuf, buflen, errnop)),
             status == NSS_STATUS_TRYAGAIN)
            && *errnop == ERANGE)
        {
          buflen *= 2;
          tmpbuf = __alloca (buflen);
        }

      if (status != NSS_STATUS_SUCCESS)
        goto done;

      if (grpbuf.gr_gid != group)
        {
          char **m;

          for (m = grpbuf.gr_mem; *m != NULL; ++m)
            if (strcmp (*m, user) == 0)
              {
              /* Check whether the group is already on the list.  */
              long int cnt;
              for (cnt = 0; cnt < *start; ++cnt)
                if (groups[cnt] == grpbuf.gr_gid)
                  break;

              if (cnt == *start)
                {
                  /* Matches user and not yet on the list.  Insert
                     this group.  */
                  if (__builtin_expect (*start == *size, 0))
                    {
                     /* Need a bigger buffer.  */
                     gid_t *newgroups;
                     long int newsize;

                     if (limit > 0 && *size == limit)
                       /* We reached the maximum.  */
                       goto done;

                     if (limit <= 0)
                       newsize = 2 * *size;
                     else
                       newsize = MIN (limit, 2 * *size);

                     newgroups = realloc (groups,
                                        newsize * sizeof (*groups));
                     if (newgroups == NULL)
                       goto done;
                     *groupsp = groups = newgroups;
                     *size = newsize;
                    }

                  groups[*start] = grpbuf.gr_gid;
                  *start += 1;
                }

                break;
              }
        }
    }
  while (status == NSS_STATUS_SUCCESS);

 done:
  if (endgrent_fct)
    DL_CALL_FCT (endgrent_fct, ());

  return NSS_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function: