275 lines
7.9 KiB
Perl
275 lines
7.9 KiB
Perl
#!perl -w
|
|
|
|
use strict;
|
|
|
|
my $DEFAULT_DOMAIN_NAME = 'karinthy.hu';
|
|
my $DEFAULT_CONFIG_FILE_NAME = 'pkgtool.cfg';
|
|
|
|
my $base_directory;
|
|
|
|
BEGIN {
|
|
$base_directory = $0;
|
|
if ($^O eq 'MSWin32') {
|
|
if ($base_directory =~ /^(.*[\/\\])[^\/\\]*$/o) {
|
|
$base_directory = $1;
|
|
}
|
|
else {
|
|
$base_directory = '.';
|
|
}
|
|
}
|
|
else {
|
|
if ($base_directory =~ /^(.*\/)[^\/]*$/o) {
|
|
$base_directory = $1;
|
|
}
|
|
else {
|
|
$base_directory = '.';
|
|
}
|
|
}
|
|
push @INC, $base_directory if -d $base_directory;
|
|
}
|
|
|
|
use logging;
|
|
use cmdline;
|
|
use cfgparser;
|
|
use pkgtool;
|
|
|
|
my $print_help;
|
|
my $config_file_name;
|
|
my $proxycmd = $base_directory.'\\install.cmd';
|
|
my $standalone = 0;
|
|
my $globals = {};
|
|
|
|
sub set_standalone_flag ($)
|
|
{
|
|
my ($param) = @_;
|
|
|
|
$standalone = $param;
|
|
}
|
|
|
|
sub set_global ($)
|
|
{
|
|
my ($param) = @_;
|
|
|
|
if ($param =~ /^([^=]+)=(.*)$/o) {
|
|
my $key = $1;
|
|
my $value = $2;
|
|
$$globals{$key} = $value;
|
|
}
|
|
}
|
|
|
|
my $CONFIG_OPTIONS = [{
|
|
General => 1,
|
|
Option => '<command>',
|
|
Description => 'Command: list, status, update'
|
|
}, {
|
|
Short => 'c',
|
|
Long => 'config',
|
|
Description => 'Config file name',
|
|
Type => 'string',
|
|
Default => $DEFAULT_CONFIG_FILE_NAME,
|
|
StoreInto => \$config_file_name
|
|
}, {
|
|
Short => 'd',
|
|
Long => 'debug',
|
|
Description => 'Debug log level (0=off)',
|
|
Type => 'integer',
|
|
Default => 0,
|
|
StoreFunc => \&set_log_level
|
|
}, {
|
|
Short => 'g',
|
|
Long => 'global',
|
|
Description => 'Set generic variable (key=value)',
|
|
Type => 'keyvalue',
|
|
StoreFunc => \&set_global
|
|
}, {
|
|
Short => 'h',
|
|
Long => 'help',
|
|
Description => 'Print usage',
|
|
Type => 'flag',
|
|
Default => 0,
|
|
StoreInto => \$print_help
|
|
}, {
|
|
Short => 's',
|
|
Long => 'standalone',
|
|
Description => 'Skip accessing install server',
|
|
Type => 'flag',
|
|
StoreFunc => \&set_standalone_flag
|
|
}, {
|
|
Short => 'v',
|
|
Long => 'verbose',
|
|
Description => 'Verbose logging',
|
|
Type => 'flag',
|
|
Default => 0,
|
|
StoreFunc => \&set_verbose_flag
|
|
}];
|
|
|
|
set_pkgtool_dir($base_directory);
|
|
my $commands = parse_cmdline($CONFIG_OPTIONS);
|
|
if (! defined $commands || scalar @$commands < 1 || $print_help) {
|
|
print_usage($CONFIG_OPTIONS);
|
|
exit(1);
|
|
}
|
|
my $cmd = $$commands[0];
|
|
if ($cmd ne 'list' && $cmd ne 'status' && $cmd ne 'update') {
|
|
print_log('global', ERROR, 'Unknown command: %s', $cmd);
|
|
print_usage($CONFIG_OPTIONS);
|
|
exit(1);
|
|
}
|
|
|
|
my $dns_domain = get_default_dnsdomain();
|
|
$dns_domain = $DEFAULT_DOMAIN_NAME unless defined $dns_domain;
|
|
my $install_host = 'install.'.$dns_domain;
|
|
|
|
my $config = parse_cfg_file(substitute_variables({}, $config_file_name,
|
|
1, $base_directory, 'global'), get_cfg_syntax());
|
|
exit(1) unless defined $config;
|
|
$$config{'generic-variables'} = [] unless defined $$config{'generic-variables'};
|
|
$$config{'proxy-command'} = $proxycmd;
|
|
$$config{'install-host'} = $install_host;
|
|
set_log_base_dir(substitute_variables(get_default_vars(),
|
|
$$config{'log-directory'}, 1, $base_directory, 'global'));
|
|
set_log_defs($$config{logging}) if defined $$config{logging};
|
|
if ($standalone) {
|
|
print_log('global', INFO, 'Skipping install server');
|
|
}
|
|
else {
|
|
print_log('global', INFO, 'Install server: %s', $install_host);
|
|
my $error = get_install_sets($config);
|
|
exit(1) if defined $error;
|
|
}
|
|
my $error = scan_package_dirs($config, $base_directory);
|
|
exit(1) if defined $error;
|
|
$$config{'package-def'} = {} unless defined $$config{'package-def'};
|
|
$$config{'global-variables'} = $globals;
|
|
|
|
my $db = {};
|
|
read_installed_packages($db);
|
|
read_installed_patches($db);
|
|
|
|
my $counters = {
|
|
RebootFlag => 0,
|
|
InstalledList => [],
|
|
InstalledCount => 0,
|
|
RemovedList => [],
|
|
RemovedCount => 0,
|
|
FailList => [],
|
|
FailCount => 0,
|
|
SkipList => [],
|
|
SkipCount => 0,
|
|
ToInstallList => [],
|
|
ToInstallCount => 0,
|
|
ToRemoveList => [],
|
|
ToRemoveCount => 0
|
|
};
|
|
|
|
my $stats;
|
|
my $results;
|
|
if ($cmd eq 'list') {
|
|
print_log('global', INFO, '== Listing packages');
|
|
my $pkgdefs = $$config{'package-def'};
|
|
foreach my $key (sort keys %$pkgdefs) {
|
|
my $def = $$pkgdefs{$key};
|
|
next unless defined $def;
|
|
print_log('global', INFO, 'Definition: %s "%s"', $key, $$def{description});
|
|
}
|
|
my $installed = $$db{Installed};
|
|
foreach my $instname (sort keys %$installed) {
|
|
my $inst = $$installed{$instname};
|
|
next unless defined $inst && defined $$inst{DisplayName} && defined $$inst{DisplayVersion};
|
|
print_log('global', INFO, 'Installed: %s "%s" "%s" "%s"',
|
|
$$inst{UserPackage} ? 'user' : 'global', $instname, $$inst{DisplayName}, $$inst{DisplayVersion});
|
|
}
|
|
$installed = $$db{InstalledSpec};
|
|
foreach my $instname (sort keys %$installed) {
|
|
my $inst = $$installed{$instname};
|
|
next unless defined $inst && defined $$inst{DisplayName} && defined $$inst{DisplayVersion};
|
|
print_log('global', INFO, 'Installed: %s "%s" "%s" "%s"',
|
|
$$inst{UserPackage} ? 'user' : 'global', $instname, $$inst{DisplayName}, $$inst{DisplayVersion});
|
|
}
|
|
print_log('global', INFO, '== Listing patches');
|
|
my $patches = $$db{Patches};
|
|
foreach my $kb (sort { ${$$patches{$a}}{Number} <=> ${$$patches{$b}}{Number} } keys %$patches) {
|
|
my $patch = $$patches{$kb};
|
|
next unless defined $patch;
|
|
print_log('global', INFO, 'Installed: %s %s %s %s',
|
|
$$patch{KB},
|
|
($$patch{Type} eq 'OS' ? 'OS' : 'Packages('.join(',', sort keys %{$$patch{Packages}}).')'),
|
|
($$patch{Original} ? 'original' : 'update'),
|
|
($$patch{Current} ? 'current' : 'obsoleted'));
|
|
}
|
|
}
|
|
elsif ($cmd eq 'status') {
|
|
print_log('global', INFO, '== Displaying package status');
|
|
my $pkgdefs = $$config{'package-def'};
|
|
my $pkgs = $$config{'packages'};
|
|
foreach my $pkg (@$pkgs) {
|
|
handle_pkg($config, $base_directory, $db, $pkg, $counters, 0);
|
|
}
|
|
$stats = '';
|
|
}
|
|
elsif ($cmd eq 'update') {
|
|
my $pkgname = $$commands[1];
|
|
print_log('global', INFO, '== Updating packages/patches: %s', defined $pkgname ? $pkgname : 'all');
|
|
my $pkgdefs = $$config{'package-def'};
|
|
my $pkgs = $$config{'packages'};
|
|
foreach my $pkg (@$pkgs) {
|
|
my $name = $$pkg{name};
|
|
next if defined $pkgname && $name ne $pkgname;
|
|
handle_pkg($config, $base_directory, $db, $pkg, $counters, 1);
|
|
}
|
|
$stats = '';
|
|
}
|
|
if (defined $stats) {
|
|
$results = '';
|
|
if ($$counters{SkipCount} > 0) {
|
|
$stats .= $stats eq '' ? 'S' : ', s';
|
|
$stats .= sprintf('kipping %d', $$counters{SkipCount});
|
|
$results .= $results eq '' ? 'S' : ', s';
|
|
$results .= 'kipping: '.join(',', @{$$counters{SkipList}});
|
|
}
|
|
if ($$counters{FailCount} > 0) {
|
|
$stats .= $stats eq '' ? 'F' : ', f';
|
|
$stats .= sprintf('ailed %d', $$counters{FailCount});
|
|
$results .= $results eq '' ? 'F' : ', f';
|
|
$results .= 'ailed: '.join(',', @{$$counters{FailList}});
|
|
}
|
|
if ($$counters{ToInstallCount} > 0) {
|
|
$stats .= $stats eq '' ? 'To ' : ', to ';
|
|
$stats .= sprintf('install %d', $$counters{ToInstallCount});
|
|
$results .= $results eq '' ? 'To ' : ', to ';
|
|
$results .= 'install: '.join(',', @{$$counters{ToInstallList}});
|
|
}
|
|
if ($$counters{ToRemoveCount} > 0) {
|
|
$stats .= $stats eq '' ? 'To ' : ', to ';
|
|
$stats .= sprintf('remove %d', $$counters{ToRemoveCount});
|
|
$results .= $results eq '' ? 'To ' : ', to ';
|
|
$results .= 'remove: '.join(',', @{$$counters{ToRemoveList}});
|
|
}
|
|
if ($cmd eq 'update') {
|
|
$stats .= $stats eq '' ? 'I' : ', i';
|
|
$stats .= sprintf('nstalled %d, removed %d', $$counters{InstalledCount}, $$counters{RemovedCount});
|
|
$results .= $results eq '' ? 'I' : ', i';
|
|
if (scalar @{$$counters{InstalledList}} > 0) {
|
|
$results .= 'nstalled: '.join(',', @{$$counters{InstalledList}});
|
|
}
|
|
else {
|
|
$results .= 'nstalled: -';
|
|
}
|
|
if (scalar @{$$counters{RemovedList}} > 0) {
|
|
$results .= ', removed: '.join(',', @{$$counters{RemovedList}});
|
|
}
|
|
else {
|
|
$results .= ', removed: -';
|
|
}
|
|
}
|
|
if ($$counters{RebootFlag}) {
|
|
$stats .= $stats eq '' ? 'R' : ', r';
|
|
$stats .= sprintf('eboot needed!');
|
|
}
|
|
}
|
|
print_log('global', WARNING, 'Package/patch statistics: %s', $stats) if defined $stats;
|
|
print_log('global', INFO, '%s', $results) if defined $results;
|
|
|
|
close_all_log_files(0);
|
|
exit(0);
|