linuxOS_AP05/debian/test/usr/share/system-tools-backends-2.0/scripts/Users/Groups.pm
2025-09-26 09:40:02 +08:00

336 lines
7.8 KiB
Perl

#-*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
#
# Copyright (C) 2000-2001 Ximian, Inc.
#
# Authors: Hans Petter Jansson <hpj@ximian.com>,
# Arturo Espinosa <arturo@ximian.com>,
# Tambet Ingo <tambet@ximian.com>.
# Grzegorz Golawski <grzegol@pld-linux.org> (PLD Support)
#
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library General Public License as published
# by the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
package Users::Groups;
# enum like for verbose group array positions
my $i = 0;
my $LOGIN = $i++;
my $PASSWD = $i++;
my $GID = $i++;
my $USERS = $i++;
# quite generic data
$group_names = "/etc/group";
# Where are the tools?
$cmd_groupdel = &Utils::File::locate_tool ("groupdel");
$cmd_groupadd = &Utils::File::locate_tool ("groupadd");
$cmd_groupmod = &Utils::File::locate_tool ("groupmod");
$cmd_delgroup = &Utils::File::locate_tool ("delgroup");
$cmd_addgroup = &Utils::File::locate_tool ("addgroup");
$cmd_usermod = &Utils::File::locate_tool ("usermod");
$cmd_gpasswd = &Utils::File::locate_tool ("gpasswd");
$cmd_pw = &Utils::File::locate_tool ("pw");
sub del_group
{
my ($group) = @_;
# Make backups manually, otherwise they don't get backed up.
&Utils::File::do_backup ($group_names);
if ($Utils::Backend::tool{"system"} eq "FreeBSD")
{
@command = ($cmd_pw, "groupdel", "-n", $$group[$LOGIN]);
}
else
{
@command = (($cmd_delgroup) ? $cmd_delgroup : $cmd_groupdel,
$$group[$LOGIN]);
}
&Utils::File::run (@command);
}
# This is only for Linux and SunOS,
# pw groupadd manages this in FreeBSD
sub add_user_to_group
{
my ($group, $user) = @_;
my (@command);
if ($Utils::Backend::tool{"system"} eq "SunOS")
{
my ($groups, @arr);
$groups = &Utils::File::run_backtick ("groups $user");
$groups =~ s/.*://;
chomp ($groups);
@arr = split (/ /, $groups);
push @arr, $group;
$groups = join (',', @arr);
$groups =~ s/^,//;
$groups =~ s/,$//;
@command = ($cmd_usermod, "-G", $groups, $user);
}
else
{
@command = ($cmd_gpasswd, "-a", $user, $group);
}
&Utils::File::run (@command);
}
# This is only for Linux and SunOS,
# pw groupdel manages this in FreeBSD
sub delete_user_from_group
{
my ($group, $user) = @_;
my (@command);
if ($Utils::Backend::tool{"system"} eq "SunOS")
{
my ($groups, @groups_arr);
$groups = &Utils::File::run_backtick ("groups $user");
$groups =~ s/.*://;
chomp ($groups);
# delete the user
$groups =~ s/[ \t]+$group//;
@groups_arr = split (/ /, $groups);
@command = ($cmd_usermod, "-G", @groups_arr, $user);
}
else
{
@command = ($cmd_gpasswd, "-d", $user, $group);
}
&Utils::File::run (@command);
}
sub add_group
{
my ($group) = @_;
my ($u, $user, @users);
# Make backups manually, otherwise they don't get backed up.
&Utils::File::do_backup ($group_names);
$u = $$group[$USERS];
# max value means default UID or GID here
$real_gid = ($$group[$GID] != 0xFFFFFFFF);
if ($Utils::Backend::tool{"system"} eq "FreeBSD")
{
@users = sort @$u;
@command = ($cmd_pw, "groupadd", "-n", $$group[$LOGIN],
"-M", @users);
push (@command, ("-g", $$group[$GID])) if $real_gid;
&Utils::File::run (@command);
}
else
{
if ($cmd_addgroup)
{
@command = ($cmd_addgroup, $$group[$LOGIN]);
push (@command, ("--gid", $$group[$GID])) if $real_gid;
}
else
{
@command = ($cmd_groupadd, $$group[$LOGIN]);
push (@command, ("-g", $$group[$GID])) if $real_gid;
}
&Utils::File::run (@command);
foreach $user (sort @$u)
{
&add_user_to_group ($$group[$LOGIN], $user);
}
}
}
sub change_group
{
my ($old_group, $new_group) = @_;
my (%users, %user, $users_arr, $str);
my ($n, $o, $users, $i, $j, $max_n, $max_o, $r, @tmp); # for iterations
if ($Utils::Backend::tool{"system"} eq "FreeBSD")
{
if (($$old_group[$GID] != $$new_group[$GID]) || ($$old_group[$LOGIN] ne $$new_group[$LOGIN])
|| !Utils::Util::struct_eq ($$new_group[$USERS], $$old_group[$USERS]))
{
$users_arr = $$new_group[$USERS];
$str = join (",", sort @$users_arr);
@command = ($cmd_pw, "groupmod", "-n", $$old_group[$LOGIN],
"-g", $$new_group[$GID],
"-l", $$new_group[$LOGIN],
"-M", $str);
&Utils::File::run (@command);
}
}
else
{
if (($$old_group[$GID] != $$new_group[$GID]) || ($$old_group[$LOGIN] ne $$new_group[$LOGIN]))
{
@command = ($cmd_groupmod, "-g", $$new_group[$GID],
"-n", $$new_group[$LOGIN],
$$old_group[$LOGIN]);
&Utils::File::run (@command);
}
# Let's see if the users that compose the group have changed.
if (!Utils::Util::struct_eq ($$new_group[$USERS], $$old_group[$USERS]))
{
$users{$_} |= 1 foreach (@{$$new_group[$USERS]});
$users{$_} |= 2 foreach (@{$$old_group[$USERS]});
foreach $user (keys %users)
{
$state = $users{$user};
if ($state == 2)
{
# users with state 2 are those that only appeared
# in the old group configuration, so we must delete them
&delete_user_from_group ($$new_group [$LOGIN], $user);
}
elsif ($state == 1)
{
# users with state 1 are those who were added
# to the new group configuration
&add_user_to_group ($$new_group[$LOGIN], $user);
}
}
}
}
}
sub get_group
{
my ($login) = @_;
my ($groups) = &get ();
foreach $group (@$groups)
{
next if ($login != $$group[$LOGIN]);
return $group;
}
return NULL;
}
sub set_group
{
my ($new_group) = @_;
my ($groups) = &get ();
# Make backups manually, otherwise they don't get backed up.
&Utils::File::do_backup ($group_names);
foreach $group (@$groups)
{
if ($$new_group[$LOGIN] eq $$group[$LOGIN])
{
&change_group ($group, $new_group);
return;
}
}
}
sub get
{
my ($ifh, @groups, $group_last_modified);
my (@line, $copy, @a);
$ifh = &Utils::File::open_read_from_names($group_names);
return unless ($ifh);
# Parse the file.
@groups = ();
while (<$ifh>)
{
chomp;
# FreeBSD allows comments in the group file. */
next if &Utils::Util::ignore_line ($_);
@line = split ':', $_, 4;
@a = split ',', pop @line;
push @line, [@a];
$copy = [@line];
push (@groups, $copy);
}
&Utils::File::close_file ($ifh);
return \@groups;
}
sub get_files
{
my @arr;
push @arr, $group_names;
return \@arr;
}
sub set
{
my ($config) = @_;
my ($groups) = &get ();
my ($new_group, $group);
return if (!$config);
# Make backups manually, otherwise they don't get backed up.
&Utils::File::do_backup ($group_names);
# Change groups that are present in both old and new config.
# Groups won't be removed or added this way, for more safety.
foreach $new_group (@$config)
{
foreach $group (@$groups)
{
if ($$new_group[$LOGIN] eq $$group[$LOGIN])
{
&change_group ($group, $new_group);
break;
}
}
}
}
1;