mirror of
https://github.com/webmin/webmin.git
synced 2026-03-14 14:32:15 +00:00
Merge branch 'master' of github.com:webmin/webmin
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
Some checks failed
webmin.dev: webmin/webmin / build (push) Has been cancelled
This commit is contained in:
727
bin/webmin
727
bin/webmin
@@ -1,408 +1,435 @@
|
||||
#!/usr/bin/env perl
|
||||
# Webmin CLI - Allows performing a variety of common Webmin-related
|
||||
# functions on the command line.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
BEGIN { $Pod::Usage::Formatter = 'Pod::Text::Color'; }
|
||||
use 5.010; # Version in CentOS 6
|
||||
use Getopt::Long qw(:config permute pass_through);
|
||||
use 5.010;
|
||||
use Getopt::Long qw(:config no_ignore_case permute pass_through);
|
||||
use Term::ANSIColor qw(:constants);
|
||||
use Pod::Usage;
|
||||
|
||||
# Check if root
|
||||
if ($> != 0) {
|
||||
die BRIGHT_RED, "Error: ", RESET, BRIGHT_YELLOW,"webmin", RESET,
|
||||
" command must be run as root\n";
|
||||
exit 1;
|
||||
}
|
||||
die BRIGHT_RED,
|
||||
"Error: ", RESET, BRIGHT_YELLOW,"webmin", RESET,
|
||||
" command must be run as root\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $a0 = $ARGV[0];
|
||||
|
||||
sub main {
|
||||
my ( %opt, $subcmd );
|
||||
GetOptions(
|
||||
'help|h' => \$opt{'help'},
|
||||
'config|c=s' => \$opt{'config'},
|
||||
'list-commands|l' => \$opt{'list'},
|
||||
'describe|d' => \$opt{'describe'},
|
||||
'man|m' => \$opt{'man'},
|
||||
'version|v' => \$opt{'version'},
|
||||
'versions' => \$opt{'versions'},
|
||||
'<>' => sub {
|
||||
# Handle unrecognized options, inc. subcommands.
|
||||
my($arg) = @_;
|
||||
if ($arg =~ m{^-}) {
|
||||
say "Usage error: Unknown option $arg.";
|
||||
pod2usage(0);
|
||||
} else {
|
||||
# It must be a subcommand.
|
||||
$subcmd = $arg;
|
||||
die "!FINISH";
|
||||
}
|
||||
}
|
||||
);
|
||||
sub main
|
||||
{
|
||||
my ( %opt, $subcmd );
|
||||
GetOptions(
|
||||
'help|h' => \$opt{'help'},
|
||||
'config|c=s' => \$opt{'config'},
|
||||
'list-commands|l' => \$opt{'list'},
|
||||
'describe|d' => \$opt{'describe'},
|
||||
'man|m' => \$opt{'man'},
|
||||
'version|v' => \$opt{'version'},
|
||||
'versions|V' => \$opt{'versions'},
|
||||
'<>' => sub {
|
||||
# Handle unrecognized options, inc. subcommands.
|
||||
my($arg) = @_;
|
||||
if ($arg =~ m{^-}) {
|
||||
say "Usage error: Unknown option $arg.";
|
||||
pod2usage(0);
|
||||
}
|
||||
else {
|
||||
# It must be a subcommand.
|
||||
$subcmd = $arg;
|
||||
die "!FINISH";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# Set defaults
|
||||
$opt{'config'} ||= "/etc/webmin";
|
||||
$opt{'commands'} = $a0;
|
||||
|
||||
# Load libs
|
||||
loadlibs(\%opt);
|
||||
# Set defaults
|
||||
$opt{'config'} ||= "/etc/webmin";
|
||||
$opt{'commands'} = $a0;
|
||||
|
||||
my @remain = @ARGV;
|
||||
# List commands?
|
||||
if ($opt{'list'}) {
|
||||
list_commands(\%opt);
|
||||
exit 0;
|
||||
} elsif ($opt{'version'} || $opt{'versions'}) {
|
||||
# Load libs
|
||||
my $ver_checked = sub {
|
||||
my ($ver_remote, $ver_curr) = @_;
|
||||
if ($ver_remote && $ver_curr &&
|
||||
compare_version_numbers($ver_remote, $ver_curr) > 0 ) {
|
||||
return (BRIGHT_RED, $ver_curr, RESET, DARK, " (" . RESET, BRIGHT_GREEN, $ver_remote, RESET, DARK . " is available)", RESET);
|
||||
} else {
|
||||
return GREEN, $ver_curr, RESET;
|
||||
}
|
||||
};
|
||||
my $print_mod_vers = sub {
|
||||
my ($module_type, $modules_list, $prod_root, $prod_ver, $versions_remote_local) = @_;
|
||||
my @minfo;
|
||||
if (ref($modules_list)) {
|
||||
my $head;
|
||||
my @modules_list = sort(@{$modules_list});
|
||||
foreach my $mod (@modules_list) {
|
||||
my %mod_info;
|
||||
read_file($mod, \%mod_info);
|
||||
my $mod_ver = $mod_info{'version_actual'} || $mod_info{'version'};
|
||||
my $mod_desc = $mod_info{'desc'};
|
||||
if ($mod_ver && $prod_ver && $mod_desc && $prod_ver !~ /^$mod_ver/) {
|
||||
say CYAN, " $module_type: ", RESET if (!$head++);
|
||||
my ($mod_dir) = $mod =~ m/$prod_root\/(.*?)\//;
|
||||
push(@minfo, {'desc' => $mod_desc, 'ver' => $mod_ver, 'dir' => $mod_dir});
|
||||
}
|
||||
}
|
||||
@minfo = sort { $a->{'desc'} cmp $b->{'desc'} } @minfo;
|
||||
foreach my $mod (@minfo) {
|
||||
say " $mod->{'desc'}: " , &$ver_checked($versions_remote_local->{$mod->{'dir'}}, $mod->{'ver'}), DARK " [$mod->{'dir'}]", RESET;
|
||||
}
|
||||
}
|
||||
};
|
||||
# Load libs
|
||||
loadlibs(\%opt);
|
||||
|
||||
my $root = root($opt{'config'});
|
||||
if ($root && -d $root) {
|
||||
require("$root/web-lib-funcs.pl");
|
||||
|
||||
# Try to get remote versions first
|
||||
my %versions_remote;
|
||||
if ($opt{'versions'}) {
|
||||
my ($latest_known_versions_remote, $latest_known_versions_remote_error);
|
||||
http_download("virtualmin.com", 443, '/software-latest',
|
||||
\$latest_known_versions_remote, \$latest_known_versions_remote_error,
|
||||
undef, 1, undef, undef, 5);
|
||||
if ($latest_known_versions_remote &&
|
||||
!$latest_known_versions_remote_error) {
|
||||
%versions_remote = map {
|
||||
my ($k, $v) = split(/=/, $_, 2);
|
||||
defined($v) ? ($k => $v) : ();
|
||||
} split(/\n/, $latest_known_versions_remote);
|
||||
} elsif ($latest_known_versions_remote_error) {
|
||||
say BRIGHT_YELLOW, "Warning: ", RESET, "Cannot fetch remote packages versions list - $latest_known_versions_remote_error";
|
||||
}
|
||||
}
|
||||
|
||||
# Get Webmin version installed
|
||||
my $ver1 = "$root/version";
|
||||
my $ver2 = "$opt{'config'}/version";
|
||||
my $ver = read_file_contents($ver1) || read_file_contents($ver2);
|
||||
my $verrel_file = "$root/release";
|
||||
my $verrel = -r $verrel_file ? read_file_contents($verrel_file) : "";
|
||||
if ($verrel) {
|
||||
$verrel = ":@{[trim($verrel)]}";
|
||||
}
|
||||
$ver = trim($ver);
|
||||
if ($ver) {
|
||||
if ($opt{'version'}) {
|
||||
say "$ver$verrel";
|
||||
exit 0;
|
||||
} else {
|
||||
say CYAN, "Webmin: ", RESET, &$ver_checked($versions_remote{'webmin'}, "$ver$verrel"), DARK " [$root]", RESET;
|
||||
}
|
||||
} else {
|
||||
say RED, "Error: ", RESET, "Cannot determine Webmin version";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Get other Webmin themes/modules versions if available
|
||||
my ($dir, @themes, @mods);
|
||||
if (opendir($dir, $root)) {
|
||||
while (my $file = readdir($dir)) {
|
||||
my $theme_info_file = "$root/$file/theme.info";
|
||||
push(@themes, $theme_info_file)
|
||||
if (-r $theme_info_file);
|
||||
my @remain = @ARGV;
|
||||
# List commands?
|
||||
if ($opt{'list'}) {
|
||||
list_commands(\%opt);
|
||||
exit 0;
|
||||
}
|
||||
elsif ($opt{'version'} || $opt{'versions'}) {
|
||||
# Load libs
|
||||
my $print_mod_vers = sub {
|
||||
my ($module_type, $modules_list, $prod_root, $prod_ver) = @_;
|
||||
return if (!ref($modules_list));
|
||||
# Gather module info
|
||||
my @mods;
|
||||
foreach my $mod (@{$modules_list}) {
|
||||
my %mi;
|
||||
read_file($mod, \%mi);
|
||||
my $ver = $mi{'version'};
|
||||
my ($dir) = $mod =~ m/$prod_root\/(.*?)\//;
|
||||
next if (!$ver || !$mi{'desc'} || !$dir);
|
||||
next if ($prod_ver =~ /^\Q$ver\E/);
|
||||
push(@mods, { desc => $mi{'desc'}, ver => $ver,
|
||||
dir => $dir });
|
||||
}
|
||||
# Print sorted by description
|
||||
my $head;
|
||||
foreach my $m (sort { $a->{'desc'} cmp $b->{'desc'} } @mods) {
|
||||
my $mod_ver = $m->{'ver'};
|
||||
if (-r "$prod_root/$m->{'dir'}/module.info") {
|
||||
eval { no warnings 'once';
|
||||
local $main::error_must_die = 1;
|
||||
&foreign_require($m->{'dir'}) };
|
||||
# Get module edition if available
|
||||
my $ed;
|
||||
$ed = eval { &foreign_call(
|
||||
$m->{'dir'},
|
||||
"get_module_edition")
|
||||
} if (&foreign_defined($m->{'dir'},
|
||||
"get_module_edition"));
|
||||
$mod_ver .= " $ed" if ($ed);
|
||||
}
|
||||
say CYAN, " $module_type: ", RESET if (!$head++);
|
||||
say " $m->{'desc'}: ", GREEN, $mod_ver, RESET,
|
||||
DARK " [$m->{'dir'}]", RESET;
|
||||
}
|
||||
};
|
||||
|
||||
my $mod_info_file = "$root/$file/module.info";
|
||||
push(@mods, $mod_info_file)
|
||||
if (-r $mod_info_file);
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
&$print_mod_vers('Themes', \@themes, $root, $ver, \%versions_remote);
|
||||
&$print_mod_vers('Modules', \@mods, $root, $ver, \%versions_remote);
|
||||
my $root = root($opt{'config'});
|
||||
if ($root && -d $root) {
|
||||
$ENV{'WEBMIN_CONFIG'} = $opt{'config'};
|
||||
no warnings 'once';
|
||||
@main::root_directories = ($root);
|
||||
$main::root_directory = $root;
|
||||
*unique = sub { my %seen; grep { !$seen{$_}++ } @_ }
|
||||
if (!defined(&unique));
|
||||
use warnings;
|
||||
require("$root/web-lib-funcs.pl");
|
||||
|
||||
# Get Webmin version installed
|
||||
my $ver1 = "$root/version";
|
||||
my $ver2 = "$opt{'config'}/version";
|
||||
my $ver = read_file_contents($ver1) ||
|
||||
read_file_contents($ver2);
|
||||
my $verrel_file = "$root/release";
|
||||
my $verrel = -r $verrel_file
|
||||
? read_file_contents($verrel_file) : "";
|
||||
if ($verrel) {
|
||||
$verrel = ":@{[trim($verrel)]}";
|
||||
}
|
||||
$ver = trim($ver);
|
||||
if ($ver) {
|
||||
if ($opt{'version'}) {
|
||||
say "$ver$verrel";
|
||||
exit 0;
|
||||
}
|
||||
else {
|
||||
say CYAN, "Webmin: ", RESET, GREEN,
|
||||
"$ver$verrel", RESET,
|
||||
DARK " [$root]", RESET;
|
||||
}
|
||||
}
|
||||
else {
|
||||
say RED, "Error: ", RESET,
|
||||
"Cannot determine Webmin version";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
# Get other Webmin themes/modules versions if available
|
||||
my ($dir, @themes, @mods);
|
||||
if (opendir($dir, $root)) {
|
||||
while (my $file = readdir($dir)) {
|
||||
my $theme_info_file =
|
||||
"$root/$file/theme.info";
|
||||
push(@themes, $theme_info_file)
|
||||
if (-r $theme_info_file);
|
||||
my $mod_info_file = "$root/$file/module.info";
|
||||
push(@mods, $mod_info_file)
|
||||
if (-r $mod_info_file);
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
&$print_mod_vers('Themes', \@themes, $root, $ver);
|
||||
&$print_mod_vers('Modules', \@mods, $root, $ver);
|
||||
|
||||
# Check for Usermin
|
||||
my $wmumconfig = "$opt{'config'}/usermin/config";
|
||||
if (-r $wmumconfig) {
|
||||
my %wmumconfig;
|
||||
read_file($wmumconfig, \%wmumconfig);
|
||||
# Check for Usermin
|
||||
my $wmumconfig = "$opt{'config'}/usermin/config";
|
||||
if (-r $wmumconfig) {
|
||||
my %wmumconfig;
|
||||
read_file($wmumconfig, \%wmumconfig);
|
||||
|
||||
# Usermin config dir
|
||||
$wmumconfig = $wmumconfig{'usermin_dir'};
|
||||
if ($wmumconfig) {
|
||||
my %uminiserv;
|
||||
read_file("$wmumconfig/miniserv.conf", \%uminiserv);
|
||||
my $uroot = $uminiserv{'root'};
|
||||
# Usermin config dir
|
||||
$wmumconfig = $wmumconfig{'usermin_dir'};
|
||||
if ($wmumconfig) {
|
||||
my %uminiserv;
|
||||
read_file("$wmumconfig/miniserv.conf",
|
||||
\%uminiserv);
|
||||
my $uroot = $uminiserv{'root'};
|
||||
|
||||
# Get Usermin version installed
|
||||
if ($uroot && -d $uroot) {
|
||||
my $uver1 = "$uroot/version";
|
||||
my $uver2 = "$wmumconfig/version";
|
||||
my $uver = read_file_contents($uver1) || read_file_contents($uver2);
|
||||
my $uverrel_file = "$uroot/release";
|
||||
my $uverrel = -r $uverrel_file ? read_file_contents($uverrel_file) : "";
|
||||
if ($uverrel) {
|
||||
$uverrel = ":@{[trim($uverrel)]}";
|
||||
}
|
||||
$uver = trim($uver) . $uverrel;
|
||||
if ($uver) {
|
||||
say CYAN, "Usermin: ", RESET, &$ver_checked($versions_remote{'usermin'}, $uver), DARK " [$uroot]", RESET;
|
||||
my ($udir, @uthemes, @umods);
|
||||
if (opendir($udir, "$uroot")) {
|
||||
while (my $file = readdir($udir)) {
|
||||
my $theme_info_file = "$uroot/$file/theme.info";
|
||||
push(@uthemes, $theme_info_file)
|
||||
if (-r $theme_info_file);
|
||||
# Get Usermin version installed
|
||||
if ($uroot && -d $uroot) {
|
||||
my $uver1 = "$uroot/version";
|
||||
my $uver2 = "$wmumconfig/version";
|
||||
my $uver = read_file_contents($uver1) ||
|
||||
read_file_contents($uver2);
|
||||
my $uverrel_file = "$uroot/release";
|
||||
my $uverrel = -r $uverrel_file
|
||||
? read_file_contents($uverrel_file) : "";
|
||||
$uverrel = ":@{[trim($uverrel)]}" if ($uverrel);
|
||||
$uver = trim($uver) . $uverrel;
|
||||
if ($uver) {
|
||||
say CYAN, "Usermin: ", RESET, GREEN, $uver, RESET, DARK " [$uroot]", RESET;
|
||||
my ($udir, @uthemes, @umods);
|
||||
if (opendir($udir, "$uroot")) {
|
||||
while (my $file = readdir($udir)) {
|
||||
my $theme_info_file = "$uroot/$file/theme.info";
|
||||
push(@uthemes, $theme_info_file)
|
||||
if (-r $theme_info_file);
|
||||
|
||||
my $mod_info_file = "$uroot/$file/module.info";
|
||||
push(@umods, $mod_info_file)
|
||||
if (-r $mod_info_file);
|
||||
my $mod_info_file = "$uroot/$file/module.info";
|
||||
push(@umods, $mod_info_file)
|
||||
if (-r $mod_info_file);
|
||||
|
||||
}
|
||||
}
|
||||
closedir($udir);
|
||||
&$print_mod_vers('Themes', \@uthemes, $uroot, $uver, \%versions_remote);
|
||||
&$print_mod_vers('Modules', \@umods, $uroot, $uver, \%versions_remote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($udir);
|
||||
&$print_mod_vers('Themes', \@uthemes, $uroot, $uver);
|
||||
&$print_mod_vers('Modules', \@umods, $uroot, $uver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
elsif ($opt{'man'} || $opt{'help'} || !defined($remain[0])) {
|
||||
# Show the full manual page
|
||||
man_command(\%opt, $subcmd);
|
||||
exit 0;
|
||||
}
|
||||
elsif ($subcmd) {
|
||||
run_command( \%opt, $subcmd, \@remain );
|
||||
}
|
||||
|
||||
exit 0;
|
||||
} elsif ($opt{'man'} || $opt{'help'} || !defined($remain[0])) {
|
||||
# Show the full manual page
|
||||
man_command(\%opt, $subcmd);
|
||||
exit 0;
|
||||
} elsif ($subcmd) {
|
||||
run_command( \%opt, $subcmd, \@remain );
|
||||
}
|
||||
|
||||
exit 0;
|
||||
exit 0;
|
||||
}
|
||||
exit main( \@ARGV ) if !caller(0);
|
||||
|
||||
# run_command - Run a subcommand
|
||||
# $optref is a reference to an options object passed down from global options
|
||||
# like --help or a --config path.
|
||||
sub run_command {
|
||||
my ( $optref, $subcmd, $remainref ) = @_;
|
||||
sub run_command
|
||||
{
|
||||
my ( $optref, $subcmd, $remainref ) = @_;
|
||||
|
||||
# Load libs
|
||||
loadlibs($optref);
|
||||
# Load libs
|
||||
loadlibs($optref);
|
||||
|
||||
# Figure out the Webmin root directory
|
||||
my $root = root($optref->{'config'});
|
||||
# Figure out the Webmin root directory
|
||||
my $root = root($optref->{'config'});
|
||||
|
||||
my (@commands) = list_commands($optref);
|
||||
if (! grep( /^$subcmd$/, @commands ) ) {
|
||||
say RED, "Error: ", RESET, "Command \`$subcmd\` doesn't exist", RESET;
|
||||
exit 1;
|
||||
}
|
||||
my (@commands) = list_commands($optref);
|
||||
if (! grep( /^$subcmd$/, @commands ) ) {
|
||||
say RED, "Error: ", RESET, "Command \`$subcmd\` doesn't exist", RESET;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $command_path = get_command_path($root, $subcmd, $optref);
|
||||
|
||||
# Merge the options
|
||||
# Only handling config, right now...
|
||||
# XXX Should we do this with libraries instead of commands?
|
||||
# Maybe detect .pm for that possibility.
|
||||
my @allopts = ("--config", "$optref->{'config'}", @$remainref);
|
||||
# Run that binch
|
||||
system($command_path, @allopts);
|
||||
# Try to exit with the passed through exit code (rarely used, but
|
||||
# why not?)
|
||||
if ($? == -1) {
|
||||
say RED, "Error: ", RESET, "Failed to execute \`$command_path\`: $!";
|
||||
exit 1;
|
||||
} else {
|
||||
exit $? >> 8;
|
||||
}
|
||||
my $command_path = get_command_path($root, $subcmd, $optref);
|
||||
|
||||
# Merge the options
|
||||
my @allopts = ("--config", "$optref->{'config'}", @$remainref);
|
||||
# Run
|
||||
system($command_path, @allopts);
|
||||
# Try to exit with the passed through exit code (rarely used, but why not?)
|
||||
if ($? == -1) {
|
||||
say RED, "Error: ", RESET, "Failed to execute \`$command_path\`: $!";
|
||||
exit 1;
|
||||
}
|
||||
else {
|
||||
exit $? >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
sub get_command_path {
|
||||
my ($root, $subcmd, $optref) = @_;
|
||||
sub get_command_path
|
||||
{
|
||||
my ($root, $subcmd, $optref) = @_;
|
||||
|
||||
# Load libs
|
||||
loadlibs($optref);
|
||||
# Load libs
|
||||
loadlibs($optref);
|
||||
|
||||
# Check for a root-level command (in "$root/bin")
|
||||
my $command_path;
|
||||
if ($subcmd) {
|
||||
$command_path = File::Spec->catfile($root, 'bin', $subcmd);
|
||||
} else {
|
||||
$command_path = File::Spec->catfile($root, 'bin', 'webmin');
|
||||
}
|
||||
my $module_name;
|
||||
my $command;
|
||||
if ( -x $command_path) {
|
||||
$command = $command_path;
|
||||
} else {
|
||||
# Try to extract a module name from the command
|
||||
# Get list of directories
|
||||
opendir (my $DIR, $root);
|
||||
my @module_dirs = grep { -d "$root/$_" } readdir($DIR);
|
||||
# See if any of them are a substring of $subcmd
|
||||
for my $dir (@module_dirs) {
|
||||
if (index($subcmd, $dir) == 0) {
|
||||
$module_name = $dir;
|
||||
my $barecmd = substr($subcmd, -(length($subcmd)-length($module_name)-1));
|
||||
$command = File::Spec->catfile($root, $dir, 'bin', $barecmd);
|
||||
# Could be .pl or no extension
|
||||
if ( -x $command ) {
|
||||
last;
|
||||
} elsif ( -x $command . ".pl" ) {
|
||||
$command = $command . ".pl";
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($optref->{'commands'} &&
|
||||
$optref->{'commands'} =~ /^(stats|status|start|stop|restart|reload|force-restart|force-reload|kill)$/) {
|
||||
exit system("$0 server $optref->{'commands'}");
|
||||
} elsif ($command) {
|
||||
return $command;
|
||||
} else {
|
||||
die RED, "Unrecognized subcommand: $subcmd", RESET , "\n";
|
||||
}
|
||||
# Check for a root-level command (in "$root/bin")
|
||||
my $command_path;
|
||||
if ($subcmd) {
|
||||
$command_path = File::Spec->catfile($root, 'bin', $subcmd);
|
||||
}
|
||||
else {
|
||||
$command_path = File::Spec->catfile($root, 'bin', 'webmin');
|
||||
}
|
||||
|
||||
my $module_name;
|
||||
my $command;
|
||||
if ( -x $command_path) {
|
||||
$command = $command_path;
|
||||
}
|
||||
else {
|
||||
# Try to extract a module name from the command
|
||||
# Get list of directories
|
||||
opendir (my $DIR, $root);
|
||||
my @module_dirs = grep { -d "$root/$_" } readdir($DIR);
|
||||
closedir($DIR);
|
||||
# See if any of them are a substring of $subcmd
|
||||
for my $dir (@module_dirs) {
|
||||
if (index($subcmd, $dir) == 0) {
|
||||
$module_name = $dir;
|
||||
my $barecmd = substr($subcmd, -(length($subcmd)-length($module_name)-1));
|
||||
$command = File::Spec->catfile($root, $dir, 'bin', $barecmd);
|
||||
# Could be .pl or no extension
|
||||
if ( -x $command ) {
|
||||
last;
|
||||
}
|
||||
elsif ( -x $command . ".pl" ) {
|
||||
$command = $command . ".pl";
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($optref->{'commands'} &&
|
||||
$optref->{'commands'} =~ /^(stats|status|start|stop|restart|reload|force-restart|force-reload|kill)$/) {
|
||||
exit system("$0 server $optref->{'commands'}");
|
||||
}
|
||||
elsif ($command) {
|
||||
return $command;
|
||||
}
|
||||
else {
|
||||
die RED, "Unrecognized subcommand: $subcmd", RESET , "\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub list_commands {
|
||||
my ($optref) = @_;
|
||||
sub list_commands
|
||||
{
|
||||
my ($optref) = @_;
|
||||
|
||||
my $root = root($optref->{'config'});
|
||||
my @commands;
|
||||
my $root = root($optref->{'config'});
|
||||
my @commands;
|
||||
|
||||
# Find and list global commands
|
||||
for my $command (glob ("$root/bin/*")) {
|
||||
my ($bin, $path) = fileparse($command);
|
||||
if ($bin =~ "webmin") {
|
||||
next;
|
||||
}
|
||||
if ($optref->{'describe'}) {
|
||||
# Display name and description
|
||||
say YELLOW, "$bin", RESET;
|
||||
pod2usage( -verbose => 99,
|
||||
-sections => [ qw(DESCRIPTION) ],
|
||||
-input => $command,
|
||||
-exitval => "NOEXIT");
|
||||
} else {
|
||||
if (wantarray) {
|
||||
push(@commands, $bin);
|
||||
} else {
|
||||
# Just list the names
|
||||
say "$bin";
|
||||
}
|
||||
}
|
||||
}
|
||||
# Find and list global commands
|
||||
for my $command (glob ("$root/bin/*")) {
|
||||
my ($bin, $path) = fileparse($command);
|
||||
if ($bin =~ "webmin") {
|
||||
next;
|
||||
}
|
||||
if ($optref->{'describe'}) {
|
||||
# Display name and description
|
||||
say YELLOW, "$bin", RESET;
|
||||
pod2usage( -verbose => 99,
|
||||
-sections => [ qw(DESCRIPTION) ],
|
||||
-input => $command,
|
||||
-exitval => "NOEXIT");
|
||||
}
|
||||
else {
|
||||
if (wantarray) {
|
||||
push(@commands, $bin);
|
||||
}
|
||||
else {
|
||||
# Just list the names
|
||||
say "$bin";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @modules;
|
||||
# Find all module directories with something in bin
|
||||
for my $command (glob ("$root/*/bin/*")) {
|
||||
my ($bin, $path) = fileparse($command);
|
||||
my $module = (split /\//, $path)[-2];
|
||||
if ($optref->{'describe'}) {
|
||||
# Display name and description
|
||||
say YELLOW, "$module-$bin", RESET;
|
||||
pod2usage( -verbose => 99,
|
||||
-sections => [ qw(DESCRIPTION) ],
|
||||
-input => $command,
|
||||
-exitval => "NOEXIT");
|
||||
} else {
|
||||
if (wantarray) {
|
||||
push(@modules, "$module-$bin");
|
||||
} else {
|
||||
# Just list the names
|
||||
say "$module-$bin";
|
||||
}
|
||||
}
|
||||
}
|
||||
my @modules;
|
||||
# Find all module directories with something in bin
|
||||
for my $command (glob ("$root/*/bin/*")) {
|
||||
my ($bin, $path) = fileparse($command);
|
||||
my $module = (split /\//, $path)[-2];
|
||||
if ($optref->{'describe'}) {
|
||||
# Display name and description
|
||||
say YELLOW, "$module-$bin", RESET;
|
||||
pod2usage( -verbose => 99,
|
||||
-sections => [ qw(DESCRIPTION) ],
|
||||
-input => $command,
|
||||
-exitval => "NOEXIT");
|
||||
}
|
||||
else {
|
||||
if (wantarray) {
|
||||
push(@modules, "$module-$bin");
|
||||
}
|
||||
else {
|
||||
# Just list the names
|
||||
say "$module-$bin";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wantarray) {
|
||||
return (@commands, @modules);
|
||||
}
|
||||
if (wantarray) {
|
||||
return (@commands, @modules);
|
||||
}
|
||||
}
|
||||
|
||||
# Display either a short usage message (--help) or a full manual (--man)
|
||||
sub man_command {
|
||||
my ($optref, $subcmd) = @_;
|
||||
sub man_command
|
||||
{
|
||||
my ($optref, $subcmd) = @_;
|
||||
|
||||
my $root = root($optref->{'config'});
|
||||
my $command_path = get_command_path($root, $subcmd, $optref);
|
||||
my $root = root($optref->{'config'});
|
||||
my $command_path = get_command_path($root, $subcmd, $optref);
|
||||
|
||||
$ENV{'PAGER'} ||= "more";
|
||||
open(my $PAGER, "|-", "$ENV{'PAGER'}");
|
||||
if ($optref->{'help'}) {
|
||||
pod2usage( -input => $command_path );
|
||||
} else {
|
||||
pod2usage( -verbose => 99,
|
||||
-input => $command_path,
|
||||
-output => $PAGER);
|
||||
}
|
||||
$ENV{'PAGER'} ||= "more";
|
||||
open(my $PAGER, "|-", "$ENV{'PAGER'}");
|
||||
if ($optref->{'help'}) {
|
||||
pod2usage( -input => $command_path );
|
||||
}
|
||||
else {
|
||||
pod2usage( -verbose => 99,
|
||||
-input => $command_path,
|
||||
-output => $PAGER);
|
||||
}
|
||||
close($PAGER);
|
||||
}
|
||||
|
||||
sub root {
|
||||
my ($config) = @_;
|
||||
open(my $CONF, "<", "$config/miniserv.conf") || die RED,
|
||||
"Failed to open $config/miniserv.conf", RESET , "\n";
|
||||
my $root;
|
||||
while (<$CONF>) {
|
||||
if (/^root=(.*)/) {
|
||||
$root = $1;
|
||||
}
|
||||
}
|
||||
close($CONF);
|
||||
# Does the Webmin root exist?
|
||||
if ( $root ) {
|
||||
die "$root is not a directory. Is --config correct?\n" unless (-d $root);
|
||||
} else {
|
||||
die "Unable to determine Webmin installation directory from $ENV{'WEBMIN_CONFIG'}\n";
|
||||
}
|
||||
sub root
|
||||
{
|
||||
my ($config) = @_;
|
||||
open(my $CONF, "<", "$config/miniserv.conf") ||
|
||||
die RED, "Failed to open $config/miniserv.conf", RESET , "\n";
|
||||
my $root;
|
||||
while (<$CONF>) {
|
||||
if (/^root=(.*)/) {
|
||||
$root = $1;
|
||||
}
|
||||
}
|
||||
close($CONF);
|
||||
|
||||
return $root;
|
||||
# Does the Webmin root exist?
|
||||
if ( $root ) {
|
||||
die "$root is not a directory. Is --config correct?\n" unless (-d $root);
|
||||
}
|
||||
else {
|
||||
die "Unable to determine Webmin installation directory ".
|
||||
"from $ENV{'WEBMIN_CONFIG'}\n";
|
||||
}
|
||||
|
||||
return $root;
|
||||
}
|
||||
|
||||
# loadlibs - Load libraries from the Webmin vendor dir
|
||||
# as those may not be installed as dependency, because
|
||||
# Webmin already provides them from package manager
|
||||
# perspective.
|
||||
sub loadlibs {
|
||||
my ($optref) = @_;
|
||||
$optref->{'config'} ||= "/etc/webmin";
|
||||
my $root = root($optref->{'config'});
|
||||
my $libroot = "$root/vendor_perl";
|
||||
eval "use lib '$libroot'";
|
||||
eval "use File::Basename";
|
||||
eval "use File::Spec";
|
||||
sub loadlibs
|
||||
{
|
||||
my ($optref) = @_;
|
||||
$optref->{'config'} ||= "/etc/webmin";
|
||||
my $root = root($optref->{'config'});
|
||||
my $libroot = "$root/vendor_perl";
|
||||
eval "use lib '$libroot'";
|
||||
eval "use File::Basename";
|
||||
eval "use File::Spec";
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -462,7 +489,7 @@ Returns Webmin and other modules and themes versions installed (only those for w
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 2018 Jamie Cameron <jcameron@webmin.com>
|
||||
Joe Cooper <joe@virtualmin.com>
|
||||
Ilia Ross <ilia@virtualmin.com>
|
||||
Copyright 2018 Jamie Cameron <jamie@webmin.com>
|
||||
Joe Cooper <joe@virtualmin.com>
|
||||
Ilia Ross <ilia@virtualmin.com>
|
||||
|
||||
|
||||
@@ -504,11 +504,7 @@ acl_sysinfo=Show available disk data on Dashboard?
|
||||
|
||||
sysinfo_total=Total
|
||||
sysinfo_dev=Device ID
|
||||
<<<<<<< HEAD
|
||||
sysinfo_smalltmp=Warning! The filesystem $2 which contains the Webmin temp files directory $1 has a size of only $4, which is less than the recommended minimum of $3 for temporary and backup files. Consider switching the temp files location to a different directory in the <a href='$5'>Webmin Configuration</a> module.
|
||||
sysinfo_ramtmp=Warning! The filesystem $2 which contains the Webmin temp files directory $1 is mounted from a <tt>tmpfs</tt> RAM disk, which may be too small for temporary and backup files. Consider switching the temp files location to a different directory in the <a href='$3'>Webmin Configuration</a> module.
|
||||
=======
|
||||
sysinfo_smalltmp=The filesystem $2 which contains the Webmin temp files directory $1 has a size of only $4, which is less than the recommended minimum of $3 for temporary and backup files. Consider switching the temp files location to a different directory in the <a href='$5'>Webmin Configuration</a> module.
|
||||
>>>>>>> 3354a0cc2fa31610b76563f3baa444766d86b7e3
|
||||
sysinfo_ramtmp=The filesystem $2 which contains the Webmin temp files directory $1 is mounted from a <tt>tmpfs</tt> RAM disk, which may be too small for temporary and backup files. Consider switching the temp files location to a different directory in the <a href='$3'>Webmin Configuration</a> module.
|
||||
|
||||
__norefs=1
|
||||
|
||||
@@ -318,11 +318,12 @@ if (&has_command("zpool")) {
|
||||
|
||||
# Add up all local filesystems
|
||||
foreach my $m (@mounted) {
|
||||
my $tmp_is_tmpfs = $m->[0] eq "/tmp" && $m->[2] eq "tmpfs";
|
||||
if ($m->[2] =~ /^ext/ ||
|
||||
$m->[2] eq "reiserfs" || $m->[2] eq "ufs" || $m->[2] eq "f2fs" ||
|
||||
$m->[2] eq "zfs" || $m->[2] eq "simfs" || $m->[2] eq "vzfs" ||
|
||||
$m->[2] eq "xfs" || $m->[2] eq "jfs" || $m->[2] eq "btrfs" ||
|
||||
$m->[2] eq "apfs" || $m->[2] eq "fuseblk" ||
|
||||
$m->[2] eq "apfs" || $m->[2] eq "fuseblk" || $tmp_is_tmpfs ||
|
||||
$m->[1] =~ /^\/dev\// ||
|
||||
&indexof($m->[1], @$always) >= 0) {
|
||||
my $zp;
|
||||
@@ -333,13 +334,13 @@ foreach my $m (@mounted) {
|
||||
$zp = $zpools{$1};
|
||||
}
|
||||
if ($donedevice{$m->[0]}++ ||
|
||||
$donedevice{$m->[1]}++) {
|
||||
!$tmp_is_tmpfs && $donedevice{$m->[1]}++) {
|
||||
# Don't double-count mounts from the same device, or
|
||||
# on the same directory.
|
||||
next;
|
||||
}
|
||||
my @st = stat($m->[0]);
|
||||
if (@st && $donedevno{$st[0]}++) {
|
||||
if (!$tmp_is_tmpfs && @st && $donedevno{$st[0]}++) {
|
||||
# Don't double-count same filesystem by device number
|
||||
next;
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ my @rv = ({ 'type' => 'html',
|
||||
});
|
||||
|
||||
# Check if the filesystem the Webmin temp dir is on is too small
|
||||
if (&foreign_available("webmin")) {
|
||||
my $tmp = $gconfig{'tempdir'} || &default_webmin_temp_dir();
|
||||
if (!$gconfig{'tempdir'} && &foreign_available("webmin")) {
|
||||
my $tmp = &default_webmin_temp_dir();
|
||||
my $small = 10*1024*1024; # 10 MB
|
||||
my $url = &get_webprefix()."/webmin/edit_advanced.cgi";
|
||||
foreach my $disk (sort { length($b->{'dir'}) <=>
|
||||
|
||||
@@ -32,7 +32,8 @@ $miniserv{'twofactor_provider'} = $in{'twofactor_provider'};
|
||||
&put_miniserv_config(\%miniserv);
|
||||
&unlock_file($ENV{'MINISERV_CONFIG'});
|
||||
|
||||
$msg = $text{'restart_done'}."<p>\n";
|
||||
$msg = "";
|
||||
$msg .= $text{'restart_done'}."<p>\n" if ($gconfig{'restart_async'});
|
||||
if ($in{'twofactor_provider'}) {
|
||||
$msg .= &text('twofactor_enrolllink',
|
||||
"../acl/twofactor_form.cgi")."<p>\n";
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
require './webmin-lib.pl';
|
||||
|
||||
&show_restart_page($text{'blocked_title'}, $text{'blocked_restarting'});
|
||||
&show_restart_page($text{'blocked_title'},
|
||||
$gconfig{'restart_async'}
|
||||
? $text{'blocked_restarting'}
|
||||
: undef);
|
||||
|
||||
|
||||
|
||||
@@ -82,6 +82,10 @@ for(my $i=0; $i<@wlinks; $i++) {
|
||||
$i--;
|
||||
}
|
||||
}
|
||||
|
||||
print &ui_alert_box(&filter_javascript($in{'message'}), 'success', undef, 1,
|
||||
&html_escape($in{'title'})) if ($in{'message'});
|
||||
|
||||
&icons_table(\@wlinks, \@wtitles, \@wicons);
|
||||
|
||||
print &ui_hr();
|
||||
|
||||
@@ -994,7 +994,7 @@ cache_enone=None selected
|
||||
cache_efile=Invalid filename
|
||||
|
||||
restart_title=Restarting Webmin
|
||||
restart_done=The Webmin server process is now restarting - please wait for a few seconds before continuing.
|
||||
restart_done=The Webmin server process is restarting. Please wait a few seconds before continuing.
|
||||
|
||||
mobile_title=Mobile Device Options
|
||||
mobile_header=Options for mobile browsers
|
||||
@@ -1015,7 +1015,7 @@ blocked_user=Webmin user
|
||||
blocked_host=Client host
|
||||
blocked_clear=Clear All Blocks
|
||||
blocked_cleardesc=Click this button to clear all current host and user blocks, by restarting the Webmin server process.
|
||||
blocked_restarting=The Webmin server process is now restarting to clear blocked hosts and users - please wait for a few seconds before continuing.
|
||||
blocked_restarting=The Webmin server process is restarting to clear blocked hosts and users. Please wait a few seconds before continuing.
|
||||
|
||||
refreshmods_title=Refresh Modules
|
||||
refreshmods_installed=Checking for usable Webmin modules ..
|
||||
|
||||
@@ -1954,12 +1954,14 @@ Output a page with header and footer about Webmin needing to restart.
|
||||
=cut
|
||||
sub show_restart_page
|
||||
{
|
||||
my ($title, $msg) = @_;
|
||||
if (!$gconfig{'restart_async'}) {
|
||||
&restart_miniserv();
|
||||
&redirect("");
|
||||
my $msg_redir = "";
|
||||
$msg_redir = "?title=".&urlize($title)."&message=".&urlize($msg) if $msg;
|
||||
&redirect($msg_redir);
|
||||
return;
|
||||
}
|
||||
my ($title, $msg) = @_;
|
||||
$title ||= $text{'restart_title'};
|
||||
$msg ||= $text{'restart_done'};
|
||||
&ui_print_header(undef, $title, "");
|
||||
|
||||
Reference in New Issue
Block a user