RemoteCommand
Remote command execution example program
(distributed in source form only)

---------------------------------------------------------------------------------------------------------------------------------
Permission is granted to freely redistribute this application, accompanying programs and source code, and to use fragments of this code in your own applications if you find them to be useful.  This example application and source code come with no warranty of any kind, and the user assumes all responsibility for its use.
---------------------------------------------------------------------------------------------------------------------------------

Overview:
RemoteCommand is an example program which uses remote-object technology to perform remote command execution on another host.

RemoteCommand accomplishes this by launching a command server (RemoteRunServer) on the specified host, then connecting to it via a remote object connection.  When command execution requests are made by RemoteCommand, the command is sent to the command server for execution, and the output is sent back to RemoteCommand.  This would be similar to executing the command directly with "rsh host command" (using 'system', or 'popen'), except that much greater flexibility is provided to allow for better monitoring and interaction with the command execution server.

The ExecServer class (the heart of the RemoteCommand app) can also be set up to run commands/scripts under different users, provided root access is allowed.

Usage:
Upon execution of RemoteCommand, a panel will be displayed requesting the name of a host on which to launch the command server 'RemoteRunServer'.  After 'RemoteRunServer' has been launched, RemoteCommand will establish a connection to it.  If a connection cannot be made, a message will appear in the console window indicating the connection failure (see important note below).  When a successful connection has been established, an Execution Monitor window will be displayed.  Commands entered in the command scrollview will be executed when the "Execute Command" button is pressed.  Output from the command will appear in the output scrollview.

Important Note: The RemoteCommand.app directory must be accessible to the remote host in order for 'RemoteRunServer' to be launched successfully.  This restriction can be removed if a local copy of 'RemoteRunServer' is placed on the remote host and the source is modified to look for 'RemoteRunServer' in the new location on the remote machine.
 
By selecting "New Monitor", many remote command monitors can be active on different hosts, or the same host.

Command execution:
The commands entered into the command scrollview are executed on RemoteRunServer with "/bin/csh" (via 'execle()').  If the first 2 characters of the command are "#!", then it assumes the contents of the command scrollview is a script, and the contents will first be written to a temporary file in /tmp on the remote host machine prior to execution.

For example:

If the following lines were entered into the command scrollview
	echo "Hello World"
	echo "Be Happy"
Then these commands would be executed directly by /bin/csh.

If the following lines were entered into the command scrollview:
	#!/bin/csh -f
	echo "Hello World"
	echo "Be Happy"
Then the contents of the command scrollview would first be written to a temporary file, then the name of the temporary script file would be sent to /bin/csh.

"_askop" Usage:
Each child process that executes a command has an environment variable defined (CMDPATH) that specifies the path to the app wrapper.  This is useful for executing the command "$CMDPATH/_askop" to establishes a remote object connection back to the main app to get information from the operator, such as button selections, or a text string.

For Example:

If the following lines were entered into the command scrollview
	set RTN=`$CMDPATH/_askop "Buttons" "Select a Button" "B1" "B2" "B3"`
	echo "You selected $RTN"
Then, when executed, a panel will be displayed asking the operator to "Select a Button".  The selected button title will be echoed back to the operator.
	
--------------------------------------------------------------------------------------------------------------------------
Technical Documentation:

RemoteCommand.[hm]
This is the main Application subclass which handles app initialization and menu events.

ExecMonitor.[hm]
This handles the events for the window which accepts commands from the operator, sends them to RemoteRunServer, and displays the execution results.

AskOperator.[hm]
This object handles the "getResponseForMessage:" messages sent by _askop to RemoteCommand to display requests, and return the operator response.

execServer.subproj
This subproject contains the core of the remote object hooks to make the remote command execution possible.  execServer.subproj contains the following class source modules: ExecServer.[hm], ExecScrollText.[hm], RemoteRunServer.m, & _askop.m.

ExecServer.[hm]
This module is the heart of the RemoteCommand example application.  ExecServer actually contains several class definitions which support the remote object connections between the server, main-app client, and command execution client.

ExecScrollText.[hm]
This is an object which handles the command output sent by ExecServer and displays it in a Text object within a ScrollView (managed by ExecMonitor).

RemoteRunServer.m
This is the remote object server which runs as a separate program to handle command execution requests from the main app.  This program is launched on the remote host via /usr/ucb/rsh.

_askop.m
This is a program which can be called within a command executed by RemoteRunServer to get  a response from the operator.  It establishes a remote-object connection with the main app, which uses AskOperator to display the request, and return the response.