Index: /trunk/Ohana/src/opihi/cmd.astro/multifit.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.astro/multifit.c	(revision 8296)
+++ /trunk/Ohana/src/opihi/cmd.astro/multifit.c	(revision 8297)
@@ -141,5 +141,5 @@
     }
   }
-  gaussj (a, Ndim, b, 1);
+  dgaussj (a, Ndim, b, 1);
 
   Ny = 0;
Index: /trunk/Ohana/src/opihi/cmd.basic/cd.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.basic/cd.c	(revision 8296)
+++ /trunk/Ohana/src/opihi/cmd.basic/cd.c	(revision 8297)
@@ -3,6 +3,12 @@
 int cd (int argc, char **argv) {
 
-  int status;
+  int N, VERBOSE, status;
   char *cwd;
+
+  VERBOSE = TRUE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = FALSE;
+  }
 
   if (argc != 2) {
@@ -17,5 +23,5 @@
       return (FALSE);
     }
-    gprint (GP_LOG, "cwd: %s\n", cwd);
+    if (VERBOSE) gprint (GP_LOG, "cwd: %s\n", cwd);
     ohana_memregister (cwd);
     free (cwd);
@@ -30,8 +36,16 @@
 int pwd (int argc, char **argv) {
 
-  char *cwd;
+  int N;
+  char *cwd, *var;
+
+  var = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    var = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
 
   if (argc != 1) {
-    gprint (GP_ERR, "USAGE: pwd\n");
+    gprint (GP_ERR, "USAGE: pwd [-var variable]\n");
     return (FALSE);
   }
@@ -39,7 +53,13 @@
   if ((cwd = getcwd(NULL, 64)) == NULL) {
     gprint (GP_ERR, "error getting cwd\n");
+    if (var != NULL) free (var);
     return (FALSE);
   }
-  gprint (GP_LOG, "cwd: %s\n", cwd);
+  if (var == NULL) {
+      gprint (GP_LOG, "cwd: %s\n", cwd);
+  } else {
+      set_str_variable (var, cwd);
+      free (var);
+  }
   ohana_memregister (cwd);
   free (cwd);
Index: /trunk/Ohana/src/opihi/cmd.data/fit.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/fit.c	(revision 8296)
+++ /trunk/Ohana/src/opihi/cmd.data/fit.c	(revision 8297)
@@ -118,5 +118,5 @@
       }
     }
-    if (!gaussj (c, nterm, b, 1)) goto escape;
+    if (!dgaussj (c, nterm, b, 1)) goto escape;
 
     /* generate fitted values */
Index: /trunk/Ohana/src/opihi/cmd.data/fit2d.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/fit2d.c	(revision 8296)
+++ /trunk/Ohana/src/opihi/cmd.data/fit2d.c	(revision 8297)
@@ -168,5 +168,5 @@
     }
 
-    gaussj (c, wterm, b, 1);
+    dgaussj (c, wterm, b, 1);
 
     gprint (GP_ERR, "inverse:\n");
Index: /trunk/Ohana/src/opihi/cmd.data/gaussj.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/gaussj.c	(revision 8296)
+++ /trunk/Ohana/src/opihi/cmd.data/gaussj.c	(revision 8297)
@@ -33,5 +33,5 @@
     b[i][0] = v[i]; 
   }
-  gaussj (a, N, b, 1);
+  dgaussj (a, N, b, 1);
 
   for (i = 0; i < N; i++) {
Index: /trunk/Ohana/src/opihi/doc/pcontrol.txt
===================================================================
--- /trunk/Ohana/src/opihi/doc/pcontrol.txt	(revision 8296)
+++ /trunk/Ohana/src/opihi/doc/pcontrol.txt	(revision 8297)
@@ -1,6 +1,42 @@
+
+2006.08.11
+
+I have nearly finished the conversion of pcontrol to use a background
+thread for monitoring the remote machines.  A few questions are still
+outstanding:  
+
+- currently, we are thread-safe for interactions with the stacks.  As
+  long as an operation is only working with a single job/host, and all
+  jobs/hosts are selected by pulling them from the stacks, there will
+  never be a contention between threads for the same job/host.
+  However, are there problems for commands which require a specific
+  job or host but are unable to find it because the job/host may be in
+  flight from one stack to another.  
+
+- The CheckIdleHost command needs to join a job and a host.  In this
+  case, it is necessary to lock the job PENDING stack while searching
+  for a job to give to a host.  The host is pulled off of the IDLE
+  stack before being past to CheckIdleHost.
+
+o CheckIdleHost currently does not have a way to send a WANTHOST job
+  to any host other than the WANTHOST.  What should the rule be by
+  which a job is run on an alternative machine? (partial fix)
+
+- we are not starting any of the job or host timers?
+
+2006.08.09
+
+working on pcontrol CheckSystem background thread.  One thread runs
+the readline interaction and performs all of the user commands.  The
+second thread runs the CheckSystem loop and tests the hosts and jobs.
+We need to be sure these two do not interfere with one another.  Here
+is a list of all of the user commands and the ways in which they
+interact with the Job / Host queues:
+
+
 
 2006.08.04
 
-pcontrol get a large delay every time it tries to connect to a host.
+pcontrol gets a large delay every time it tries to connect to a host.
 this is because the readline interrupt has to wait for the connection
 to complete.  I probably need to fix this by using a threaded model
Index: /trunk/Ohana/src/opihi/include/pcontrol.h
===================================================================
--- /trunk/Ohana/src/opihi/include/pcontrol.h	(revision 8296)
+++ /trunk/Ohana/src/opihi/include/pcontrol.h	(revision 8297)
@@ -9,8 +9,9 @@
   PCONTROL_JOB_PENDING,
   PCONTROL_JOB_BUSY,  
+  PCONTROL_JOB_HUNG,  
+  PCONTROL_JOB_DONE,  
+  PCONTROL_JOB_KILL,  
   PCONTROL_JOB_EXIT,
   PCONTROL_JOB_CRASH,
-  PCONTROL_JOB_HUNG,  
-  PCONTROL_JOB_DONE,  
 } JobStat;
 
@@ -93,6 +94,9 @@
 typedef struct {
   void **object;
+  char **name;
+  int   *id;
   int    Nobject;
   int    NOBJECT;
+  // pthread_mutex_t mutex;
 } Stack;
 
@@ -107,23 +111,19 @@
 void InitPcontrol ();
 
-void *GetStack (Stack *stack, int where);
-int PutStack (Stack *stack, int where, void *object);
+/*** StackOps.c ***/
 Stack *InitStack ();
-Stack *GetHostStack (int StackID);
-int PutHost (Host *host, int StackID, int where);
-Host *GetHost (int StackID, int where);
-int FindHost (IDtype HostID, int StackID);
-Host *FindHostPtr (IDtype HostID, int StackID);
-Host *FindHostStack (IDtype HostID);
-int FindNamedHostStack (char *name);
-Host *PullHost (IDtype HostID, int StackID);
-int FindNamedHost (char *name, int StackID);
-IDtype AddHost (char *hostname);
-void DownHost (Host *host);
-void OffHost (Host *host);
-void DelHost (Host *host);
+int    PushStack (Stack *stack, int where, void *object, int id, char *name);
+void  *PullStackByLocation (Stack *stack, int where);
+void  *PullStackByName (Stack *stack, char *name);
+void  *PullStackByID (Stack *stack, int id);
+void  *FindStackByID (Stack *stack, int id);
+void  *FindStackByName (Stack *stack, char *name);
+void   LockStack (Stack *stack);
+void   UnlockStack (Stack *stack);
+
 int CheckSystem ();
 int CheckBusyJobs (float delay);
 int CheckDoneJobs (float delay);
+int CheckKillJobs (float delay);
 int CheckDoneHosts (float delay);
 int CheckLiveHosts (float delay);
@@ -144,28 +144,49 @@
 int rconnect (char *command, char *hostname, char *shell, int *stdio);
 int CheckHost (Host *host);
-Stack *GetJobStack (int StackID);
-Stack *GetJobStackByName (char *name);
-int PutJob (Job *job, int StackID, int where);
-Job *GetJob (int StackID, int where);
-int FindJob (IDtype JobID, int StackID);
-Job *FindJobPtr (IDtype JobID, int StackID);
-Job *FindJobStack (IDtype JobID);
-Job *PullJob (IDtype JobID, int StackID);
-IDtype AddJob (char *hostname, JobMode mode, int timeout, int argc, char **argv);
-int KillJob (Job *job);
-void DelJob (Job *job);
-Host *UnlinkJobAndHost (Job *job);
-void LinkJobAndHost (Job *job, Host *host);
-int StopHost (Host *host);
 
 int PrintJobStack (int Nstack);
 int PrintHostStack (int Nstack);
-void InitJobStacks ();
-void InitHostStacks ();
-void DownHost (Host *host);
-void OffHost (Host *host);
-int DownHosts ();
-int VerboseMode ();
-int StartJob (Job *job);
-void gotsignal (int signum);
-int HarvestHost (int pid);
+
+int    VerboseMode ();
+
+void   gotsignal (int signum);
+
+/*** HostOps.c ***/
+void   InitHostStacks ();
+Stack *GetHostStack (int StackID);
+Stack *GetHostStackByName (char *name);
+int    PutHost (Host *host, int StackID, int where);
+Host  *PullHostByID (IDtype HostID, int *StackID);
+Host  *PullHostByName (char *name, int *StackID);
+Host  *PullHostFromStackByID (int StackID, IDtype ID);
+Host  *PullHostFromStackByName (int StackID, char *name);
+Host  *FindHostByID (IDtype HostID, int *StackID);
+Host  *FindHostByName (char *name, int *StackID);
+Host  *FindHostInStackByID (int StackID, IDtype ID);
+Host  *FindHostInStackByName (int StackID, char *name);
+IDtype AddHost (char *hostname);
+void   DelHost (Host *host);
+
+void   DownHost (Host *host);
+void   OffHost (Host *host);
+int    DownHosts ();
+int    HarvestHost (int pid);
+int    StopHost (Host *host);
+
+/*** JobOps.c ***/
+void   InitJobStacks ();
+Stack *GetJobStack (int StackID);
+Stack *GetJobStackByName (char *name);
+int    PutJob (Job *job, int StackID, int where);
+int    PutJobSetState (Job *job, int StackID, int where, int state);
+Job   *PullJobByID (IDtype JobID, int *StackID);
+Job   *PullJobFromStackByID (int StackID, int ID);
+Job   *FindJobByID (IDtype JobID, int *StackID);
+Job   *FindJobInStackByID (int StackID, int ID);
+IDtype AddJob (char *hostname, JobMode mode, int timeout, int argc, char **argv);
+void   DelJob (Job *job);
+Host  *UnlinkJobAndHost (Job *job);
+void   LinkJobAndHost (Job *job, Host *host);
+
+int    KillJob (Job *job);
+int    StartJob (Job *job);
Index: /trunk/Ohana/src/opihi/lib.data/Makefile
===================================================================
--- /trunk/Ohana/src/opihi/lib.data/Makefile	(revision 8296)
+++ /trunk/Ohana/src/opihi/lib.data/Makefile	(revision 8297)
@@ -20,5 +20,4 @@
 $(SDIR)/sort.$(ARCH).o                  \
 $(SDIR)/fft.$(ARCH).o			\
-$(SDIR)/gaussj.$(ARCH).o		\
 $(SDIR)/svdcmp.$(ARCH).o		\
 $(SDIR)/convert.$(ARCH).o		\
Index: unk/Ohana/src/opihi/lib.data/gaussj.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.data/gaussj.c	(revision 8296)
+++ 	(revision )
@@ -1,176 +1,0 @@
-# include "data.h"
-
-int gaussj (double **a, int n, double **b, int m) {
-
-  int *indxc,*indxr,*ipiv;
-  int i, icol, irow, j, k, l, ll;
-  double big,dum,pivinv;
-  
-  ALLOCATE (indxc, int, n);
-  ALLOCATE (indxr, int, n);
-  ALLOCATE (ipiv, int, n);
-  for (j = 0; j < n; j++) 
-    ipiv[j] = 0;
-
-  irow = icol = 0;
-  big = fabs(a[0][0]);
-
-  for (i = 0; i < n; i++) {
-    big = 0.0;
-    for (j = 0; j < n; j++) {
-      if (!finite(a[i][j])) {
-	gprint (GP_ERR, "GAUSSJ: NaN\n");
-	goto escape;
-      }
-      if (ipiv[j] != 1) {
-	for (k = 0; k < n; k++) {
-	  if (ipiv[k] == 0) {
-	    if (fabs (a[j][k]) >= big) {
-	      big  = fabs (a[j][k]);
-	      irow = j;
-	      icol = k;
-	    }
-	  } 
-	  else 
-	    if (ipiv[k] > 1) {
-	      gprint (GP_ERR, "GAUSSJ: Singular Matrix! (1)\n");
-	      goto escape;
-	    }
-	}
-      }
-    }
-    ipiv[icol]++;
-    if (irow != icol) {
-      for (l = 0; l < n; l++) 
-	SWAP (a[irow][l], a[icol][l]);
-      for (l = 0; l < m; l++) 
-	SWAP (b[irow][l], b[icol][l]);
-    }
-    indxr[i] = irow;
-    indxc[i] = icol;
-    if (a[icol][icol] == 0.0) {
-      gprint (GP_ERR, "GAUSSJ: Singular Matrix! (2)\n");
-      goto escape;
-    }
-    pivinv = 1.0 / a[icol][icol];
-    a[icol][icol] = 1.0;
-    for (l = 0; l < n; l++) 
-      a[icol][l] *= pivinv;
-    for (l = 0; l < m; l++) 
-      b[icol][l] *= pivinv;
-    for (ll = 0; ll < n; ll++) {
-      if (ll != icol) {
-	dum = a[ll][icol];
-	a[ll][icol] = 0.0;
-	for (l = 0; l < n; l++) 
-	  a[ll][l] -= a[icol][l]*dum;
-	for (l = 0; l < m; l++) 
-	  b[ll][l] -= b[icol][l]*dum;
-      }
-    }
-  }
-
-  for (l = n - 1; l >= 0; l--) {
-    if (indxr[l] != indxc[l])
-      for (k = 0; k < n; k++)
-	SWAP (a[k][indxr[l]], a[k][indxc[l]]);
-  }
-  free (ipiv);
-  free (indxr);
-  free (indxc);
-  return (TRUE);
-
-escape:
-  free (ipiv);
-  free (indxr);
-  free (indxc);
-  return (FALSE);
-}
-
-
-int fgaussj (float **a, int n, float **b, int m) {
-
-  int *indxc,*indxr,*ipiv;
-  int i, icol, irow, j, k, l, ll;
-  float big,dum,pivinv;
-  
-  ALLOCATE (indxc, int, n);
-  ALLOCATE (indxr, int, n);
-  ALLOCATE (ipiv, int, n);
-  for (j = 0; j < n; j++) 
-    ipiv[j] = 0;
-
-  irow = icol = 0;
-  big = fabs(a[0][0]);
-
-  for (i = 0; i < n; i++) {
-    big = 0.0;
-    for (j = 0; j < n; j++) {
-      if (!finite(a[i][j])) {
-	gprint (GP_ERR, "GAUSSJ: NaN\n");
-	goto fescape;
-      }
-      if (ipiv[j] != 1) {
-	for (k = 0; k < n; k++) {
-	  if (ipiv[k] == 0) {
-	    if (fabs (a[j][k]) >= big) {
-	      big  = fabs (a[j][k]);
-	      irow = j;
-	      icol = k;
-	    }
-	  } 
-	  else 
-	    if (ipiv[k] > 1) {
-	      gprint (GP_ERR, "GAUSSJ: Singular Matrix! (1)\n");
-	      goto fescape;
-	    }
-	}
-      }
-    }
-    ipiv[icol]++;
-    if (irow != icol) {
-      for (l = 0; l < n; l++) 
-	SWAP (a[irow][l], a[icol][l]);
-      for (l = 0; l < m; l++) 
-	SWAP (b[irow][l], b[icol][l]);
-    }
-    indxr[i] = irow;
-    indxc[i] = icol;
-    if (a[icol][icol] == 0.0) {
-      gprint (GP_ERR, "GAUSSJ: Singular Matrix! (2)\n");
-      goto fescape;
-    }
-    pivinv = 1.0 / a[icol][icol];
-    a[icol][icol] = 1.0;
-    for (l = 0; l < n; l++) 
-      a[icol][l] *= pivinv;
-    for (l = 0; l < m; l++) 
-      b[icol][l] *= pivinv;
-    for (ll = 0; ll < n; ll++) {
-      if (ll != icol) {
-	dum = a[ll][icol];
-	a[ll][icol] = 0.0;
-	for (l = 0; l < n; l++) 
-	  a[ll][l] -= a[icol][l]*dum;
-	for (l = 0; l < m; l++) 
-	  b[ll][l] -= b[icol][l]*dum;
-      }
-    }
-  }
-
-  for (l = n - 1; l >= 0; l--) {
-    if (indxr[l] != indxc[l])
-      for (k = 0; k < n; k++)
-	SWAP (a[k][indxr[l]], a[k][indxc[l]]);
-  }
-  free (ipiv);
-  free (indxr);
-  free (indxc);
-  return (1);
-
-fescape:
-  free (ipiv);
-  free (indxr);
-  free (indxc);
-  return (FALSE);
-}
Index: /trunk/Ohana/src/opihi/mana/fitcontour.c
===================================================================
--- /trunk/Ohana/src/opihi/mana/fitcontour.c	(revision 8296)
+++ /trunk/Ohana/src/opihi/mana/fitcontour.c	(revision 8297)
@@ -57,5 +57,5 @@
   C[1][2] = C[2][1];
     
-  gaussj (C, NTERM, B, 1);
+  dgaussj (C, NTERM, B, 1);
   
   /** this is somewhat weak: if the object is too elongated, Rmin can be < 0 **/
Index: /trunk/Ohana/src/opihi/test/tests.sh
===================================================================
--- /trunk/Ohana/src/opihi/test/tests.sh	(revision 8296)
+++ /trunk/Ohana/src/opihi/test/tests.sh	(revision 8297)
@@ -1,4 +1,11 @@
 
-$VERBOSE = 0
+if ($?VERBOSE == 0)
+ $VERBOSE = 0
+end
+
+$failtest:n = 0
+$failfile:n = 0
+$faildirs:n = 0
+$currentdir = .
 
 macro fulltests
@@ -16,34 +23,5 @@
        echo "directory $testdir:$Ti"
     end
-    list testscripts -x "ls $testdir:$Ti/*.sh"
-    for Tj 0 $testscripts:n
-      if ($VERBOSE > 1)
-         echo " running $testscripts:$Tj"
-      end
-      input $testscripts:$Tj
-      for Tk 0 $tests:n
-        if ($VERBOSE > 2)
-          echo "   running $tests:$Tk"
-        end
-        $tests:$Tk
-        if ($PASS == 0)
-          echo "   ** failed test $tests:$Tk"
-          $Nfail ++
-          $n = $failtest:n
-	  $failtest:$n = $tests:$Tk
-	  $failfile:$n = $testscripts:$Tj
-	  $faildirs:$n = $testdir:$Ti
-          $failtest:n ++
-          $failfile:n ++
-          $faildirs:n ++
-        else
-          $Npass ++
-        end
-        $Ntest ++
-        # echo "finished $tests:$Tk"
-      end
-      # echo "finished $testscripts:n test scripts from $testscripts:$Tj"
-    end
-    # echo "finished tests from $testdir:$Ti"
+    runtestdir $testdir:$Ti
   end
 
@@ -54,4 +32,5 @@
 
   if ($Nfail > 0) 
+    echo " ** failed tests **"
     for i 0 $Nfail
       echo $faildirs:$i $failfile:$i $failtest:$i
@@ -60,2 +39,56 @@
 end
 
+macro runtestdir
+  if ($0 != 2)
+    echo "USAGE: runtestdir (testdir)"
+    break -auto on
+    break
+  end
+  
+  pwd -var startdir
+  cd -q $1
+  list testscripts -x "ls *.sh"
+
+  $currentdir = $1
+  for Tj 0 $testscripts:n
+    if ($VERBOSE > 1)
+      echo " running $testscripts:$Tj"
+    end
+    runtests $testscripts:$Tj      
+  end
+  
+  cd -q $startdir
+end
+
+macro runtests
+  if ($0 != 2)
+    echo "USAGE: runtests (script.sh)"
+    break -auto on
+    break
+  end
+  
+  local Tk
+
+  input $1
+  for Tk 0 $tests:n
+    if ($VERBOSE > 2)
+      echo "   running $tests:$Tk"
+    end
+    $tests:$Tk
+    if ($PASS == 0)
+      echo "   ** failed $tests:$Tk $1"
+      $Nfail ++
+      $n = $failtest:n
+      $failtest:$n = $tests:$Tk
+      $failfile:$n = $1
+      $faildirs:$n = $currentdir
+      $failtest:n ++
+      $failfile:n ++
+      $faildirs:n ++
+    else
+      $Npass ++
+    end
+    $Ntest ++
+    # echo "finished $tests:$Tk"
+  end
+end
