Index: /trunk/Ohana/src/libohana/include/ohana.h
===================================================================
--- /trunk/Ohana/src/libohana/include/ohana.h	(revision 7928)
+++ /trunk/Ohana/src/libohana/include/ohana.h	(revision 7929)
@@ -173,4 +173,5 @@
 int ExpectCommand (int device, int length, double timeout, IOBuffer *buffer);
 int SendMessage (int device, char *format, ...);
+int SendMessageFixed (int device, int length, char *messge);
 int SendCommand (int device, int length, char *format, ...);
 int SendCommandV (int device, int length, char *format, va_list argp);
Index: /trunk/Ohana/src/libohana/src/CommOps.c
===================================================================
--- /trunk/Ohana/src/libohana/src/CommOps.c	(revision 7928)
+++ /trunk/Ohana/src/libohana/src/CommOps.c	(revision 7929)
@@ -88,4 +88,14 @@
 }
 
+/* send a message of known size, sending the size first */
+int SendMessageFixed (int device, int length, char *message) {
+
+  int status;
+
+  status = SendCommand (device, 16, "NBYTES: %6d", length);
+  status = SendCommand (device, length, message);
+  return (status);
+}
+
 int SendCommand (int device, int length, char *format, ...) {
 
@@ -108,5 +118,4 @@
   vsnprintf (string, length + 1, format, argp);
 
-  /* fprintf (stderr, "msg: %s\n", string); */
   write (device, string, length);
   free (string);
Index: /trunk/Ohana/src/libohana/src/IOBufferOps.c
===================================================================
--- /trunk/Ohana/src/libohana/src/IOBufferOps.c	(revision 7928)
+++ /trunk/Ohana/src/libohana/src/IOBufferOps.c	(revision 7929)
@@ -107,5 +107,5 @@
   Nbyte = vsnprintf (&tmp, 0, format, argp);
 
-  if (buffer[0].Nbuffer + Nbyte + 1 >= buffer[0].Nalloc) {
+  if (buffer[0].Nbuffer + Nbyte + 1>= buffer[0].Nalloc) {
     buffer[0].Nalloc = buffer[0].Nbuffer + Nbyte + 64;
     REALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
@@ -113,5 +113,5 @@
 
   vsnprintf (&buffer[0].buffer[buffer[0].Nbuffer], Nbyte + 1, format, argp);
-  buffer[0].Nbuffer += Nbyte + 1;
+  buffer[0].Nbuffer += Nbyte;
   return (TRUE);
 }
Index: /trunk/Ohana/src/opihi/doc/pantasks.txt
===================================================================
--- /trunk/Ohana/src/opihi/doc/pantasks.txt	(revision 7928)
+++ /trunk/Ohana/src/opihi/doc/pantasks.txt	(revision 7929)
@@ -1,2 +1,25 @@
+
+- additional issues:
+
+  - missing dependency for shell.h?
+  - should not return an error message in client if command is not found
+  - server input needs to place files for input on a stack which is 
+    actually loaded by the RunScheduler loop
+  - have the client run a special multicommand function which passes 
+    any unfound commands along to the server.  the server should not 
+    be running multicommand, but it probably does not hurt.
+    (the client is not allowed to send ';' to the server)
+  - the multicommand needs to be available in the 'for' and other loops
+    this probably means unifying the client and non-client forms.  
+    how does multiclient get the value of the server?  I tend to use
+    globals for things like that, which is probably not the best 
+    practice.  is the client form of the tool generic? are there other
+    circumstances which would use a client/server beyond pantasks?
+    maybe pcontrol?  
+
+    the two pieces of information which need to be carried to the
+    multicommand and command functions in client/server mode are the 
+    server socket and the verbosity of the error messages.  these could
+    be defined on startup with globals and an init function of some sort.
 
 I need to do some serious work on the output messages in order 
Index: /trunk/Ohana/src/opihi/include/pantasks.h
===================================================================
--- /trunk/Ohana/src/opihi/include/pantasks.h	(revision 7928)
+++ /trunk/Ohana/src/opihi/include/pantasks.h	(revision 7929)
@@ -129,4 +129,5 @@
 
 void InitPantasks ();
+void InitPantasksServer ();
 void InitPantasksClient ();
 void InitTasks ();
Index: /trunk/Ohana/src/opihi/include/shell.h
===================================================================
--- /trunk/Ohana/src/opihi/include/shell.h	(revision 7928)
+++ /trunk/Ohana/src/opihi/include/shell.h	(revision 7929)
@@ -49,4 +49,5 @@
 int           multicommand          	PROTO((char *line));
 int           command               	PROTO((char *, char **));
+int           multicommand_client      	PROTO((char *line, int));
 int           command_client           	PROTO((char *, char **));
 char         *expand_vars           	PROTO((char *line));
@@ -146,4 +147,5 @@
 FILE *gprintGetFile (gpDest dest);
 int gprint (gpDest dest, char *format, ...);
+int gwrite (char *buffer, int size, int N, gpDest dest);
 
 # endif
Index: /trunk/Ohana/src/opihi/lib.shell/Makefile
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/Makefile	(revision 7928)
+++ /trunk/Ohana/src/opihi/lib.shell/Makefile	(revision 7929)
@@ -21,4 +21,5 @@
 $(SDIR)/ListOps.$(ARCH).o	   	\
 $(SDIR)/command.$(ARCH).o               \
+$(SDIR)/command_client.$(ARCH).o        \
 $(SDIR)/CommandOps.$(ARCH).o		\
 $(SDIR)/errors.$(ARCH).o		\
@@ -37,4 +38,5 @@
 $(SDIR)/memstr.$(ARCH).o                \
 $(SDIR)/multicommand.$(ARCH).o          \
+$(SDIR)/multicommand_client.$(ARCH).o   \
 $(SDIR)/parse.$(ARCH).o                 \
 $(SDIR)/parse_commands.$(ARCH).o	\
Index: /trunk/Ohana/src/opihi/lib.shell/command_client.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/command_client.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/lib.shell/command_client.c	(revision 7929)
@@ -2,6 +2,8 @@
 # define VERBOSE 0
 
-/* this function acts like the standard command parser,
-   but skips the expansion of variables and vectors */
+// this function is identical to the normal command.c function,
+// but it returns -1 for a missing command and does not echo the
+// 'missing command' error message
+
 int command_client (char *line, char **outline) {
 
@@ -17,4 +19,12 @@
   }
 
+  /* expand anything of the form $fred or $fred$sam, etc */ 
+  line = expand_vars (line);     /* line is freed here, new one allocated */
+  /* expand anything of the form fred[N] */ 
+  line = expand_vectors (line);  /* line is freed here, new one allocated */
+  /* solve math expresions, assign variable, if needed */
+  line = parse (line);        /* line is freed here, new one allocated */
+  /* any entry in line of the form {foo} returns value or tmp vector / buffer */
+
   /* we may have reallocated line, return new pointer */
   *outline = line;
@@ -27,7 +37,8 @@
   for (i = 0; i < argc; i++) targv[i] = argv[i];
 
-  cmd = MatchCommand (argv[0], TRUE, FALSE);
+  // use non-verbose mode to skip 'missing command' error message
+  cmd = MatchCommand (argv[0], FALSE, FALSE);
   if (cmd == NULL) {
-    status = FALSE;
+    status = -1;
   } else {
     free (argv[0]);
@@ -40,4 +51,12 @@
   free (argv);
 
+  if (!status) {
+    char *msg;
+    msg = get_variable_ptr ("ERRORMSG");
+    if (msg != (char *) NULL) gprint (GP_ERR, "%s\n", msg);
+  }
+
+  set_int_variable ("STATUS", status);
+  if (VERBOSE) gprint (GP_ERR, "command: %s, status: %d\n", line, status);
   return (status);
 }
Index: /trunk/Ohana/src/opihi/lib.shell/gprint.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/gprint.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/lib.shell/gprint.c	(revision 7929)
@@ -77,5 +77,5 @@
     return (&streams[i]);
   }
-  fprintf (STDERR, "programming error: gprintInit not called for thread\n");
+  fprintf (stderr, "programming error: gprintInit not called for thread\n");
   abort ();
 }
@@ -90,5 +90,9 @@
   if (stream[0].file != NULL) {
     fflush (stream[0].file);
-    if (stream[0].file != stdout) fclose (stream[0].file);
+    if (stream[0].file == stdout) goto skip_close;
+    if (stream[0].file == stderr) goto skip_close;
+    fclose (stream[0].file);
+
+  skip_close:
     stream[0].file = NULL;
   }
@@ -146,5 +150,5 @@
   stream[0].file = fopen (filename, "a");
   if (stream[0].file == NULL) {
-    fprintf (STDERR, "cannot open file %s\n", filename);
+    fprintf (stderr, "cannot open file %s\n", filename);
     stream[0].file = (dest == GP_LOG) ? stdout : stderr;
   }
Index: /trunk/Ohana/src/opihi/pantasks/ListenClients.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/ListenClients.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/pantasks/ListenClients.c	(revision 7929)
@@ -43,6 +43,8 @@
   struct timeval timeout;
   IOBuffer *outbuffer;
+  IOBuffer testbuffer;
 
   InitClients ();
+  gprintInit ();  // each thread needs to init the printing system
 
   while (0) {
@@ -131,18 +133,75 @@
 
       /* we now have a possible command from the client: run it */
+      /* in this thread, we set the print output destination to be an
+	 internal buffer, which we dump at the end of the execution */
       /* XXX : we need to handle ; in the client-parsing of commands */
       stripwhite (line);
       if (*line) {
-	if (1) gprint (GP_ERR, "got command: %s\n", line);
-	SetOutBuffer ();
+
+	if (1) fprintf (stderr, "got command: %s\n", line);
+
+	/* this works: we can send a simple message */
+	# if 0
+	SendMessage (clients[i], "first");
+	SendMessage (clients[i], "second");
+	# endif
+
+	/* this works: we can send a message using the IOBuffers */
+	# if 0
+	InitIOBuffer (&testbuffer, 64);
+	PrintIOBuffer (&testbuffer, "this is a test\n");
+	SendMessageFixed (clients[i], testbuffer.Nbuffer, testbuffer.buffer);
+	PrintIOBuffer (&testbuffer, "this is a second test\n");
+	SendMessageFixed (clients[i], testbuffer.Nbuffer, testbuffer.buffer);
+	# endif
+
+	/* this works: we can use the printing system to write a message */
+	# if 0
+	gprintSetBuffer (GP_LOG);
+	gprint (GP_LOG, "test is a test line\n");
+	outbuffer = gprintGetBuffer (GP_LOG);
+	SendMessageFixed (clients[i], outbuffer[0].Nbuffer, outbuffer[0].buffer);
+	
+	gprint (GP_LOG, "test is a second test line\n");
+	outbuffer = gprintGetBuffer (GP_LOG);
+	SendMessageFixed (clients[i], outbuffer[0].Nbuffer, outbuffer[0].buffer);
+	# endif
+
+	/* this works: we can use the gprint service */
+	# if 0
+	gprintSetBuffer (GP_LOG);
+	gprint (GP_LOG, "test is a test line\n");
 	status = multicommand (line);
-	outbuffer = GetOutBuffer ();
-
-	gprint (GP_ERR, "send message: %d bytes\n", outbuffer[0].Nbuffer);
-	gwrite (outbuffer[0].buffer, 1, outbuffer[0].Nbuffer, GP_ERR);
-	gprint (GP_ERR, "end message\n");
-	
-	SendMessage (clients[i], outbuffer[0].buffer);
-	SetOutfile ("stdout");
+
+	outbuffer = gprintGetBuffer (GP_LOG);
+	SendMessageFixed (clients[i], outbuffer[0].Nbuffer, outbuffer[0].buffer);
+	gprintSetFile (GP_LOG, "stdout");
+	
+	SendMessage (clients[i], "second");
+	# endif
+
+	/* this only kind of works: it acts as if we hang */
+	# if 1
+	gprintSetBuffer (GP_LOG);
+	gprintSetBuffer (GP_ERR);
+
+	// gprint (GP_LOG, "test is a test stdout\n");
+	// gprint (GP_ERR, "test is a test stderr\n");
+
+	status = multicommand (line);
+	fprintf (stderr, "sending response\n");
+
+	// return the stderr messages first
+	outbuffer = gprintGetBuffer (GP_ERR);
+	SendMessageFixed (clients[i], outbuffer[0].Nbuffer, outbuffer[0].buffer);
+	fprintf (stderr, "sent stderr\n");
+
+	outbuffer = gprintGetBuffer (GP_LOG);
+	SendMessageFixed (clients[i], outbuffer[0].Nbuffer, outbuffer[0].buffer);
+	fprintf (stderr, "sent stdout\n");
+	
+	gprintSetFile (GP_LOG, "stdout");
+	gprintSetFile (GP_ERR, "stderr");
+	# endif
       }
       free (line);
Index: /trunk/Ohana/src/opihi/pantasks/Makefile
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/Makefile	(revision 7928)
+++ /trunk/Ohana/src/opihi/pantasks/Makefile	(revision 7929)
@@ -48,4 +48,5 @@
 $(SDIR)/kill.$(ARCH).o \
 $(SDIR)/delete.$(ARCH).o \
+$(SDIR)/server.$(ARCH).o \
 $(SDIR)/verbose.$(ARCH).o \
 $(SDIR)/controller.$(ARCH).o \
Index: /trunk/Ohana/src/opihi/pantasks/SocketOps.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/SocketOps.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/pantasks/SocketOps.c	(revision 7929)
@@ -30,4 +30,6 @@
   Address[0].sin_addr.s_addr = INADDR_ANY; // use this line to bind any address / port?
 
+retry_server:
+
 # if (0)  
   status = inet_aton (hostip, &Address[0].sin_addr);
@@ -49,7 +51,27 @@
   status = bind (InitSocket, (struct sockaddr *) Address, length);
   if (status == -1) {
+    fprintf (stderr, "errno: %d\n", errno);
+    fprintf (stderr, "EACCES: %d\n", EACCES);
+    fprintf (stderr, "EBADF: %d\n", EBADF);
+    fprintf (stderr, "EINVAL: %d\n", EINVAL);
+    fprintf (stderr, "ENOTSOCK: %d\n", ENOTSOCK);
+    fprintf (stderr, "EFAULT: %d\n", EFAULT);
+    fprintf (stderr, "ELOOP: %d\n", ELOOP);
+    fprintf (stderr, "ENAMETOOLONG: %d\n", ENAMETOOLONG);
+    fprintf (stderr, "ENOENT: %d\n", ENOENT);
+    fprintf (stderr, "ENOMEM: %d\n", ENOMEM);
+    fprintf (stderr, "ENOTDIR: %d\n", ENOTDIR);
+    fprintf (stderr, "EROFS: %d\n", EROFS);
+
+    Address[0].sin_port ++;
+    if (Address[0].sin_port > MY_PORT + 10) exit (2);
+    fprintf (stderr, "trying next port: %d\n", Address[0].sin_port);
+    goto retry_server;
+
     perror ("bind: ");
     exit (2);
   }
+  /* repeated starts of the server are limited by xinetd or something:
+     requires 60sec timeout of the selected socket */
 
   status = listen (InitSocket, 10);
@@ -140,4 +162,6 @@
   Address.sin_family = AF_INET;
   Address.sin_port   = MY_PORT;
+
+retry_client:
   status = inet_aton (hostip, &Address.sin_addr);
   if (!status) {
@@ -156,4 +180,10 @@
   status = connect (InitSocket, (struct sockaddr *) &Address, length);
   if (status == -1) {
+    if (errno == ECONNREFUSED) {
+      Address.sin_port ++;
+      if (Address.sin_port > MY_PORT + 10) exit (2);
+      fprintf (stderr, "trying next port: %d\n", Address.sin_port);
+      goto retry_client;
+    }
     perror ("connect: ");
     exit (2);
Index: /trunk/Ohana/src/opihi/pantasks/client_shell.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/client_shell.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/pantasks/client_shell.c	(revision 7929)
@@ -4,5 +4,5 @@
 int client_shell (int argc, char **argv) {
 
-  int Nbad, status, server;
+  int i, Nbad, status, server;
   char *line, *outline, *prompt, *history;
   char hostname[256], PASSWORD[256];
@@ -55,10 +55,14 @@
     /* XXX the exit status of command does not allow us
        to distinguish 'failed command' and 'command not found' */
-    status = command (line, &outline);
-    if (outline == NULL) {
-      gprint (GP_ERR, "programming error: command_client returned NULL\n");
-      exit (2);
-    }
+    /* XXX eventually replace this with a multicommand parsing */
+    status = multicommand_client (line, server);
+    add_history (line);
+    append_history (1, history);
 
+    free (line);
+  }
+}
+
+# if 0
     /* command was not caught by client, send to server */
     if (*outline && !status ) {
@@ -70,11 +74,22 @@
       // XXX add this in and print to stdout
       status = ExpectMessage (server, 2.0, &message);
-      gprint (GP_ERR, "got message: %d bytes\n", message.Nbuffer);
-      gwrite (message.buffer, 1, message.Nbuffer, GP_ERR);
-      gprint (GP_ERR, "end message\n");
+      // fprintf (stderr, "got stdout message: %d bytes\n", message.Nbuffer);
+      fwrite (message.buffer, 1, message.Nbuffer, stderr);
+      // fprintf (stderr, "end message\n");
+
+      // fprintf (stderr, "got message: %d bytes\n", message.Nbuffer);
+      // for (i = 0; i < message.Nbuffer; i++) {
+      // fprintf (stderr, "%d %d %c\n", i, message.buffer[i], message.buffer[i]);
+      // }
+      // fwrite (message.buffer, 1, message.Nbuffer, stderr);
+      // fprintf (stderr, "end message\n");
+
+      // XXX add this in and print to stdout
+      status = ExpectMessage (server, 2.0, &message);
+      // fprintf (stderr, "got stderr message: %d bytes\n", message.Nbuffer);
+      fwrite (message.buffer, 1, message.Nbuffer, stderr);
+      // fprintf (stderr, "end message\n");
     }
-    free (outline);
-  }
-}
+# endif
 
 /* 
Index: /trunk/Ohana/src/opihi/pantasks/init.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/init.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/pantasks/init.c	(revision 7929)
@@ -64,2 +64,25 @@
 
 }
+
+int server         PROTO((int, char **));
+
+static Command server_cmds[] = {  
+  {"server",  server,   "server-specific commands"},
+}; 
+
+void InitPantasksServer () {
+  
+  int i;
+
+  InitTasks ();
+  InitJobs ();
+  InitJobIDs ();
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+  for (i = 0; i < sizeof (server_cmds) / sizeof (Command); i++) {
+    AddCommand (&server_cmds[i]);
+  }
+
+}
Index: /trunk/Ohana/src/opihi/pantasks/pantasks_client.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/pantasks_client.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/pantasks/pantasks_client.c	(revision 7929)
@@ -14,4 +14,6 @@
   InitData ();
   InitPantasksClient ();
+
+  gprintInit ();
 
   rl_readline_name = opihi_name;
Index: /trunk/Ohana/src/opihi/pantasks/pantasks_server.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/pantasks_server.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/pantasks/pantasks_server.c	(revision 7929)
@@ -29,7 +29,7 @@
   InitBasic ();
   InitData ();
-  InitPantasks ();
+  InitPantasksServer ();
   
-  InitPrint ();
+  gprintInit ();  // each thread needs to init the printing system
 
   // signal (SIGPIPE, gotsignal);
@@ -47,5 +47,5 @@
 
   // pthread_create (&thread, NULL, &RunScheduler, NULL);
-  // pthread_create (&thread, NULL, &pantasks_RunController, NULL);
+  // pthread_create (&thread, NULL, &RunController, NULL);
 
   /* in this loop, we listen for incoming connections, validate, and
Index: /trunk/Ohana/src/opihi/pantasks/run.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/run.c	(revision 7928)
+++ /trunk/Ohana/src/opihi/pantasks/run.c	(revision 7929)
@@ -1,3 +1,10 @@
 # include "pantasks.h"
+
+// XXX for client/server, we need to simply start or stop the
+// appropriate threads
+// with one thread for each of the major actions, this would
+// make it easy to keep the controller running and stop the 
+// scheduler (don't run CheckTasks, but run everything else 
+// until nothing is left...
 
 int run (int argc, char **argv) {
