cprice has asked for the wisdom of the Perl Monks concerning the following question:

I have a perl CGI script which gets retrieves a valid unix userid ($username) via http basic auth and mod_auth_pam. I am trying to find a way to retrieve the unix group membership(s) for $username. I am currently doing this by spawning a subshell;

@groups = `/usr/bin/groups $username`;

Which returns me a listing of all the groups a user belongs to (primary and secondaries). I would like to know if there is a better perl-esque way to do this without spawning a subshell.

  • Comment on Retrieve unix group membership for a uid in a perl CGI

Replies are listed 'Best First'.
Re: Retrieve unix group membership for a uid in a perl CGI
by Fletch (Bishop) on Apr 09, 2004 at 18:01 UTC

    perldoc -f getpwnam

    Update: To be more specific, you want to read about getgrent. You'd use getpwnam to find the user's primary group, and grobble over what getgrent returns looking for the secondary memberships. This is probably one of the cases where the efficiency loss of the qx// is going to be less trouble than the work of doing it by hand.

Re: Retrieve unix group membership for a uid in a perl CGI
by matija (Priest) on Apr 09, 2004 at 18:08 UTC
    Given that you have the username, maybe you could just parse /etc/group.

    The format is pretty simple:
    name:x:group id (integeter):list,of,usernames

    while (<GROUP>) { my ($group,$x,$gid,$list)=split(':',$_); push(@groups,$group) if ($list=~/$username/); }
      This misses the user's own group. Try
      my $username = "kvale"; my @groups = ($username); open GROUP, "</etc/group" or die "Could not find /etc/group: $!\n"; while (<GROUP>) { my ($group,$x,$gid,$list)=split(':',$_); push(@groups,$group) if ($list=~/$username/); } print "Groups: ", join " ", @groups, "\n";

      -Mark

        Actually yours (possibly mistakenly) assumes that the user's primary group is named after their username. While this is a common default value used by some variants of adduser or the like, it's not necessarily always the case. Which is of course why you should use getpwname to retrieve their primary gid and then translate that with getgrgid.

        Huh? I don't see any difference between my loop and yours...

        All you've done is provide the opening of the file, which I left as an exercise for the student

      And then you move to a system running NIS or LDAP and miss anything not defined in the local /etc/group file. This is why you go through getgrent which uses the system's group reading libraries and honours nsswitch.conf (or whatever).

        I was going to use getgrent, for the guy's answer, and I couldn't get it to work.... Until now: I just realized that instead of looping through /etc/group, you can loop through getgrent.

        The thing I didn't immediately realize is that getgrent returns different values on subsequent calls.

        (Since I've never done this particular thing before, I was testing the code before posting...)

Re: Retrieve unix group membership for a uid in a perl CGI
by tcf22 (Priest) on Apr 09, 2004 at 18:15 UTC
    This works for me:
    my $grp = getgrgid((getpwnam("user"))[3]); print $grp;

    - Tom