Index: trunk/Ohana/src/opihi/cmd.basic/shell.c
===================================================================
--- trunk/Ohana/src/opihi/cmd.basic/shell.c	(revision 16466)
+++ trunk/Ohana/src/opihi/cmd.basic/shell.c	(revision 16895)
@@ -1,3 +1,4 @@
 # include "basic.h"
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
 
 static char *defshell = "/bin/sh";
@@ -9,9 +10,18 @@
 int shell (int argc, char **argv) {
   
-  int i, pid;
+  int i, pid, N;
   int exit_status;
   int wait_status;
   int result, length;
   char **args, *shell;
+  struct timeval start, now;
+  float timeout;
+
+  timeout = 0;
+  if ((N = get_argument (argc, argv, "-timeout"))) {
+    remove_argument (N, &argc, argv);
+    timeout = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
 
   shell = getenv ("SHELL");
@@ -39,4 +49,6 @@
   // send the commands to the shell specified in the env variable SHELL, or else /bin/sh
 
+  gettimeofday (&start, NULL);
+
   // use execvp to enable a timeout on the system call 
   pid = fork ();
@@ -49,5 +61,7 @@
   
   // wait for process to finish or timeout
-  for (i = 0; i < 200; i++) {
+  // loop forever if desired, but catch C-C and stop the process on interrupt
+  interrupt = FALSE;
+  while (!interrupt) {
     result = waitpid (pid, &wait_status, WNOHANG);
     switch (result) {
@@ -65,4 +79,11 @@
       case 0:   // child not yet exited
 	usleep (10000);
+	if (timeout > 0.0) {
+	  gettimeofday (&now, NULL);
+	  if (DTIME(now, start) > timeout) {
+	    gprint (GP_ERR, "timeout on %s (pid %d)\n", argv[1], pid);
+	    return (FALSE);
+	  }
+	}
 	continue;
 
@@ -90,7 +111,19 @@
     }
   }
+  gprint (GP_ERR, "caught interrupt, killing %s (%d)\n", argv[1], pid);
 
-  gprint (GP_ERR, "timeout on %d\n", pid);
+  // user hit interrupt: kill the process and return
+  kill (pid, SIGKILL);
+  result = 0;
+  for (i = 0; (i < 10) && (result == 0); i++) {
+    usleep (10000);  // wait for job to exit
+    result = waitpid (pid, &wait_status, WNOHANG);
+  }
+  if (!result) {
+    gprint (GP_ERR, "trouble killing %s (pid %d)\n", argv[1], pid);
+  } else {
+    gprint (GP_ERR, "killed %s (pid %d)\n", argv[1], pid);
+  }
+
   return (FALSE);
 }
-
