Index: trunk/src/sh_log_check.c
===================================================================
--- trunk/src/sh_log_check.c	(revision 272)
+++ trunk/src/sh_log_check.c	(revision 275)
@@ -39,4 +39,5 @@
 #include "sh_log_mark.h"
 #include "sh_log_repeat.h"
+#include "sh_extern.h"
 
 /* List of supported logfile types, format is
@@ -57,4 +58,5 @@
     {  "PACCT",  sh_read_pacct,   sh_parse_pacct,  NULL },
 #endif
+    {  "SHELL",  sh_read_shell,   sh_parse_generic,  sh_eval_fileinfo_generic },
 };
 
@@ -237,5 +239,5 @@
     }
 
-  if (splits[1][0] != '/')
+  if (splits[1][0] != '/' && 0 != strcmp(splits[0], _("SHELL")))
     {
       sh_string * msg =  sh_string_new(0);
@@ -258,5 +260,8 @@
 
   thisfile->filename     = filename;
-  thisfile->flags        = SH_LOGFILE_REWIND;
+  if (strcmp(splits[0], _("SHELL")))
+    thisfile->flags        = SH_LOGFILE_NOFILE;
+  else
+    thisfile->flags        = SH_LOGFILE_REWIND;
   thisfile->inode        = 0;
   thisfile->device_id    = 0;
@@ -323,44 +328,47 @@
   /* Try reading saved offset. On success clear rewind flag.
    */
-  if (0 == stat(thisfile->filename, &buf))
-    {
-      if (S_ISREG(buf.st_mode)
+  if ((thisfile->flags & SH_LOGFILE_NOFILE) == 0)
+    {
+      if (0 == stat(thisfile->filename, &buf))
+	{
+	  if (S_ISREG(buf.st_mode)
 #ifdef S_ISLNK
-	  || S_ISLNK(buf.st_mode)
+	      || S_ISLNK(buf.st_mode)
 #endif 
-	  )
-	{
-	  thisfile->inode     = buf.st_ino;
-	  thisfile->device_id = buf.st_dev;
+	      )
+	    {
+	      thisfile->inode     = buf.st_ino;
+	      thisfile->device_id = buf.st_dev;
+	      
+	      if (0 != read_pos(thisfile))
+		{
+		  thisfile->flags &= ~SH_LOGFILE_REWIND;
+		}
+	    }
+	  else if (S_ISFIFO(buf.st_mode))
+	    {
+	      thisfile->inode      = buf.st_ino;
+	      thisfile->device_id  = buf.st_dev;
+	      thisfile->flags     |= SH_LOGFILE_PIPE;
+	    }
+	}
+      else
+	{
+	  sh_string * msg =  sh_string_new(0);
+	  sh_string_add_from_char(msg, _("Logfile is not a regular file, link, or named pipe: "));
+	  sh_string_add_from_char(msg, splits[1]);
 	  
-	  if (0 != read_pos(thisfile))
-	    {
-	      thisfile->flags &= ~SH_LOGFILE_REWIND;
-	    }
-	}
-      else if (S_ISFIFO(buf.st_mode))
-	{
-	  thisfile->inode      = buf.st_ino;
-	  thisfile->device_id  = buf.st_dev;
-	  thisfile->flags     |= SH_LOGFILE_PIPE;
-	}
-    }
-  else
-    {
-      sh_string * msg =  sh_string_new(0);
-      sh_string_add_from_char(msg, _("Logfile is not a regular file, link, or named pipe: "));
-      sh_string_add_from_char(msg, splits[1]);
-      
-      SH_MUTEX_LOCK(mutex_thread_nolog);
-      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		      sh_string_str(msg),
-		      _("sh_add_watch"));
-      SH_MUTEX_UNLOCK(mutex_thread_nolog);
-      sh_string_destroy(&msg);
-      
-      SH_FREE(filename);
-      SH_FREE(thisfile);
-      SH_FREE(new);
-      return -1;
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
+	  sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
+			  sh_string_str(msg),
+			  _("sh_add_watch"));
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	  sh_string_destroy(&msg);
+	  
+	  SH_FREE(filename);
+	  SH_FREE(thisfile);
+	  SH_FREE(new);
+	  return -1;
+	}
     }
 
@@ -380,11 +388,16 @@
       sh_watched_logs = thisfile->next;
 
-      if ((thisfile->flags & SH_LOGFILE_PIPE) == 0)
+      if ((thisfile->flags & SH_LOGFILE_NOFILE) == 0 &&
+	  (thisfile->flags & SH_LOGFILE_PIPE) == 0)
 	{
 	  save_pos(thisfile);
 	}
 
-      if (thisfile->fp)
-	sl_fclose(FIL__, __LINE__, thisfile->fp);
+      if ((thisfile->flags & SH_LOGFILE_NOFILE) == 0)
+	{
+	  if (thisfile->fp)
+	    sl_fclose(FIL__, __LINE__, thisfile->fp);
+	}
+
       if (thisfile->filename)
 	SH_FREE(thisfile->filename);
@@ -677,5 +690,5 @@
 sh_string * sh_default_reader (sh_string * s, struct sh_logfile * logfile)
 {
-  int         status;
+  volatile int         status;
   char * tmp;
 
@@ -712,4 +725,70 @@
   if (0 != sh_open_for_reader(logfile))
     goto start_read;
+
+  return NULL;
+}
+
+sh_string * sh_command_reader (sh_string * s, struct sh_logfile * logfile)
+{
+  sh_tas_t task;
+  struct  sigaction  new_act;
+  struct  sigaction  old_act;
+
+  volatile int         status;
+  char * tmp;
+
+ start_read:
+
+  if (logfile->fp)
+    {
+      /* ignore SIGPIPE (instead get EPIPE if connection is closed)
+       */
+      new_act.sa_handler = SIG_IGN;
+      (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &new_act, &old_act);
+
+      /* Result cannot be larger than 8192, thus cast is ok
+       */
+      status = (int) sh_string_read(s, logfile->fp, 8192);
+
+      /* restore old signal handler
+       */
+      (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &old_act, NULL);
+
+      if (status <= 0)
+	{
+	  sh_ext_pclose (&task);
+	  logfile->fp = NULL;
+	  sh_string_destroy(&s);
+
+	  if (status == 0)
+	    {
+	      return NULL;
+	    }
+
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
+	  tmp = sh_util_safe_name (logfile->filename);
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_LOGMON_EREAD,
+			  tmp);
+	  SH_FREE(tmp);
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+
+	  return NULL;
+	}
+      return s;
+    }
+
+  status = sh_ext_popen_init (&task, logfile->filename);
+  if (0 == status)
+    {
+      logfile->fp = task.pipe;
+      goto start_read;
+    }
+  else
+    {
+      SH_MUTEX_LOCK(mutex_thread_nolog);
+      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, 
+                      _("Could not open pipe"), _("sh_command reader"));
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
+    }
 
   return NULL;
