Index: trunk/Ohana/src/opihi/pantasks/TaskOps.c
===================================================================
--- trunk/Ohana/src/opihi/pantasks/TaskOps.c	(revision 4603)
+++ trunk/Ohana/src/opihi/pantasks/TaskOps.c	(revision 4684)
@@ -1,44 +1,66 @@
-# include "opihi.h"
 # include "scheduler.h"
 
-static char dot[] = ".";
-
-static Task *tasks;
-static int   Ntasks;
-static int   NTASKS;
-
-static char *TaskName = dot;
-
-static int   CurrentTask = 0;
-
-/* provide a mechanism to loop over the list of tasks */
-Task *NextTask () {
-  
-  Task *task;
-
-  if (CurrentTask >= Ntasks) {
-    CurrentTask = 0;
-    return (NULL);
-  }
-
-  task = &tasks[CurrentTask];
-  CurrentTask ++;
-  return (task);
-}
-
+static Task **tasks;
+static int    Ntasks;
+static int    NTASKS;
+
+/* counter marking task being visited by the run loop */
+static int   ActiveTask;
+
+/* temporary holder for a new task */
+static Task *NewTask = NULL;
+
+/* set up the task list system */
 void InitTasks () {
   NTASKS = 20;
   Ntasks = 0;
-  ALLOCATE (tasks, Task, NTASKS);
-  TaskName = dot;
-}
+  ALLOCATE (tasks, Task *, NTASKS);
+  ActiveTask = -1;
+}
+
+/* provide a mechanism to loop over the list of tasks */
+Task *NextTask () {
+  
+  Task *task;
+
+  /* move to the next task and return it */
+  ActiveTask ++;
+  if (ActiveTask < 0) ActiveTask = 0;
+  if (ActiveTask >= Ntasks) {
+    ActiveTask = -1;
+    return (NULL);
+  }
+  task = tasks[ActiveTask];
+  return (task);
+}
+
+/* return task with given name */
+Task *FindTask (char *name) {
+
+  int i;
+
+  /* try for an exact match first */
+  for (i = 0; i < Ntasks; i++) {
+    if (!strcmp (tasks[i][0].name, name)) {
+      return (tasks[i]);
+    }
+  }
+  return (NULL);
+}  
 
 /* list known tasks */
-void ListTasks () {
+void ListTasks (int verbose) {
 
   int i, valid;
 
+  if (Ntasks == 0) {
+    fprintf (stderr, "no defined tasks\n");
+    return;
+  }
+
+  fprintf (stderr, "Task Status\n");
+  fprintf (stderr, "  name            Njobs  command\n");
   for (i = 0; i < Ntasks; i++) {
-    valid = CheckTimeRanges (tasks[i].ranges, tasks[i].Nranges);
+    valid = CheckTimeRanges (tasks[i][0].ranges, tasks[i][0].Nranges);
     if (valid) {
       fprintf (stderr, "+ ");
@@ -46,5 +68,18 @@
       fprintf (stderr, "- ");
     }
-    fprintf (stderr, "%-15s %4d %20s\n", tasks[i].name, tasks[i].Njobs, tasks[i].argv[0]);
+    fprintf (stderr, "%-15s %4d   %-20s\n", tasks[i][0].name, tasks[i][0].Njobs, tasks[i][0].argv[0]);
+    if (verbose) {
+      fprintf (stderr, "    spawn period: %f, polling period: %f, timeout period: %f\n", 
+	       tasks[i][0].poll_period, tasks[i][0].poll_period, tasks[i][0].poll_period);
+      if (tasks[i][0].host != NULL) {
+	if (tasks[i][0].host_required) {
+	  fprintf (stderr, "    host %s (required)\n", tasks[i][0].host);
+	} else {
+	  fprintf (stderr, "    host %s (desired)\n", tasks[i][0].host);
+	}
+      } else {
+	fprintf (stderr, "    task runs locally\n");
+      }      
+    }
   }
   return;
@@ -94,65 +129,126 @@
 }
 
-/* return task with given name */
-Task *FindTask (char *name) {
-
+/* make a new named task */
+int FreeTask (Task *task) {
+  
   int i;
 
-  /* try for an exact match first */
-  for (i = 0; i < Ntasks; i++) {
-    if (!strcmp (tasks[i].name, name)) {
-      return (&tasks[i]);
-    }
-  }
-  return (NULL);
-}  
+  if (task == NULL) return (FALSE);
+  
+  if (task[0].name != NULL) free (task[0].name);
+  if (task[0].host != NULL) free (task[0].host);
+  if (task[0].argv != NULL) {
+    for (i = 0; i < task[0].argc; i++) {
+      free (task[0].argv[i]);
+    }
+    free (task[0].argv);
+  }
+  if (task[0].exec != NULL) {
+    FreeMacro (task[0].exec);
+    free (task[0].exec);
+  }
+  if (task[0].crash != NULL) {
+    FreeMacro (task[0].crash);
+    free (task[0].crash);
+  }
+  if (task[0].timeout != NULL) {
+    FreeMacro (task[0].timeout);
+    free (task[0].timeout);
+  }
+  for (i = 0; i < task[0].Nexit; i++) {
+    if (task[0].exit[i] != NULL) {
+      FreeMacro (task[0].exit[i]);
+    }
+    free (task[0].exit[i]);
+  }
+  free (task[0].exit);
+
+  if (task[0].ranges != NULL) {
+    free (task[0].ranges);
+  }
+  return (TRUE);
+}
+
+/**** new task functions ***/
 
 /* make a new named task */
 Task *CreateTask (char *name) {
   
-  tasks[Ntasks].name = strcreate (name);;
-
-  tasks[Ntasks].host = NULL;
-  tasks[Ntasks].host_required = FALSE;
-
-  tasks[Ntasks].argc = 0;
-  tasks[Ntasks].argv = NULL;
-
-  tasks[Ntasks].exec = NULL;
-  tasks[Ntasks].crash = NULL;
-  tasks[Ntasks].timeout = NULL;
-
-  tasks[Ntasks].Nexit = 0;
-  tasks[Ntasks].NEXIT = 10;
-  ALLOCATE (tasks[Ntasks].exit, Macro *, tasks[Ntasks].NEXIT);
+  ALLOCATE (NewTask, Task, 1);
+
+  NewTask[0].name = strcreate (name);;
+
+  NewTask[0].host = NULL;
+  NewTask[0].host_required = FALSE;
+
+  NewTask[0].argc = 0;
+  NewTask[0].argv = NULL;
+
+  NewTask[0].exec = NULL;
+  NewTask[0].crash = NULL;
+  NewTask[0].timeout = NULL;
+
+  NewTask[0].Nexit = 0;
+  NewTask[0].NEXIT = 10;
+  ALLOCATE (NewTask[0].exit, Macro *, NewTask[0].NEXIT);
   /* don't free tasks[0].exit, keep at least 1 allocated */
 
-  tasks[Ntasks].exec_period = 1.0;
-  tasks[Ntasks].poll_period = 1.0;
-  tasks[Ntasks].timeout_period = 1.0;
-
-  tasks[Ntasks].Nranges = 0;
-  ALLOCATE (tasks[Ntasks].ranges, TimeRange, 1);
+  NewTask[0].exec_period = 1.0;
+  NewTask[0].poll_period = 1.0;
+  NewTask[0].timeout_period = 1.0;
+
+  NewTask[0].Nranges = 0;
+  ALLOCATE (NewTask[0].ranges, TimeRange, 1);
 
   /* init task timer (is reset by 'run') */  
-  gettimeofday (&tasks[Ntasks].last, (void *) NULL);
-  tasks[Ntasks].Njobs = 0;
-  tasks[Ntasks].Nmax = 0;  /* default value means 'no limit' */
-
+  gettimeofday (&NewTask[0].last, (void *) NULL);
+  NewTask[0].Njobs = 0;
+  NewTask[0].Nmax = 0;  /* default value means 'no limit' */
+
+  return (NewTask);
+}
+
+int ValidateTask (Task *task) {
+
+  if (task[0].argc == 0) {
+    fprintf (stderr, "task command not defined\n");
+    return (FALSE);
+  }
+  if (task[0].argv == NULL) {
+    fprintf (stderr, "task command arguments not defined (programming error)\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int RegisterNewTask () {
+  
+  int N;
+
+  N = Ntasks;
   Ntasks ++;
   if (Ntasks == NTASKS) {
     NTASKS += 20;
-    REALLOCATE (tasks, Task, NTASKS);
-  }
-  return (&tasks[Ntasks-1]);
-}
-
-void SetCurrentTask (char *name) {
-  TaskName = name;
-}
-
-char *GetCurrentTask () {
-  return (TaskName);
-}
+    REALLOCATE (tasks, Task *, NTASKS);
+  }
+  tasks[N] = NewTask;
+  NewTask = NULL;
+  return (TRUE);
+}
+
+int DeleteNewTask () {
+  if (NewTask != NULL) {
+    FreeTask (NewTask);
+    free (NewTask);
+    NewTask = NULL;
+  }
+  return (TRUE);
+}
+
+Task *GetNewTask () {
+  return (NewTask);
+}
+
+/*** task timer functions ***/
 
 double GetTaskTimer (struct timeval start) {
