/usr/share/perl5/Unix/GroupFile.pm is in libunix-configfile-perl 0.6-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | package Unix::GroupFile;
# $Id: GroupFile.pm,v 1.6 2000/05/02 15:59:34 ssnodgra Exp $
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
use Unix::ConfigFile;
require Exporter;
@ISA = qw(Unix::ConfigFile Exporter);
# Items to export into callers namespace by default. Note: do not export
# names by default without a very good reason. Use EXPORT_OK instead.
# Do not simply export all your public functions/methods/constants.
@EXPORT = qw(
);
$VERSION = '0.06';
# Package variables
my $MAXLINELEN = 511;
# Implementation Notes
#
# This module adds 3 new fields to the basic ConfigFile object. The fields
# are 'gid', 'gpass', and 'group'. All three of these fields are hashes.
# The gid field maps names to GIDs. The gpass field maps names to passwords.
# The group fields maps GIDs to another hash of group members. There are
# no real values in the group subhash, just a '1' as a placeholder. This is
# a hash instead of a list because it makes duplicate elimination and user
# deletion much easier to deal with.
# Preloaded methods go here.
# Read in the data structures from the supplied file
sub read {
my ($this, $fh) = @_;
while (<$fh>) {
chop;
my ($name, $password, $gid, $users) = split /:/;
my @users = split /,/, $users;
if (defined $this->{group}{$gid}) {
foreach (@users) {
$this->{group}{$gid}{$_} = 1;
}
}
else {
$this->group($name, $password, $gid, @users);
}
}
return 1;
}
# Add, modify, or get a group
sub group {
my $this = shift;
my $name = shift;
# If no more parameters, we return group info
unless (@_) {
my $gid = $this->gid($name);
return undef unless defined $gid;
return ($this->passwd($name), $gid, $this->members($name));
}
# Create or modify a group
return undef if @_ < 2;
my $password = shift;
my $gid = shift;
# Have to be careful with this test - 0 is a legitimate return value
return undef unless defined $this->gid($name, $gid);
$this->passwd($name, $password);
$this->members($name, @_);
return ($gid, $password, $this->members($name));
}
# Delete a group
sub delete {
my ($this, $name) = @_;
my $gid = $this->gid($name);
return 0 unless defined $gid;
delete $this->{gpass}{$name};
delete $this->{group}{$gid};
delete $this->{gid}{$name};
return 1;
}
# Add users to an existing group
sub add_user {
my $this = shift;
my $name = shift;
my @groups = ($name eq "*") ? $this->groups : ($name);
foreach (@groups) {
my $gid = $this->gid($_);
return 0 unless defined $gid;
foreach my $user (@_) {
$this->{group}{$gid}{$user} = 1;
}
}
return 1;
}
# Remove users from an existing group
sub remove_user {
my $this = shift;
my $name = shift;
my @groups = ($name eq "*") ? $this->groups : ($name);
foreach (@groups) {
my $gid = $this->gid($_);
return 0 unless defined $gid;
foreach my $user (@_) {
delete $this->{group}{$gid}{$user};
}
}
return 1;
}
# Rename a user
sub rename_user {
my ($this, $oldname, $newname) = @_;
my $count = 0;
foreach ($this->groups) {
my $gid = $this->gid($_);
if (exists $this->{group}{$gid}{$oldname}) {
delete $this->{group}{$gid}{$oldname};
$this->{group}{$gid}{$newname} = 1;
$count++;
}
}
return $count;
}
# Return the list of groups
# Accepts a sorting order parameter: gid or name (default gid)
sub groups {
my $this = shift;
my $order = @_ ? shift : "gid";
return keys %{$this->{gid}} unless wantarray;
if ($order eq "name") {
return sort keys %{$this->{gid}};
}
else {
return sort { $this->gid($a) <=> $this->gid($b) } keys %{$this->{gid}};
}
}
# Returns the maximum GID in use in the file
sub maxgid {
my $this = shift;
my @gids = sort { $a <=> $b } keys %{$this->{group}};
return pop @gids;
}
# Output the file to disk
sub write {
my ($this, $fh) = @_;
foreach my $name ($this->groups) {
my @users = $this->members($name);
my $head = join(":", $name, $this->passwd($name), $this->gid($name), "");
my $ind = join(":", "$name%n", $this->passwd($name), $this->gid($name), "");
print $fh $this->joinwrap($MAXLINELEN, $head, $ind, ",", "", @users),
"\n" or return 0;
}
return 1;
}
# Accessors (these all accept a group name and an optional value)
sub passwd {
my $this = shift;
my $name = shift;
@_ ? $this->{gpass}{$name} = shift : $this->{gpass}{$name};
}
# Note that it is illegal to change a group's GID to one used by another group
# This method also has to take into account side effects produced by doing
# this, such as the fact that the member hash is keyed against the GID.
sub gid {
my $this = shift;
my $name = shift;
return $this->{gid}{$name} unless @_;
my $newgid = shift;
my $oldgid = $this->{gid}{$name};
# Return OK if you try to set the same GID a group already has
return $oldgid if defined $oldgid && $newgid == $oldgid;
return undef if grep { $newgid == $_ } values %{$this->{gid}};
if (defined $oldgid) {
$this->{group}{$newgid} = $this->{group}{$oldgid};
delete $this->{group}{$oldgid};
}
$this->{gid}{$name} = $newgid;
}
# Return or set the list of users in a group
sub members {
my $this = shift;
my $name = shift;
my $gid = $this->gid($name);
return undef unless defined $gid;
if (@_) {
$this->{group}{$gid} = { };
$this->add_user($name, @_);
}
return keys %{$this->{group}{$gid}} unless wantarray;
return sort keys %{$this->{group}{$gid}};
}
# Autoload methods go after =cut, and are processed by the autosplit program.
1;
__END__
# Below is the stub of documentation for your module. You better edit it!
=head1 NAME
Unix::GroupFile - Perl interface to /etc/group format files
=head1 SYNOPSIS
use Unix::GroupFile;
$grp = new Unix::GroupFile "/etc/group";
$grp->group("bozos", "*", $grp->maxgid + 1, @members);
$grp->remove_user("coolgrp", "bgates", "badguy");
$grp->add_user("coolgrp", "joecool", "goodguy");
$grp->remove_user("*", "deadguy");
$grp->passwd("bozos", $grp->encpass("newpass"));
$grp->commit();
undef $grp;
=head1 DESCRIPTION
The Unix::GroupFile module provides an abstract interface to /etc/group format
files. It automatically handles file locking, getting colons and commas in
the right places, and all the other niggling details.
This module also handles the annoying problem (at least on some systems) of
trying to create a group line longer than 512 characters. Typically this is
done by creating multiple lines of groups with the same GID. When a new
GroupFile object is created, all members of groups with the same GID are
merged into a single group with a name corresponding to the first name found
in the file for that GID. When the file is committed, long groups are written
out as multiple lines of no more than 512 characters, with numbers appended to
the group name for the extra lines.
=head1 METHODS
=head2 add_user( GROUP, @USERS )
This method will add the list of users to an existing group. Users that are
already members of the group are silently ignored. The special group name *
will add the users to every group. Returns 1 on success or 0 on failure.
=head2 commit( [BACKUPEXT] )
See the Unix::ConfigFile documentation for a description of this method.
=head2 delete( GROUP )
This method will delete the named group. It has no effect if the supplied
group does not exist.
=head2 encpass( PASSWORD )
See the Unix::ConfigFile documentation for a description of this method.
=head2 gid( GROUP [,GID] )
Read or modify a group's GID. Returns the GID in either case. Note that it
is illegal to change a group's GID to a GID that is already in use by another
group. In this case, the method returns undef.
=head2 group( GROUP [,PASSWD, GID, @USERS] )
This method can add, modify, or return information about a group. Supplied
with a single group parameter, it will return a list consisting of (PASSWORD,
GID, @MEMBERS), or undef if no such group exists. If you supply at least
three parameters, the named group will be created or modified if it already
exists. The list is also returned to you in this case. Note that it is
illegal to specify a GID that is already in use by another group. In this
case, the method returns undef.
=head2 groups( [SORTBY] )
This method returns a list of all existing groups. By default the list will
be sorted in order of the GIDs of the groups. You may also supply "name" as a
parameter to the method to get the list sorted by group name. In scalar
context, this method returns the total number of groups.
=head2 maxgid( )
This method returns the maximum GID in use by all groups.
=head2 members( GROUP [,@USERS] )
Read or modify the list of members associated with a group. If you specify
any users when you call the method, all existing members of the group are
removed and your list becomes the new set of members. In scalar context,
this method returns the total number of members in the group.
=head2 new( FILENAME [,OPTIONS] )
See the Unix::ConfigFile documentation for a description of this method.
=head2 passwd( GROUP [,PASSWD] )
Read or modify a group's password. Returns the encrypted password in either
case. If you have a plaintext password, use the encpass method to encrypt it
before passing it to this method.
=head2 remove_user( GROUP, @USERS )
This method will remove the list of users from an existing group. Users that
are not members of the group are silently ignored. The special group name *
will remove the users from every group. Returns 1 on success or 0 on failure.
=head2 rename_user( OLDNAME, NEWNAME )
This method will change one username to another in every group. Returns the
number of groups affected.
=head1 AUTHOR
Steve Snodgrass, ssnodgra@fore.com
=head1 SEE ALSO
Unix::AliasFile, Unix::AutomountFile, Unix::ConfigFile, Unix::PasswdFile
=cut
|