File Coverage

blib/lib/Unix/GroupFile.pm
Criterion Covered Total %
statement 110 115 95.6
branch 33 46 71.7
condition 2 3 66.6
subroutine 15 15 100.0
pod 10 12 83.3
total 170 191 89.0


line stmt bran cond sub pod time code
1             package Unix::GroupFile;
2              
3             # $Id: GroupFile.pm,v 1.6 2000/05/02 15:59:34 ssnodgra Exp $
4              
5 1     1   585 use strict;
  1         2  
  1         40  
6 1     1   4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         2  
  1         64  
7 1     1   5 use Unix::ConfigFile;
  1         1  
  1         1537  
8              
9             require Exporter;
10              
11             @ISA = qw(Unix::ConfigFile Exporter);
12             # Items to export into callers namespace by default. Note: do not export
13             # names by default without a very good reason. Use EXPORT_OK instead.
14             # Do not simply export all your public functions/methods/constants.
15             @EXPORT = qw(
16            
17             );
18             $VERSION = '0.06';
19              
20             # Package variables
21             my $MAXLINELEN = 511;
22              
23             # Implementation Notes
24             #
25             # This module adds 3 new fields to the basic ConfigFile object. The fields
26             # are 'gid', 'gpass', and 'group'. All three of these fields are hashes.
27             # The gid field maps names to GIDs. The gpass field maps names to passwords.
28             # The group fields maps GIDs to another hash of group members. There are
29             # no real values in the group subhash, just a '1' as a placeholder. This is
30             # a hash instead of a list because it makes duplicate elimination and user
31             # deletion much easier to deal with.
32              
33             # Preloaded methods go here.
34              
35             # Read in the data structures from the supplied file
36             sub read {
37 1     1 0 10 my ($this, $fh) = @_;
38              
39 1         42 while (<$fh>) {
40 16         22 chop;
41 16         69 my ($name, $password, $gid, $users) = split /:/;
42 16         33 my @users = split /,/, $users;
43 16 50       48 if (defined $this->{group}{$gid}) {
44 0         0 foreach (@users) {
45 0         0 $this->{group}{$gid}{$_} = 1;
46             }
47             }
48             else {
49 16         43 $this->group($name, $password, $gid, @users);
50             }
51             }
52 1         9 return 1;
53             }
54              
55              
56             # Add, modify, or get a group
57             sub group {
58 19     19 1 95 my $this = shift;
59 19         32 my $name = shift;
60              
61             # If no more parameters, we return group info
62 19 100       37 unless (@_) {
63 1         4 my $gid = $this->gid($name);
64 1 50       22 return undef unless defined $gid;
65 0         0 return ($this->passwd($name), $gid, $this->members($name));
66             }
67              
68             # Create or modify a group
69 18 50       47 return undef if @_ < 2;
70 18         18 my $password = shift;
71 18         23 my $gid = shift;
72              
73             # Have to be careful with this test - 0 is a legitimate return value
74 18 50       45 return undef unless defined $this->gid($name, $gid);
75 18         42 $this->passwd($name, $password);
76 18         82 $this->members($name, @_);
77 18         41 return ($gid, $password, $this->members($name));
78             }
79              
80              
81             # Delete a group
82             sub delete {
83 1     1 1 36 my ($this, $name) = @_;
84              
85 1         3 my $gid = $this->gid($name);
86 1 50       6 return 0 unless defined $gid;
87 1         3 delete $this->{gpass}{$name};
88 1         4 delete $this->{group}{$gid};
89 1         4 delete $this->{gid}{$name};
90 1         3 return 1;
91             }
92              
93              
94             # Add users to an existing group
95             sub add_user {
96 13     13 1 52 my $this = shift;
97 13         16 my $name = shift;
98 13 50       39 my @groups = ($name eq "*") ? $this->groups : ($name);
99              
100 13         23 foreach (@groups) {
101 13         25 my $gid = $this->gid($_);
102 13 50       28 return 0 unless defined $gid;
103 13         27 foreach my $user (@_) {
104 32         96 $this->{group}{$gid}{$user} = 1;
105             }
106             }
107 13         28 return 1;
108             }
109              
110              
111             # Remove users from an existing group
112             sub remove_user {
113 2     2 1 75 my $this = shift;
114 2         5 my $name = shift;
115 2 100       11 my @groups = ($name eq "*") ? $this->groups : ($name);
116              
117 2         7 foreach (@groups) {
118 18         32 my $gid = $this->gid($_);
119 18 50       36 return 0 unless defined $gid;
120 18         34 foreach my $user (@_) {
121 18         54 delete $this->{group}{$gid}{$user};
122             }
123             }
124 2         6 return 1;
125             }
126              
127              
128             # Rename a user
129             sub rename_user {
130 1     1 1 85 my ($this, $oldname, $newname) = @_;
131              
132 1         4 my $count = 0;
133 1         3 foreach ($this->groups) {
134 16         32 my $gid = $this->gid($_);
135 16 100       48 if (exists $this->{group}{$gid}{$oldname}) {
136 3         7 delete $this->{group}{$gid}{$oldname};
137 3         9 $this->{group}{$gid}{$newname} = 1;
138 3         6 $count++;
139             }
140             }
141 1         6 return $count;
142             }
143              
144              
145             # Return the list of groups
146             # Accepts a sorting order parameter: gid or name (default gid)
147             sub groups {
148 4     4 1 41 my $this = shift;
149 4 50       12 my $order = @_ ? shift : "gid";
150              
151 4 100       31 return keys %{$this->{gid}} unless wantarray;
  1         12  
152 3 50       8 if ($order eq "name") {
153 0         0 return sort keys %{$this->{gid}};
  0         0  
154             }
155             else {
156 3         4 return sort { $this->gid($a) <=> $this->gid($b) } keys %{$this->{gid}};
  141         329  
  3         29  
157             }
158             }
159              
160              
161             # Returns the maximum GID in use in the file
162             sub maxgid {
163 1     1 1 39 my $this = shift;
164 1         3 my @gids = sort { $a <=> $b } keys %{$this->{group}};
  48         72  
  1         9  
165 1         7 return pop @gids;
166             }
167              
168              
169             # Output the file to disk
170             sub write {
171 1     1 0 3 my ($this, $fh) = @_;
172              
173 1         3 foreach my $name ($this->groups) {
174 16         41 my @users = $this->members($name);
175 16         44 my $head = join(":", $name, $this->passwd($name), $this->gid($name), "");
176 16         46 my $ind = join(":", "$name%n", $this->passwd($name), $this->gid($name), "");
177 16 50       82 print $fh $this->joinwrap($MAXLINELEN, $head, $ind, ",", "", @users),
178             "\n" or return 0;
179             }
180 1         8 return 1;
181             }
182              
183              
184             # Accessors (these all accept a group name and an optional value)
185             sub passwd {
186 51     51 1 102 my $this = shift;
187 51         58 my $name = shift;
188 51 100       207 @_ ? $this->{gpass}{$name} = shift : $this->{gpass}{$name};
189             }
190              
191              
192             # Note that it is illegal to change a group's GID to one used by another group
193             # This method also has to take into account side effects produced by doing
194             # this, such as the fact that the member hash is keyed against the GID.
195             sub gid {
196 440     440 1 767 my $this = shift;
197 440         502 my $name = shift;
198              
199 440 100       1823 return $this->{gid}{$name} unless @_;
200 19         22 my $newgid = shift;
201 19         37 my $oldgid = $this->{gid}{$name};
202             # Return OK if you try to set the same GID a group already has
203 19 50 66     51 return $oldgid if defined $oldgid && $newgid == $oldgid;
204 19 100       21 return undef if grep { $newgid == $_ } values %{$this->{gid}};
  170         288  
  19         69  
205 18 100       46 if (defined $oldgid) {
206 1         4 $this->{group}{$newgid} = $this->{group}{$oldgid};
207 1         4 delete $this->{group}{$oldgid};
208             }
209 18         134 $this->{gid}{$name} = $newgid;
210             }
211              
212              
213             # Return or set the list of users in a group
214             sub members {
215 56     56 1 83 my $this = shift;
216 56         72 my $name = shift;
217              
218 56         95 my $gid = $this->gid($name);
219 56 50       111 return undef unless defined $gid;
220 56 100       102 if (@_) {
221 12         115 $this->{group}{$gid} = { };
222 12         38 $this->add_user($name, @_);
223             }
224 56 100       99 return keys %{$this->{group}{$gid}} unless wantarray;
  40         181  
225 16         21 return sort keys %{$this->{group}{$gid}};
  16         99  
226             }
227              
228             # Autoload methods go after =cut, and are processed by the autosplit program.
229              
230             1;
231             __END__