On Thu, Dec 21, 2006 at 01:25:01PM -0700, Tom Smith wrote:
> Chad Perrin wrote:
> >
> >That's why I said you may as well either just use the id utility from
> >the shell if you're not going to grab group memberships in an
> >idiomatically Perlish way -- the Perl code is likely to be more
> >portable.  Of course, specifying the path to the group file, as I
> >originally suggested, might not be the most portable way to do that (in
> >retrospect).
> >  
> 
> That's interesting... But I couldn't determine another (perhaps better) 
> way of doing it.
> 
> I tried the getgr* and getpw* functions, but they were too 
> specific--that is, one has to specify which user or group they want 
> information about. And the user information won't tell me such things as 
> which groups the user belongs to... And I can't get information about a 
> group unless I know the group name ahead of time... And so on. This is 
> why I decided on the method I did. (Perhaps I wasn't doing something 
> correctly with those functions?)

Actually, using getgrent and getpwent is probably the way to go, unless
there's a module that makes this easier.  Something I just threw
together (caution -- I have not tested it much) that seems to do the
trick is:

  #!/usr/local/bin/perl -l
  use strict;
  use warnings;

  my $user = $ARGV[0];
  my @gr_list;
  my @pw_info;

  while (@pw_info = getpwent) {
    if ($pw_info[0] eq $user) {
      my @gr_info;
      while (@gr_info = getgrent) {
        push(@gr_list, $gr_info[0]) if ($gr_info[3] =~ /\b$user\b/);
        push(@gr_list, $gr_info[0]) if ($gr_info[2] eq $pw_info[3]);
      }
    }
  }

  print foreach @gr_list;

In the above, I'm using the first if statement to ensure that each
result from both getpwent() and getgrent() will only be included once,
because there's only one line in /etc/passwd that'll match ($pw_info[0]
eq $user).  The reason I have the first push statement where it is,
composed the way it is, should be obvious: I'm pushing all getgrent()
results for the group name where its member list includes $user onto the
@gr_list array.  The second push statement is there, and necessarily
composed the way it is, because getpwent() only gives you the gid, and
if you're looking for the group name you need to match the gid from
getpwent() with the gid from getgrent() to figure out the group name.

The print statement is there for testing the ouptut of my complex little
control structure, and it uses a foreach because, coupled with the -l
option in the shebang line, it prints out each array element on its own
line in STDOUT.

I'm sure that could be made prettier by someone with better Perl mojo
than I have at the moment, and it could be made a bit simpler if all you
want is the gid for each group rather than the group name.

  
> 
> In either case, the interesting point about your comment is that every 
> *nix system I've ever touched (Linux (includes Redhat, Debian, Ubuntu, 
> Mandrake, and Gentoo), FreeBSD, Solaris, and AIX) have all had their 
> group file located at /etc/group. Do you have a specific example or 
> reason of why someone might want to change this location?

No, I don't.  I'm just sometimes paranoid about such things when writing
code for portability.

-- 
CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ]
"The first rule of magic is simple. Don't waste your time waving your
hands and hopping when a rock or a club will do." - McCloctnick the Lucid

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to