Index: /trunk/Ohana/src/opihi/cmd.basic/run_if.c
===================================================================
--- /trunk/Ohana/src/opihi/cmd.basic/run_if.c	(revision 4461)
+++ /trunk/Ohana/src/opihi/cmd.basic/run_if.c	(revision 4462)
@@ -94,12 +94,10 @@
     if (logic) {
       if (*input) { 
+	status = multicommand (input);
 	if (ThisList == 0) add_history (input);
-	status = command (input, &outline);
-	if (outline != (char *) NULL) free (outline);
-	if (!status) return (FALSE);
+	if (auto_break && !status) return (FALSE);
       }
-    } else {
-      free (input);
-    }
+    } 
+    free (input);
   }
   return (TRUE);
Index: /trunk/Ohana/src/opihi/include/shell.h
===================================================================
--- /trunk/Ohana/src/opihi/include/shell.h	(revision 4461)
+++ /trunk/Ohana/src/opihi/include/shell.h	(revision 4462)
@@ -40,5 +40,5 @@
 void          initialize            	PROTO((int argc, char **argv));
 void          startup               	PROTO((int argc, char **argv));
-char        **multicommand          	PROTO((char *line, int *nlist));
+int           multicommand          	PROTO((char *line));
 int           command               	PROTO((char *, char **));
 char         *expand_vars           	PROTO((char *line));
Index: /trunk/Ohana/src/opihi/lib.shell/command.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/command.c	(revision 4461)
+++ /trunk/Ohana/src/opihi/lib.shell/command.c	(revision 4462)
@@ -2,13 +2,9 @@
 # define VERBOSE 0
 
-static int Ncalls = 0;
-
 int command (char *line, char **outline) {
 
-  int i, status, argc, targc;
-  char **argv, **targv;
+  int i, status, argc;
+  char **argv;
   Command *cmd;
-
-  Ncalls ++;
 
   /* force a space between ! and first word: !ls becomes ! ls */
@@ -26,63 +22,30 @@
   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;
   
-  targv = parse_commands (line, &targc);
-  if (targc == 0) {
-    /* empty command or assignment */
-    if (line != (char *) NULL) free (line);
-    *outline = (char *) NULL;
-    return (TRUE);
+  argv = parse_commands (line, &argc);
+  if (argc == 0) return (TRUE);  /* empty command or assignment */
+
+  cmd = MatchCommand (argv[0], TRUE, FALSE);
+  if (cmd == NULL) {
+    status = FALSE;
+  } else {
+    free (argv[0]);
+    argv[0] = strcreate (cmd[0].name);
+    status = (*cmd[0].func) (argc, argv);
+  }
+  for (i = 0; i < argc; i++) free (argv[i]);
+  free (argv);
+
+  if (!status) {
+    char *msg;
+    msg = get_variable_ptr ("ERRORMSG");
+    if (msg != (char *) NULL) fprintf (stderr, "%s\n", msg);
   }
 
-  /* this needs some work to use multicommand correctly */
-  /* allocate extra space to have null terminated list */
-  ALLOCATE (argv, char *, targc + 1); 
-  argc = 0;
-  status = TRUE;
-  for (i = 0; status && (i < targc); i++) {
-    if (targv[i][0] != ';') {
-      argv[argc] = targv[i];
-      argc ++;
-    }
-    if ((targv[i][0] == ';') || (i == targc - 1)) {
-
-      if (argc == 0) continue;
-      argv[argc] = 0;
-
-      /* i +> argc + 1, argv[argc-1] = targv[i] 
-       * argv[n] = argv[argc - 1 - argc + 1 + n] = targv[i - argc + 1 + n] 
-       */
-
-      cmd = MatchCommand (argv[0], TRUE, FALSE);
-      if (cmd != NULL) {
-	REALLOCATE (argv[0], char, strlen(cmd[0].name) + 1);
-	targv[i-argc+1] = argv[0];  /* need to keep ptr in sync */
-	strcpy (argv[0], cmd[0].name);
-	status &= (*cmd[0].func) (argc, argv);
-	if (auto_break && !status) break;
-      }
-      argc = 0;
-    }
-  }
-  for (i = 0; i < targc; i++) free (targv[i]);
-  free (argv);
-  free (targv);
-  *outline = line;
-  if (!status) {
-    char *msg;
-    msg = get_variable ("ERRORMSG");
-    if (msg != (char *) NULL) {
-      fprintf (stderr, "%s\n", msg);
-      free (msg);
-    }
-  }
   set_int_variable ("STATUS", status);
   if (VERBOSE) fprintf (stderr, "command: %s, status: %d\n", line, status);
   return (status);
-
 }
-
-void print_ncalls () {
-  fprintf (stderr, "Ncalls to command(): %d\n", Ncalls);
-}
-
Index: /trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 4461)
+++ /trunk/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 4462)
@@ -68,4 +68,5 @@
     if (!strcmp (argv[i], "/"))      { type = 7; goto gotit; }
     if (!strcmp (argv[i], "*"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "%"))      { type = 7; goto gotit; }
 
     if (!strcmp (argv[i], "+"))      { type = 6; goto gotit; }
Index: /trunk/Ohana/src/opihi/lib.shell/exec_loop.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/exec_loop.c	(revision 4461)
+++ /trunk/Ohana/src/opihi/lib.shell/exec_loop.c	(revision 4462)
@@ -5,5 +5,5 @@
   void *Signal;
   int n, Nlines, j, status, ThisList;
-  char *outline;
+  char *line;
   
   /* increase the shell level (Nlists) by one */
@@ -29,8 +29,9 @@
   for (n = 0; (n < Nlines) && !interrupt; n++) {
     lists[ThisList].n = n; 
-    status = command (lists[ThisList].line[n], &outline);
+    line = lists[ThisList].line[n];
+    status = multicommand (line);
+    if (line != NULL) free (line);
     n = lists[ThisList].n;
     Nlines = lists[ThisList].Nlines;
-    if (outline != NULL) free (outline);
     if (auto_break && !status) loop_break = TRUE;
     if (loop_break || loop_continue) break;
Index: /trunk/Ohana/src/opihi/lib.shell/multicommand.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/multicommand.c	(revision 4461)
+++ /trunk/Ohana/src/opihi/lib.shell/multicommand.c	(revision 4462)
@@ -1,16 +1,31 @@
 # include "opihi.h"
 
-char **multicommand (char *line, int *nlist) {
+/* take input line and split into multiple lines
+   at the semi-colons.  send these to 'command' */
 
-  char **list;
-  int Nlist, NLIST;
+int multicommand (char *line) {
+ 
+  int done, status;
+  char *p, *q, *tmpline, *outline;
 
-  Nlist = 0;
-  NLIST = 10;
-  ALLOCATE (list, char *, NLIST);
-
-  list[0] = strcreate (line);
-  *nlist = 1;
-  return (list);
+  p = line; 
+  done = FALSE;
+  while (!done) {
+    q = strchr (p, ';');
+    if (q == NULL) {
+      q = p + strlen(p);
+      done = TRUE;
+    }
+    tmpline = strncreate (p, q - p);
+    stripwhite (tmpline);
+    if (*tmpline) {
+      status = command (tmpline, &outline);
+      if (outline != NULL) free (outline);
+      if (!status && auto_break) done = TRUE;
+    }
+    p = q + 1;
+  }
+  return (status);
 }
 
+/* should skip ; surrounded by "" */
Index: /trunk/Ohana/src/opihi/lib.shell/opihi.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/opihi.c	(revision 4461)
+++ /trunk/Ohana/src/opihi/lib.shell/opihi.c	(revision 4462)
@@ -36,12 +36,7 @@
     stripwhite (line);
     if (*line) {
-      list = multicommand (line, &Nlist);
-      for (i = 0; i < Nlist; i++) {
-	status = command (list[i], &outline);
-	if (outline != NULL) free (outline);
-      }
+      status = multicommand (line);
       add_history (line);
       append_history (1, history);
-      free (list);
     }
     free (line);
@@ -49,8 +44,2 @@
   }
 }
-
-  /* this needs some work to use multicommand correctly 
-     multicommand is currently a do-nothing function.  
-     if we want multicommand to interact with the list/macro style commands, 
-     we need a command to push all the elements of the line onto the command stack.
-   */
Index: /trunk/Ohana/src/opihi/lib.shell/stack_math.c
===================================================================
--- /trunk/Ohana/src/opihi/lib.shell/stack_math.c	(revision 4461)
+++ /trunk/Ohana/src/opihi/lib.shell/stack_math.c	(revision 4462)
@@ -52,4 +52,8 @@
       *out = *M1 / *M2;
     break; 
+  case '%': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
   case 0x5e: 
     for (i = 0; i < Nx; i++, out++, M1++, M2++) 
@@ -168,4 +172,8 @@
       *out = *M1 / *M2;
     break; 
+  case '%': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
   case 0x5e: 
     for (i = 0; i < Nx; i++, out++, M2++) 
@@ -278,4 +286,8 @@
     for (i = 0; i < Nx; i++, out++, M1++)
       *out = *M1 / *M2;
+    break; 
+  case '%': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = (int) *M1 % (int) *M2;
     break; 
   case 0x5e: 
@@ -405,4 +417,10 @@
     }
     break; 
+  case '%': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = (int) *M1 % (int) *M2;
+    }
+    break; 
   case 0x5e: 
     for (i = 0; i < Ny; i++, M2++) {
@@ -565,4 +583,11 @@
       for (j = 0; j < Nx; j++, out++, M1++, M2++)
         *out = *M1 / *M2;
+    }
+    break; 
+  case '%': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = (int) *M1 % (int) *M2;
     }
     break; 
@@ -731,4 +756,8 @@
       *out = *M1 / *M2;
     break; 
+  case '%': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
   case 0x5e: 
     for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
@@ -851,4 +880,8 @@
       *out = *M1 / *M2;
     break; 
+  case '%': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
   case 0x5e: 
     for (i = 0; i < Nx*Ny; i++, out++, M1++) 
@@ -961,4 +994,8 @@
     for (i = 0; i < Nx*Ny; i++, out++, M2++)
       *out = *M1 / *M2;
+    break; 
+  case '%': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = (int) *M1 % (int) *M2;
     break; 
   case 0x5e: 
@@ -1057,4 +1094,7 @@
   case '/': 
     *out = *M1 / *M2;
+    break; 
+  case '%': 
+    *out = (int) *M1 % (int) *M2;
     break; 
   case 0x5e: 
Index: /trunk/Ohana/src/opihi/pcontrol/GetJobOutput.c
===================================================================
--- /trunk/Ohana/src/opihi/pcontrol/GetJobOutput.c	(revision 4461)
+++ /trunk/Ohana/src/opihi/pcontrol/GetJobOutput.c	(revision 4462)
@@ -3,5 +3,5 @@
 
 /* we read Nbytes from the host, then watch for the prompt */ 
-int GetJobOutput (char *command, Host *host, IOBuffer *buffer, int Nbytes) {
+int GetJobOutput (char *cmd, Host *host, IOBuffer *buffer, int Nbytes) {
   
   int i, status, Nstart;
@@ -13,7 +13,7 @@
   Nstart = buffer[0].Nbuffer;
 
-  /* send command (stdout / stderr) */
-  ALLOCATE (line, char, MAX (1, strlen(command) + 1));
-  sprintf (line, "%s\n", command);
+  /* send cmd (stdout / stderr) */
+  ALLOCATE (line, char, MAX (1, strlen(cmd) + 1));
+  sprintf (line, "%s\n", cmd);
   status = write (host[0].stdin, line, strlen(line));
   free (line);
@@ -46,5 +46,5 @@
 
     default:
-      fprintf (stderr, "message received (GetJobOutput : %s)\n", command);  
+      fprintf (stderr, "message received (GetJobOutput : %s)\n", cmd);  
       /* drop extra bytes from pclient (not pclient:job) */
       buffer[0].Nbuffer = Nstart + Nbytes;
Index: /trunk/Ohana/src/opihi/scripts/sched.pro
===================================================================
--- /trunk/Ohana/src/opihi/scripts/sched.pro	(revision 4461)
+++ /trunk/Ohana/src/opihi/scripts/sched.pro	(revision 4462)
@@ -1,4 +1,4 @@
 
-controller host localhost
+# controller host localhost
 
 task test
@@ -6,5 +6,5 @@
   periods -poll 1.0
   periods -exec 2.0
-  periods -timeout 2.0
+  periods -timeout 8.0
   # host local
   host localhost
@@ -16,17 +16,15 @@
 
   task.exit 0
-    echo stdout: $stdout
-    echo stderr: $stderr
-    exec echo "foo bar" >> failure.log
-    output test.log
+    # note that $stdout/$stderr may contain return characters
+    # which will interfere with 'exec'
+    output success.log
     echo $stdout
     output stdout
-    echo "successful job"
   end
 
   task.exit 1
-    echo stdout: $stdout
-    echo stderr: $stderr
-    echo "failed job"
+    output failure.log
+    echo $stdout
+    output stdout
   end
 
@@ -36,5 +34,7 @@
 
   task.exit timeout
-    echo "job timed out"
+    output timeout.log
+    echo $stdout
+    output stdout
   end
 end
