Index: /trunk/Ohana/src/opihi/cmd.data/queuepop.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.data/queuepop.c	(revision 6248)
+++ /trunk/Ohana/src/opihi/cmd.data/queuepop.c	(revision 6249)
@@ -3,7 +3,8 @@
 int queuepop (int argc, char **argv) {
   
-  int N;
+  int N, Key;
   char *var;
   char *line;
+  char *Value;
   Queue *queue;
 
@@ -15,6 +16,16 @@
   }
 
+  Key = -1;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    Key = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    Value = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+
   if (argc != 2) {
-    fprintf (stderr, "USAGE: queuepop (queue) [-var variable]\n");
+    fprintf (stderr, "USAGE: queuepop (queue) [-var variable] [-key N value]\n");
     return (FALSE);
   }
@@ -27,14 +38,24 @@
   }
 
-  line = PopQueue (queue);
-  if (line == NULL) {
-    fprintf (stderr, "ERROR: queue %s is empty\n", argv[1]);
-    return (FALSE);
+  if (Key == -1) {
+      line = PopQueue (queue);
+  } else {
+      line = PopQueueMatch (queue, Key, Value);
   }
 
-  if (var == (char *) NULL) {
-    fprintf (stderr, "%s\n", line);
+  if (var == NULL) {
+      if (line == NULL) {
+	  fprintf (stderr, "queue %s is empty or match not found\n", argv[1]);
+	  return (FALSE);
+      } else {
+	  fprintf (stderr, "%s\n", line);
+	  return (TRUE);
+      }
+  }
+
+  if (line == NULL) {
+    set_str_variable (var, "NULL");
   } else {
-    set_str_variable (argv[2], line);
+    set_str_variable (var, line);
   }
 
Index: /trunk/Ohana/src/opihi/include/psched.h
===================================================================
--- /trunk/Ohana/src/opihi/include/psched.h	(revision 6248)
+++ /trunk/Ohana/src/opihi/include/psched.h	(revision 6249)
@@ -73,4 +73,9 @@
 
   struct timeval last;
+
+  int Nsuccess;
+  int Nfailure;
+  int Ntimeout;
+
 } Task;
 
Index: /trunk/Ohana/src/opihi/lib.data/queues.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.data/queues.c	(revision 6248)
+++ /trunk/Ohana/src/opihi/lib.data/queues.c	(revision 6249)
@@ -281,4 +281,5 @@
   queue[0].Nlines --;
 
+  /* shrink queue allocation if small enough */
   NLINES_2 = MAX (16, queue[0].NLINES / 2);
   if (queue[0].Nlines < NLINES_2) {
@@ -289,4 +290,38 @@
 }
 
+/* pop the first entry which for which the key matches */
+char *PopQueueMatch (Queue *queue, int Key, char *value) {
+
+  int i, choice, NLINES_2;
+  char *line, *test;
+
+  if (queue[0].Nlines == 0) return (NULL);
+
+  /* find the matching key */
+  choice = -1;
+  for (i = 0; (i < queue[0].Nlines) && (choice == -1); i++) {
+      test = ChooseKey (queue[0].lines[i], Key);
+      if (test == NULL) continue;
+      if (strcmp (value, test)) continue;
+      choice = i;
+  }
+  if (choice == -1) return NULL;
+
+  line = queue[0].lines[choice];
+
+  for (i = choice; i < queue[0].Nlines - 1; i++) {
+    queue[0].lines[i] = queue[0].lines[i+1];
+  }
+  queue[0].Nlines --;
+
+  /* shrink queue allocation if small enough */
+  NLINES_2 = MAX (16, queue[0].NLINES / 2);
+  if (queue[0].Nlines < NLINES_2) {
+    queue[0].NLINES = NLINES_2;
+    REALLOCATE (queue[0].lines, char *, queue[0].NLINES);
+  }    
+  return (line);
+}
+
 int PrintQueue (FILE *f, Queue *queue) {
 
Index: /trunk/Ohana/src/opihi/lib.shell/check_stack.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/check_stack.c	(revision 6248)
+++ /trunk/Ohana/src/opihi/lib.shell/check_stack.c	(revision 6249)
@@ -14,4 +14,12 @@
       stack[i].Float = strtod (stack[i].name, &c);
       if (c == stack[i].name + strlen (stack[i].name)) {
+	# if (0)
+	if (Nstack == 1) {
+	  stack[i].type = 'W';
+	} else {
+	  stack[i].ptr   = &(stack[i].Float);
+	  stack[i].type  = 'S';
+	}
+        # endif
 	stack[i].ptr   = &(stack[i].Float);
 	stack[i].type  = 'S';
Index: /trunk/Ohana/src/opihi/pantasks/CheckJobs.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/CheckJobs.c	(revision 6248)
+++ /trunk/Ohana/src/opihi/pantasks/CheckJobs.c	(revision 6249)
@@ -6,4 +6,5 @@
   Macro *macro;
   int i, status;
+  char varname[64];
 
   /** test all jobs: ready to test?  finished? **/
@@ -30,4 +31,11 @@
 	PushNamedQueue ("stdout", job[0].stdout.buffer);
 	PushNamedQueue ("stderr", job[0].stderr.buffer);
+	/* set taskarg variables */
+	for (i = 0; i < job[0].argc; i++) {
+	    sprintf (varname, "taskarg:%d", i);
+	    set_str_variable (varname, job[0].argv[i]);
+	}
+	set_int_variable ("taskarg:n", job[0].argc);
+
 	/* XXX this will break on 0 values in output streams */
 	/* perhaps define PushNamedQueueBuffer */
@@ -43,4 +51,18 @@
 	PushNamedQueue ("stdout", job[0].stdout.buffer);
 	PushNamedQueue ("stderr", job[0].stderr.buffer);
+	/* set taskarg variables */
+	for (i = 0; i < job[0].argc; i++) {
+	    sprintf (varname, "taskarg:%d", i);
+	    set_str_variable (varname, job[0].argv[i]);
+	}
+	set_int_variable ("taskarg:n", job[0].argc);
+
+	/* update the exit status counters */
+	if (job[0].exit_status) {
+	    job[0].task[0].Nfailure ++;
+	} else {
+	    job[0].task[0].Nsuccess ++;
+	}
+
 	/* run corresponding task[0].exit macro, if it exists */
 	macro = job[0].task[0].defexit;
@@ -68,4 +90,8 @@
       if (GetTaskTimer(job[0].start) < job[0].task[0].timeout_period) continue;
       if (VerboseMode()) fprintf (stderr, "timeout on %s\n", job[0].task[0].name);
+
+      /* update the timeout counter */
+      job[0].task[0].Ntimeout ++;
+
       if (!KillLocalJob (job)) {
 	job[0].state = JOB_HUNG;
@@ -73,4 +99,13 @@
 	continue;
       }
+
+      /* set taskarg variables */
+      for (i = 0; i < job[0].argc; i++) {
+	  sprintf (varname, "taskarg:%d", i);
+	  set_str_variable (varname, job[0].argv[i]);
+      }
+      set_int_variable ("taskarg:n", job[0].argc);
+
+
       /* run task[0].timeout macro, if it exists */
       if (job[0].task[0].timeout != NULL) {
Index: /trunk/Ohana/src/opihi/pantasks/TaskOps.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/TaskOps.c	(revision 6248)
+++ /trunk/Ohana/src/opihi/pantasks/TaskOps.c	(revision 6249)
@@ -229,7 +229,10 @@
   /* init task timer (is reset by 'run') */  
   gettimeofday (&NewTask[0].last, (void *) NULL);
+  NewTask[0].Nmax = 0;  /* default value means 'no limit' */
+
   NewTask[0].Njobs = 0;
-  NewTask[0].Nmax = 0;  /* default value means 'no limit' */
-
+  NewTask[0].Nsuccess = 0;
+  NewTask[0].Nfailure = 0;
+  NewTask[0].Ntimeout = 0;
   return (NewTask);
 }
Index: /trunk/Ohana/src/opihi/pantasks/task_periods.c
===================================================================
--- /trunk/Ohana/src/opihi/pantasks/task_periods.c	(revision 6248)
+++ /trunk/Ohana/src/opihi/pantasks/task_periods.c	(revision 6249)
@@ -42,6 +42,9 @@
   task = GetNewTask ();
   if (task == NULL) {
-    fprintf (stderr, "ERROR: not defining or running a task\n");
-    return (FALSE);
+    task = GetActiveTask ();
+    if (task == NULL) {
+      fprintf (stderr, "ERROR: not defining or running a task\n");
+      return (FALSE);
+    }
   }
 
