#!/usr/bin/env perl
# list-config - List one or all config directives for Webmin or a specific
# module.
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 Pod::Usage;
use Term::ANSIColor qw(:constants);
sub main {
my %opt;
GetOptions(
'help|h' => \$opt{'help'},
'config|c=s' => \$opt{'config'},
'module|m=s' => \$opt{'module'},
'option|o=s' => \$opt{'option'},
'describe|d' => \$opt{'describe'}
);
pod2usage(0) if ( $opt{'help'} );
$opt{'config'} ||= "/etc/webmin";
list_config( \%opt );
return 0;
}
exit main( \@ARGV ) if !caller(0);
sub list_config {
my ($optref) = @_;
my @config_lines;
# Module or root-level config?
if ($optref->{'module'}) {
# Read the module config file
@config_lines = load_config($optref->{'config'}, "$optref->{'module'}/config");
} else {
@config_lines = load_config($optref->{'config'}, "miniserv.conf");
}
# Display either a single item or the whole thing
if ($optref->{'option'}) {
# Show one item
my $value;
if ($optref->{'module'} and $optref->{'describe'}) {
$value = get_description($optref);
} else {
$value = get_config_value($optref->{'option'}, \@config_lines)
|| die RED, "Unable to retrieve value of $optref->{'option'}", RESET;
}
say $value;
} else {
# Show all
if ($optref->{'module'} and $optref->{'describe'}) {
@config_lines = get_description($optref);
} elsif ($optref->{'describe'}) {
die RED, "--describe only available for modules", RESET;
}
say for @config_lines;
}
}
sub load_config {
my ($config_dir, $file_path) = @_;
my @config_lines;
if (-e "$config_dir/$file_path") {
open my $fh, '<', "$config_dir/$file_path"
|| die RED, "Unable to open $config_dir/$file_path", RESET;
chomp(@config_lines = <$fh>);
close $fh;
} else {
die RED, "Unable to open $config_dir/$file_path.", RESET;
}
return @config_lines;
}
# get_config_var
# Read the file at $config and return the value of key
sub get_config_value {
my ($key, $config_lines_ref) = @_;
my $value;
foreach my $line (@$config_lines_ref) {
if ($line =~ /^${key}=(.*)/) {
$value = $1;
}
}
return $value;
}
# get_description
# Return a description of one or more options from config.info
sub get_description {
my ($optref) = @_;
my $root = root($optref->{'config'});
my $config_info = "$root/$optref->{'module'}/config.info";
my $key = $optref->{'option'};
open my $fh, '<', $config_info
or die RED, "Unable to open $config_info", RESET;
if ($optref->{'option'}) {
my $found = 0;
# return one description
while (<$fh>) {
if (/^${key}=([^,]*)/) {
$found++;
return "$key - $1";
}
}
$found or die RED, "Unrecognized option $key", RESET;
} else {
my $found;
# return all descriptions
my @lines;
while (<$fh>) {
if (/^(.*)=([^,]*)/) {
push (@lines, "$1 - $2");
$found++;
}
}
$found or die RED, "No options found for module $optref->{'module'}";
return @lines;
}
}
sub root {
my ($config) = @_;
open(my $CONF, "<", "$config/miniserv.conf") || die RED,
"Failed to open $config/miniserv.conf", RESET;
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?" unless (-d $root);
} else {
# Try to guess where Webmin lives, since config file didn't know.
die "Unable to determine Webmin installation directory from $ENV{'WEBMIN_CONFIG'}";
}
return $root;
}
1;
=pod
=head1 NAME
list-config
=head1 DESCRIPTION
List one or all configuration directives for C<miniserv.conf> or a module C<config> file.
=head1 SYNOPSIS
webmin list-config [options]
=head1 OPTIONS
=over
=item --help, -h
Print this usage summary and exit.
=item --config, -c
Specify the full path to the Webmin configuration directory. Defaults to
C</etc/webmin>
=item --module, -m
Specify which module configuration to display. If none given, configuration will be assumed to be the Webmin core configuration (/etc/webmin/miniserv.conf).
=item --option, -o
Specify a single option to display. By default, the entire configuration file will be displayed. If this option is given, only the option specified will be shown.
=item --describe, -d
Display the description of the option from the module C<config.info> file, instead of it's current value. This option is only available for modules, as miniserv.conf does not have a config.info.
=back
=head1 LICENSE AND COPYRIGHT
Copyright 2018 Jamie Cameron <jcameron@webmin.com>
Joe Cooper <joe@virtualmin.com>