SUMMARY: getgroups(2) of another user

From: <haymanR_at_icefog.uacn.alaska.edu>
Date: Mon, 13 Feb 1995 13:09:47 -0900

Original question:
------------------------------------
Greetings -

I'm having a slight bit of difficulty getting the grouplist of another user
(except when using groups(1)).

Below is a code fragment which returns primary group of the other user, but then
displays the current user's grouplist.

What am I missing? The man pages are not all that clear, and W.R. Stevens book
on Advanced Programming in the UNIX Environment (p151) states "In addition to
finding all the groups that 'username' is a member of in the group file,
'initgroups' also includes 'basegid' in the supplementary group ID list."

I'm confused.

---code fragment---
...
struct pr_passwd *pr;
struct passwd *upr;
struct group *gpr;
int num_groups;
gid_t grouplist[NGROUPS_MAX];
int i; /* grouplist[] index */
...
char name[16];
...

/* /etc/group entries */

if (NULL == (gpr = getgrgid(upr->pw_gid)) )
  {
    fprintf(stderr, "\n**Error getting primary /etc/group entry for %s.\n",
        pr->ufld.fd_name);
  }
  else
  {
    fprintf(stdout, "\n\tprimary group:\t\t%s", gpr->gr_name);
  }

  if (-1 == setreuid(pr->ufld.fd_uid, pr->ufld.fd_uid))
        /* real and effective uids to 'name' context */
  {
    fprintf(stderr, "\nCan not seuid there\n");
  }

  if (NULL == initgroups(name, gpr->gr_gid) )
  {
    fprintf(stderr, "\n**Error initializing /etc/group entries for %s.\n",
        pr->ufld.fd_name);
  }
  else
  {
    if (-1 == (num_groups = getgroups(NGROUPS_MAX, grouplist)) )
    {
      fprintf(stderr, "\n**Error getting /etc/group entries for %s.\n",
          pr->ufld.fd_name);
    }
    else
    {
      i = 0; /* grouplist[0] is the primary group for this user */
      for (fprintf(stdout, "\n\tgroup membership (%u):\t", num_groups) ;
          i < num_groups ;
          i++, (0 == (i % 5))?fprintf(stdout, "\n\t\t\t\t"):NULL )
      {
        if (NULL == (gpr = getgrgid(grouplist[i])) )
        {
          fprintf(stderr, "\n**Error getting additional groups for %s.\n",
                pr->ufld.fd_name);
        }
        else
        {
          fprintf(stdout, "%s (%u) ", gpr->gr_name, grouplist[i]);
        }
      }
    }
  }
...

output ends up being of the following format:

...
primary group: users
group membership (10): system (0) daemon (1) mem (3) bin (4) sec (5)
                        auth (11) users (15) sysadmin (16) tcb (18) adm (19)
...

Where primary group is correct for the user inquired about, but the group
membership is correct for the user actually running the program.
------------------------------------

Thanks to:

Spider Boardman - spider_at_Orb.Nashua.NH.US
Larry Scott USG - scott_at_zk3.dec.com
Bryan Curnutt - bryan.curnutt_at_stoner.com
anthony baxter - anthony.baxter_at_aaii.oz.au
Benoit Maillard - maillard_at_atyisa.enet.dec.com


SOLUTION:
---------

use getgrent(): code fragment included below:

...
/* /etc/group entries */

  if (NULL == (gpr = getgrgid(upr->pw_gid)) )
  {
    fprintf(stderr, "\n**Error getting primary /etc/group entry for %s.\n",
        pr->ufld.fd_name);
  }
  else
  {
     fprintf(stdout, "\n\tprimary group:\t\t%s (%u)", gpr->gr_name,
        upr->pw_gid);
  }

  fprintf(stdout, "\n\tgroup membership:\t");

  j = 0; /* group membership counter */
  while (NULL != (gpr = getgrent()) )
  {
    char tmpstr[80]; /* sizeof output unit for groups */
    i = 0; /* group member counter */
    while (NULL != gpr->gr_mem[i])
      {
      if (!strcmp(name, gpr->gr_mem[i]))
      {
        if (!(j % 3) && j) /* new line every 3 groups for user */
        {
           fprintf(stdout, "\n\t\t\t\t");
        }
        sprintf(tmpstr, "%s (%u)", gpr->gr_name, gpr->gr_gid);
        fprintf(stdout, "%-15.15s", tmpstr); /* column align them */
        j++;
        }
      i++;
    }
  }
  fprintf(stdout, "\n\tgroup count:\t\t%u", j);
...

Output now fits desired results:

...
        primary group: sysadmin (16)
        group membership: system (0) users (15) sysadmin (16)
                                tempbfin (111) temphrs (112) tempksh (113)
                                tempsis (114) tempexit (115)
        group count: 8
...

Thank you very much. I am no longer confused.

Randy M. Hayman
haymanr_at_icefog.alaska.edu
Received on Mon Feb 13 1995 - 18:27:35 NZDT

This archive was generated by hypermail 2.4.0 : Wed Nov 08 2023 - 11:53:45 NZDT