qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mgoul...@apache.org
Subject svn commit: r800481 - in /qpid/trunk/qpid/cpp/src/tests: ./ qrsh_utils/
Date Mon, 03 Aug 2009 18:07:13 GMT
Author: mgoulish
Date: Mon Aug  3 18:07:12 2009
New Revision: 800481

URL: http://svn.apache.org/viewvc?rev=800481&view=rev
Log:
qrsh initial checkin.


Added:
    qpid/trunk/qpid/cpp/src/tests/qrsh.cpp
    qpid/trunk/qpid/cpp/src/tests/qrsh_run.cpp
    qpid/trunk/qpid/cpp/src/tests/qrsh_server.cpp
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/10_all   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/1_remote_run   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/2_forever   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/3_kill_it   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/4_wait_for_it   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/5_exited   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/6_get   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/7_get_output   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/8_any   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/9_alias   (with props)
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_forever.cpp
    qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qsh_doc.txt
Modified:
    qpid/trunk/qpid/cpp/src/tests/Makefile.am

Modified: qpid/trunk/qpid/cpp/src/tests/Makefile.am
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/Makefile.am?rev=800481&r1=800480&r2=800481&view=diff
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/Makefile.am (original)
+++ qpid/trunk/qpid/cpp/src/tests/Makefile.am Mon Aug  3 18:07:12 2009
@@ -256,6 +256,18 @@
 datagen_SOURCES=datagen.cpp
 datagen_LDADD=$(lib_common)
 
+check_PROGRAMS+=qrsh_server
+qrsh_server_SOURCES=qrsh_server.cpp
+qrsh_server_LDADD=$(lib_client)
+
+check_PROGRAMS+=qrsh_run
+qrsh_run_SOURCES=qrsh_run.cpp
+qrsh_run_LDADD=$(lib_client)
+
+check_PROGRAMS+=qrsh
+qrsh_SOURCES=qrsh.cpp
+qrsh_LDADD=$(lib_client)
+
 
 TESTS_ENVIRONMENT = \
     VALGRIND=$(VALGRIND) \

Added: qpid/trunk/qpid/cpp/src/tests/qrsh.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh.cpp?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh.cpp (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh.cpp Mon Aug  3 18:07:12 2009
@@ -0,0 +1,166 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <qpid/client/Connection.h>
+#include <qpid/client/Session.h>
+#include <qpid/client/AsyncSession.h>
+#include <qpid/client/Message.h>
+#include <qpid/client/MessageListener.h>
+#include <qpid/client/SubscriptionManager.h>
+
+
+#include <cstdlib>
+#include <iostream>
+
+#include <sstream>
+
+using namespace qpid::client;
+using namespace qpid::framing;
+
+using namespace std;
+
+
+class ResponseListener : public MessageListener
+{
+    public :
+    
+    int exitCode;
+
+    ResponseListener ( SubscriptionManager & subscriptions )
+        : exitCode(-1),
+          subscriptions ( subscriptions )
+    {
+    }
+
+    virtual void 
+    received ( Message & message )
+    {
+        char first_word[1000];
+        sscanf ( message.getData().c_str(), "%s", first_word );
+
+        if ( ! strcmp ( first_word, "wait_response" ) )
+        {
+            // If we receive a message here, parse out the exit code.
+            sscanf ( message.getData().c_str(), "%*s%d", & exitCode );
+            subscriptions.cancel(message.getDestination());
+        }
+        else
+        if ( ! strcmp ( first_word, "get_response" ) )
+        {
+            // The remainder of the message is the file we requested.
+            fprintf ( stdout, 
+                      "%s", 
+                      message.getData().c_str() + strlen("get_response" ) 
+                    );
+            subscriptions.cancel(message.getDestination());
+        }
+    }
+
+
+    private :
+    
+    SubscriptionManager & subscriptions;
+};
+
+
+
+
+/*
+ *  argv[1] host
+ *  argv[2] port
+ *  argv[3] server name
+ *  argv[4] command name
+ *  argv[5..N] args to the command
+ */
+int 
+main ( int argc, char ** argv ) 
+{
+    const char* host = argv[1];
+    int port = atoi(argv[2]);
+
+
+    Connection connection;
+
+    try 
+    {
+        connection.open ( host, port );
+        Session session = connection.newSession ( );
+
+        // Make a queue and bind it to fanout.
+        string myQueue = session.getId().getName();
+  
+        session.queueDeclare ( arg::queue=myQueue,
+                               arg::exclusive=true,
+                               arg::autoDelete=true
+                             );
+
+        session.exchangeBind ( arg::exchange="amq.fanout",
+                               arg::queue=myQueue,
+                               arg::bindingKey="my-key"
+                             );
+
+        // Get ready to listen for the wait-response.
+        // or maybe a get-response.
+        // ( Although this may not be one of those types
+        // of command, get ready anyway.
+        SubscriptionManager subscriptions ( session );
+        ResponseListener responseListener ( subscriptions );
+        subscriptions.subscribe ( responseListener, myQueue );
+
+        bool response_command = false;
+        if(! strcmp("exec_wait", argv[4] ))
+            response_command = true;
+        else
+        if(! strcmp("exited", argv[4] ))
+            response_command = true;
+        else
+        if(! strcmp("get", argv[4] ))
+            response_command = true;
+
+        // Send the payload message.
+        // Skip "qrsh host_name port" 
+        Message message;
+        stringstream ss;
+        for ( int i = 3; i < argc; ++ i )
+            ss << argv[i] << ' ';
+
+        message.setData ( ss.str() );
+
+        session.messageTransfer(arg::content=message, 
+                                arg::destination="amq.fanout");
+
+        if ( response_command )
+            subscriptions.run();
+
+        session.close();
+        connection.close();
+        return responseListener.exitCode;
+    } 
+    catch ( exception const & e) 
+    {
+        cerr << e.what() << endl;
+    }
+
+    return 1;
+}
+
+
+

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_run.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_run.cpp?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_run.cpp (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_run.cpp Mon Aug  3 18:07:12 2009
@@ -0,0 +1,321 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+
+using namespace std;
+
+
+
+int 
+main ( int argc, char ** argv )
+{
+    int  exit_code = -1;
+    int  fd[2];
+    int  my_pid = getpid();
+    int  child_pid;
+
+    pipe(fd); 
+
+    char const * root_dir   = argv[1]; // This arg is prepended by qrsh_server.
+    char const * child_name = argv[2]; // This arg comes from qrsh.
+    char const * child_path = argv[3]; // This arg comes from qrsh.
+
+    // This is the problem..
+    fprintf ( stderr, "MDEBUG  qrsh_run: root_dir: |%s|\n", root_dir );
+    fprintf ( stderr, "MDEBUG  qrsh_run: child_name: |%s|\n", child_name );
+    fprintf ( stderr, "MDEBUG  qrsh_run: child_path: |%s|\n", child_path );
+
+    /*
+     * A named child is one for whom we will create a directory and
+     * store information.  There are some magic names that are not
+     * real symbolic names -- but are instead the names of actions.
+     */
+
+    bool named_child = true;
+
+    if ( ! strcmp ( child_name, "exec" ) )
+        named_child = false;
+    else
+    if ( ! strcmp ( child_name, "exec_wait" ) )
+        named_child = false;
+    else
+    if ( ! strcmp ( child_name, "exited" ) )
+        named_child = false;
+    else
+        named_child = true;
+
+    stringstream child_dir_name;
+
+    if ( named_child ) 
+    {
+      child_dir_name << root_dir
+                     << '/'
+                     << child_name;
+
+      /*
+       *  Make the child directory before forking, or there is
+       *  a race in which the child might be trying to make its 
+       *  stdout and stderr files while we are tring to make 
+       *  the directory.
+       */
+      if ( -1 == mkdir ( child_dir_name.str().c_str(), 0777 ) )
+      {
+        fprintf ( stderr, 
+                  "qrsh_run error: Can't mkdir |%s|\n", 
+                  child_dir_name.str().c_str() 
+                );
+        exit ( 1 );
+      }
+
+    }
+    else
+    /*
+     * If this is an 'exited' command that means we are 
+     * waiting for a pre-existing child.
+     */
+    if ( ! strcmp ( child_name, "exited" ) )
+    {
+      int wait_pid = atoi(child_path);
+  
+      // Find the child's symbolic name.
+      stringstream pid_to_name_file_name;
+      pid_to_name_file_name << root_dir
+                            << '/'
+                            << wait_pid;
+      FILE * fp = fopen ( pid_to_name_file_name.str().c_str(), "r" );
+      if (! fp)
+      {
+          fprintf ( stderr, 
+                    "qrsh_run %d error: Can't open pid2name file |%s|.\n",
+                    my_pid,
+                    pid_to_name_file_name.str().c_str()
+                  );
+          exit(1);
+      }
+      char symbolic_name[1000];
+      strcpy ( symbolic_name, "qrsh_no_name" );
+      fscanf ( fp, "%s", symbolic_name );
+      fclose ( fp );
+
+      // Make the name of the child's exit code file.
+      stringstream exit_code_file_name;
+      exit_code_file_name << root_dir
+                          << '/'
+                          << symbolic_name
+                          << "/exit_code";
+
+      struct stat stat_buf;
+      int file_does_not_exist = stat ( exit_code_file_name.str().c_str(), & stat_buf );
+
+      /*
+       * If the result of stat is zero, the file exists, which means that
+       * the command has exited.  The question we are being asked here is
+       * "has it exited yet?"  
+       */
+      if ( ! file_does_not_exist )
+          return 1;
+      else
+      if ( errno == ENOENT )
+         return 0;
+      else
+         return 2 ;
+    }
+
+
+    // We are not waiting on a pre-wxiting child: we have a 
+    // new child to create.
+  
+    child_pid = fork();
+
+    if ( child_pid == 0 ) 
+    {
+        // This code is executed in the child process.
+
+        // If it's a *named* child, then redirect its stdout and stderr.
+        if ( named_child )
+        {
+            stringstream stdout_path,
+                         stderr_path;
+
+            // Redirect the child's stdout. -----------------
+            stdout_path << root_dir
+                        << '/'
+                        << child_name
+                        << '/'
+                        << "stdout";
+      
+            int redirected_stdout = open ( stdout_path.str().c_str(),
+                                           O_WRONLY|O_CREAT|O_TRUNC,
+                                           S_IRWXU|S_IRWXG|S_IRWXO
+                                         );
+            if ( redirected_stdout < 0 )
+            {
+                perror ( "qrsh_run: error opening redirected_stdout: " );
+                fprintf ( stderr, "stdout path: |%s|\n", stdout_path.str().c_str() );
+                exit ( 1 );
+            }
+            if ( -1 == dup2 ( redirected_stdout, 1 ) )
+            {
+                perror ( "qrsh_run: dup2 (stdout) error: " );
+                exit(1);
+            }
+
+            // Redirect the child's stderr. -----------------
+            stderr_path << root_dir
+                        << '/'
+                        << child_name
+                        << '/'
+                        << "stderr";
+      
+            int redirected_stderr = open ( stderr_path.str().c_str(),
+                                           O_WRONLY|O_CREAT|O_TRUNC,
+                                           S_IRWXU|S_IRWXG|S_IRWXO
+                                         );
+            if ( redirected_stderr < 0 )
+            {
+                perror ( "qrsh_run: error opening redirected_stderr: " );
+                fprintf ( stderr, "stderr path: |%s|\n", stderr_path.str().c_str() );
+                exit ( 1 );
+            }
+            if(-1 == dup2 ( redirected_stderr, 2 ) )
+            {
+                perror ( "qrsh_run: dup2 (stderr) error: " );
+                exit(1);
+            }
+        }
+
+        fprintf ( stderr, "MDEBUG  -------------  qrsh_run argv   -------------\n" );
+        for ( int i = 0; i < argc; ++ i )
+            fprintf ( stderr, "MDEBUG  argv[%d] : |%s|\n", i, argv[i] );
+
+        execv ( child_path, argv + 2 );
+        perror ( "qrsh_run: execv error: " );
+        fprintf ( stderr, "on path |%s|\n", child_path );
+        exit ( 1 );
+    }
+    else
+    {
+        // This code is executed in the parent process.
+
+        if ( named_child )
+        {
+            // Write the name-to-pid mapping.
+            stringstream pid_file_name;
+            pid_file_name << child_dir_name.str()
+                          << "/pid";
+      
+            FILE * fp;
+            if ( ! (fp = fopen ( pid_file_name.str().c_str(), "w") ) )
+            {
+                fprintf ( stderr, 
+                          "qrsh_run %d error: Can't open file |%s|\n", 
+                          my_pid, 
+                          pid_file_name.str().c_str() 
+                        );
+                exit(1);
+            }
+            fprintf ( fp, "%d\n", child_pid );
+            fclose ( fp );
+
+
+            // Write the pid-to-name mapping.
+            stringstream name_to_pid_file_name;
+            name_to_pid_file_name << root_dir
+                                  << '/'
+                                  << child_pid;
+            if(! (fp = fopen ( name_to_pid_file_name.str().c_str(), "w")))
+            {
+                fprintf ( stderr, 
+                          "qrsh_run %d error: Can't open file |%s|\n", 
+                          my_pid, 
+                          name_to_pid_file_name.str().c_str() 
+                        );
+                exit(1);
+            }
+            fprintf ( fp, "%s\n", child_name );
+            fclose(fp);
+        }
+
+        pid_t awaited_pid;
+        while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+        {
+            fprintf ( stderr, 
+                      "qrsh_run %d info: parent: waiting for child %d...\n",
+                      my_pid,
+                      child_pid
+                    );
+            sleep(1);
+        }
+
+        if ( -1 == awaited_pid )
+        {
+            fprintf ( stderr, "qrsh_run error awaiting child!\n" );
+            exit ( 1 );
+        }
+  
+        /*
+         * Write the exit code.
+         */
+        exit_code >>= 8;
+
+        if ( named_child )
+        {
+            if ( child_pid == awaited_pid )
+            {
+                stringstream exit_code_file_name;
+                exit_code_file_name << child_dir_name.str()
+                                    << "/exit_code";
+        
+                FILE * fp;
+                if ( ! (fp = fopen ( exit_code_file_name.str().c_str(), "w") ) )
+                {
+                    fprintf ( stderr, 
+                              "qrsh_run error: Can't open file |%s|\n", 
+                              exit_code_file_name.str().c_str() 
+                            );
+                    exit(1);
+                }
+                fprintf ( fp, "%d\n", exit_code );
+                fclose ( fp );
+            }
+        }
+    }
+
+    fprintf ( stderr, "MDEBUG  qrsh_run returning exit code %d\n", exit_code );
+    return exit_code;
+}
+
+
+
+

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_server.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_server.cpp?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_server.cpp (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_server.cpp Mon Aug  3 18:07:12 2009
@@ -0,0 +1,1062 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+
+#include <unistd.h>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <dirent.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <qpid/client/Connection.h>
+#include <qpid/client/Session.h>
+#include <qpid/client/AsyncSession.h>
+#include <qpid/client/Message.h>
+#include <qpid/client/MessageListener.h>
+#include <qpid/client/SubscriptionManager.h>
+
+
+using namespace qpid::client;
+using namespace qpid::framing;
+using namespace std;
+
+
+
+
+int
+mrand ( int max_desired_val )
+{
+  double zero_to_one = (double) rand() / (double) RAND_MAX;
+  return (int) (zero_to_one * (double) max_desired_val);
+}
+
+
+
+char * 
+file2str ( char const * file_name )
+{
+  FILE * fp = fopen ( file_name, "r" );
+  if(! fp)
+  {
+    fprintf ( stderr, "file2str error: can't open file |%s|.\n", file_name );
+    return 0;
+  }
+
+  fseek ( fp, 0, SEEK_END );
+  size_t file_len = (size_t) ftell ( fp );
+  rewind ( fp );
+  char * content = (char *) malloc ( file_len + 1 );
+
+  if ( ! content )
+  {
+    fprintf ( stderr, 
+              "file2str error: can't malloc %d bytes.\n", 
+              (int)file_len 
+            );
+    return 0;
+  }
+
+  size_t items_read = fread ( content, file_len, 1, fp );
+
+  if ( 1 != items_read )
+  {
+    fprintf ( stderr, "file2str error: read failed.\n" );
+    free ( content );
+    return 0;
+  }
+
+  fclose ( fp );
+  content[file_len] = 0;
+
+  return content;
+}
+
+
+
+
+
+class QrshServer : public MessageListener
+{
+  public:
+
+    QrshServer ( SubscriptionManager & subscriptions,
+                char const * name,
+                char const * qrsh_run_path,
+                char const * host,
+                int          port
+              );
+
+    virtual void received ( Message & message);
+
+
+  private:
+
+    set<string> all_server_names;
+
+    stringstream data_dir;
+
+    SubscriptionManager & subscriptions;
+
+    // Is this message addressed to me?
+    bool myMessage            ( Message const & message );
+
+    /* ----------------------------------------------
+     * Special Commands 
+     * These are commands that the qrsh_server executes
+     * directly, rather than through a child process 
+     * instance of qrsh_run.
+     */
+    void runCommand           ( Message const & message );
+    void execute              ( Message const & message );
+    void wait                 ( Message const & message );
+    void exited               ( Message const & message );
+    void get                  ( Message const & message );
+    void rememberIntroduction ( Message const & message );
+    void getStraw             ( Message const & message );
+    void addAlias             ( Message const & message );
+
+    void start    ( );
+    void sayHello ( );
+    void sayName  ( );
+    // end Special Commands ------------------------
+
+
+    void saveCommand          ( Message const & message );
+
+    void send                 ( string const & content );
+
+    void drawStraws      ( );
+    void getNames        ( );
+    void runSavedCommand ( );
+
+    char ** getArgs        ( char const * s );
+    bool isProcessName     ( char const * s );
+    int  string_countWords ( char const * s );
+    char const * skipWord  ( char const * s );
+
+
+    void string_replaceAll ( string & str, 
+                             string & target, 
+                             string & replacement 
+                           );
+
+
+    string name,
+           qrsh_run_path,
+           host;
+
+    vector<string *> aliases;
+
+    int port;
+
+    map < char *, int > abstract_name_map;
+
+    set < string > myFellowBrokers;
+
+    bool saidHello;
+
+    Message savedCommand;
+
+    vector < int > straws;
+    int myStraw;
+
+};
+
+
+
+QrshServer::QrshServer ( SubscriptionManager & subs, 
+                         char const * name,
+                         char const * qrsh_run_path,
+                         char const * host,
+                         int          port
+                       ) 
+    : subscriptions ( subs ),
+      name ( name ),
+      qrsh_run_path ( qrsh_run_path ),
+      host ( host ),
+      port ( port ),
+      saidHello ( false ),
+      myStraw ( 0 )
+{
+    data_dir << "/tmp/qrsh_"
+             << getpid();
+  
+    if(mkdir ( data_dir.str().c_str(), 0777 ) )
+    {
+        fprintf ( stderr, 
+                  "QrshServer::QrshServer error: can't mkdir |%s|\n", 
+                  data_dir.str().c_str()
+                );
+        exit ( 1 );
+    }
+}
+
+
+
+void
+QrshServer::saveCommand ( Message const & message )
+{
+    savedCommand = message;
+}
+
+
+
+void
+QrshServer::runSavedCommand ( )
+{
+    runCommand ( savedCommand );
+}
+
+
+
+void
+QrshServer::start ( )
+{
+    stringstream announcement_data;
+    announcement_data << "hello_my_name_is "
+                      << name;
+
+    send ( announcement_data.str() );
+  
+    saidHello = true;
+}
+
+
+
+
+void 
+QrshServer::send ( string const & content )
+{
+    try
+    {
+        Message message;
+        message.setData ( content );
+  
+        Connection connection;
+        connection.open ( host, port );
+        Session session = connection.newSession ( );
+        session.messageTransfer ( arg::content     = message,
+                                  arg::destination = "amq.fanout"
+                                );
+        session.close();
+        connection.close();
+    }
+    catch ( exception const & e )
+    {
+        fprintf ( stderr, "QrshServer::send error: |%s|\n", e.what() );
+    }
+}
+
+
+
+
+void
+QrshServer::sayHello ( )
+{
+    if ( saidHello )
+        return;
+
+    stringstream ss;
+
+    ss << "hello_my_name_is "
+       << name;
+
+    send ( ss.str() );
+    saidHello = true;
+}
+
+
+
+void 
+QrshServer::sayName  ( )
+{
+    fprintf ( stderr, "My name is: |%s|\n", name.c_str() );
+}
+
+
+
+
+void
+QrshServer::drawStraws ( )
+{
+    myStraw = mrand ( 1000000000 );
+    stringstream ss;
+    ss << "straw "
+       << name
+       << ' '
+       << myStraw;
+    send ( ss.str() );
+}
+
+
+
+void
+QrshServer::getStraw ( Message const & message )
+{
+    int straw;
+
+    char brokerName[1000];
+    sscanf ( message.getData().c_str(), "%*s%s", brokerName );
+
+    if ( ! strcmp ( brokerName, name.c_str() ) )
+        return;
+
+    sscanf ( message.getData().c_str(), "%*s%*s%d", & straw );
+    straws.push_back ( straw );
+
+    bool i_win = true;
+    int ties = 0;
+
+    if ( straws.size() >= myFellowBrokers.size() )
+    {
+        // All votes are in!  Let's see if I win!
+        for ( unsigned int i = 0; i < straws.size(); ++ i )
+        {
+            if ( straws[i] == myStraw )
+                ++ ties;
+            else
+            if ( straws[i] > myStraw )
+            {
+                i_win = false;
+                break;
+            }
+        }
+    
+        if ( i_win && (ties <= 0) )
+        {
+            myStraw = 0;
+            straws.clear();
+            runSavedCommand ( );
+        }
+        else
+        if ( i_win && (ties > 0) )
+        {
+            fprintf ( stderr, "MDEBUG  oh no!  drawStraws error: server %s tied with straw %d!\n", name.c_str(), straw );
+        }
+    }
+}
+
+
+
+
+/*
+ * "APB" command (all-points-bullitens (commands that are not addressed
+ * specifically to any server)) are handled directly, here.
+ * Because if I return simply "true", the normal command processing code 
+ * will misinterpret the command.
+ */
+bool 
+QrshServer::myMessage ( Message const & message )
+{
+    int const maxlen = 100;
+    char head[maxlen];
+    char first_word [ maxlen + 1 ];
+    strncpy ( head, message.getData().c_str(), maxlen );
+    sscanf ( head, "%s", first_word );
+
+    if ( ! strcmp ( name.c_str(), first_word ) )
+    {
+        return true;
+    }
+    else
+    {
+        // Is the given name one of my aliases?
+        char possibleAlias[1000];
+        if(1 == sscanf ( message.getData().c_str(), "%s", possibleAlias ))
+        {
+            for ( unsigned int i = 0; i < aliases.size(); ++ i )
+            {
+
+              if ( ! strcmp ( possibleAlias, aliases[i]->c_str() ))
+              {
+                return true;
+              }
+            }
+        }
+    }
+
+    if ( ! strcmp ( first_word, "hello_my_name_is" ) )
+    {
+        rememberIntroduction ( message );
+        sayHello ( );
+        return false;
+    }
+    else
+    if ( ! strcmp ( first_word, "straw" ) )
+    {
+        getStraw ( message );
+        return false;
+    }
+    else
+    if ( ! strcmp ( first_word, "all" ) )
+    {
+        return true;
+    }
+    else 
+    if ( ! strcmp ( first_word, "any" ) )
+    {
+        straws.clear();
+        usleep ( 200000 );
+        saveCommand ( message );
+        drawStraws ( );
+        return false;
+    }
+    else
+        return false;
+}
+
+
+
+
+void
+QrshServer::rememberIntroduction ( Message const & message )
+{
+    char brokerName [ 1000 ];
+    sscanf ( message.getData().c_str(), "%*s%s", brokerName );
+
+    if ( strcmp ( brokerName, name.c_str() ) )
+        myFellowBrokers.insert ( string ( brokerName ) );
+}
+
+
+
+
+void 
+QrshServer::addAlias ( Message const & message )
+{
+    char alias[1000];
+    sscanf ( message.getData().c_str(), "%*s%*s%s", alias );
+    aliases.push_back ( new string(alias) );
+}
+
+
+
+
+void
+QrshServer::getNames ( )
+{
+    abstract_name_map.clear();
+
+    DIR * dir = opendir ( data_dir.str().c_str() );
+
+    if ( ! dir )
+    {
+        fprintf ( stderr, 
+                  "QrshServer::getNames error: could not open dir |%s|.\n", 
+                  data_dir.str().c_str()
+                );
+        return;
+    }
+
+    struct dirent * file;
+    while ( (file = readdir ( dir ) ) )
+    {
+        if ( '.' != file->d_name[0] )
+        {
+            stringstream pid_file_name;
+            pid_file_name << data_dir.str()
+                          << '/'
+                          << file->d_name
+                          << "/pid";
+
+            int pid = 0;
+            FILE * fp;
+            if ( (fp = fopen ( pid_file_name.str().c_str(), "r" ) ) )
+            {
+                fscanf ( fp, "%d", & pid );
+                fclose ( fp );
+                abstract_name_map.insert(pair<char*, int>(strdup(file->d_name), pid));
+            }
+            else
+            {
+                /* 
+                 * Fail silently.  The non-existence of this file 
+                 * is not necessarily an error.
+                 */
+            }
+        }
+    }
+    closedir ( dir );
+}
+
+
+
+void
+QrshServer::string_replaceAll ( string & str, 
+                                string & target, 
+                                string & replacement 
+                              )
+{
+    int target_size = target.size();
+    int found_pos = 0;
+
+    while ( 0 <= (found_pos = str.find ( target ) ) )
+        str.replace ( found_pos, target_size, replacement );
+}
+
+
+
+
+bool 
+QrshServer::isProcessName ( char const * str )
+{
+    getNames();
+    map<char *, int>::iterator it;
+    for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+    {
+        if ( ! strcmp ( str, it->first ) )
+          return true;
+    }
+
+    return false;
+}
+
+
+
+
+
+int 
+QrshServer::string_countWords ( char const * s1 )
+{
+    int count = 0;
+    char const * s2 = s1 + 1;
+  
+    if ( ! isspace(* s1) )
+    {
+        ++ count;
+    }
+
+    for ( ; * s2; ++ s1, ++ s2 )
+    {
+        // count space-to-word transitions.
+        if ( isspace(*s1) && (! isspace(*s2)) )
+          ++ count;
+    }
+
+    return count;
+}
+
+
+
+
+void
+QrshServer::execute ( Message const & message )
+{
+    // First, gather all the symbolic names we know.
+    getNames();
+
+    // Now make a copy of the command, that I can alter.
+    string command ( message.getData() );
+
+
+    // Replace each occurrence of every abstract name with its pid.
+    char pid_str[100];
+    map<char *, int>::iterator it;
+    for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+    {
+        sprintf ( pid_str, "%d", it->second );
+        string target      ( it->first ),
+               replacement ( pid_str );
+        string_replaceAll ( command, target, replacement );
+    }
+
+
+    char const * truncated_command = skipWord(skipWord(command.c_str()));
+
+    if ( truncated_command )
+        system ( truncated_command );
+}
+
+
+
+
+
+void
+QrshServer::get ( Message const & request_message )
+{
+    char * file_content;
+
+    /*
+     * Get the contents of the requested file.
+     */
+    char file_or_process_name[1000];
+    sscanf ( request_message.getData().c_str(), "%*s%*s%s", file_or_process_name );
+  
+    if ( isProcessName ( file_or_process_name ) )
+    {
+        stringstream desired_file_name;
+        desired_file_name << data_dir.str()
+                          << '/'
+                          << file_or_process_name
+                          << '/';
+        char requested_output_stream[1000];
+        if(1 != sscanf ( request_message.getData().c_str(), 
+                         "%*s%*s%*s%s", 
+                         requested_output_stream 
+                       )
+          )
+        {
+            fprintf ( stderr, 
+                      "QrshServer::get error: Can't read requested data file name from this message: |%s|\n",
+                      request_message.getData().c_str()
+                    );
+            return;
+        }
+        desired_file_name << requested_output_stream;
+        file_content = file2str ( desired_file_name.str().c_str() );
+    }
+    else
+    {
+        file_content = file2str ( file_or_process_name );
+    }
+
+    stringstream reply_data ;
+    reply_data << "get_response "
+               << file_content;
+    /*
+     * Send a response-message to the server who is waiting.
+     */
+    send ( reply_data.str() );
+}
+
+
+
+
+
+
+void
+QrshServer::exited ( Message const & message )
+{
+    int  exit_code = -1;
+
+    // First, gather all the symbolic names we know.
+    getNames();
+
+    // Now make a copy of the command, that I can alter.
+    string edited_command ( message.getData() );
+
+    // Replace each occurrence of every abstract name with its pid.
+    char pid_str[100];
+    map<char *, int>::iterator it;
+    for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+    {
+        sprintf ( pid_str, "%d", it->second );
+        string target      ( it->first ),
+               replacement ( pid_str );
+        string_replaceAll ( edited_command, target, replacement );
+    }
+
+    // Skip the service name.  That is not used by the child.
+    char const * truncated_command = skipWord(edited_command.c_str());
+
+    if ( truncated_command )
+    {
+        stringstream ss;
+        ss << qrsh_run_path 
+           << ' '
+           << data_dir.str()
+           << ' '
+           << truncated_command;
+
+        int child_pid;
+        if ( ! (child_pid = fork() ) )
+        {
+            // This is the child.
+
+            char ** argv = getArgs ( ss.str().c_str() );
+            execv ( qrsh_run_path.c_str(), argv );
+
+            perror ( "qrsh_server: execv error: " );
+            exit ( 1 );
+        }
+        else
+        {
+            // This is the parent.
+            pid_t awaited_pid;
+            while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+            {
+                fprintf ( stderr, "qrsh_server info: parent: waiting for child...\n" );
+                sleep(1);
+            }
+
+            if ( -1 == awaited_pid )
+            {
+                fprintf ( stderr, "qrsh_server error awaiting child!\n" );
+                exit ( 1 );
+            }
+      
+            exit_code >>= 8;
+    
+            stringstream data;
+            data << "wait_response "
+                 << exit_code;
+
+            send ( data.str() );
+        }
+    }
+}
+
+
+
+
+void
+QrshServer::wait ( Message const & message )
+{
+    bool pre_existing = false;
+    if ( 3 == string_countWords ( message.getData().c_str() ) )
+    {
+        // The first word is the name of this service.
+        // The second word is "exec_wait".
+        // The third word is the symbolic name of the command to wait for.
+        // The fact that there are exactly three words means that this
+        // must be a command that has already been named and started -- 
+        // we just need to find its pid and wait on it.
+        pre_existing = true;
+    }
+
+
+    int  exit_code = -1;
+
+    // First, gather all the symbolic names we know.
+    getNames();
+
+    // Now make a copy of the command, that I can alter.
+    string edited_command ( message.getData() );
+
+    // Replace each occurrence of every abstract name with its pid.
+    char pid_str[100];
+    map<char *, int>::iterator it;
+    for ( it = abstract_name_map.begin(); it != abstract_name_map.end(); ++ it )
+    {
+        sprintf ( pid_str, "%d", it->second );
+        string target      ( it->first ),
+               replacement ( pid_str );
+        string_replaceAll ( edited_command, target, replacement );
+    }
+
+    // Skip the service name.  That is not used by the child.
+    char const * truncated_command = skipWord(edited_command.c_str());
+
+    if ( truncated_command )
+    {
+        stringstream ss;
+        ss << qrsh_run_path 
+           << ' '
+           << data_dir.str()
+           << ' '
+           << truncated_command;
+
+        int child_pid;
+        if ( ! (child_pid = fork() ) )
+        {
+            // This is the child.
+
+            char ** argv = getArgs ( ss.str().c_str() );
+            execv ( qrsh_run_path.c_str(), argv );
+
+            perror ( "qrsh_server: execv error: " );
+            exit ( 1 );
+        }
+        else
+        {
+            // This is the parent.
+            pid_t awaited_pid;
+            while ( 0 == (awaited_pid = waitpid ( child_pid, & exit_code, WNOHANG)) )
+            {
+                fprintf ( stderr, "qrsh_server info: parent: waiting for child...\n" );
+                sleep(1);
+            }
+
+            if ( -1 == awaited_pid )
+            {
+                fprintf ( stderr, "qrsh_server error awaiting child!\n" );
+                exit ( 1 );
+            }
+        }
+    
+        exit_code >>= 8;
+
+        stringstream data;
+        data << "wait_response "
+             << exit_code;
+
+        send ( data.str() );
+    }
+}
+
+
+
+
+
+char const * 
+QrshServer::skipWord ( char const * s )
+{
+    if(! (s && *s) )
+        return 0;
+
+    // skip past initial white space
+    while ( isspace(*s) )
+    {
+        ++ s;
+        if(! *s)
+            return 0;
+    }
+
+    // skip past first word
+    while ( ! isspace(*s) )
+    {
+        ++ s;
+        if(! *s)
+            return 0;
+    }
+
+    return s;
+}
+
+
+
+
+
+char **
+QrshServer::getArgs ( char const * str )
+{
+    char const * s = str;
+
+    char ** argv = 0;
+    vector<int> start_positions,
+                lengths;
+
+    int pos     = 0;
+    int arg_len = 0;
+
+    int n_args = 0;
+    while ( 1 )
+    {
+        // advance over whitespace.
+        while ( isspace ( *s ) )
+        {
+            ++ s; ++ pos;
+            if(! *s)
+            {
+                goto done;
+            }
+        }
+
+        ++ n_args;
+        start_positions.push_back ( pos );
+        arg_len = 0;
+
+        // advance over non-whitespace.
+        while ( ! isspace ( *s ) )
+        {
+            ++ s; ++ pos; ++ arg_len;
+            if(! *s)
+            {
+                lengths.push_back ( arg_len );
+                arg_len = 0;
+                goto done;
+            }
+        }
+
+        lengths.push_back ( arg_len );
+        arg_len = 0;
+    }
+
+    done: 
+
+    if ( arg_len > 0 )
+        lengths.push_back ( arg_len );
+
+    // Alloc the array.
+    argv = (char **) malloc ( sizeof(char *) * ( n_args + 1 ) );
+    argv[n_args] = 0; // mull-term the array.
+
+    for ( int i = 0; i < n_args; ++ i )
+    {
+        argv[i] = ( char *) malloc ( lengths[i] + 1 );
+        strncpy ( argv[i], 
+                  str + start_positions[i], 
+                  lengths[i]
+                );
+        argv[i][lengths[i]] = 0;
+    }
+
+    return argv;
+}
+
+
+
+void
+QrshServer::runCommand ( Message const & message )
+{
+    char const * s = message.getData().c_str();
+
+    /*
+     * Skip the first word, which is this server's name.
+     */
+    while ( isspace(*s) )     // go to start of first word.
+        ++ s;
+
+    while ( ! isspace(*s) )   // go to end of first word.
+        ++ s;
+
+    while ( isspace(*s) )     // go to start of second word.
+        ++ s;
+
+    char command_name[1000];
+    sscanf ( s, "%s", command_name );
+
+    if ( ! strcmp ( "get", command_name ) )
+    {
+        get ( message );
+    }
+    else
+    if ( ! strcmp ( "exited", command_name ) )
+    {
+        exited ( message );
+    }
+    else
+    if ( ! strcmp ( "exec_wait", command_name ) )
+    {
+        wait ( message );
+    }
+    else
+    if ( ! strcmp ( "exec", command_name ) )
+    {
+        execute ( message );
+    }
+    else
+    if ( ! strcmp ( "start", command_name ) )
+    {
+        start ( );
+    }
+    else
+    if ( ! strcmp ( "alias", command_name ) )
+    {
+      addAlias ( message );
+    }
+    else
+    if ( ! strcmp ( "sayName", command_name ) )
+    {
+      sayName ( );
+    }
+    else
+    {
+        /*
+         * If the command is not any of the "special" commands
+         * above, then it's a "normal" command.
+         * That means we run it with a child process instance of
+         * qrsh_run, which will save all its data in the qrsh dir.
+         */
+        stringstream ss;
+        ss << qrsh_run_path 
+           << ' '
+           << data_dir.str()
+           << ' '
+           << s;
+    
+        if ( ! fork() )
+        {
+            char ** argv = getArgs ( ss.str().c_str() );
+            execv ( qrsh_run_path.c_str(), argv );
+            perror ( "qrsh_server: execv error: " );
+        }
+    }
+}
+
+
+
+void 
+QrshServer::received ( Message & message ) 
+{
+    if ( myMessage ( message ) )
+        runCommand ( message );
+}
+
+
+
+
+
+/*
+ *  fixme mick Mon Aug  3 10:29:26 EDT 2009
+ *  argv[1] server name
+ *  argv[2] qrsh exe path
+ *  argv[3] host
+ *  argv[4] port
+ */
+int
+main ( int /*argc*/, char** argv )
+{
+    const char* host = argv[3];
+    int port = atoi(argv[4]);
+    Connection connection;
+    Message msg;
+
+    srand ( getpid() );
+
+    try
+    {
+        connection.open ( host, port );
+        Session session =  connection.newSession();
+
+
+        // Declare queues.
+        string myQueue = session.getId().getName();
+        session.queueDeclare ( arg::queue=myQueue, 
+                               arg::exclusive=true,
+                               arg::autoDelete=true);
+
+        session.exchangeBind ( arg::exchange="amq.fanout", 
+                               arg::queue=myQueue, 
+                               arg::bindingKey="my-key");
+  
+        // Create a server and subscribe it to my queue.
+        SubscriptionManager subscriptions ( session );
+        QrshServer server ( subscriptions, 
+                            argv[1],         // server name
+                            argv[2],         // qrsh exe path
+                            host,
+                            port
+                          );
+        subscriptions.subscribe ( server, myQueue );  
+
+        // Receive messages until the subscription is cancelled
+        // by QrshServer::received()
+        subscriptions.run();
+
+        connection.close();
+    }
+    catch(const exception& error) 
+    {
+        cout << error.what() << endl;
+        return 1;
+    }
+
+    return 0;
+}
+
+
+
+

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/10_all
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/10_all?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/10_all (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/10_all Mon Aug  3 18:07:12 2009
@@ -0,0 +1,30 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+echo "Asking all servers to say their names... "
+qrsh 127.0.0.1 5813 \
+     all sayName
+
+
+
+

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/10_all
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/1_remote_run
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/1_remote_run?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/1_remote_run (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/1_remote_run Mon Aug  3 18:07:12 2009
@@ -0,0 +1,26 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+
+./qrsh 127.0.0.1 5813 \
+       mrg23 command_1 /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/1_remote_run
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/2_forever
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/2_forever?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/2_forever (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/2_forever Mon Aug  3 18:07:12 2009
@@ -0,0 +1,26 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+
+./qrsh 127.0.0.1 5813 \
+       mrg23 command_2 /home/mick/redhat/qrsh/qrsh_run/forever foo bar baz

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/2_forever
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/3_kill_it
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/3_kill_it?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/3_kill_it (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/3_kill_it Mon Aug  3 18:07:12 2009
@@ -0,0 +1,27 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+echo "Killing command 2... "
+./qrsh 127.0.0.1 5813 \
+       mrg23 exec kill -9 command_2 
+

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/3_kill_it
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/4_wait_for_it
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/4_wait_for_it?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/4_wait_for_it (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/4_wait_for_it Mon Aug  3 18:07:12 2009
@@ -0,0 +1,26 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+./qrsh 127.0.0.1 5813 \
+       mrg23 exec_wait /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz
+echo "my_command returned an exit code of $?"

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/4_wait_for_it
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/5_exited
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/5_exited?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/5_exited (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/5_exited Mon Aug  3 18:07:12 2009
@@ -0,0 +1,64 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+path=/home/mick/redhat/qrsh/qrsh_run
+
+echo "Running command_3 ..."
+./qrsh 127.0.0.1 5813 \
+       mrg23 command_3 $path/my_command foo bar baz
+
+echo "Now I do some other stuff..."
+sleep 1
+echo "And then some more stuff..."
+sleep 1
+echo "and so on..."
+sleep 1
+
+echo "Now I'm waiting for command_3 ..."
+./qrsh 127.0.0.1 5813 \
+       mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+       mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+       mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+       mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+./qrsh 127.0.0.1 5813 \
+       mrg23 exited command_3
+echo "has command_3 exited: $? ."
+sleep 5
+
+
+

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/5_exited
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/6_get
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/6_get?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/6_get (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/6_get Mon Aug  3 18:07:12 2009
@@ -0,0 +1,29 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+echo "getting /tmp/foo ..."
+./qrsh 127.0.0.1 5813 \
+       mrg23 get /tmp/foo
+
+
+

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/6_get
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/7_get_output
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/7_get_output?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/7_get_output (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/7_get_output Mon Aug  3 18:07:12 2009
@@ -0,0 +1,44 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+echo "Run a command..."
+./qrsh 127.0.0.1 5813 \
+       mrg23 command_4 /home/mick/redhat/qrsh/qrsh_run/my_command foo bar baz
+
+echo "Wait for a while..."
+sleep 20
+
+echo "Get stderr output:"
+echo "-------------  begin stderr ---------------"
+./qrsh 127.0.0.1 5813 \
+       mrg23 get command_4 stderr
+echo "-------------  end stderr ---------------"
+echo " "
+echo " "
+echo " "
+echo "Get stdout output:"
+echo "-------------  begin stdout ---------------"
+./qrsh 127.0.0.1 5813 \
+       mrg23 get command_4 stdout
+echo "-------------  end stdout ---------------"
+

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/7_get_output
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/8_any
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/8_any?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/8_any (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/8_any Mon Aug  3 18:07:12 2009
@@ -0,0 +1,43 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+       any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+       any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+       any sayName
+sleep 1
+echo "asking any server to say his name ..."
+./qrsh 127.0.0.1 5813 \
+       any sayName
+sleep 1
+
+
+
+

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/8_any
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/9_alias
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/9_alias?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/9_alias (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/9_alias Mon Aug  3 18:07:12 2009
@@ -0,0 +1,38 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#! /bin/bash
+
+# Make a group of two of the servers, using "alias",
+# and send the group a command.
+
+qrsh 127.0.0.1 5813 \
+     mrg22 alias group_1
+qrsh 127.0.0.1 5813 \
+     mrg23 alias group_1
+
+echo "Asking group_1 to say their names... "
+qrsh 127.0.0.1 5813 \
+     group_1 sayName
+
+
+
+

Propchange: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/9_alias
------------------------------------------------------------------------------
    svn:executable = *

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_example_command.cpp Mon Aug  3 18:07:12 2009
@@ -0,0 +1,52 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+
+main ( int argc, char ** argv )
+{
+    fprintf ( stderr, "Hello, I am the Example Child!\n");
+    fprintf ( stderr, "my arguments %d are:\n", argc - 1 );
+    fprintf ( stdout, "And hello to stdout, too!\n");
+
+    int i;
+    for ( i = 1; i < argc; ++ i )
+    {
+        fprintf ( stderr, "arg %d: |%s|\n", i, argv[i] );
+    }
+
+    for ( i = 0; i < 15; ++ i )
+    {
+        fprintf ( stderr, "child sleeping...\n" );
+        sleep ( 1 );
+    }
+
+    fprintf ( stderr, "child exiting with code 13.\n" );
+
+    return 13;
+}
+
+
+
+

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_forever.cpp
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_forever.cpp?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_forever.cpp (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qrsh_forever.cpp Mon Aug  3 18:07:12 2009
@@ -0,0 +1,50 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+
+#include <stdio.h>
+#include <unistd.h>
+
+
+
+main ( int argc, char ** argv )
+{
+    fprintf ( stderr, "Hello, I am the Forever Example Child!\n");
+    fprintf ( stderr, "my %d arguments are:\n", argc - 1 );
+
+    int i;
+    for ( i = 1; i < argc; ++ i )
+        fprintf ( stderr, "arg %d: |%s|\n", i, argv[i] );
+
+    for ( i = 0; i >= 0; ++ i )
+    {
+        fprintf ( stderr, "child sleeping forever %d ...\n" , i);
+        sleep ( 1 );
+    }
+
+    fprintf ( stderr, "child exiting with code 12.\n" );
+
+    return 12;
+}
+
+
+
+

Added: qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qsh_doc.txt
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qsh_doc.txt?rev=800481&view=auto
==============================================================================
--- qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qsh_doc.txt (added)
+++ qpid/trunk/qpid/cpp/src/tests/qrsh_utils/qsh_doc.txt Mon Aug  3 18:07:12 2009
@@ -0,0 +1,309 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */ 
+
+##############################################
+  qrsh: a Qpid-based remote shell utility
+
+  Last updated:  3 Aug 09    Mick Goulish
+##############################################
+
+
+
+=============================
+Overview
+=============================
+
+  You're writing a multi-box test, and you want to write a 
+  shell script in which you start processes on other boxes 
+  and kill them (or send arbitrary signals to them).  
+
+  But ssh doesn't let you signal them, and bash isn't the 
+  greatest language in the world for creating data structures 
+  (like you need to associate the PIDs with box names and 
+  executable names.)
+
+  Qsh is a utility implemented on Qpid that you can use from 
+  within your bash script, or any other scripting language.
+  With it, you can:
+
+    1. run any executable on any box in your cluster.
+
+    2. don't worry about PIDs and box-names.  You associate 
+       your own abstract names with the executable instances, 
+       and then use those names in the rest of your script.  
+       I.e. "broker_1" "sender_3" etc.
+
+    3. Launch the executable and wait until it returns, and
+       get its exit code.
+
+    4. Launch your executable and do other stuff, then come 
+       back later and see if it has exited.
+
+    5. Get whatever it sent to stdout or stderr.
+
+    6. Get the contents of any other file.
+
+    7. send a command to all your boxes at once
+
+    8. send a command to a randomly selected box.
+
+    9. define groups of boxes, and send a command simultaneously
+       to all boxes in a given group.
+
+
+
+
+=============================
+Using It
+=============================
+
+   1. You need to run a Qpid broker.
+
+   2. You start a Qpid client ( which is called a qrsh_server )
+      on all the boxes you care about.  And you give them all 
+      names like "mrg13", "mrg14" etc.  The names can be anything
+      you want, but I've always used one qrsh_server per box, 
+      and given it the box name.   ( However, you can run two on
+      one box, they won't collide. )
+
+   3. After you start all servers, send a "start" command to any
+      one of them:
+
+   4. The qrsh_servers use the fanout exchange to talk to each 
+      other.
+
+   5. In your script, you run an executable called "qrsh".  It knows
+      how to talk to the servers, do what you want, and retrieve 
+      the data you want.
+
+
+   example start script:  (this does 4 servers on the same box)
+   -------------------------------------------------------------
+
+       echo "Starting server mrg22 ..."
+       ./qrsh_server mrg22  ./qrsh_run 127.0.0.1  5813  &
+
+       echo "Starting server mrg23 ..."
+       ./qrsh_server mrg23  ./qrsh_run 127.0.0.1  5813  &
+
+       echo "Starting server mrg24 ..."
+       ./qrsh_server mrg24  ./qrsh_run 127.0.0.1  5813  &
+
+       echo "Starting server mrg25 ..."
+       ./qrsh_server mrg25  ./qrsh_run 127.0.0.1  5813  &
+
+       echo "Issuing start command..."
+       sleep 2
+       ./qrsh 127.0.0.1  5813 mrg22 start
+       sleep 1
+
+       echo "Ready."
+
+       # end of script.
+
+
+
+
+
+
+=============================
+Qrsh Syntax
+=============================
+  
+     qrsh  host port server_name  command_name  arg*
+
+
+       "host" and "port" specify the Qpid server to connect to.
+
+       "server_name" can be anything you want.  I always use the name 
+         of the box that the server is running on.
+
+       "command_name" is the name that you choose to assign to 
+         the process you are running.  Each process that you decide
+         to name must have a unique name within this script.
+
+         Or it could be a reserved command name, that Qsh 
+         interprets in a special way.
+
+         Reserved command names are:
+             
+             exec
+             exec_wait
+             exited
+             get
+
+         "exec" means "interpret the rest of the command line as a
+           command to be executed by the designated server.
+
+         "exec_wait" means same as "exec", but wait for the command
+           to terminate, and return its exit code.
+
+         "exited" -- you provide 1 arg, which is an abstract 
+           process name.  qrsh returns 1 if that process has exited, 
+           else 0.
+
+         "get" -- you provide one arg which is a path.  qrsh returns
+           (by printing to stdout) the contents of that file.
+
+       "arg*" is zero or more arguments.  They are interpreted 
+         differently depending on whether you are using one of
+         the above reserved command names, or making up your own
+         abstract name for a command.
+
+
+
+
+=============================
+Examples
+=============================
+
+  1. Run a process on a remote box.
+     
+         qrsh mrg23 command_1 /usr/sbin/whatever foo bar baz
+
+     Returns immediately.
+
+
+
+  2. Kill a process that you started earlier:
+
+         qrsh mrg23 exec kill -9 command_1
+
+     After the word "exec" put any command line you want.
+     The server you're sending this to will replace all abstract
+     names in the command with process IDs.  ( In this example, 
+     just the word "command_1" will be replaced. )  Then it will 
+     execute the command.
+
+
+
+  3. Execute a command, and wait for it to finish
+
+         qrsh mrg23 exec_wait command_name args
+
+
+
+  4. Check on whether a command you issude earlier has exited.
+
+         ./qrsh mrg23 exited command_3
+
+     Returns 1 if it has exited, else 0.
+
+
+
+  5. Get the contents of a file from the remote system:
+
+        ./qrsh mrg23 get /tmp/foo
+
+     Prints the contents to stdout.
+
+
+
+  6. Send a command to all servers at once:
+
+        # This example causes them all to print thir names to stderr.
+        ./qrsh all sayName
+
+
+  7. Define a group of servers and send a command to that group.
+
+      #! /bin/bash
+      
+      # Make a group of two of the servers, using "alias",
+      # and send the group a command.
+      
+      qrsh 127.0.0.1 5813 \
+           mrg22 alias group_1
+
+      qrsh 127.0.0.1 5813 \
+          mrg23 alias group_1
+      
+      echo "Asking group_1 to say their names... "
+      qrsh 127.0.0.1 5813 \
+           group_1 sayName
+
+      # end of script.
+      
+  
+
+
+  8. Execute a command and get its stdout and stderr contents.
+
+        #! /bin/bash
+
+        echo "Run a command..."
+        ./qrsh 127.0.0.1 5813 \
+               mrg23 command_4 my_command foo bar baz
+
+        echo "Wait for a while..."
+        sleep 10
+
+        echo "Get stderr output:"
+        echo "-------------  begin stderr ---------------"
+        ./qrsh 127.0.0.1 5813 \
+               mrg23 get command_4 stderr
+        echo "-------------  end stderr ---------------"
+        echo " "
+
+        echo " "
+        echo "Get stdout output:"
+        echo "-------------  begin stdout ---------------"
+        ./qrsh 127.0.0.1 5813 \
+               mrg23 get command_4 stdout
+        echo "-------------  end stdout ---------------"
+
+        # end of script.
+    
+
+
+
+  9. Send a command to one of your servers, selected
+     at random.
+
+           #! /bin/bash
+
+           # I do it multiple times here, so I can see 
+           # that it really is selecting randomly.
+
+          echo "asking any server to say his name ..."
+          ./qrsh 127.0.0.1 5813 \
+                 any sayName
+          sleep 1
+
+          echo "asking any server to say his name ..."
+          ./qrsh 127.0.0.1 5813 \
+                 any sayName
+          sleep 1
+
+          echo "asking any server to say his name ..."
+          ./qrsh 127.0.0.1 5813 \
+                 any sayName
+          sleep 1
+
+          echo "asking any server to say his name ..."
+          ./qrsh 127.0.0.1 5813 \
+                 any sayName
+
+        # end of script.
+
+
+
+



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org


Mime
View raw message