X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=src%2FPVE%2FCLIHandler.pm;h=e6fd415b3ef4fd237c03db93eb038e835e7d1bed;hp=9113c383142ae8f8844b1152f6ce8dba0a60aaa2;hb=2a8ced7bacb7da8ab4143a59720e74a2897cf714;hpb=c45707a0c98e0b602daa787907fb5b89b60a2d64 diff --git a/src/PVE/CLIHandler.pm b/src/PVE/CLIHandler.pm index 9113c38..e6fd415 100644 --- a/src/PVE/CLIHandler.pm +++ b/src/PVE/CLIHandler.pm @@ -34,6 +34,19 @@ my $expand_command_name = sub { return $cmd; }; +my $complete_command_names = sub { + my $res = []; + + return if ref($cmddef) ne 'HASH'; + + foreach my $cmd (keys %$cmddef) { + next if $cmd eq 'help'; + push @$res, $cmd; + } + + return $res; +}; + __PACKAGE__->register_method ({ name => 'help', path => 'help', @@ -46,6 +59,7 @@ __PACKAGE__->register_method ({ description => "Command name", type => 'string', optional => 1, + completion => $complete_command_names, }, verbose => { description => "Verbose output format.", @@ -93,6 +107,20 @@ __PACKAGE__->register_method ({ }}); +sub print_simple_pod_manpage { + my ($podfn, $class, $name, $arg_param, $uri_param) = @_; + + my $synopsis = " $name help\n\n"; + my $str = $class->usage_str($name, $name, $arg_param, $uri_param, 'long'); + $str =~ s/^USAGE://; + $str =~ s/\n/\n /g; + $synopsis .= $str; + + my $parser = PVE::PodParser->new(); + $parser->{include}->{synopsis} = $synopsis; + $parser->parse_from_file($podfn); +} + sub print_pod_manpage { my ($podfn) = @_; @@ -289,57 +317,83 @@ complete -C '$exename bashcomplete' $exename __EOD__ } -sub generate_pod_manpage { - my ($class, $podfn) = @_; +sub find_cli_class_source { + my ($exename) = @_; - no strict 'refs'; - $cmddef = ${"${class}::cmddef"}; + my $filename; - $exename = $class; - $exename =~ s/^.*:://; - - if (!defined($podfn)) { - my $cpath = "$class.pm"; - $cpath =~ s/::/\//g; - foreach my $p (@INC) { - my $testfn = "$p/$cpath"; + my $cpath = "PVE/CLI/${exename}.pm"; + my $spath = "PVE/Service/${exename}.pm"; + foreach my $p (@INC) { + foreach my $s (($cpath, $spath)) { + my $testfn = "$p/$s"; if (-f $testfn) { - $podfn = $testfn; + $filename = $testfn; last; } } + last if defined($filename); } + return $filename; +} + +sub generate_pod_manpage { + my ($class, $podfn) = @_; + + $exename = $class; + $exename =~ s/^.*:://; + + $podfn = find_cli_class_source($exename) if !defined($podfn); + die "unable to find source for class '$class'" if !$podfn; - print_pod_manpage($podfn); + no strict 'refs'; + my $def = ${"${class}::cmddef"}; + + if (ref($def) eq 'ARRAY') { + print_simple_pod_manpage($podfn, @$def); + } else { + $cmddef = $def; + + $cmddef->{help} = [ __PACKAGE__, 'help', ['cmd'] ]; + + print_pod_manpage($podfn); + } } -sub run { - my ($class, $pwcallback, $preparefunc) = @_; +sub run_cli { + my ($class, $pwcallback, $podfn, $preparefunc) = @_; $ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin'; - no strict 'refs'; - $cmddef = ${"${class}::cmddef"}; - $exename = $class; $exename =~ s/^.*:://; initlog($exename); - die "please run as root\n" if $> != 0; - PVE::INotify::inotify_init(); + if ($class !~ m/^PVE::Service::/) { + die "please run as root\n" if $> != 0; - my $rpcenv = PVE::RPCEnvironment->init('cli'); - $rpcenv->init_request(); - $rpcenv->set_language($ENV{LANG}); - $rpcenv->set_user('root@pam'); + PVE::INotify::inotify_init(); + + my $rpcenv = PVE::RPCEnvironment->init('cli'); + $rpcenv->init_request(); + $rpcenv->set_language($ENV{LANG}); + $rpcenv->set_user('root@pam'); + } - my $cmd = shift @ARGV; + no strict 'refs'; + my $def = ${"${class}::cmddef"}; - handle_cmd($cmddef, $exename, $cmd, \@ARGV, $pwcallback, $0, $preparefunc); + if (ref($def) eq 'ARRAY') { + handle_simple_cmd($def, \@ARGV, $pwcallback, $podfn, $preparefunc); + } else { + $cmddef = $def; + my $cmd = shift @ARGV; + handle_cmd($cmddef, $exename, $cmd, \@ARGV, $pwcallback, $podfn, $preparefunc); + } exit 0; } @@ -359,6 +413,7 @@ sub handle_cmd { PVE::RESTHandler::validate_method_schemas(); return; } elsif ($cmd eq 'printmanpod') { + $podfn = find_cli_class_source($exename) if !defined($podfn); print_pod_manpage($podfn); return; } elsif ($cmd eq 'bashcomplete') { @@ -384,7 +439,7 @@ sub handle_cmd { } sub handle_simple_cmd { - my ($def, $args, $pwcallback, $podfn) = @_; + my ($def, $args, $pwcallback, $podfn, $preparefunc) = @_; my ($class, $name, $arg_param, $uri_param, $outsub) = @{$def}; die "no class specified" if !$class; @@ -403,19 +458,14 @@ sub handle_simple_cmd { PVE::RESTHandler::validate_method_schemas(); return; } elsif ($args->[0] eq 'printmanpod') { - my $synopsis = " $name help\n\n"; - my $str = $class->usage_str($name, $name, $arg_param, $uri_param, 'long'); - $str =~ s/^USAGE://; - $str =~ s/\n/\n /g; - $synopsis .= $str; - - my $parser = PVE::PodParser->new(); - $parser->{include}->{synopsis} = $synopsis; - $parser->parse_from_file($podfn); + $podfn = find_cli_class_source($name) if !defined($podfn); + print_simple_pod_manpage($podfn, @$def); return; } } + &$preparefunc() if $preparefunc; + my $res = $class->cli_handler($name, $name, \@ARGV, $arg_param, $uri_param, $pwcallback); &$outsub($res) if $outsub;