App-BCVI

 view release on metacpan or  search on metacpan

bin/bcvi  view on Meta::CPAN

an scp URI.  This is the default command if no C<--command> option is
specified.  If multiple filenames are supplied, the first will be opened
in gvim and you should use C<:n> to load the 'next' file.
END_POD
    );

    $class->register_command(
        name        => 'viwait',
        description => <<'END_POD'
This command works exactly the same as C<vi> above, except it waits for the
editor process to exit before bcvi exits on the remote machine.  This is
primarily for use with C<sudoedit>.  Note: when used with C<sudoedit>, the file
will not be updated on the remote machine until you exit the editor on your
workstation.
END_POD
    );

    $class->register_command(
        name        => 'scpd',
        description => <<'END_POD'
Uses C<scp> to copy the specified files or directories to the calling user's
F<~/Desktop>.`
END_POD
    );


    $class->add_home_bin();
    $class->register_aliases(
        'test -n "$(which bcvi)" && eval "$(bcvi --unpack-term)"',
        'test -n "${BCVI_CONF}"  && alias vi="bcvi"',
        'test -n "${BCVI_CONF}"  && alias suvi="EDITOR=\'bcvi -c viwait\' sudoedit"',
        'test -n "${BCVI_CONF}"  && alias bcp="bcvi -c scpd"',
    );

    $class->pod_class->init();

}


sub register_option {
    my $class = shift;

bin/bcvi  view on Meta::CPAN

user F<sally> establishes an SSH connection from her workstation to a server
named F<pluto> and runs the command C<bcvi .bashrc>

=item *

bcvi tunnels the details back to sally's workstation which then invokes the
command C<gvim scp://pluto//home/sally/.bashrc>

=item *

the result is that sally gets a responsive GUI editor running on her local
machine, but editing a file on the remote machine

=back

See C<< perldoc App::BCVI >> for more examples and background information.

=head1 OPTIONS

=for BCVI_OPTIONS

=head1 COMMANDS

lib/App/BCVI.pm  view on Meta::CPAN


The C<bcvi> utility works with SSH to allow commands issued on the SSH server
host to be sent I<back> to the SSH client host over a port-forwarded 'back
channel'.  A few examples might help clarify how C<bcvi> is used (note you can
read an illustrated version of the following examples at:
L<http://sshmenu.sourceforge.net/articles/bcvi/>):

=head2 Example 1

A user 'sally' opens a gnome-terminal window on her workstation and uses the
SSH command to log in to the host 'pluto'.  She then types a command to edit a
file:

  ~$ ssh pluto
  sally@pluto:~$ vi .bashrc

Through the magic of C<bcvi>, the result is that the file is opened for editing
in a 'gvim' editor window on Sally's workstation.  Note, this does B<not> use
X-forwarding.  The GUI editor process is running on Sally's workstation.  The
file is copied transparently to and from the server pluto using scp (via gvim's
'netrw' network transport layer).

Compared to running vim on the remote server in the terminal window, C<bcvi>
provides these advantages to Sally:

=over 4

=item *

lib/App/BCVI.pm  view on Meta::CPAN

set up the environment and invoked the real ssh command with additional
parameters for port forwarding the 'back channel'

=item *

Sally's login script on 'pluto' invoked C<bcvi> to unpack the environment and
set up the required authentication key

=item *

the 'vi' command used to edit the file on pluto was actually a shell alias
that invoked C<bcvi> to pass a message over the backchannel to the listener
process on Sally's workstation

=item *

the listener process unpacked the message to extract the hostname and filename
information needed to launch this command:

  gvim scp://pluto//home/sally/.bashrc

lib/App/BCVI.pm  view on Meta::CPAN

    bcvi --install HOSTNAME

At this point it should all work.  When you log in to the machine using SSH, a
number of shell aliases will be available to you:

=over 4

=item B<vi>

Invokes gvim on your workstation, passing it an scp://... URL of the file(s)
you wish to edit

=item B<suvi>

Same as above, but uses sudoedit so system files (requiring root access) can be
edited too

=item B<bcp>

Copies the named file back to your workstation desktop

=back

Note: you may like to try SSHMenu (L<http://sshmenu.sourceforge.net/>) which
can invoke the ssh wrapper automatically when connecting to servers.

lib/App/BCVI.pm  view on Meta::CPAN

The ssh wrapper command arranges for these pieces of information to be
forwarded to the remote host.  If you don't want to know how it does that then
please skip the rest of this paragraph.  WARNING: It's not pretty.  OK, so you
really want to know?  Don't say I didn't warn you.  SSH does not normally pass
environment variables from client to server unless you customise the ssh config
files on the client and the server.  However, SSH B<does> pass the TERM
variable.  So, C<bcvi> appends all the extra info to the end of the TERM
variable before invoking SSH.  This 'overstuffed' TERM variable then needs to
be unpacked by the user's shell startup script on the server.  If this is not
done, then your term variable will be wrong and you'll need to set it manually
before editing your .profile to fix it.

Unpacking the environment is achieved by running C<bcvi> with the C<<
--unpack-term >> option to generate a few lines of Bash script.  Those lines
then need to be eval'd in the shell.  The standard installation procedure
achieves this by adding this line to your shell startup script:

  test -n "$(which bcvi)" && eval "$(bcvi --unpack-term)"

This line assumes that C<bcvi> is in your path.  Normally C<bcvi> will be in
your C<$HOME/bin> directory and normally this will be in your $PATH, but it's

lib/App/BCVI/Plugins.pod  view on Meta::CPAN

modify almost any existing functionality of C<bcvi> (including removing
functionality)

=item *

modify both the server (listener) and/or the client

=back

Ideally you should be able to customise the behaviour of C<bcvi> in pretty
much any way you want without needing to edit the C<bcvi> script itself.

=head1 A SIMPLE EXAMPLE

Here's a silly plugin (that no sane person would ever want to use) which
overrides the 'vi' command handler and instead of launching C<gvim> it launches
C<gedit> (the GNOME text editor) - I did warn you it was a silly example:

  package App::BCVI::Gedit;
  
  use strict;
  use warnings;
  
  sub execute_vi {
      my($self) = @_;

      my $alias = $self->calling_host();
      my @files = map { "sftp://${alias}$_" } $self->get_filenames();
      system('gedit', '--', @files);
  }
  
  App::BCVI->hook_server_class();
  
  1;

This file should be saved as F<$HOME/.config/bcvi/Gedit.pm>.  Let's go through
it line-by-line.

Each plugin must have a unique package name.  The App::BCVI namespace is there
for plugins to use.  By convention, the filename should match the last part of
the package name, with '.pm' appended.

The C<use strict;> and C<use warnings;> are good practice in any Perl module.

The C<execute_vi> subroutine was copy/pasted from the C<bcvi> script itself
and then modified to work with C<gedit> rather than C<gvim>.

The C<hook_server_class> line is a method call that pushes this class onto the
inheritance chain for the object class that implements the listener process.
When the listener process calls C<execute_vi> in response to a request from a
client, our method is called instead of the standard method.  In some plugins,
it might make sense to delegate to the standard method using the syntax
C<< $self->SUPER::execute_vi(@args) >>, but in our case we're replacing the
standard method rather than augmenting it.

=head1 PLUGIN LOADING

lib/App/BCVI/Plugins.pod  view on Meta::CPAN


  App::BCVI->hook_server_class();

or for the client by calling

  App::BCVI->hook_client_class();

There are currently no hook methods for either the base class or the POD class
because that didn't seem very useful (just ask if you really need this).

The example plugin above had a package name of C<App::BCVI::Gedit> and it
called C<hook_server_class()>.  This has two effects:

=over 4

=item 1

When a listener process is started, it will be an instance of the
C<App::BCVI::Gedit> class

=item 2

The C<@ISA> array in the C<App::BCVI::Gedit> package will be adjusted to
point to C<App::BCVI::Server> so that all the existing methods of the server
class will be inherited

=back

If another package calls C<hook_server_class()> then its C<@ISA> array will be
adjusted to point to the C<App::BCVI::Gedit> class and when the listener starts
it will be an instance of the second plugin class.  Usually the order of
loading would not be significant, but the plugin filenames are sorted
alphanumerically before loading so you can rename the C<.pm> files to have them
load in a specific order.

If your plugin calls a hook method it should not explicitly set up any other
inheritance relationship (either through C<use base> or by directly altering
@ISA).

Sometimes it might not be immediately obvious whether you need to hook the



( run in 0.525 second using v1.01-cache-2.11-cpan-de7293f3b23 )