#!/usr/bin/perl -w
# = HISTORY SECTION =====================================================================
# ---------------------------------------------------------------------------------------
# version | date | author | changes
# ---------------------------------------------------------------------------------------
# 2.01 |30.12.99| ets | added more CPAN specific POD sections;
# | | ets | first CPAN release;
# 2.00 |16.09.99| ets | translated POD into English;
# |28.12.99| ets | removed private module access;
# | | ets | bugfix: option -nocopyright took no effect;
# | | ets | replaced calls of bug() by Carp::confess();
# | | ets | made handling of non CPAN module Admin::File::Lock optional,
# | | | depending on its availability;
# | | ets | added usual option checks;
# | | ets | removed unused temporary directory and file handling;
# | | ets | translated remaining messages into English;
# |30.12.99| ets | added CPAN script categories;
# | | ets | replaced Admin::Oen::xxx() calls by internal code because
# | | | Admin::Oen is no public module;
# 1.12 |30.06.99| ets | class file2handle: added methods READ() and WRITE();
# | | ets | target script is forced now to run under perl 5.005 at least;
# 1.11 |24.06.99| ets | bugfix in own open;$main::_runningUnderRSC;
# | | ets | the tunneled script can now check if it runs under rsc
# | | | control, because rsc sets $main::_runningUnderRSC now;
# | | ets | bugfix in localized stat() and lstat() calls;
# | | ets | modified file test operator translation slightly;
# |25.06.99| ets | chmod() and chown() are overridden now;
# 1.10 |25.03.99| ets | completed POD once more ...;
# | | ets | removed forgotten debug traces;
# | | ets | bugfixes in directive handling (complex conditions);
# 1.09 |24.03.99| ets | target host is no longer pinged in tracelevel 1;
# | | ets | added new tracelevel 256;
# | | ets | added new directive #!TRACE##;
# | | ets | directive can now contain a combined condition;
# | | | (#TRACE#[\+|\|+]#);
# | | ets | new option -lresponse;
# | | ets | added trace to show tunneled @ARGV;
# 1.08 |19.03.99| ets | added a restriction hint: interaction;
# |23.03.99| ets | implemented real redirection of Storable::retrieve();
# 1.07 |19.03.99| ets | temporary files now named process specifically;
# | | ets | calls of _rscFiletest() are now generated WITH parantheses;
# 1.06 |19.03.99| ets | added target script support for Getopt::ArgvFile;
# | | ets | rsc now checks the target host first by ping;
# | | ets | documented default response file handling;
# 1.05 |17.03.99| ets | switched from Admin::Oen::response() to
# | | | Getopt::ArgvFile::argvFile();
# | | ets | completed POD;
# |18.03.99| ets | improved AUTOLOAD();
# 1.04 |15.03.99| ets | added controlable remote traces;
# | | ets | added really overloaded stat() and lstat();
# | | ets | overloaded file test operators, stat() and lstat() can
# | | | handle the special argument '_' correctly now;
# | | ets | improved by running a hpf script;
# 1.03 |12.03.99| ets | added new option -interpreter;
# | | ets | completed POD;
# 1.02 |10.03.99| ets | added File::Path::mkpath() localization;
# |11.03.99| ets | added AUTOLOAD() for non overriden file access functions;
# | | ets | added file test operator localization;
# | | ets | extended POD;
# | | ets | fixes and improvements;
# 1.01 |09.03.99| ets | the first version working with "serverspace -mode scan";
# 1.00 |09.03.99| ets | new.
# ---------------------------------------------------------------------------------------
# = POD SECTION =========================================================================
=head1 NAME
rsc - "tunnels" another Perl script
=head1 SCRIPT CATEGORIES
Networking
UNIX/System_administration
=head1 VERSION
This documentation describes version B<2.01>.
=head1 DESCRIPTION
=head2 Overview
B executes a (Perl!-)Script on another host. Neither this target script,
nor B or parts of it, nor input or output files I to be located
on the target machine.
There's no need to prepare the target system in any I way. No special
deamon has to run there, only perl 5.005 or higher with a few modules installed
and an rsh deamon are required. Additionally, this remote perl installation needs
installations of the modules the executed script wants to use.
If the work is done, B cleans up the target host even if it dies
accidentially (or) by a signal. No zombie in the process list, no remaining file
on disk (except of those which might be written by the executed script, of course).
Communication is done I via STDIN, STDOUT and STDERR. (This
makes it easy to establish a secure connection between the initiating
and the target machine if B is installed. Encryption will be done
automatically.)
Ideally, the called script has not to be prepared for this kind of execution.
Every script that runs standalone should be a good candidate for tunneling by
B - well, in fact, there really I I which are documented
in section "I".
=head2 Why doing jobs this way?
Of course, every script can be called I or via B if you need
remote execution. But in reality, this is difficult sometimes:
=over 4
=item In a network I saw,
hosts for administration purposes were especially installed and prepared.
A host inside the cell could access all other hosts in the net, but
only cell hosts could access other cell hosts.
Important scripts normally were located inside the cell to hide them from
"normal" users and were intended to be executed only inside the cell. But
some day there was a need to execute scripts I the cell - but still
without making them available there.
=item Mounts between servers
are a real problem if NFS becomes unavailable. That's why administrators of a
certain network decided to forbid such cross mounts. But now, if a script should be
run on several servers and reads or produces data in a shared directory, there is
a new problem because of the missed mounts, and finding a real good solution becomes
difficult.
=back
B was designed as a solution to this kind of problem.
=head2 How does it work?
Well, this is hidden in tricky code. This section provides an overview of the used
techniques. If it sounds too complicated, feel free to skip it and simply use the tool.
1) The target script is analyzed and modified I. Default option files are
solved I if a call of B is detected.
2) B starts a remote process which you can imagine a kind of a I.
3) The prepared target script is sent to the server.
4) The server executes the received target script on the remote machine. File
handling is redirected to the I process on the I system
if it works in directories the user predeclared as "local". (To do so, the
I process called a server before takes control and acts as a I
performing operations on the initial system via the initial process which acts
as a I in this step. Just to confuse you. ;-)
5) If the target script is executed completely, remote and initial process
terminate transparently without leaving zombies or helper files on the target
system.
=head2 Does it work for my script too?
There is a real chance. That's why I decided to publish this script on CPAN.
Nevertheless, it was designed to tunnel a I (large) script which is
tunnelled successfully. The algorithm is complex and I restrictions, so
there is no guarantee for other scripts to be executable this way too. Please
check out the I section.
=head1 SYNOPSIS
rsc [] -- []
Please note that "--" is absolutely necessary to mark where B options are
complete. Without this flag, B would read the target script options as well
(and remove them from the command line).
If the target script uses I by calling I,
B takes care of them automatically. They will be resolved on the I side,
and B will pass them to the target script using @ARGV.
=head2 Options
All options can be abbreviated uniqly.
=over 4
=item -help
displays an online help and terminates the script.
=item -interpreter
The B which should be executed on the target machine to start the target script.
Without such a hint, B tries to evaluate the target scripts "shebang" line.
To make the target script runnable under B control, the passed interpreter should
be a perl of version 5.003 or above, ideally 5.005 or above. The is no need of built in
multitheading support. The modules I, I and I have to be
installed.
=item -localize
redirects file access to this directory or any subdirectory from the target machine back
to the initial system. This is useful if the path is (under your account) not to be found
on the target host or if access to it should be avoided on the target system.
Example: If the target script checks a directory for existence which is located under the
specified path, B redirects this file check transparently a way that it is performed
on the I system. The check result will be passed to the target script which is
running on the target system.
This option may be used multiply.
=item lresponse
Usually, B passes all target script options unmodified to the target script. With this
option set, B is called on the I side so that option
files are solved I.
Example:
If the target options include an option file hint like
"-a -b @optionFile", it usually would be passed to the
target script on the target machine, where "optionFile"
would be searched and resolved. Now, possibly this file
is located in a path not to be found on the target system.
No problem, use -lresponse, and rsc will solve the option
file on the initial system BEFORE the results are passed
to the target side.
Please see B for details about option files.
=item -nocopyright
suppresses the copyright message;
=item -noinfo
supresses runtime informations;
=item -nowarn
supresses warnings;
=item -quiet
a shortcut for "-nocopyright -noinfo -nowarn": all non critical runtime messages are suppressed;
=item -trace []
activates traces of the specified level. You may use the environment variable SCRIPTDEBUG
alternatively.
Note: certain levels I the amount of data transfered between the involved machines
and may slow down the operation therefore.
Stufen:
=over 20
=item one (1)
The target script is not tunnelled but reported on STDOUT in its final generated represantation.
One may redirect this to a file which can be executed on the target system manually, e.g.
under debugger control.
The behaviour of the generated script can be controled by level 256.
=item two (2)
This level is currently not in operation.
=item four (4)
traces everything the remote process sends to the initial side.
=item eight (8)
reports running local actions.
=item sixteen (16)
reports current remote actions.
=item thirtytwo (32)
traces everything the initial process sends to the target side.
=item sixtyfour (64)
traces code executed remotely.
I
=item hundredtwentyeight (128)
activates hint messages pointing to function calls in the remote script which should
better be redirected to the initial machine. See the I section for details.
=item twohundredfiftysix (256)
if you choose trace level 1 to execute the result on the target system yourself,
the generated script will still iinteract with a "local" process via STDIN and SDOUT.
Because the initial process is now I, and I are the one controling STDIN
and STDOUT, I have to answer the script. This may become nerveracking ... To
help you, level 256 activates I for the following operations:
opening, closing, checking (, locking and releasing) of a file on the initial side
are automatically flagged as I as well as making directories by I.
=back
Levels are combined by addition. To use levels 1 I 4, enter a level of 5. (Internally,
combination is done bitwise, so if you use a random level, results depend from set bits of
existing level numbers.)
Examples:
-trace 1 # 1
-trace 2 # 2
-trace 3 # 1 and 2
-trace 4 # 4
-trace 5 # 1 and 4
-trace 6 # 2 and 4
-trace 7 # 1, 2 and 4
=back
=head2 Option files
Options may be loaded from files where they are stored exactly as you write them in the
command line, but may be spread to several lines and extended by comment lines which start
with a "#" character. To mark an option file in the commandline, simply enter its (path and)
name prededed by a "@" character.
Option files may be nested. To avoid endless recursion, every option file is resolved only
the first time it is detected.
The script also takes care of a I.
=head1 RETURN VALUES
=head1 ENVIRONMENT VARIABLES
=over 4
=item SCRIPTDEBUG
may be set to a numeric value to activate certain trace levels. You can use option I
alternatively. The several levels are described with this option.
=back
=head1 NOTES
The concept of B is new and only proved with a few scripts. (Nevertheless, proved
successfully.) This is why I still call it alpha software which will grow for a certain
period with every additionally tunnelled script. Please send a message if you see a way to
improve it or anything does not work.
This section describes both the ways of implementation and known problems.
=head2 Implementation
To work on another system, you need a kind of I to operate on your request.
B initially uses B which can usually be found on every UNIX system around,
and starts a short Perl script remotely. This first remote script works as follows:
it receives the target task (as code and additional data) using a minimal protocol.
After a startup signal, it translates the received code and executes it. From this
point on, all operations are determined by this received and now running code, which
communicates with the initial process on the initial machines which acts as a server now.
This is possible because it was manipulated by the same initial process before it was
sent to the remote side. That is why this concept offers a wide range of data transfer
and remote control - the I (which is in fact B) prepared both
sides and did it on the fly.
This principle is the base concept of B. Thanks to perl and the work of certain
module authors, namely B, the code which performes it is significantly shorter
than my description above.
To implement this concept, B uses a number of special Perl features. The original
target script code is modified a way that it can act as a client which can delegate
file access to the initial process if necessary. After modification, it is sent to the
installed remote process. The modification is done using the following features:
=over 4
=item tie()
File access to directories in a path specified by option I should be
redirected to the initial machine. To enforce this behaviour, B overwrites
B a way that it checks a passed file name for its path and generates a
tied "handle" instead of a real one if necessary. This tied handle is an object
of a small special class and works a way that all access to it is redirected to
method calls of the tied class. These methods send commands via STDOUT to the
server process acting at the initial side, which performs the file access I
and sends results back to the target side where the methods receive it via STDIN.
Literature note: See "perldoc perltie", "Programming Perl" and "Advanced Perl
Programming" for details about B.
=item Overidden functions
The overiding of B was already mentioned in the section about B usage.
Other functions need overiding, too, because they are working on file handles but
are not integrated into I - currently these are B, B,
B and B. So the overidden versions can work with the tied handles, too.
And there are still more which are I currently overidden yet but should be done,
these are B, B, B, B, B, B,
B and B. The reason overidden versions are currently not there
is simply that nobody used it in tunneled script until now. They should be added
on request.
=item Replaced functions
There are cases when a redirection to the initial machine cannot be implemented via B.
File check operators, for instance, currently cannot be overridden like B
or B, nor are they covered by I. That is why B I
them by calls of a special functions which redirects file access as necessary.
Without further details, here comes a list of more replaced functions which may be extended
if necessary: B. (The module B, if available, is
overridden by a self defined subclass a way that its objects can act tunnelled as expected,
this module is an internal wrapper around B and not currently published on CPAN.)
=back
=head2 Restrictions and Problems
The following list is surely incomplete, but this is what I currently know. There are
workarounds, but unfortunately they often break the concept of an "unprepared target
code".
B
B cannot be used with I script. This restriction is caused by the way of
implementation:
=over 4
=item rsc needs to run under perl 5.005 or above.
Earlier versions do not provide the necessary features.
=item A script which already uses tricks of rsc cannot be tunneled.
Obviously, the same trick cannot be used twice. That means that if the target script
code overrides perl functions which are overridden by B as well, or uses B
on handles B reclaims for itself, tunneling becomes a real challenge.
=item Code replacements depend on style.
Function replacements are done by pattern matching. Function calls not matching expected
calling styles may remain undetected and unreplaced and could cause an unexpected behaviour
when executed.
These are the assumptions made: File check operators are expected at line start, after an
opening paranthesis or after a whitespace. They are I before a closing bracket
("}"). Workaround if replacements fail: Modify the target script and use interpolated strings
as file parameter, they should be detected correctly.
=item Actions in used modules
mostly I be redirected to the initial machine because B cannot see and modify
the code for them which is hidden in the modules. This is true for both plain Perl and C
modules.
Exeption: if a file is opened in the I script and tied by B, all functions which
are wrapped by I (B, B, <>, B, B, B
and B) should I even in C modules which use the Perl API.
=item Files opened in modules
cannot be redirected by B for the same reasons. Examples are B and
B.
Workaround: These calls have to be wrapped by B. For B and
B, this wrapping is already implemented.
=item Interaction
cannot be fully provided yet. For instance, I found no way to make a remotley working texteditor
be usable via B.
=back
B
=over 4
=item Overloading
There are more candidates for overriding:
eof(), fileno(),
ioctl(), fcntl(),
chdir(), opendir(), readdir(), closedir(),
Currently, all calls of them are performed unmodified (remotely). This is even true if
a call of B leads the script to a directory in a path specified by I.
The tunneling of directory handling is an open question. Is it useful? Consequent tunneling
here in fact means to install a virtual mount point. On teh other hand, it would fit the
initial design targets of B. Ideas are welcome.
=item select()
Reading or writing files via this function is currently not possible. (I am speaking about
the select(, , , []).)
=back
B
A third group of problems is unfortunately caused by bugs in the current perl version. So
teh following may be difficult:
=over 4
=item Using a handle multiply
if the connected files are located in pathes specified by I.
Workaround: sorry, use different handles.
=item redirected handles passed to functions in C modules
According to "Advanced Perl Programming", C modules should delegate access to a tied handle
transparently to the specified "replacement function". Unfortunately, this does not work (or
not everytime).
Workaround: adding B wrappers. If this is impossible, there may be alternative functions
using file names instead of handles which I be wrapped - e.g., you may use
B and B instead of B and
B. B and B are already
wrapped by B.
=back
=head2 Runtime control
A script can detect if it is currently executed under B control by checking
$main::_runningUnderRSC.
=head2 Troubleshooting
Increase the trace level step by step. Note the possibilities given by level 1.
=head2 Generating help
The script description is stored I the script in POD and may be transformed into various
formats by the usual converters like B, B etc.
=head1 FILES
=head2 Default option file
At startup time, the script searches for a file I in its own installation directory (the
path used to call it) and automatically resolves it as an I