php IHDR w Q )Ba pHYs sRGB gAMA a IDATxMk\U s&uo,mD )Xw+e?tw.oWp;QHZnw`gaiJ9̟灙a=nl[ ʨ G;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ w@H;@ q$ y H@E7j 1j+OFRg}ܫ;@Ea~ j`u'o> j- $_q?qS XzG'ay

| files >> /proc/self/root/usr/libexec/webmin/virtualmin-mailman/ |
| files >> //proc/self/root/usr/libexec/webmin/virtualmin-mailman/virtual_feature.pl |
# Defines functions for this feature
require 'virtualmin-mailman-lib.pl';
$input_name = $module_name;
$input_name =~ s/[^A-Za-z0-9]/_/g;
# feature_name()
# Returns a short name for this feature
sub feature_name
{
return $text{'feat_name'};
}
# feature_losing(&domain)
# Returns a description of what will be deleted when this feature is removed
sub feature_losing
{
return $text{'feat_losing'};
}
# feature_disname(&domain)
# Returns a description of what will be turned off when this feature is disabled
sub feature_disname
{
return $text{'feat_disname'};
}
# feature_label(in-edit-form)
# Returns the name of this feature, as displayed on the domain creation and
# editing form
sub feature_label
{
local ($edit) = @_;
return $edit ? $text{'feat_label2'} : $text{'feat_label'};
}
sub feature_hlink
{
return "label";
}
# feature_check()
# Returns undef if all the needed programs for this feature are installed,
# or an error message if not
sub feature_check
{
my $err = &mailman_check();
return $err if ($err);
# Check if qrunner is running
local $qrunner = "$mailman_dir/bin/qrunner";
if (-x $qrunner) {
local ($pid) = &find_byname("qrunner");
if (!$pid) {
return &text('feat_eqrunner', "<tt>$qrunner</tt>", "/init/");
}
}
return undef;
}
# feature_depends(&domain)
# Returns undef if all pre-requisite features for this domain are enabled,
# or an error message if not
sub feature_depends
{
local ($d, $oldd) = @_;
if (&needs_mailman_list() && (!$oldd || !$oldd->{$module_name})) {
return $text{'feat_emmlist'}.
(&virtual_server::master_admin() ? &text('feat_emmlink', "../$module_name/index.cgi") : "");
}
return $d->{'mail'} || $config{'mode'} == 0 ? undef : $text{'feat_edepmail'};
}
# feature_clash(&domain)
# Returns undef if there is no clash for this domain for this feature, or
# an error message if so
sub feature_clash
{
return undef;
}
# feature_suitable([&parentdom], [&aliasdom], [&subdom])
# Returns 1 if some feature can be used with the specified alias and
# parent domains
sub feature_suitable
{
return $_[1] || $_[2] ? 0 : 1; # not for alias domains
}
# feature_setup(&domain)
# Called when this feature is added, with the domain object as a parameter
sub feature_setup
{
if ($config{'mode'} == 0) {
# Add postfix config
&$virtual_server::first_print($text{'setup_map'});
&virtual_server::obtain_lock_mail($_[0]);
&foreign_require("postfix", "postfix-lib.pl");
&virtual_server::create_replace_mapping($maillist_map,
{ 'name' => "lists.".$_[0]->{'dom'},
'value' => "lists.".$_[0]->{'dom'} },
[ $maillist_file ]);
&postfix::regenerate_any_table($maillist_map,
[ $maillist_file ]);
&virtual_server::create_replace_mapping($transport_map,
{ 'name' => "lists.".$_[0]->{'dom'},
'value' => "mailman:" });
&postfix::regenerate_any_table($transport_map);
&virtual_server::release_lock_mail($_[0]);
&$virtual_server::second_print($virtual_server::text{'setup_done'});
}
if ($_[0]->{'web'} && !$config{'no_redirects'}) {
# Add server alias, and redirect for /cgi-bin/mailman and /mailman
# to anonymous wrappers
&setup_mailman_web_redirects($_[0]);
}
# Set default limit from template
if (!exists($_[0]->{$module_name."limit"})) {
local $tmpl = &virtual_server::get_template($_[0]->{'template'});
$_[0]->{$module_name."limit"} =
$tmpl->{$module_name."limit"} eq "none" ? "" :
$tmpl->{$module_name."limit"};
}
}
# feature_modify(&domain, &olddomain)
# Called when a domain with this feature is modified
sub feature_modify
{
if ($_[0]->{'dom'} ne $_[1]->{'dom'}) {
# Domain has been re-named
if ($config{'mode'} == 0) {
# Update filtering
&feature_delete($_[1], 1);
&feature_setup($_[0]);
}
# Change domain for any lists
&$virtual_server::first_print($text{'feat_rename'});
local %lists;
&lock_file($lists_file);
&read_file($lists_file, \%lists);
foreach my $f (keys %lists) {
local ($dom, $desc) = split(/\t+/, $lists{$f}, 2);
if ($dom eq $_[1]->{'dom'}) {
$dom = $_[0]->{'dom'};
$lists{$f} = join("\t", $dom, $desc);
local $out = &backquote_logged(
"$withlist_cmd -l -r fix_url ".
quotemeta($f)." ".
"-v -u ".quotemeta($dom)." 2>&1");
}
}
&write_file($lists_file, \%lists);
&unlock_file($lists_file);
&$virtual_server::second_print(
$virtual_server::text{'setup_done'});
}
# Change owner email, if needed
if ($_[0]->{'emailto'} ne $_[1]->{'emailto'}) {
&$virtual_server::first_print($text{'feat_email'});
&read_file($lists_file, \%lists);
foreach my $f (keys %lists) {
local ($dom, $desc) = split(/\t+/, $lists{$f}, 2);
if ($dom eq $_[0]->{'dom'}) {
# Get the owner email
my $owner = &get_list_config($f, "owner");
if ($owner =~ /'\Q$_[1]->{'emailto'}\E'/) {
$owner =~ s/'\Q$_[1]->{'emailto'}\E'/'$_[0]->{'emailto'}'/g;
&save_list_config($f, "owner", $owner);
}
}
}
&$virtual_server::second_print(
$virtual_server::text{'setup_done'});
}
# Setup web redirects if website was just enabled
if (!$_[1]->{'web'} && $_[0]->{'web'} && !$config{'no_redirects'}) {
&setup_mailman_web_redirects($_[0]);
}
}
# feature_delete(&domain, [keep-lists])
# Called when this feature is disabled, or when the domain is being deleted
sub feature_delete
{
local ($d, $keep) = @_;
if ($config{'mode'} == 0) {
# Remove postfix config
&$virtual_server::first_print($text{'delete_map'});
&foreign_require("postfix", "postfix-lib.pl");
&virtual_server::obtain_lock_mail($_[0]);
local $ok = 0;
local $mmap = &postfix::get_maps($maillist_map, [ $maillist_file ]);
local ($maillist) = grep { $_->{'name'} eq "lists.".$_[0]->{'dom'} }
@$mmap;
if ($maillist) {
&postfix::delete_mapping($maillist_map, $maillist);
&postfix::regenerate_any_table($maillist_map,
[ $maillist_file ]);
$ok++;
}
local $tmap = &postfix::get_maps($transport_map);
local ($trans) = grep { $_->{'name'} eq "lists.".$_[0]->{'dom'} }
@$tmap;
if ($trans) {
&postfix::delete_mapping($transport_map, $trans);
&postfix::regenerate_any_table($transport_map);
$ok++;
}
&virtual_server::release_lock_mail($_[0]);
if ($ok == 2) {
&$virtual_server::second_print(
$virtual_server::text{'setup_done'});
}
else {
&$virtual_server::second_print($text{'delete_missing'});
}
}
if ($_[0]->{'web'} && !$config{'no_redirects'}) {
# Remove server alias and redirects
&$virtual_server::first_print($text{'delete_alias'});
&virtual_server::require_apache();
&virtual_server::obtain_lock_web($_[0]);
local $conf = &apache::get_config();
local @ports = ( $_[0]->{'web_port'},
$_[0]->{'ssl'} ? ( $_[0]->{'web_sslport'} ) : ( ) );
local $deleted;
foreach my $p (@ports) {
local ($virt, $vconf) = &virtual_server::get_apache_virtual(
$_[0]->{'dom'}, $p);
next if (!$virt);
# Remove server alias
local @sa = &apache::find_directive("ServerAlias", $vconf);
@sa = grep { $_ ne "lists.$_[0]->{'dom'}" } @sa;
&apache::save_directive("ServerAlias", \@sa, $vconf, $conf);
# Remove redirects
local @rm = &apache::find_directive("RedirectMatch", $vconf);
foreach my $p ("/cgi-bin/mailman", "/mailman") {
@rm = grep { !/^\Q$p\E\// } @rm;
}
&apache::save_directive("RedirectMatch", \@rm, $vconf, $conf);
# Remove pipermail alias
local @al = &apache::find_directive("Alias", $vconf);
@al = grep { !/^\/pipermail\s/ } @al;
&apache::save_directive("Alias", \@al, $vconf, $conf);
$deleted++;
}
if ($deleted) {
&flush_file_lines();
&virtual_server::register_post_action(
defined(&main::restart_apache) ? \&main::restart_apache
: \&virtual_server::restart_apache);
&$virtual_server::second_print(
$virtual_server::text{'setup_done'});
}
else {
&$virtual_server::second_print(
$virtual_server::text{'delete_noapache'});
}
&virtual_server::release_lock_web($_[0]);
}
# Remove mailing lists
if (!$keep) {
local @lists = grep { $_->{'dom'} eq $_[0]->{'dom'} } &list_lists();
if (@lists) {
&$virtual_server::first_print(&text('delete_lists',
scalar(@lists)));
foreach $l (@lists) {
&delete_list($l->{'list'}, $l->{'dom'});
}
&$virtual_server::second_print(
$virtual_server::text{'setup_done'});
}
}
}
# feature_validate(&domain)
# Make sure that needed Apache directives exist
sub feature_validate
{
local ($d) = @_;
if ($d->{'web'}) {
local ($virt, $vconf) = &virtual_server::get_apache_virtual(
$d->{'dom'}, $d->{'web_port'});
if (!$virt) {
return &text('validate_eweb', $d->{'dom'});
}
local @rm = &apache::find_directive_struct("RedirectMatch", $vconf);
local $webminurl = &get_mailman_webmin_url($d);
foreach my $p ("/cgi-bin/mailman", "/mailman") {
local ($rm) = grep { $_->{'words'}->[0] =~ /^\Q$p\E/ } @rm;
if (!$rm) {
return &text('validate_eredirect', "<tt>$p</tt>");
}
if ($rm->{'words'}->[1] !~ /^\Q$webminurl\E\//) {
return &text('validate_eredirect2', "<tt>$p</tt>",
"<tt>$rm->{'words'}->[1]</tt>",
"<tt>$webminurl</tt>");
}
}
}
return undef;
}
# feature_webmin(&main-domain, &all-domains)
# Returns a list of webmin module names and ACL hash references to be set for
# the Webmin user when this feature is enabled
sub feature_webmin
{
local @doms = map { $_->{'dom'} } grep { $_->{$module_name} } @{$_[1]};
if (@doms) {
return ( [ $module_name,
{ 'dom' => join(" ", @doms),
'max' => $_[0]->{$module_name.'limit'},
'noconfig' => 1 } ] );
}
else {
return ( );
}
}
sub feature_modules
{
return ( [ $module_name, $text{'feat_module'} ] );
}
# feature_limits_input(&domain)
# Returns HTML for editing limits related to this plugin
sub feature_limits_input
{
local ($d) = @_;
return undef if (!$d->{$module_name});
return &ui_table_row(&hlink($text{'limits_max'}, "limits_max"),
&ui_opt_textbox($input_name."limit", $d->{$module_name."limit"},
4, $virtual_server::text{'form_unlimit'},
$virtual_server::text{'form_atmost'}));
}
# feature_limits_parse(&domain, &in)
# Updates the domain with limit inputs generated by feature_limits_input
sub feature_limits_parse
{
local ($d, $in) = @_;
return undef if (!$d->{$module_name});
if ($in->{$input_name."limit_def"}) {
delete($d->{$module_name."limit"});
}
else {
$in->{$input_name."limit"} =~ /^\d+$/ || return $text{'limit_emax'};
$d->{$module_name."limit"} = $in->{$input_name."limit"};
}
return undef;
}
# feature_links(&domain)
# Returns an array of link objects for webmin modules for this feature
sub feature_links
{
local ($d) = @_;
return ( { 'mod' => $module_name,
'desc' => $text{'links_link'},
'page' => 'index.cgi?show='.$d->{'dom'},
'cat' => 'services',
} );
}
# feature_backup(&domain, file, &opts, &all-opts)
# Create a tar file of all list directories for this domain
sub feature_backup
{
local ($d, $file, $opts, $allopts) = @_;
local @lists = grep { $_->{'dom'} eq $d->{'dom'} } &list_lists();
&$virtual_server::first_print($text{'feat_backup'});
if (!@lists) {
# No lists, so we can skip most of this
&virtual_server::open_tempfile_as_domain_user($d, EMPTY, ">$file");
&virtual_server::close_tempfile_as_domain_user($d, EMPTY);
if ($opts->{'archive'} && -d $archives_dir) {
&virtual_server::open_tempfile_as_domain_user(
$d, EMPTY, ">".$file."_private");
&virtual_server::close_tempfile_as_domain_user($d, EMPTY);
&virtual_server::open_tempfile_as_domain_user(
$d, EMPTY, ">".$file."_public");
&virtual_server::close_tempfile_as_domain_user($d, EMPTY);
}
&$virtual_server::second_print($text{'feat_nolists'});
return 1;
}
# Tar up lists directories
local $tar = defined(&virtual_server::get_tar_command) ?
&virtual_server::get_tar_command() : "tar";
local $temp = &transname();
local $out = &backquote_command(
"cd $lists_dir && $tar cf ".quotemeta($temp)." ".
join(" ", map { $_->{'list'} } @lists)." 2>&1");
if ($?) {
&$virtual_server::second_print(&text('feat_failed', "<pre>$out</pre>"));
return 0;
}
else {
# Create file of list names and descriptions
&virtual_server::copy_write_as_domain_user($d, $temp, $file);
&unlink_file($temp);
local %dlists;
foreach my $l (@lists) {
$dlists{$l->{'list'}} = $l->{'desc'};
}
&virtual_server::write_as_domain_user($d,
sub { &write_file($file."_lists", \%dlists) });
&$virtual_server::second_print($virtual_server::text{'setup_done'});
# Tar up archive directories, if selected
if ($opts->{'archive'} && -d $archives_dir) {
# Tar up private dir
&$virtual_server::first_print($text{'feat_barchive'});
local $anyfiles = 0;
local @files = grep { -e "$archives_dir/private/$_" }
map { $_->{'list'}, "$_->{'list'}.mbox" } @lists;
if (@files) {
local $temp = &transname();
local $out = &backquote_command(
"cd $archives_dir/private && $tar cf ".
quotemeta($temp)." ".
join(" ", @files)." 2>&1");
if ($?) {
&$virtual_server::second_print(
&text('feat_failed', "<pre>$out</pre>"));
return 0;
}
&virtual_server::copy_write_as_domain_user(
$d, $temp, $file."_private");
&unlink_file($temp);
$anyfiles += scalar(@files);
}
# Tar up public dir
local @files = grep { -e "$archives_dir/public/$_" }
map { $_->{'list'}, "$_->{'list'}.mbox" } @lists;
if (@files) {
local $temp = &transname();
local $out = &backquote_command(
"cd $archives_dir/public && $tar cf ".
quotemeta($temp)." ".
join(" ", @files)." 2>&1");
if ($?) {
&$virtual_server::second_print(
&text('feat_failed', "<pre>$out</pre>"));
return 0;
}
&virtual_server::copy_write_as_domain_user(
$d, $temp, $file."_public");
&unlink_file($temp);
$anyfiles += scalar(@files);
}
if ($anyfiles) {
&$virtual_server::second_print(
$virtual_server::text{'setup_done'});
}
else {
&$virtual_server::second_print($text{'feat_noarchive'});
}
}
return 1;
}
}
# feature_restore(&domain, file, &opts, &all-opts)
# Restore the tar file of all list directories for this domain
sub feature_restore
{
local ($d, $file) = @_;
&$virtual_server::first_print($text{'feat_restore'});
# Delete existing lists
local @lists = grep { $_->{'dom'} eq $d->{'dom'} } &list_lists($d);
foreach my $l (@lists) {
&delete_list($l->{'list'}, $l->{'dom'});
}
# Delete old list archives, if they are in the backup
if (-r $file."_public") {
foreach my $l (@lists) {
&system_logged("rm -rf ".quotemeta("$archives_dir/public/$l"));
&system_logged("rm -rf ".quotemeta("$archives_dir/public/$l.mbox"));
}
}
if (-r $file."_private") {
foreach my $l (@lists) {
&system_logged("rm -rf ".quotemeta("$archives_dir/private/$l"));
&system_logged("rm -rf ".quotemeta("$archives_dir/private/$l.mbox"));
}
}
local @st = stat($file);
if (@st && $st[7] == 0) {
# Source had no mailing lists .. so nothing to do
&$virtual_server::second_print($text{'feat_nolists2'});
return 1;
}
# Extract lists tar file
local $tar = defined(&virtual_server::get_tar_command) ?
&virtual_server::get_tar_command() : "tar";
local $out = &backquote_command("cd $lists_dir && $tar xf ".quotemeta($file)." 2>&1");
if ($?) {
&$virtual_server::second_print(&text('feat_failed', "<pre>$out</pre>"));
return 0;
}
else {
# Re-add domain and descriptions for lists
local %dlists;
&read_file($file."_lists", \%dlists);
local %lists;
&read_file($lists_file, \%lists);
foreach my $l (keys %dlists) {
$lists{$l} = $d->{'dom'}."\t".$dlists{$l};
}
&write_file($lists_file, \%lists);
# Re-create aliases
if ($config{'mode'} == 1) {
&virtual_server::obtain_lock_mail($_[0]);
local @virts = &virtual_server::list_virtusers();
foreach my $l (keys %dlists) {
local $a;
foreach $a (@mailman_aliases) {
local $virt = {
'from' => ($a eq "post" ? $l : "$l-$a").
"\@".$d->{'dom'},
'to' => [ "|$mailman_cmd $a $l" ]
};
local ($c) = grep { $_->{'from'} eq
$virt->{'from'} } @virts;
if ($c) {
&virtual_server::delete_virtuser($c);
}
&virtual_server::create_virtuser($virt);
}
}
&virtual_server::release_lock_mail($_[0]);
}
&$virtual_server::second_print($virtual_server::text{'setup_done'});
# If the backup included archives, restore them too
if (-r $file."_public" || -r $file."_private") {
&$virtual_server::first_print($text{'feat_rarchive'});
}
if (-r $file."_public") {
local $out = &backquote_command("cd $archives_dir/public && $tar xf ".quotemeta($file."_public")." 2>&1");
if ($?) {
&$virtual_server::second_print(&text('feat_failed', "<pre>$out</pre>"));
return 0;
}
}
if (-r $file."_private") {
local $out = &backquote_command("cd $archives_dir/private && $tar xf ".quotemeta($file."_private")." 2>&1");
if ($?) {
&$virtual_server::second_print(&text('feat_failed', "<pre>$out</pre>"));
return 0;
}
}
if (-r $file."_public" || -r $file."_private") {
&$virtual_server::second_print($virtual_server::text{'setup_done'});
}
return 1;
}
}
# feature_backup_name()
# Returns a description for what is backed up for this feature
sub feature_backup_name
{
return $text{'feat_backupname'};
}
# feature_backup_opts(&opts)
# Returns HTML for selecting options for a backup of this feature
sub feature_backup_opts
{
local ($opts) = @_;
if (-d $archives_dir) {
return &ui_checkbox("virtualmin_mailman_archive", 1,
$text{'feat_archive'}, $opts->{'archive'});
}
else {
return undef;
}
}
# feature_backup_parse(&in)
# Return a hash reference of backup options, based on the given HTML inputs
sub feature_backup_parse
{
local ($in) = @_;
if (-d $archives_dir) {
return { 'archive' => $in->{'virtualmin_mailman_archive'} };
}
else {
return { };
}
}
# virtusers_ignore([&domain])
# Returns a list of virtuser addresses (like foo@bar.com) that are used by
# mailing lists.
sub virtusers_ignore
{
local ($d) = @_;
return ( ) if ($config{'mode'} == 0);
local @rv;
foreach my $l (&list_lists()) {
if ($d && $l->{'dom'} eq $d->{'dom'} ||
!$d && $l->{'dom'}) {
my $short_list = $l->{'list'};
$short_list =~ s/_\Q$l->{'dom'}\E$//;
push(@rv, $l->{'list'}."\@".$l->{'dom'});
push(@rv, $short_list."\@".$l->{'dom'});
foreach my $a (@mailman_aliases) {
push(@rv, $l->{'list'}."-".$a."\@".$l->{'dom'});
push(@rv, $short_list."-".$a."\@".$l->{'dom'});
}
}
}
return @rv;
}
# template_input(&template)
# Returns HTML for editing per-template options for this plugin
sub template_input
{
local ($tmpl) = @_;
local $v = $tmpl->{$module_name."limit"};
$v = "none" if (!defined($v) && $tmpl->{'default'});
return &ui_table_row($text{'tmpl_limit'},
&ui_radio($input_name."_mode",
$v eq "" ? 0 : $v eq "none" ? 1 : 2,
[ $tmpl->{'default'} ? ( ) : ( [ 0, $text{'default'} ] ),
[ 1, $text{'tmpl_unlimit'} ],
[ 2, $text{'tmpl_atmost'} ] ])."\n".
&ui_textbox($input_name, $v eq "none" ? undef : $v, 10));
}
# template_parse(&template, &in)
# Updates the given template object by parsing the inputs generated by
# template_input. All template fields must start with the module name.
sub template_parse
{
local ($tmpl, $in) = @_;
if ($in->{$input_name.'_mode'} == 0) {
$tmpl->{$module_name."limit"} = "";
}
elsif ($in->{$input_name.'_mode'} == 1) {
$tmpl->{$module_name."limit"} = "none";
}
else {
$in->{$input_name} =~ /^\d+$/ || &error($text{'tmpl_elimit'});
$tmpl->{$module_name."limit"} = $in->{$input_name};
}
}
# setup_mailman_web_redirects(&domain)
# Configure Apache to support mailman CGIs for this domain
sub setup_mailman_web_redirects
{
&$virtual_server::first_print($text{'setup_alias'});
&virtual_server::require_apache();
&virtual_server::obtain_lock_web($_[0]);
local $conf = &apache::get_config();
local @ports = ( $_[0]->{'web_port'},
$_[0]->{'ssl'} ? ( $_[0]->{'web_sslport'} ) : ( ) );
local $added;
foreach my $p (@ports) {
local ($virt, $vconf) = &virtual_server::get_apache_virtual(
$_[0]->{'dom'}, $p);
next if (!$virt);
# Add lists.$domain alias, if in special Postfix mode
if ($config{'mode'} == 0) {
local @sa = &apache::find_directive("ServerAlias",
$vconf);
push(@sa, "lists.$_[0]->{'dom'}");
&apache::save_directive("ServerAlias",
\@sa, $vconf, $conf);
}
# Add wrapper redirects
local @rm = &apache::find_directive("RedirectMatch", $vconf);
local $webminurl = &get_mailman_webmin_url($_[0]);
foreach my $p ("/cgi-bin/mailman", "/mailman") {
local ($already) = grep { /^\Q$p\E\// } @rm;
if (!$already) {
push(@rm, "$p/([^/\\.]*)(.cgi)?(.*) ".
"$webminurl/$module_name/".
"unauthenticated/\$1.cgi\$3");
}
}
&apache::save_directive("RedirectMatch", \@rm, $vconf, $conf);
$added++;
# Add alias from /pipermail to archives directory
local @al = &apache::find_directive("Alias", $vconf);
local ($already) = grep { /^\/pipermail\s/ } @al;
if (!$already) {
push(@al, "/pipermail $archives_dir/public");
&apache::save_directive("Alias", \@al, $vconf, $conf);
}
}
if ($added) {
&flush_file_lines();
&virtual_server::register_post_action(
defined(&main::restart_apache) ? \&main::restart_apache
: \&virtual_server::restart_apache);
&$virtual_server::second_print(
$virtual_server::text{'setup_done'});
}
else {
&$virtual_server::second_print(
$virtual_server::text{'delete_noapache'});
}
&virtual_server::release_lock_web($_[0]);
# Add the apache user to the mailman group, so that symlinks work
my $auser = &virtual_server::get_apache_user($_[0]);
my @st = stat("$archives_dir/public");
if ($auser && @st) {
&virtual_server::obtain_lock_unix($_[0]);
my ($group) = grep { $_->{'gid'} == $st[5] }
&virtual_server::list_all_groups();
if ($group) {
my @mems = split(/,/, $group->{'members'});
if (&indexof($auser, @mems) < 0) {
my $oldgroup = { %$group };
$group->{'members'} = join(",", @mems, $auser);
&foreign_call($group->{'module'},
"set_group_envs", $group,
'MODIFY_GROUP', $oldgroup);
&foreign_call($group->{'module'},
"making_changes");
&foreign_call($group->{'module'},
"modify_group", $oldgroup, $group);
&foreign_call($group->{'module'},
"made_changes");
}
}
&virtual_server::release_lock_unix($_[0]);
}
}
1;
y~or5J={Eeu磝Qk ᯘG{?+]ן?wM3X^歌>{7پK>on\jy Rg/=fOroNVv~Y+ NGuÝHWyw[eQʨSb> >}Gmx[o[<{Ϯ_qFvM IENDB`