6,9c6
< 
< package CfgTie::TieUser;
< require CfgTie::filever;
< require CfgTie::Cfgfile;
---
> package CfgTie::TieGroup;
13c10
< CfgTie::TieUser -- an associative array of user names and ids to information
---
> CfgTie::TieGroup -- an associative array of group names and ids to information
17c14
< makes the user database available as a regular hash
---
> Makes the groups database available as regular hash
19,20c16,17
<         tie %user,'CfgTie::TieUser'
<         print "randym's full name: ", $user{'randym'}->{gcos}, "\n";
---
>         tie %group,'CfgTie::TieGroup'
>         $group{'myfriends'}=['jonj', @{$group{'myfriends'}];
24,25c21,22
< This is a straight forward HASH tie that allows us to access the user database
< sanely.
---
> This is a straight forward HASH tie that allows us to access the user group
> database sanely.
27c24
< It cross ties with the groups packages and the mail packages
---
> It cross ties with the user package and the mail packages
35c32
< =item C<tie %user,'CfgTie::TieUser'>
---
> =item C<tie %group,'CfgTie::TieGroup'>
37c34
< C<$user{$name}> will return a HASH reference of the named user information
---
> C<$group{$name}> will return a HASH reference of the named group information
39c36
< =item C<tie %user_id,'CfgTie::TieUser_id'>
---
> =item C<tie %group_id,'CfgTie::Group_id'>
41c38
< C<$user_id{$id}> will return a HASH reference for the specified user.
---
> C<$group_id{$id}> will return a HASH reference for the specified group.
47,48c44
< Any given user entry has the following information assoicated with it (the
< keys are case insensitive):
---
> Any given group entry has the following information assoicated with it:
52,89c48
< =item C<Name>
< 
< Login name
< 
< =item C<GroupId>
< 
< =item C<Id>
< 
< The user id number that they have been assigned.  It is possible for many
< different user names to given the same id.  However, changing the Id for
< the user (ie, setting it to a new one), has one of two effects.  If
< C<user'Chg_FS> is set 1, then all the files in the system owned by that id
< will changed to the new id in addition to changing the id in the system table.
< Otherwise, only the system table will be modified.
< 
< 
< =item C<Quota>
< 
< =item C<Comment>
< 
< =item C<Home>
< 
< The users home folder
< 
< =item C<LOGIN_Last>
< 
< This is the information from the last time the user logged in.  It is an
< array reference to data like:
< 
<         [$time, $line, $from_host]
< 
< =item C<Shell>
< 
< The users shell
< 
< =item C<AuthMethod>
< 
< The authentication method if other than the default
---
> =item C<name>
91c50
< =item C<ExpireDate>
---
> =item C<id>
93c52
< The date the account expires on
---
> =item C<members>
95c54
< =item C<Inactive>
---
> A list reference to all of the users that are part of this group.
97c56
< The number of days after a password expires.s...
---
> =item C<_members>
99,101c58,59
< =item C<Priority>
< 
< The scheduling priority for that user.
---
> A list reference to all of the users that are explicitly listed in the
> F</etc/group> file.
106c64
< Plus two (probably) obsolete fields:
---
> Plus an (probably) obsolete fields:
114,121d71
< =item C<GCOS>
< 
< I<General Electric Comprehensive Operating System> or
< I<General Comprehensive Operating System>
< field
< 
< This is now the users full name under many Unix's, incl. LINUX.
< 
129,130d78
< =head2 Configuration Variables
< 
135c83
< =item C<&CfgTie::TieUser'status()>
---
> =item C<&CfgTie:TieGroup'status()>
137c85
< =item C<&CfgTie::TieUser_id'status()>
---
> =item C<&CfgTie::TieGroup_id'status()>
139c87
< Will return C<stat> information on the user database.
---
> Will return C<stat> information on the group database.
143,158d90
< =head2 Adding or overiding methods for user records
< 
< Lets say you wanted to change the default HTML handling to a different method.
< To do this you need only include code like the following:
< 
<    package CfgTie::TieUser_rec;
<    sub HTML($)
<    {
<       my $self=shift;
<       "<h1>".$Self->{name}."</h1>\n".
<       "<table border=0><tr><th align=right>\n".
<         join("</td></tr>\n<tr><th align=right>",
<           map {$_."</th><td>".$self->{$_}} (sort keys %{$self})
<        </td></tr><lt></table>C<\n>";
<    }
< 
161c93
< C<$CfgTie::TieUser_rec'usermod> contains the path to the program F<usermod>.
---
> C<$CfgTie::TieGroup_rec'groupmod> contains the path to the program F<groupmod>.
164c96
< C<$CfgTie::TieUser_rec'useradd> contains the path to the program F<useradd>.
---
> C<$CfgTie::TieGroup_rec'groupadd> contains the path to the program F<groupadd>.
167c99
< C<$CfgTie::TieUser_rec'userdel> contains the path to the program F<userdel>.
---
> C<$CfgTie::TieGroup_rec'groupdel> contains the path to the program F<groupdel>.
170,173d101
< Not all keys are supported on all systems.
< 
< This may transparently use a shadow tie in the future.
< 
177a106
> F</etc/gshadow>
183,187c112,116
< L<CfgTie::Cfgfile>, L<CfgTie::TieAliases>, L<CfgTie::TieGeneric>,
< L<CfgTie::TieGroup>,
< L<CfgTie::TieHost>, L<CfgTie::TieNamed>,   L<CfgTie::TieNet>,
< L<CfgTie::TiePh>,   L<CfgTie::TieProto>,   L<CfgTie::TieServ>,
< L<CfgTie::TieShadow>
---
> L<CfgTie::Cfgfile>,
> L<CfgTie::TieAliases>, L<CfgTie::TieGeneric>, L<CfgTie::TieHost>,
> L<CfgTie::TieNamed>,   L<CfgTie::TieNet>,     L<CfgTie::TiePh>,
> L<CfgTie::TieProto>,   L<CfgTie::TieRCService>,
> L<CfgTie::TieServ>, L<CfgTie::TieShadow>, L<CfgTie::TieUser>
192,194c121,123
< L<usermod(8)>,
< L<useradd(8)>,
< L<userdel(8)>
---
> L<groupmod(8)>,
> L<groupadd(8)>,
> L<groupdel(8)>
206,208d134
< my $Chg_FS = 1; #By default we want to update the file system when the user
< # Id changes
< 
262,264c188
< 
<    if (!defined $name) {return;}
< 
---
>    if (!defined $name) {return undef;}
269c193,195
<      {return $CfgTie::TieUser_rec'by_name{$lname};}
---
>      {return $CfgTie::TieGroup_rec'by_name{$lname};}
> 
>    return undef;
335c261,263
<    if (exists $CfgTie::TieUser_rec'by_id{$id}) {return 1;}
---
>    if (!defined $id) {return 0;}
> 
>    if (exists $CfgTie::TieGroup_rec'by_id{$id}) {return 1;}
351c280,283
<    if (&EXISTS($self,$id)) {return $CfgTie::TieUser_rec'by_id{$id};}
---
>    if (&EXISTS($self,$id))
>      {return $CfgTie::TieGroup_rec'by_id{$id};}
> 
>    return undef;
392c324,335
< sub new {&TIEHASH(@_);}
---
> use CfgTie::TieUser;
> my %Users;
> tie %Users, 'CfgTie::TieUser';
> sub uniq ($)
> {
>    my $L=shift;
>    my @Ret=();
>    my $J;
>    foreach my $I (sort @{$L})
>     {if (!defined $J || $J ne $I) {$J=$I; push @Ret,$I;}}
>    \@Ret;
> }
393a337
> sub new {&TIEHASH(@_);}
398c342
<    my $Node;
---
>    my $Node={};
403,405c347
<         ($Node->{password},$Node->{id},   $Node->{groupid},
<          $Node->{quota}, $Node->{comment}, $Node->{gcos}, $Node->{home},
<          $Node->{shell}) = @Rest;
---
>         ($Node->{password},$Node->{id}, $Node->{_members})=@Rest;
409a352,354
> #   $by_name{$lname} = $Node;
> #   $by_id{$Node->{id}} = $Node;
> 
426,489d370
< #Modified from PERL Cookbook:
< my $lastlog_fmt="L a16 A16"; #on sunos "L A8 A16"
< sub lastlog_FETCH($)
< {
<    use User::pwent;
<    use IO::Seekable qw(SEEK_SET);
< 
<    #SECURITY NOTE:
<    #Change our real user id and group id to be whatever out user
<    #id and group id really are
<    my ($UID_save, $GID_save);
<    ($UID_save,$>)=($>,$<);
<    ($GID_save,$))=($(,$();
< 
<    my $LASTLOG=$CfgTie::Cfgfile'FNum++;
<    if (!open(LASTLOG, "</var/log/lastlog")) {return;}
< 
<    my $User = shift;
<    my $U = ($User =~ /^\d+$/) ? getpwuid($User) : getpwnam($User);
<    my $R;
<    if (!$U) {goto ret_from_here;}
<    my $sizeof = length(pack($lastlog_fmt,()));
<    if (seek(LASTLOG, $U->uid + $sizeof,SEEK_SET) &&
<        read(LASTLOG, $buffer, $sizeof) == $sizeof)
<      {
<         #time line host
<         $R = [unpack($lastlog_fmt, $buffer)];
<      }
< 
<   ret_from_here:
< 
<    close LASTLOG;
<    #SECURITY NOTE:
<    #Restore real user id and group id to whatever they were before
<    ($>,$))=($UID_save,$GID_save);
< 
<    $R;
< }
< 
< sub scan_lasts
< {
<    #Get the last time the read their email
<    #SECURITY NOTE:
<    #Change our real user id and group id to be whatever out user
<    #id and group id really are
<    my ($UID_save, $GID_save);
<    ($UID_save,$>)=($>,$<);
<    ($GID_save,$))=($(,$();
< 
<    my $L = $CfgTie::Cfgfile'FNum++;
<    open (L, "</var/log/maillog");
<    while (<L>)
<     {
<        if(/([\d\w\s:]+)\s\w+\s\w+\[\d+\]:\sLogout\suser\s(\w+).*/)
<            {$Last{lc($2)} = $1;}
<      }
< 
<    close L;
<    #SECURITY NOTE:
<    #Restore real user id and group id to whatever they were before
<    ($>,$))=($UID_save,$GID_save);
< 
< }
< 
494,512d374
< 
<       if ($lkey eq 'login_last' && !exists $self->{'login_last'})
<         {
<            my $R = lastlog_FETCH($self->{name});
<            if (undef $R) {return 0;}
<            $self->{'login_last'} = $R;
<         }
<    elsif ($lkey eq 'last' && !exists $self->{'last'})
<      {
<         #Try to recover it from our shadow, but avoid scanning the last
<         #file if we can -- it takes a *long* time
<         if (!exists $Last{lc($self->{name})} && !defined $scanned_last)
<           {
<              &scan_lasts();
<              $scanned_last=1;
<           }
<         if (exists $Last{lc($self->{name})})
<           {$self->{'last'} = $Last{lc($self->{name})};}
<      }
520a383
>    if (exists $self->{$lkey}) {return $self->{$lkey};}
527,529d393
<    elsif ($lkey eq 'last' && !exists $self->{$lkey}) {&EXISTS($self,$lkey);}
< 
<    if (exists $self->{$lkey}) {return $self->{$lkey};}
533,546c397
< my $usermod_opt =
<  {
<    comment => '-c',
<    home    => '-d',
<    expire  => '-e',
<    inactive=> '-f',
<    name    => '-l',
<    shell   => '-s',
<    group1  => '-g',
<    groups  => '-G',
<    id      => '-u',
<  };
< 
< my $usermod_opt2 =
---
> $groupmod_opt =
548c399,400
<    id      => '-o',
---
>    name => '-n',
>    id   => '-g',
551,552c403,404
< my $usermod = '/usr/sbin/usermod';  #Hard path to usermod
< my $userdel = '/usr/sbin/userdel';  #Hard path to userdel
---
> $groupmod = '/usr/sbin/groupmod';  #Hard path to groupmod
> $groupdel = '/usr/sbin/groupdel';  #Hard path to groupdel
567,572c419
<         system "$usermod $self->{name} -g $i -G ". join(',', @g);
<      }
<    elsif ($lkey eq 'priority')
<      {
<         #Pass the priority setting onto the system
<         setpriority(PRIO_USER,$self->{id},$val);
---
>         system "$groupmod $self->{Name} -g $i -G ". join(',', @g);
574c421
<    elsif (exists $usermod_opt->{$lkey})
---
>    if (exists $groupmod_opt{$lkey})
576,604c423,424
<         #This is something for user mod!
<         my ($FSUp, @FSet)=(0);
< 
<         if (defined $user'Chg_FS && $user'Chg_FS == 1 && $lkey eq 'id')
<           {
<              #We are supposed to change all of the files in the system to
<              #have the new new one.
<              #We have a race condition: someone else may change soemthing in
<              #the file system, so we may not get everything, but we try to
<              #be reasonable
< 
<              # Now we need to identify all of the files.. this may take a
<              # long time
<              @FSet= &CfgTie::filever'find_by_user ('/', $self->{id});
< 
<              if (defined @FSet && scalar @FSet) {$FSUp = 1;}
<           }
< 
<         my $X = $usermod_opt2->{$lkey};
<         if (!defined $X) {$X='';}
< 
<         #Change the system tables
<         system "$usermod ".$usermod_opt->{$lkey}." $val $X ".$self->{name}.
<                 "\n";
<         #If bad things should throw exception
< 
<         if ($FSUp) {chown $val,-1, @FSet;}
< 
<         $self->{$lkey} = $val;
---
>         #This is something for group mod!
>         system "$groupmod $groupmod_opt{$lkey} $val $self->{Name}";
625,626c445,446
<            #This is something for user mod!
<            system "$usermod ".$usermod_opt->{$lkey}." ".$self->{name};
---
>            #This is something for group mod!
>            system "$groupmod $self->{name} $groupmod_opt->{$lkey}";
634a455
> 
641d461
<    $Keys2{'last'}=1;
643d462
<    delete $Keys2{gcos};
646d464
<    delete $Keys2{groupid};
648c466
<    my ($G) = getgrgid($self->{groupid});
---
>    delete $Keys2{members};
652,653c470
<      "<tr><th align=right>Full Name:</th><td>".$self->{gcos}."</td></tr>".
<      "<tr><th align=right>login:</th><td>".$self->{name}."</td></tr>".
---
>      "<tr><th align=right>Name:</th><td>".$self->{name}."</td></tr>".
655,656c472,473
<      "<tr><th align=right>Group:</th><td><a href=\"/group/$G\">".$G."</a> (".
< 	$self->{groupid}.")</td></tr>".
---
>      "<tr><th align=right>Members:</th><td>".join(', ',@{$self->{members}}).
> 		"</td></tr>".
663a481
> 
