mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
add missing files from previous set of commits
This commit is contained in:
parent
28860a8386
commit
ba6606460d
3 changed files with 1288 additions and 0 deletions
117
utils/Config.pm
Normal file
117
utils/Config.pm
Normal file
|
@ -0,0 +1,117 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2006 Novell, Inc. All Rights Reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Novell, Inc.
|
||||
#
|
||||
# To contact Novell about this file by physical or electronic mail,
|
||||
# you may find current contact information at www.novell.com.
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
package Immunix::Config;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp;
|
||||
use Cwd qw(cwd realpath);
|
||||
use File::Basename;
|
||||
use File::Temp qw/ tempfile tempdir /;
|
||||
use Data::Dumper;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(
|
||||
read_config
|
||||
write_config
|
||||
find_first_file
|
||||
find_first_dir
|
||||
);
|
||||
|
||||
our $confdir = "/etc/apparmor";
|
||||
|
||||
# config vars
|
||||
our $cfg;
|
||||
our $repo_cfg;
|
||||
|
||||
sub read_config {
|
||||
my $filename = shift;
|
||||
my $config;
|
||||
|
||||
if (open(CONF, "$confdir/$filename")) {
|
||||
my $which;
|
||||
while (<CONF>) {
|
||||
chomp;
|
||||
# ignore comments
|
||||
next if /^\s*#/;
|
||||
if (m/^\[(\S+)\]/) {
|
||||
$which = $1;
|
||||
} elsif (m/^\s*(\S+)\s*=\s*(.*)\s*$/) {
|
||||
my ($key, $value) = ($1, $2);
|
||||
$config->{$which}{$key} = $value;
|
||||
}
|
||||
}
|
||||
close(CONF);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
sub write_config {
|
||||
my ($filename, $config) = @_;
|
||||
if (open(my $CONF, ">$confdir/$filename")) {
|
||||
for my $section (sort keys %$config) {
|
||||
print $CONF "[$section]\n";
|
||||
|
||||
for my $key (sort keys %{$config->{$section}}) {
|
||||
print $CONF " $key = $config->{$section}{$key}\n"
|
||||
if ($config->{$section}{$key});
|
||||
}
|
||||
}
|
||||
chmod(0600, $CONF);
|
||||
close($CONF);
|
||||
} else {
|
||||
die "Can't write config file $filename: $!";
|
||||
}
|
||||
}
|
||||
|
||||
sub find_first_file {
|
||||
my $list = shift;
|
||||
return if ( not defined $list );
|
||||
my $filename;
|
||||
for my $f (split(/\s+/, $list)) {
|
||||
if (-f $f) {
|
||||
$filename = $f;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
sub find_first_dir {
|
||||
my $list = shift;
|
||||
return if ( not defined $list );
|
||||
my $dirname;
|
||||
for my $f (split(/\s+/, $list)) {
|
||||
if (-d $f) {
|
||||
$dirname = $f;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $dirname;
|
||||
}
|
||||
|
||||
1;
|
347
utils/Repository.pm
Normal file
347
utils/Repository.pm
Normal file
|
@ -0,0 +1,347 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2008 Dominic Reynolds
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
package Immunix::Repository;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp;
|
||||
use Cwd qw(cwd realpath);
|
||||
use Data::Dumper;
|
||||
use File::Basename;
|
||||
use File::Temp qw/ tempfile tempdir /;
|
||||
use Immunix::Config;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
use RPC::XML;
|
||||
use RPC::XML::Client;
|
||||
|
||||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw(
|
||||
get_repo_client
|
||||
did_result_succeed
|
||||
get_result_error
|
||||
user_login
|
||||
user_register
|
||||
upload_profile
|
||||
fetch_profile_by_id
|
||||
fetch_profiles_by_user
|
||||
fetch_profiles_by_name
|
||||
fetch_profiles_by_name_and_user
|
||||
fetch_newer_profile
|
||||
get_repo_config
|
||||
set_repo_config
|
||||
);
|
||||
|
||||
our %clients;
|
||||
our %uid2login;
|
||||
our $DEBUGGING = 0;
|
||||
our $repo_cfg;
|
||||
our $aa_cfg;
|
||||
|
||||
sub get_repo_client ($) {
|
||||
my $repo_url = shift;
|
||||
unless ( $clients{$repo_url} ) {
|
||||
$clients{$repo_url} = new RPC::XML::Client $repo_url;
|
||||
}
|
||||
return $clients{$repo_url};
|
||||
}
|
||||
|
||||
sub did_result_succeed {
|
||||
my $result = shift;
|
||||
|
||||
my $ref = ref $result;
|
||||
return ($ref && $ref ne "RPC::XML::fault") ? 1 : 0;
|
||||
}
|
||||
|
||||
sub get_result_error {
|
||||
my $result = shift;
|
||||
|
||||
if (ref $result) {
|
||||
if (ref $result eq "RPC::XML::fault") {
|
||||
$result = $result->string;
|
||||
} else {
|
||||
$result = $$result;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub user_login ($$$) {
|
||||
my ($repo_url,$user,$pass) = @_;
|
||||
my ($status,$detail);
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
if ( $repo_client ) {
|
||||
my $res = $repo_client->send_request('LoginConfirm', $user, $pass);
|
||||
if (did_result_succeed($res)) {
|
||||
$status = 1;
|
||||
$detail = "";
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
|
||||
sub user_register ($$$$) {
|
||||
my ($repo_url,$user,$pass,$email) = @_;
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my ($status,$detail);
|
||||
if ( $repo_client ) {
|
||||
my $res = $repo_client->send_request('Signup', $user, $pass, $email);
|
||||
if (did_result_succeed($res)) {
|
||||
$status = 1;
|
||||
$detail = "";
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
sub upload_profile ($$$$$$$) {
|
||||
my ($repo_url,$user,$pass,$distro,$pname,$profile,$changelog) = @_;
|
||||
my ($status,$detail);
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $res = $repo_client->send_request( 'Create', $user, $pass, $distro,
|
||||
$pname, $profile, $changelog);
|
||||
if (did_result_succeed($res)) {
|
||||
$detail = $res->value;
|
||||
$status = 1;
|
||||
} else {
|
||||
$detail = get_result_error($res);
|
||||
$status = 0;
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
sub fetch_profile_by_id ($$) {
|
||||
my ($repo_url,$id) = @_;
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $repo_profile;
|
||||
my ($status,$detail);
|
||||
my $res = $repo_client->send_request('Show', $id);
|
||||
if (did_result_succeed($res)) {
|
||||
$status = 1;
|
||||
$detail = $res->value();
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
|
||||
return $status, $detail;
|
||||
}
|
||||
|
||||
|
||||
sub fetch_profiles ($$$$) {
|
||||
my ($repo_url,$distro,$username,$fqdn) = @_;
|
||||
my $p_hash = {};
|
||||
my ($status,$detail);
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $res =
|
||||
$repo_client->send_request('FindProfiles', $distro, $fqdn, $username);
|
||||
if (did_result_succeed($res)) {
|
||||
$status = 1;
|
||||
for my $p ( @$res ) {
|
||||
my $p_repo = $p->{profile}->value();
|
||||
$p_repo =~ s/flags=\(complain\)// if ( $p_repo ); #strip complain flag
|
||||
$p->{profile} = $p_repo;
|
||||
$p->{user_id} = $p->{user_id}->value();
|
||||
$p->{id} = $p->{id}->value();
|
||||
$p->{name} = $p->{name}->value();
|
||||
$p->{created_at} = $p->{created_at}->value();
|
||||
$p->{downloaded_count} = $p->{downloaded_count}->value();
|
||||
}
|
||||
$detail = $res;
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
sub fetch_profiles_by_user ($$$) {
|
||||
my ($repo_url,$distro,$username) = @_;
|
||||
my $p_hash = {};
|
||||
my ($status,$detail) = fetch_profiles( $repo_url, $distro, $username, "" );
|
||||
if ( $status ) {
|
||||
for my $p ( @$detail ) {
|
||||
my $p_repo = $p->{profile};
|
||||
if ($p_repo ne "") {
|
||||
$p->{username} = $username;
|
||||
$p_hash->{$p->{name}} = $p;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return ($status,$detail);
|
||||
}
|
||||
return($status,$p_hash);
|
||||
}
|
||||
|
||||
|
||||
sub fetch_profiles_by_name_and_user ($$$$) {
|
||||
my ($repo_url,$distro,$fqdbin, $username) = @_;
|
||||
my $p_hash = {};
|
||||
my ($status,$detail) = fetch_profiles( $repo_url, $distro, $username, $fqdbin );
|
||||
if ( $status ) {
|
||||
for my $p ( @$detail ) {
|
||||
my $p_repo = $p->{profile}?$p->{profile}:"";
|
||||
$p_hash->{$p->{name}} = $p if ($p_repo ne "");
|
||||
}
|
||||
} else {
|
||||
return ($status,$detail);
|
||||
}
|
||||
return($status,$p_hash);
|
||||
}
|
||||
|
||||
|
||||
sub fetch_profiles_by_name ($$$) {
|
||||
my ($repo_url,$distro,$fqdbin) = @_;
|
||||
my ($status,$detail,$data);
|
||||
$detail = {};
|
||||
($status,$data) = fetch_profiles( $repo_url, $distro, "", $fqdbin);
|
||||
if ($status) {
|
||||
my @uids;
|
||||
for my $p (@$data) {
|
||||
push @uids, $p->{user_id};
|
||||
}
|
||||
my ($status_unames,$unames) = fetch_usernames_from_uids($repo_url, @uids);
|
||||
if ( $status_unames ) {
|
||||
for my $p (@$data) {
|
||||
if ( $unames->{$p->{user_id}} ) {
|
||||
$p->{username} = $unames->{$p->{user_id}};
|
||||
} else {
|
||||
$p->{username} = "unkown-" . $p->{user_id};
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
print STDOUT "ERROR UID\n";
|
||||
}
|
||||
for my $p (@$data) {
|
||||
$p->{profile_type} = "REPOSITORY";
|
||||
$detail->{$p->{username}} = $p;
|
||||
}
|
||||
} else {
|
||||
$detail = $data;
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
|
||||
sub fetch_newer_profile ($$$$$) {
|
||||
my ($repo_url,$distro,$user,$id,$profile) = @_;
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $p;
|
||||
my ($status,$detail);
|
||||
|
||||
if ($repo_client) {
|
||||
my $res =
|
||||
$repo_client->send_request('FindProfiles', $distro, $profile, $user);
|
||||
if (did_result_succeed($res)) {
|
||||
my @profiles;
|
||||
my @profile_list = @{$res->value};
|
||||
$status = 1;
|
||||
|
||||
if (@profile_list) {
|
||||
if ($profile_list[0]->{id} > $id) {
|
||||
$p = $profile_list[0];
|
||||
}
|
||||
}
|
||||
$detail = $p;
|
||||
} else {
|
||||
$status = 0;
|
||||
$detail = get_result_error($res);
|
||||
}
|
||||
}
|
||||
return $status,$detail;
|
||||
}
|
||||
|
||||
sub fetch_usernames_from_uids ($) {
|
||||
my ($repo_url,@searchuids) = @_;
|
||||
my ($status,$result) = (1,{});
|
||||
my @uids;
|
||||
|
||||
for my $uid ( @searchuids ) {
|
||||
if ( $uid2login{$uid} ) {
|
||||
$result->{$uid} = $uid2login{$uid};
|
||||
} else {
|
||||
push @uids, $uid;
|
||||
}
|
||||
}
|
||||
if (@uids) {
|
||||
my $repo_client = get_repo_client( $repo_url );
|
||||
my $res = $repo_client->send_request('LoginNamesFromUserIds', [@uids]);
|
||||
if (did_result_succeed($res)) {
|
||||
my @usernames = @{ $res->value };
|
||||
for my $uid (@uids) {
|
||||
my $username = shift @usernames;
|
||||
$uid2login{$uid} = $username;
|
||||
$result->{$uid} = $uid2login{$uid};
|
||||
}
|
||||
} else {
|
||||
$status = 0;
|
||||
$result = get_result_error($res);
|
||||
}
|
||||
}
|
||||
return $status,$result;
|
||||
}
|
||||
|
||||
sub get_repo_config {
|
||||
unless ( $repo_cfg ) {
|
||||
$repo_cfg = Immunix::Config::read_config("repository.conf");
|
||||
}
|
||||
unless ( $aa_cfg ) {
|
||||
$aa_cfg = Immunix::Config::read_config("logprof.conf");
|
||||
}
|
||||
return {
|
||||
"url" => $aa_cfg->{repository}{url},
|
||||
"distro" => $aa_cfg->{repository}{distro},
|
||||
"enabled" => $repo_cfg->{repository}{enabled},
|
||||
"upload" => $repo_cfg->{repository}{upload},
|
||||
"user" => $repo_cfg->{repository}{user},
|
||||
"password" => $repo_cfg->{repository}{pass},
|
||||
"email" => $repo_cfg->{repository}{email}
|
||||
};
|
||||
}
|
||||
|
||||
sub set_repo_config ($) {
|
||||
my $cfg = shift;
|
||||
my ($url,$distro,$enabled,$upload,$user,$pass);
|
||||
unless ( $repo_cfg ) {
|
||||
$repo_cfg = Immunix::Config::read_config("repository.conf");
|
||||
}
|
||||
unless ( $aa_cfg ) {
|
||||
$aa_cfg = Immunix::Config::read_config("logprof.conf");
|
||||
}
|
||||
$repo_cfg->{repository}{enabled} = $cfg->{enabled} if ( $cfg->{enabled} );
|
||||
$repo_cfg->{repository}{upload} = $cfg->{upload} if ( $cfg->{upload} );
|
||||
$repo_cfg->{repository}{user} = $cfg->{user} if ( $cfg->{user} );
|
||||
$repo_cfg->{repository}{pass} = $cfg->{password}if ( $cfg->{password} );
|
||||
$repo_cfg->{repository}{email} = $cfg->{email} if ( $cfg->{email} );
|
||||
$aa_cfg->{repository}{distro} = $cfg->{distro} if ( $cfg->{distro} );
|
||||
$aa_cfg->{repository}{url} = $cfg->{url} if ( $cfg->{url} );
|
||||
write_config("repository.conf", $repo_cfg);
|
||||
write_config("logprof.conf", $aa_cfg);
|
||||
}
|
||||
|
||||
|
||||
1;
|
824
utils/aa-repo.pl
Normal file
824
utils/aa-repo.pl
Normal file
|
@ -0,0 +1,824 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# $Id: $
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) 2008 Dominic Reynolds. All Rights Reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
#
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
#
|
||||
my $usage =
|
||||
"aa-repo.pl --command args\n";
|
||||
|
||||
my $usage_search =
|
||||
" --search [author=XXX] [prog=XXX] [id=XXX]
|
||||
Search the repository for profiles matching the search criteria
|
||||
and return the results.
|
||||
NOTE: One --search switch per option
|
||||
|
||||
--verbose|v
|
||||
Verbosity level. Supply either one or two switches. Two switches
|
||||
adds full profile text in returned search results.\n";
|
||||
|
||||
my $usage_push =
|
||||
|
||||
" --push [--profile=XXX|all] [--changelog=XXX]
|
||||
Push local profiles to repository, uses configured user and upon
|
||||
overwrite of an existing profile in the repository then prompt
|
||||
user with a diff for confirmation XXX the name of the application
|
||||
whose profile should be uploaded or \"all\" to upload all
|
||||
profiles. Multiple --profile switches may be passed to supply
|
||||
multiple profile names
|
||||
|
||||
e.g. --push --profile /usr/sbin/mdnsd --profile /usr/sbin/ftp
|
||||
e.g. --push --profile all\n";
|
||||
|
||||
my $usage_pull =
|
||||
" --pull [--author=XXX] [--profile=XXX] or [--id=XXX] [--mode=complain]
|
||||
pull remote profiles and install on local system
|
||||
If operation will change local profiles then prompt user with
|
||||
diff for confirmation
|
||||
NOTE: One --pull switch per option and there are three acceptable
|
||||
combinations
|
||||
|
||||
--pull --author=XXX
|
||||
* pull all profiles in the repo for the author
|
||||
|
||||
--pull --author=XXX --profile=XXXX
|
||||
* pull the profile for prog owned by author
|
||||
|
||||
--pull --id=XXXX
|
||||
* pull the profile with id
|
||||
|
||||
--pull --mode=complain
|
||||
* set the profile(s) to complain mode when installed
|
||||
|
||||
Profiles are checked for conflicts with currently installed
|
||||
profiles and presented as a list to the user to confirm and view.\n";
|
||||
|
||||
|
||||
my $usage_sync =
|
||||
" --sync [--up] [--down] [--noconfirm]
|
||||
Synchronize local profile set with the repository - showing
|
||||
changes and allowing prompting the user with the diffs and
|
||||
suggest the newest version to be activated. If the --all option
|
||||
is passed then treat profiles not marked as remote as new
|
||||
profiles that will be uploaded to the repository.\n";
|
||||
|
||||
my $usage_stat =
|
||||
" --status
|
||||
Show the current status of the local profile set. This operation
|
||||
is similar to sync but does not prompt the user to up|down load
|
||||
changes\n";
|
||||
|
||||
my $usage_getconfig =
|
||||
" --getconfig|c
|
||||
Print the current configuration for the repsository\n";
|
||||
|
||||
|
||||
my $usage_setconfig =
|
||||
" --setconfig [url=xxx] [username=xxxx] [password=xxxx] [enabled=(yes|no)]
|
||||
[upload=(yes|no)]
|
||||
Set the configuration options for the repository.
|
||||
NOTE: One --setconfig switch per option\n";
|
||||
|
||||
my $usage_bottom =
|
||||
" --quiet|q Don't prompt user - assume that all changes should be made.
|
||||
|
||||
ISSUES:
|
||||
o Should changes made to the system be recorded somehow? An audit event?
|
||||
o Should the tool allow a repo/distro to be passed for each operation?
|
||||
|
||||
";
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
use Immunix::SubDomain;
|
||||
use Immunix::Repository;
|
||||
use Data::Dumper;
|
||||
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
# force $PATH to be sane
|
||||
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
|
||||
|
||||
# initialize the local poo
|
||||
setlocale(LC_MESSAGES, "");
|
||||
textdomain("apparmor-utils");
|
||||
|
||||
# options variables
|
||||
my $help = '';
|
||||
my $verbose = '';
|
||||
|
||||
my ( $id, $author, $mode, %search, $sync, $getconfig, $push,
|
||||
$pull, %setconfig, @profiles, $all, $changelog, $stat );
|
||||
|
||||
GetOptions(
|
||||
'search=s%' => \%search,
|
||||
'sync=s' => \$sync,
|
||||
'status' => \$stat,
|
||||
'getconfig|c' => \$getconfig,
|
||||
'setconfig=s%' => \%setconfig,
|
||||
'push' => \$push,
|
||||
'id=s' => \$id,
|
||||
'author=s' => \$author,
|
||||
'profile=s' => \@profiles,
|
||||
'changelog=s' => \$changelog,
|
||||
'pull' => \$pull,
|
||||
'all|a' => \$all,
|
||||
'help|h' => \$help,
|
||||
'verbose|v+' => \$verbose
|
||||
);
|
||||
|
||||
#
|
||||
# Root privs required to run the repo tool
|
||||
#
|
||||
if ( geteuid() != 0 ) {
|
||||
print STDERR gettext(
|
||||
"You must be logged in with root user privileges to use this program.\n"
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
# --help
|
||||
# tell 'em how to use it...
|
||||
&usage && exit if $help;
|
||||
|
||||
my $config = get_repo_config();
|
||||
|
||||
#
|
||||
# --getconfig operation
|
||||
#
|
||||
&config && exit if $getconfig;
|
||||
|
||||
my $sd_mountpoint = check_for_subdomain();
|
||||
unless ($sd_mountpoint) {
|
||||
fatal_error(gettext(
|
||||
"AppArmor does not appear to be started. Please enable AppArmor and try again."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#
|
||||
# --setconfig operation
|
||||
#
|
||||
if ( keys %setconfig ) {
|
||||
$config->{url} = $setconfig{url} if ( $setconfig{url} );
|
||||
$config->{distro} = $setconfig{distro} if ( $setconfig{distro} );
|
||||
$config->{enabled} = $setconfig{enabled} if ( $setconfig{enabled} );
|
||||
$config->{email} = $setconfig{email} if ( $setconfig{email} );
|
||||
$config->{user} = $setconfig{username} if ( $setconfig{username} );
|
||||
$config->{password} = $setconfig{password} if ( $setconfig{password} );
|
||||
$config->{upload} = $setconfig{upload} if ( $setconfig{upload} );
|
||||
set_repo_config( $config );
|
||||
}
|
||||
|
||||
#
|
||||
# --push operation
|
||||
#
|
||||
if ( $push ) {
|
||||
my ($conflicts, $repo_profiles, $local_profiles, @overrides);
|
||||
if ( ! @profiles ) {
|
||||
print STDERR gettext(
|
||||
"Must supply at least one profile using \"--profile XXX\" to --push\n"
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
print STDERR Data::Dumper->Dump([@profiles], [qw(*profiles)]);
|
||||
}
|
||||
my $changelog = $changelog?$changelog:"none";
|
||||
push_profiles( \@profiles, $changelog, 1 );
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# --pull operation
|
||||
#
|
||||
if ( $pull ) {
|
||||
my $type = "";
|
||||
if ( $id ) {
|
||||
if ( $author || @profiles ) {
|
||||
print STDERR gettext(
|
||||
"Option --id=XX is only allowed by itself and not in combination to
|
||||
other options for the --pull command.\n"
|
||||
);
|
||||
exit 1;
|
||||
}
|
||||
$type = "id";
|
||||
}
|
||||
if ( @profiles && ! $author ) {
|
||||
print STDERR gettext(
|
||||
"Option --profile=XX requires that the --author=XX option be supplied
|
||||
to distinguish a specific profile.\n"
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
$type = "profile";
|
||||
}
|
||||
|
||||
my $mode = $mode eq "complain"?1:0;
|
||||
pull_profiles( \@profiles, $type, $mode, 1 );
|
||||
}
|
||||
|
||||
#
|
||||
# --search operation
|
||||
#
|
||||
if ( keys %search ) {
|
||||
if ( $search{id} ) {
|
||||
my($status,$result) = fetch_profile_by_id( $config->{url},
|
||||
$search{id} );
|
||||
if ($status) {
|
||||
my $title = sprintf(gettext( "Profile ID %s\n"), $search{id});
|
||||
console_print_search_results( $title,
|
||||
"profile",
|
||||
{ $result->{name} => $result }
|
||||
);
|
||||
|
||||
} else {
|
||||
print STDERR "ERROR $result\n";
|
||||
}
|
||||
} elsif ( $search{author} && $search{prog} ) {
|
||||
my($status,$result) =
|
||||
fetch_profiles_by_name_and_user( $config->{url},
|
||||
$config->{distro},
|
||||
$search{prog},
|
||||
$search{author}
|
||||
);
|
||||
if ( $status ) {
|
||||
my $title =
|
||||
sprintf(gettext("Profiles matching user: %s and program: %s\n"),
|
||||
$search{author},
|
||||
$search{prog}
|
||||
);
|
||||
console_print_search_results( $title, "profile", $result );
|
||||
} else {
|
||||
print STDERR "ERROR $result\n";
|
||||
}
|
||||
} elsif ( $search{author} ) {
|
||||
my($status,$result) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$search{author}
|
||||
);
|
||||
if ( $status ) {
|
||||
my $title = sprintf(gettext( "Profiles for %s\n"), $search{author});
|
||||
console_print_search_results( $title, "profile", $result );
|
||||
} else {
|
||||
print STDERR "ERROR $result\n";
|
||||
}
|
||||
} elsif ( $search{prog} ) {
|
||||
my($status,$result) = fetch_profiles_by_name( $config->{url},
|
||||
$config->{distro},
|
||||
$search{prog},
|
||||
);
|
||||
if ( $status ) {
|
||||
my $title = sprintf(gettext("Profiles matching program: %s\n"),
|
||||
$search{prog});
|
||||
console_print_search_results( $title, "user", $result );
|
||||
} else {
|
||||
print STDERR "ERROR $result\n";
|
||||
}
|
||||
} else {
|
||||
print STDERR
|
||||
"Unsupported search criteria. Please specify at least one of
|
||||
author=XXX prog=XXX id=XXX\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $stat ) {
|
||||
my ( $local_profiles, $remote_profiles );
|
||||
my $msg =
|
||||
" The following profiles are stored in the repository but
|
||||
are not synchronized with the copy in the repository\n";
|
||||
|
||||
my ($status, $result) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$config->{user}
|
||||
);
|
||||
if ( $status ) {
|
||||
$remote_profiles = $result;
|
||||
} else {
|
||||
print STDERR sprintf(gettext("ERROR connecting to repository: %s\n"),
|
||||
$result);
|
||||
exit;
|
||||
}
|
||||
|
||||
readprofiles();
|
||||
$local_profiles = serialize_local_profiles( \%sd );
|
||||
my ($local_only,$unsynched,$synched,$conflicts) = ({}, {}, {});
|
||||
$unsynched = find_profile_conflicts($remote_profiles, $local_profiles);
|
||||
for my $p ( keys %$local_profiles ) {
|
||||
if ( ! $remote_profiles->{$p} ) {
|
||||
$local_only->{$p} = $local_profiles->{$p};
|
||||
}
|
||||
}
|
||||
|
||||
for my $p ( keys %$remote_profiles ) {
|
||||
$synched->{$p} =
|
||||
$remote_profiles->{$p}->{profile} if ( ! %$unsynched->{$p} );
|
||||
}
|
||||
UI_status($synched, $unsynched, $local_only);
|
||||
}
|
||||
|
||||
######################
|
||||
# Helper functions
|
||||
######################
|
||||
|
||||
#
|
||||
# Compare the local profile set with the remote profile set.
|
||||
# Return a list of the conflicting profiles as a list
|
||||
# { PROFILE_NAME => [LOCAL_PROFILE, REMOTE_PROFILE] ]
|
||||
#
|
||||
#
|
||||
# remote_profiles = repository profiles as returned by one of the
|
||||
# Immunix::Repository::fetch... functions
|
||||
# local_profiles = hash ref containing
|
||||
# { name => serialized local profile }
|
||||
#
|
||||
#
|
||||
|
||||
sub find_profile_conflicts ($$) {
|
||||
my ($remote_profiles,$local_profiles) = @_;
|
||||
my $conflicts = {};
|
||||
for my $p ( keys(%$local_profiles) ) {
|
||||
if ( $local_profiles->{$p} and $remote_profiles->{$p} ) {
|
||||
my $p_local = $local_profiles->{$p};
|
||||
my $p_remote = $remote_profiles->{$p}->{profile};
|
||||
chomp($p_local);
|
||||
chomp($p_remote);
|
||||
if ( $p_remote ne $p_local ) {
|
||||
$conflicts->{$p} = [ $p_local, $p_remote ];
|
||||
}
|
||||
}
|
||||
}
|
||||
return( $conflicts );
|
||||
}
|
||||
|
||||
sub serialize_local_profiles ($) {
|
||||
my $profiles = shift;
|
||||
my $local_profiles = {};
|
||||
for my $p ( keys %$profiles ) {
|
||||
my $serialize_opts = {};
|
||||
$serialize_opts->{NO_FLAGS} = 1;
|
||||
my $p_local = serialize_profile( $profiles->{$p},
|
||||
$p,
|
||||
$serialize_opts );
|
||||
$local_profiles->{$p} = $p_local;
|
||||
}
|
||||
return $local_profiles;
|
||||
}
|
||||
|
||||
|
||||
sub console_print_search_results ($$$) {
|
||||
my ($title, $type,$result) = @_;
|
||||
open(PAGER, "| less") or die "Can't open pager";
|
||||
print PAGER $title;
|
||||
print PAGER "Found " . values(%$result) . " profiles \n";
|
||||
for my $p ( values(%$result) ) {
|
||||
if ( $verbose ) {
|
||||
if ( $type eq "user" ) {
|
||||
print PAGER " Author [ " . $p->{username} . " ]\n";
|
||||
} elsif ( $type eq "profile" ) {
|
||||
print PAGER " Name [ " . $p->{name} . " ]\n";
|
||||
}
|
||||
print PAGER " Created [ " . $p->{created_at} . " ]\n";
|
||||
print PAGER " Downloads [ " . $p->{downloaded_count} . " ]\n";
|
||||
print PAGER " ID [ " . $p->{id} . " ]\n";
|
||||
if ( $verbose > 1 ) {
|
||||
print PAGER " Profile [ \n" . $p->{profile} . " ]\n\n";
|
||||
} else {
|
||||
print PAGER "\n";
|
||||
}
|
||||
} else {
|
||||
my $data = $type eq "user"?$p->{username}:$p->{name};
|
||||
print PAGER " " . $data . "\n";
|
||||
}
|
||||
}
|
||||
close PAGER;
|
||||
}
|
||||
|
||||
sub UI_resolve_profile_conflicts {
|
||||
|
||||
my ($explanation, $conflict_hash) = @_;
|
||||
my $url = $config->{url};
|
||||
my @conflicts = map { [ $_,
|
||||
$conflict_hash->{$_}->[0],
|
||||
$conflict_hash->{$_}->[1]
|
||||
] }
|
||||
keys %$conflict_hash;
|
||||
my @commits = [];
|
||||
my $title = "Profile conflicts";
|
||||
my %resolution = ();
|
||||
my $q = {};
|
||||
$q->{title} = $title;
|
||||
$q->{headers} = [ "Repository", $url, ];
|
||||
|
||||
$q->{explanation} = $explanation;
|
||||
|
||||
$q->{functions} = [ "CMD_OVERWRITE",
|
||||
"CMD_KEEP",
|
||||
"CMD_VIEW_CHANGES",
|
||||
"CMD_ABORT",
|
||||
"CMD_CONTINUE", ];
|
||||
|
||||
$q->{default} = "CMD_OVERWRITE";
|
||||
$q->{options} = [ map { $_->[0] } @conflicts ];
|
||||
$q->{selected} = 0;
|
||||
|
||||
my ($ans, $arg);
|
||||
do {
|
||||
($ans, $arg) = UI_PromptUser($q);
|
||||
|
||||
if ($ans eq "CMD_VIEW_CHANGES") {
|
||||
display_changes($conflicts[$arg]->[2], $conflicts[$arg]->[1]);
|
||||
}
|
||||
if ( $ans eq "CMD_OVERWRITE") {
|
||||
$q->{options} =
|
||||
[ map { $_ =~ /$conflicts[$arg]->[0]( K| O)?$/?
|
||||
$conflicts[$arg]->[0] . " O":
|
||||
$_ }
|
||||
@{$q->{options}}
|
||||
];
|
||||
$resolution{$conflicts[$arg]->[0]} = "O";
|
||||
}
|
||||
if ( $ans eq "CMD_KEEP") {
|
||||
$q->{options} =
|
||||
[ map { $_ =~ /$conflicts[$arg]->[0]( K| O)?$/?
|
||||
$conflicts[$arg]->[0] . " K":
|
||||
$_ }
|
||||
@{$q->{options}}
|
||||
];
|
||||
$resolution{$conflicts[$arg]->[0]} = "K";
|
||||
}
|
||||
$q->{selected} = ($arg+1) % @conflicts;
|
||||
} until $ans =~ /^CMD_CONTINUE/;
|
||||
if ($ans eq "CMD_CONTINUE") {
|
||||
my @results = ();
|
||||
for my $p ( keys %resolution ) {
|
||||
if ( $resolution{$p} eq "O" ) {
|
||||
push @results, $p;
|
||||
}
|
||||
}
|
||||
return @results;
|
||||
}
|
||||
}
|
||||
|
||||
sub UI_display_profiles {
|
||||
my ($explanation, $profile_hash) = @_;
|
||||
my $url = $config->{url};
|
||||
my @profiles = map { [ $_, $profile_hash->{$_} ] } keys %$profile_hash;
|
||||
my $title = gettext("Profiles");
|
||||
my $q = {};
|
||||
$q->{title} = $title;
|
||||
$q->{headers} = [ "Repository", $url, ];
|
||||
|
||||
$q->{explanation} = $explanation;
|
||||
|
||||
$q->{functions} = [ "CMD_VIEW",
|
||||
"CMD_CONTINUE", ];
|
||||
|
||||
$q->{default} = "CMD_CONTINUE";
|
||||
$q->{options} = [ map { $_->[0] } @profiles ];
|
||||
$q->{selected} = 0;
|
||||
|
||||
my ($ans, $arg);
|
||||
do {
|
||||
($ans, $arg) = UI_PromptUser($q);
|
||||
|
||||
if ($ans eq "CMD_VIEW") {
|
||||
my $pager = get_pager();
|
||||
open ( PAGER, "| $pager" ) or die "Can't open $pager";
|
||||
print PAGER gettext("Profile: ") . $profiles[$arg]->[0] . "\n";
|
||||
print PAGER $profiles[$arg]->[1];
|
||||
close PAGER;
|
||||
}
|
||||
$q->{selected} = ($arg+1) % @profiles;
|
||||
} until $ans =~ /^CMD_CONTINUE/;
|
||||
return;
|
||||
}
|
||||
|
||||
sub UI_display_profile_conflicts {
|
||||
my ($explanation, $conflict_hash) = @_;
|
||||
my $url = $config->{url};
|
||||
my @conflicts = map { [ $_,
|
||||
$conflict_hash->{$_}->[0],
|
||||
$conflict_hash->{$_}->[1]
|
||||
] }
|
||||
keys %$conflict_hash;
|
||||
my @commits = [];
|
||||
my $title = gettext("Profile conflicts");
|
||||
my $q = {};
|
||||
$q->{title} = $title;
|
||||
$q->{headers} = [ "Repository", $url, ];
|
||||
|
||||
$q->{explanation} = $explanation;
|
||||
|
||||
$q->{functions} = [ "CMD_VIEW_CHANGES",
|
||||
"CMD_CONTINUE", ];
|
||||
|
||||
$q->{default} = "CMD_CONTINUE";
|
||||
$q->{options} = [ map { $_->[0] } @conflicts ];
|
||||
$q->{selected} = 0;
|
||||
|
||||
my ($ans, $arg);
|
||||
do {
|
||||
($ans, $arg) = UI_PromptUser($q);
|
||||
|
||||
if ($ans eq "CMD_VIEW_CHANGES") {
|
||||
display_changes($conflicts[$arg]->[2], $conflicts[$arg]->[1]);
|
||||
}
|
||||
$q->{selected} = ($arg+1) % @conflicts;
|
||||
} until $ans =~ /^CMD_CONTINUE/;
|
||||
return;
|
||||
}
|
||||
|
||||
sub usage {
|
||||
if ( $help eq "push" ) {
|
||||
print STDERR $usage . $usage_push ."\n";
|
||||
} elsif ( $help eq "pull" ) {
|
||||
print STDERR $usage . $usage_pull ."\n";
|
||||
} elsif ( $help eq "sync" ) {
|
||||
print STDERR $usage . $usage_sync ."\n";
|
||||
} elsif ( $help eq "getconfig" ) {
|
||||
print STDERR $usage . $usage_getconfig ."\n";
|
||||
} elsif ( $help eq "setconfig" ) {
|
||||
print STDERR $usage . $usage_setconfig ."\n";
|
||||
} elsif ( $help eq "status" ) {
|
||||
print STDERR $usage . $usage_stat ."\n";
|
||||
} elsif ( $help eq "search" ) {
|
||||
print STDERR $usage . $usage_search ."\n";
|
||||
} else {
|
||||
open(PAGER, "| less") or die "Can't open pager";
|
||||
print PAGER $usage .
|
||||
$usage_search .
|
||||
$usage_push .
|
||||
$usage_pull .
|
||||
$usage_sync .
|
||||
$usage_stat .
|
||||
$usage_setconfig .
|
||||
$usage_getconfig .
|
||||
$usage_bottom . "\n";
|
||||
close PAGER;
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# --getconfig helper function
|
||||
#
|
||||
sub config {
|
||||
my $configstr = gettext("Current config\n");
|
||||
my $config = get_repo_config();
|
||||
$configstr .= "\turl:\t\t$config->{url}\n";
|
||||
$configstr .= "\tdistro:\t\t$config->{distro}\n";
|
||||
$configstr .= "\tenabled:\t$config->{enabled}\n";
|
||||
$configstr .= "\temail:\t\t$config->{email}\n";
|
||||
$configstr .= "\tusername:\t$config->{user}\n";
|
||||
$configstr .= "\tpassword:\t$config->{password}\n";
|
||||
$configstr .= "\tupload:\t\t$config->{upload}\n";
|
||||
print STDERR $configstr . "\n";
|
||||
}
|
||||
|
||||
#
|
||||
# helper function to push profiles to the repository
|
||||
# used by --push and --sync options
|
||||
#
|
||||
sub push_profiles($$$) {
|
||||
my ( $p_ref, $changelog, $confirm ) = @_;
|
||||
my ( $conflicts, $remote_profiles, $local_profiles, @overrides );
|
||||
my @profiles = @$p_ref;
|
||||
|
||||
my $conflict_msg =
|
||||
" The following profile(s) selected for upload conflicts with a profile already
|
||||
stored in the repository for your account. Please choose whether to keep the
|
||||
current version or overwrite it.\n";
|
||||
$all = 0;
|
||||
|
||||
readprofiles();
|
||||
my ($status, $result) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$config->{user}
|
||||
);
|
||||
if ( $status ) {
|
||||
$remote_profiles = $result;
|
||||
} else {
|
||||
print STDERR sprintf(gettext("ERROR connecting to repository: %s\n"),
|
||||
$result);
|
||||
exit;
|
||||
}
|
||||
|
||||
$all = 1 if ( grep(/^all$/, @profiles) );
|
||||
|
||||
if ( $all ) {
|
||||
$local_profiles = serialize_local_profiles( \%sd );
|
||||
} else {
|
||||
my $local_sd = {};
|
||||
for my $p ( @profiles ) {
|
||||
if ( !$sd{$p} ) {
|
||||
print STDERR
|
||||
sprintf(gettext("Profile for [%s] does not exist\n"), $p);
|
||||
exit;
|
||||
}
|
||||
$local_sd->{$p} = $sd{$p};
|
||||
}
|
||||
$local_profiles = serialize_local_profiles( $local_sd );
|
||||
}
|
||||
|
||||
$conflicts = find_profile_conflicts($remote_profiles, $local_profiles);
|
||||
|
||||
if ( keys %$conflicts ) {
|
||||
@overrides = UI_resolve_profile_conflicts( $conflict_msg, $conflicts );
|
||||
}
|
||||
|
||||
if ( $local_profiles ) {
|
||||
my @uploads;
|
||||
for my $p ( keys %$local_profiles ) {
|
||||
unless ( $conflicts->{$p} and !grep(/^$p$/, @overrides) ) {
|
||||
print STDERR gettext("Uploading ") . $p . "... ";
|
||||
my ($status,$result) = upload_profile( $config->{url},
|
||||
$config->{user},
|
||||
$config->{password},
|
||||
$config->{distro},
|
||||
$p,
|
||||
$local_profiles->{$p},
|
||||
$changelog
|
||||
);
|
||||
print STDERR gettext("done") . "\n";
|
||||
}
|
||||
if ( $status ) {
|
||||
push @uploads, $p;
|
||||
} else {
|
||||
print STDERR gettext("Error uploading") . "$p: $result\n";
|
||||
}
|
||||
}
|
||||
if ( @uploads ) {
|
||||
#
|
||||
# Currently the upload API with the repository returns the
|
||||
# the current users profile set before the update so we have
|
||||
# to refetch to obtain the metadata to update the local profiles
|
||||
#
|
||||
my $repo_p = [];
|
||||
print STDERR gettext("Updating local profile metedata....\n");
|
||||
my ($status,$result) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$config->{user} );
|
||||
if ( $status ) {
|
||||
for my $p ( @uploads ) {
|
||||
push( @$repo_p, [$p, $result->{$p}] ) if ( $result->{$p} );
|
||||
}
|
||||
activate_repo_profiles( $config->{url}, $repo_p, 0 );
|
||||
print STDERR gettext(" done\n");
|
||||
} else {
|
||||
print STDERR gettext(
|
||||
"Failed to retrieve updated profiles from the repository. Error: "
|
||||
) . $result . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Helper function for pulling profiles from the repository
|
||||
# used by --pull and --sync options
|
||||
#
|
||||
sub pull_profiles($$$$) {
|
||||
my ( $p_ref, $mode, $confirm, $opts ) = @_;
|
||||
my @profiles = @$p_ref;
|
||||
my ( $conflicts, $commit_list, $remote_profiles,
|
||||
$local_profiles, @overrides );
|
||||
|
||||
my $conflict_msg =
|
||||
" The following profiles selected for download conflict with profiles
|
||||
already deployed on the system. Please choose whether to keep the local
|
||||
version or overwrite with the version from the repository\n";
|
||||
|
||||
readprofiles();
|
||||
|
||||
if ( $opts->{id} ) {
|
||||
my ($status,$newp) = fetch_profile_by_id( $config->{url}, $opts->{id} );
|
||||
if ( ! $status ) {
|
||||
print STDERR gettext(
|
||||
sprintf("Error occured during operation\n\t[%s]\n",
|
||||
$newp
|
||||
)
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
$remote_profiles = { $newp->{name} => $newp->{profile} };
|
||||
}
|
||||
} elsif ( @profiles && $opts->{author} ) {
|
||||
$remote_profiles = {};
|
||||
for my $p ( @profiles ) {
|
||||
my ($status,$profiles) =
|
||||
fetch_profiles_by_name_and_user( $config->{url},
|
||||
$config->{distro},
|
||||
$p,
|
||||
$opts->{author} );
|
||||
if ( ! $status ) {
|
||||
print STDERR gettext(sprintf(
|
||||
"Error occured during operation\n\t[%s]\n",
|
||||
$profiles
|
||||
)
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
$remote_profiles->{$p} = $profiles->{$p};
|
||||
}
|
||||
}
|
||||
} elsif ( $opts->{author} ) {
|
||||
my ($status,$profiles) = fetch_profiles_by_user( $config->{url},
|
||||
$config->{distro},
|
||||
$opts->{author} );
|
||||
if ( ! $status ) {
|
||||
print STDERR gettext(sprintf(
|
||||
"Error occured during operation\n\t[%s]\n",
|
||||
$profiles
|
||||
)
|
||||
);
|
||||
exit 1;
|
||||
} else {
|
||||
$remote_profiles = $profiles;
|
||||
}
|
||||
}
|
||||
$local_profiles = serialize_local_profiles( \%sd );
|
||||
$conflicts = find_profile_conflicts( $remote_profiles, $local_profiles );
|
||||
if ( keys %$conflicts ) {
|
||||
@overrides = UI_resolve_profile_conflicts( $conflict_msg, $conflicts );
|
||||
}
|
||||
for my $p ( keys %$remote_profiles ) {
|
||||
unless ( $conflicts->{$p} and !grep(/^$p$/, @overrides) ) {
|
||||
$remote_profiles->{$p}->{username} = $opts->{author};
|
||||
push @$commit_list, [$p, $remote_profiles->{$p}];
|
||||
}
|
||||
}
|
||||
|
||||
if ( $commit_list and @$commit_list ) {
|
||||
activate_repo_profiles( $config->{url}, $commit_list, $mode );
|
||||
system("rcapparmor reload");
|
||||
} else {
|
||||
UI_Info(gettext("No changes to make"));
|
||||
}
|
||||
}
|
||||
|
||||
sub UI_status {
|
||||
|
||||
my ($synched, $unsynched, $local) = @_;
|
||||
my $url = $config->{url};
|
||||
my $synched_text = gettext("Synchronized repository profiles:\t\t") .
|
||||
keys %$synched;
|
||||
my $unsynched_text = gettext("Unsynchronized repository profiles:\t") .
|
||||
keys %$unsynched;
|
||||
my $local_text = gettext("Local only profiles :\t\t\t") . keys %$local;
|
||||
my $options = [ $synched_text, $unsynched_text, $local_text ];
|
||||
my $title = gettext("Profile Status");
|
||||
my $explanation = gettext(
|
||||
" This is the current status of active profiles on the system.
|
||||
To view the profiles or unsyncronized changes select VIEW\n"
|
||||
);
|
||||
my $q = {};
|
||||
$q->{title} = $title;
|
||||
$q->{headers} = [ "Repository", $url, ];
|
||||
$q->{explanation} = $explanation;
|
||||
$q->{functions} = [ "CMD_VIEW", "CMD_FINISHED", ];
|
||||
$q->{default} = "CMD_FINISHED";
|
||||
$q->{options} = $options;
|
||||
$q->{selected} = 0;
|
||||
|
||||
my ($ans, $arg);
|
||||
do {
|
||||
($ans, $arg) = UI_PromptUser($q);
|
||||
|
||||
if ($ans eq "CMD_VIEW") {
|
||||
if ( $arg == 0 ) {
|
||||
UI_display_profiles(
|
||||
gettext("Profiles stored in the repository"),
|
||||
$synched
|
||||
);
|
||||
} elsif ( $arg == 1 ) {
|
||||
UI_display_profile_conflicts(
|
||||
gettext("Unsyncronised profile changes"),
|
||||
$unsynched
|
||||
);
|
||||
} elsif ( $arg == 2 ) {
|
||||
UI_display_profiles(
|
||||
gettext("Profiles stored in the repository"),
|
||||
$local
|
||||
);
|
||||
}
|
||||
}
|
||||
} until $ans =~ /^CMD_FINSHED/;
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue