#!/usr/local/bin/perl # Modifies a virtual domain, based on command-line parameters package virtual_server; if (!$module_name) { $main::no_acl_check++; $ENV{'WEBMIN_CONFIG'} ||= "/etc/webmin"; $ENV{'WEBMIN_VAR'} ||= "/var/webmin"; if ($0 =~ /^(.*\/)[^\/]+$/) { chdir($1); } chop($pwd = `pwd`); $0 = "$pwd/modify-domain.pl"; require './virtual-server-lib.pl'; $< == 0 || die "modify-domain.pl must be run as root"; } $first_print = \&first_text_print; $second_print = \&second_text_print; # Parse command-line args $name = 1; $virt = 0; while(@ARGV > 0) { local $a = shift(@ARGV); if ($a eq "--domain") { $domain = lc(shift(@ARGV)); } elsif ($a eq "--desc") { $owner = shift(@ARGV); $owner =~ /:/ && &usage($text{'setup_eowner'}); } elsif ($a eq "--pass") { $pass = shift(@ARGV); } elsif ($a eq "--email") { $email = shift(@ARGV); } elsif ($a eq "--quota") { $quota = shift(@ARGV); $quota =~ /^\d+$/ || &usage("Quota must be a number of blocks"); } elsif ($a eq "--uquota") { $uquota = shift(@ARGV); $uquota =~ /^\d+$/ ||&usage("Quota must be a number of blocks"); } elsif ($a eq "--user") { $user = shift(@ARGV); $user =~ /^[^\t :]+$/ || &usage($text{'setup_euser2'}); defined(getpwnam($user)) && &usage("A user named $user already exists"); } elsif ($a eq "--home") { $home = shift(@ARGV); $home =~ /^\/\S+$/ || &usage("Home directory must be an absolute path"); -d $home || &usage("New home directory already exists"); } elsif ($a eq "--newdomain") { $newdomain = shift(@ARGV); $newdomain =~ /^[A-Za-z0-9\.\-]+$/ || &usage("Invalid new domain name"); $newdomain = lc($newdomain); foreach $d (&list_domains()) { if (lc($d->{'dom'}) eq $newdomain) { &usage("A domain called $newdomain already exists"); } } } elsif ($a eq "--bw") { # Setting or removing the bandwidth limit $bw = shift(@ARGV); $bw eq "NONE" || $bw =~ /^\d+$/ || &usage("Bandwidth limit must be a number of bytes, or NONE"); } elsif ($a eq "--bw-disable") { # Set over-bw limit disable to yes $bw_no_disable = 0; } elsif ($a eq "--bw-no-disable") { # Set over-bw limit disable to no $bw_no_disable = 1; } elsif ($a eq "--ip") { # Changing or adding a virtual IP $ip = shift(@ARGV); &check_ipaddress($ip) || &usage("Invalid IP address"); } elsif ($a eq "--shared-ip") { # Changing the shared IP $sharedip = shift(@ARGV); &check_ipaddress($sharedip) || &usage("Invalid shared IP address"); } elsif ($a eq "--allocate-ip") { # Allocating an IP $ip = "allocate"; } elsif ($a eq "--reseller") { # Changing the reseller $resel = shift(@ARGV); } elsif ($a eq "--prefix") { # Changing the prefix $prefix = shift(@ARGV); } elsif ($a eq "--template") { # Changing the template $templatename = shift(@ARGV); foreach $t (&list_templates()) { if ($t->{'name'} eq $templatename || $t->{'id'} eq $templatename) { $template = $t->{'id'}; } } $template eq "" && &usage("Unknown template name"); } elsif ($a eq "--add-exclude") { push(@add_excludes, shift(@ARGV)); } elsif ($a eq "--remove-exclude") { push(@remove_excludes, shift(@ARGV)); } else { usage(); } } # Find the domain $domain || usage(); $dom = &get_domain_by("dom", $domain); $dom || usage("Virtual server $domain does not exist."); $old = { %$dom }; $tmpl = &get_template(defined($template) ? $template : $dom->{'template'}); # Make sure options are valid for domain if ($dom->{'parent'}) { defined($user) && &usage("The username cannot be changed for a sub-domain"); defined($pass) && &usage("The password cannot be changed for a sub-domain"); (defined($quota) || defined($uquota)) && &usage("Quotas cannot be changed for a sub-domain"); } if ($ip && $dom->{'alias'}) { &usage("An IP address cannot be added to a virtual domain"); } if ($dom->{'virt'} && $ip eq "allocate") { &usage("An IP address cannot be allocated when one is already active"); } elsif (!$dom->{'virt'} && $ip eq "allocate") { $config{'all_namevirtual'} && &usage("The --allocate-ip option cannot be used when all virtual servers are name-based"); %racl = $d->{'reseller'} ? &get_reseller_acl($d->{'reseller'}) : ( ); if ($racl{'ranges'}) { # Allocating IP from reseller's ranges $ip = &free_ip_address(\%racl); $ip || &usage("Failed to allocate IP address from reseller's ranges!"); } else { # Allocating from template's ranges $tmpl->{'ranges'} eq "none" && &usage("The --allocate-ip option cannot be used unless automatic IP allocation is enabled - use --ip instead"); $ip = &free_ip_address($tmpl); $ip || &usage("Failed to allocate IP address from ranges!"); } } if ($dom->{'virt'} && defined($sharedip)) { &usage("The shared IP address cannot be changed for a virtual server with a private IP"); } if (defined($resel)) { $dom->{'parent'} && &usage("Reseller cannot be set for a sub-server"); @resels = &list_resellers(); ($rinfo) = grep { $_->{'name'} eq $resel } @resels; $resel eq "NONE" || $rinfo || &usage("Reseller $resel not found"); } if (defined($prefix)) { $dom->{'alias'} && &usage("Prefix cannot be changed for alias domains"); @users = &list_domain_users($dom, 1, 1, 1, 1); @users && &usage("Prefix cannot be changed for virtual servers with existing mailbox users"); $prefix =~ /^[a-z0-9\.\-]+$/i || &usage($text{'setup_eprefix'}); if ($prefix ne $dom->{'prefix'}) { $pclash = &get_domain_by("prefix", $prefix); $pclash && &usage($text{'setup_eprefix2'}); } } if (defined($template)) { if ($dom->{'parent'} && !$dom->{'alias'} && !$tmpl->{'for_sub'}) { &usage("The selected template cannot be used for sub-servers"); } elsif (!$dom->{'parent'} && !$tmpl->{'for_parent'}) { &usage("The selected template cannot be used for top-level servers"); } elsif ($dom->{'alias'} && !$tmpl->{'for_alias'}) { &usage("The selected template cannot be used for alias servers"); } $dom->{'template'} = $template; } # Find all other domains to be changed @doms = ( $dom ); @olddoms = ( $old ); foreach $sdom (&get_domain_by("parent", $dom->{'id'})) { $oldsdom = { %$sdom }; push(@doms, $sdom); push(@olddoms, $oldsdom); } # Make the changes to the domain objects if (defined($owner)) { $dom->{'owner'} = $owner; } if (defined($prefix)) { $dom->{'prefix'} = $prefix; } if (defined($pass)) { foreach $d (@doms) { if ($d->{'disabled'}) { # Clear any saved passwords, as they should # be reset at this point $d->{'disabled_mysqlpass'} = undef; $d->{'disabled_postgrespass'} = undef; } $d->{'pass'} = $pass; $d->{'pass_set'} = 1; } } if (defined($email)) { foreach $d (@doms) { $d->{'email'} = $email; } } if (defined($quota)) { $dom->{'quota'} = $quota; } if (defined($uquota)) { $dom->{'uquota'} = $uquota; } if (defined($user)) { foreach $d (@doms) { $d->{'user'} = $user; } } if (defined($home)) { foreach $d (@doms) { local $k; foreach $k (keys %$d) { $d->{$k} =~ s/$old->{'home'}/$home/g; } } } if (defined($newdomain)) { $dom->{'dom'} = $newdomain; } if (defined($bw)) { $dom->{'bw_limit'} = $bw eq "none" ? undef : $bw; } if (defined($bw_no_disable)) { $dom->{'bw_no_disable'} = $bw_no_disable; } if (defined($ip)) { # Just change the IP $dom->{'ip'} = $ip; delete($dom->{'dns_ip'}); if (!$config{'all_namevirtual'}) { $dom->{'virt'} = 1; $dom->{'name'} = 0; $dom->{'virtalready'} = 0; } } if (defined($sharedip)) { # Just change the shared IP address $dom->{'ip'} = $sharedip; } if (defined($resel)) { $dom->{'reseller'} = $resel eq "NONE" ? undef : $resel; } # Apply the IP change if ($dom->{'virt'} && !$old->{'virt'}) { &setup_virt($dom); } elsif ($dom->{'virt'} && $old->{'virt'}) { &modify_virt($dom, $dom); } # Actually update the domains for(my $i=0; $i<@doms; $i++) { $d = $doms[$i]; $od = $olddoms[$i]; print "Updating virtual server $d->{'dom'} ..\n\n"; foreach $f (@features) { if ($config{$f} && $d->{$f}) { local $mfunc = "modify_$f"; &try_function($f, $mfunc, $d, $od); } } foreach $f (@feature_plugins) { if ($d->{$f}) { &plugin_call($f, "feature_modify", $d, $od); } } # Save new domain details &$first_print($text{'save_domain'}); &save_domain($d); &$second_print($text{'setup_done'}); } # Apply exclude changes if (@add_excludes || @remove_excludes) { &$first_print("Updating excluded directories .."); @excludes = &get_backup_excludes($dom); push(@excludes, @add_excludes); %remove_excludes = map { $_, 1 } @remove_excludes; @excludes = grep { !$remove_excludes{$_} } @excludes; @excludes = &unique(@excludes); &save_backup_excludes($dom, \@excludes); &$second_print($text{'setup_done'}); } &refresh_webmin_user($dom); # Run the after command &run_post_actions(); &set_domain_envs($d, "MODIFY_DOMAIN"); &made_changes(); &reset_domain_envs($d); print "All done\n"; sub usage { print $_[0],"\n\n" if ($_[0]); print "Changes the settings for a Virtualmin server, based on the specified\n"; print "command-line parameters.\n"; print "\n"; print "usage: modify-domain.pl --domain domain.name\n"; print " [--desc new-description]\n"; print " [--user new-username]\n"; print " [--pass new-password]\n"; print " [--email new-email]\n"; print " [--quota new-quota]\n"; print " [--uquota new-unix-quota]\n"; print " [--newdomain new-name]\n"; print " [--bw bytes|NONE]\n"; if ($config{'bw_disable'}) { print " [--bw-disable|--bw-no-disable]\n"; } print " [--resel reseller|NONE]\n"; print " [--ip address] | [--allocate-ip] |\n"; print " [--shared-ip address]\n"; print " [--prefix name]\n"; print " [--template name|id]\n"; print " [--add-exclude directory]*\n"; print " [--remove-exclude directory]*\n"; exit(1); }