Agent-TCLI
view release on metacpan or search on metacpan
lib/Agent/TCLI/Control.pm view on Meta::CPAN
my (@args,$request);
# is input a request object or plaintext?
if (ref($input) =~ /Request/)
{
$request = $input;
$input = $request->input;
$self->Verbose( "Execute: Request ".$request->dump(1),4);
$self->Verbose( "Execute: input from Request ($input)",2,\$input);
# Here we need to extract the command for FindCommand
# Odds are the request doesn't have args or command populated
# if it was built outside of the Control.
if ( defined($request->args) )
# Hmm, someone thinks they're smarter than the Control at
# parsing. OK, we'll take that. Later we'll use the real args.
{
@args = reverse( @{$request->command} );
}
# add self to sender/postback stack so that we can put ourself
# into PostResponse to Transport to handle many contrls per transport
# Or should I just stuff that into the request at the Transport
# Well, what if there isn't a request yet at the transport?
# Either the request exists or it will come from the control....
# Or just make the stateful transports create a request...
# I think that is more elegant.
# Scratch all this.
}
$self->Verbose( "Execute: args",2,\@args);
# Now get args from input.
if ( ! @args )
{
# TODO Still need a better parser.
# Parsewords chokes on single singlequotes.
$input =~ s/'//;
# parsewords also parses whitespace at the beginning poorly.
$input =~ s/^\s*//;
# Parsewords doesn't handle trailing backslashes well.
$input =~ s/\\$//;
@args = shellwords($input);
}
# substitute for help
$args[0] = 'help' if ($args[0] eq '?');
# # The command is broken down into a context, a command, and args.
# # The context helps find the command to execute and usually
# # remains the same between transactions unless changed by the user.
# # Context may be up to five layers deep. A single command may be
# # usable in more than one context, or even in all.
#
# # The command is sent as the first arg in @args.
#
# # Each command gets the following to execute:
# # $postback -> to send the response
# # \@args -> typically the user input in an array
# # $input -> the original user input
# # $thread -> the thread object for the user's session
# # The current context is stored in the $thread as an array but is
# # retrievable as a string as well.
#
# # Some commands merely establish context. Such as 'enable' in a Cisco
# # CLI. Though enable may require additional args. A default method/session
# # of the Agent::TCLI::Package::Base class called establish_context can handle
# # the simple case of setting context and confirming for the user.
#
# # $args[0] will always be the command word to execute, but may have
# # not been the first word entered if the command is nested deep in a
# # context. If a command needs to determine exactly how it was called
# # then it needs to reparse $input.
my ($cmd, $context, $txt, $code) = $self->FindCommand(\@args);
unless ($code == 404)
{
$self->Verbose("Execute: Executing cmd(".$cmd->name.
") for ".$id[$$self]." \n");
# Now actually execute the command
if ( ref($request) =~ /Request/ )
{
if ( !defined($request->args) || $request->depth_args == 0 )
{
$request->args( \@args );
$request->command( $context );
$self->Verbose( "Execute: Request post FindCommand".$request->dump(1),3);
}
# The response may bypass the Control's AsYouWished, and go
# directly back to the Transport if that is what is $request(ed)
if ( $cmd->call_style eq 'sub')
{
# Subs can't handle request objects.
my (@rargs, $rinput);
# subs want the command in the @rargs
push( @rargs, $request->command->[0], $request->args );
# Make sure there is input, just in case....
$rinput = defined($request->input) ? $request->input :
join(' ',$request->command->[0],$request->args);
# do it
($txt, $code) = $self->DoSub($cmd, \@rargs, $rinput );
$request->Respond( $kernel, $txt, $code);
return;
}
elsif ( $cmd->call_style eq 'state')
{
$self->Verbose("Execute: Executing state ".$cmd->handler." \n");
$kernel->yield( $cmd->handler => $request );
return;
}
elsif ( $cmd->call_style eq 'session')
{
$self->Verbose("Execute: Executing session ".$cmd->command.
"->".$cmd->handler." \n");
$kernel->post($cmd->command => $cmd->handler =>
lib/Agent/TCLI/Control.pm view on Meta::CPAN
} #end sub exit
=item dumpcmd
A POE event to handle some debugging in band.
It expects a request object parameter.
=cut
sub dumpcmd {
my ($kernel, $self, $request) =
@_[KERNEL, OBJECT, ARG0];
my $command = $request->command->[0];
my $txt;
# dump them all if no args
if ( $request->ArgsDepth == 0 )
{
foreach my $cmd ( keys %{ $registered_commands[$$self] } )
{
$txt .= $registered_commands[$$self]{$cmd}->dump(1);
}
}
elsif ( $request->ArgsDepth > 0 )
{
foreach my $cmd ( @{$request->args} )
{
$txt .= $registered_commands[$$self]{$cmd}->dump(1);
}
}
$request->Respond( $kernel, $txt );
} #end sub dumpcmd
#sub listcmd {
# my ($kernel, $self, $request) =
# @_[KERNEL, OBJECT, ARG0];
#
# my $command = $request->command->[0];
#
# my $txt;
# # TODO this is broken with new commands hash.
# if ( $request->depth_args == 0
# { # dump them all
# foreach my $context ( $registered_commands[$$self] )
# {
# $txt .= "\nCommands in context ".$context." \n\t";
# foreach my $command ( %{ $registered_commands[$$self]{ $context } } )
# {
# $txt .= $registered_commands[$$self]{ $context }{ $command }{'name'}.", ";
# } #end foreach command
# } #end foreach context
# }
# else
# {
# # just dump some in a context
#
# # tHIS SHOULD GRAB AN ARRAY
# my $context = $request->depth_args > 0 ? $request->args->[0] : $thread[$$self]->context;
#
# # if/eslif on size of array.
# # loop over hash1.hash2.hash3.keys getting '.'{'name'}
# # loop over wildcards too
#
# foreach my $cmd ( %{ $registered_commands[$$self]{ $context } } )
# {
# $txt .= $registered_commands[$$self]{ $context }{ $cmd }{'name'}.", ";
# }
# }
# $txt =~ s/,\s$//;
# $request->Respond( $kernel, $txt );
#} #end sub listcmd
#=item establish_context
#
#This POE event handler is the primary way to set context with a command.
#Just about any command that has subcommands will use this method as it's handler.
#An exception would be a command that sets an single handler to process all
#subcoammnds/args using the 'A*' context. See the Eliza package for an example of
#how to establish that type of context.
#
#=cut
#
#sub establish_context {
# my ($kernel, $self, $sender, $request, ) =
# @_[KERNEL, OBJECT, SENDER, ARG0, ];
# $self->Verbose("establish_context: ".$self->name." for request(".
# $request->id().")");
#
# my $txt;
# # if we have args, then the command is invalid
# if ( $request->depth_args > 0 )
# {
# $txt .= "Invalid input: ".$request->input;
# $self->Verbose("establish_context: Invalid input (".$request->input.")" );
# $request->Respond($kernel, $txt, 404) if $txt;
# return;
# }
#
# # we don't know how deep we're in already. So we'll force a full context shift.
# # by sending the entire command array back, which is revesred.
# my @context = reverse (@{$request->command});
#
# # We don't actualy set the controls context, but let change context do that.
# # It will also inform the user of change.
#
# # Post context back to sender (Control)
# $kernel->call( $sender => 'ChangeContext' => $request, \@context );
# $self->Verbose("establish_context: setting context to "
# .join(' ',@context)." ",2);
#
#}
#
#=item show
#
#This POE event handler i will accept an argument for the setting to show.
#It will also take an argument of all or * and show all settings.
#
( run in 1.709 second using v1.01-cache-2.11-cpan-c966e8aa7e8 )