Index: /trunk/Makefile.in
===================================================================
--- /trunk/Makefile.in	(revision 184)
+++ /trunk/Makefile.in	(revision 185)
@@ -155,4 +155,5 @@
 	$(srcsrc)/sh_pthread.c $(srcsrc)/sh_string.c \
 	$(srcsrc)/sh_log_parse_syslog.c $(srcsrc)/sh_log_parse_pacct.c \
+	$(srcsrc)/sh_log_parse_samba.c \
 	$(srcsrc)/sh_log_parse_apache.c $(srcsrc)/sh_log_evalrule.c \
 	$(srcsrc)/sh_log_check.c $(srcsrc)/dnmalloc.c \
@@ -172,5 +173,5 @@
 	sh_processcheck.o sh_portcheck.o sh_port2proc.o \
 	sh_log_parse_syslog.o sh_log_parse_pacct.o sh_log_parse_apache.o \
-	sh_log_evalrule.o sh_log_check.o \
+	sh_log_parse_samba.o sh_log_evalrule.o sh_log_check.o \
 	sh_pthread.o sh_string.o dnmalloc.o
 
@@ -1724,2 +1725,3 @@
 sh_log_evalrule.o: $(srcsrc)/sh_log_evalrule.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/zAVLTree.h 
 sh_log_check.o: $(srcsrc)/sh_log_check.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/sh_modules.h 
+sh_log_parse_samba.o: $(srcsrc)/sh_log_parse_samba.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_string.h 
Index: /trunk/depend.dep
===================================================================
--- /trunk/depend.dep	(revision 184)
+++ /trunk/depend.dep	(revision 185)
@@ -74,2 +74,3 @@
 sh_log_evalrule.o: $(srcsrc)/sh_log_evalrule.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/zAVLTree.h 
 sh_log_check.o: $(srcsrc)/sh_log_check.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_utils.h $(srcinc)/sh_string.h $(srcinc)/sh_log_check.h $(srcinc)/sh_log_evalrule.h $(srcinc)/sh_modules.h 
+sh_log_parse_samba.o: $(srcsrc)/sh_log_parse_samba.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_pthread.h $(srcinc)/sh_log_check.h $(srcinc)/sh_string.h 
Index: /trunk/depend.sum
===================================================================
--- /trunk/depend.sum	(revision 184)
+++ /trunk/depend.sum	(revision 185)
@@ -1,1 +1,1 @@
-3470897936
+2389503463
Index: /trunk/docs/Changelog
===================================================================
--- /trunk/docs/Changelog	(revision 184)
+++ /trunk/docs/Changelog	(revision 185)
@@ -1,3 +1,6 @@
 2.5.0:
+	* fix improved error reporting for failed fstat in checksumming
+	* report process/user for open ports (Linux only currently)
+	* fix deadlock on exit in sh_hash_init()
 	* fix --enable-mounts-check for FreeBSD 7.0 (no MNT_NODEV anymore)
 	* log monitoring support
Index: /trunk/include/sh_cat.h
===================================================================
--- /trunk/include/sh_cat.h	(revision 184)
+++ /trunk/include/sh_cat.h	(revision 185)
@@ -277,5 +277,6 @@
  MSG_E_HASH,      
  MSG_E_ACCESS,    
- MSG_E_READ,      
+ MSG_E_READ,
+ MSG_E_NOTREG,
  MSG_E_TIMEOUT,
  MSG_NODEV,       
Index: /trunk/include/sh_log_check.h
===================================================================
--- /trunk/include/sh_log_check.h	(revision 184)
+++ /trunk/include/sh_log_check.h	(revision 185)
@@ -64,4 +64,8 @@
 			       struct sh_logfile * logfile);
 
+/* Continued line reader.   */ 
+sh_string * sh_cont_reader (sh_string * record, 
+			    struct sh_logfile * logfile, char * cont);
+
 /* Binary reader */
 sh_string * sh_binary_reader (void * s, size_t size, struct sh_logfile * logfile);
@@ -81,4 +85,11 @@
 /* Parses a pacct record. */
 struct sh_logrecord * sh_parse_pacct (sh_string * logline, void * fileinfo);
+
+/* Get a samba record */
+sh_string * sh_read_samba (sh_string * record, struct sh_logfile * logfile);
+
+/* Parses a samba record. */
+struct sh_logrecord * sh_parse_samba (sh_string * logline, void * fileinfo);
+
 
 /**
Index: /trunk/include/sh_string.h
===================================================================
--- /trunk/include/sh_string.h	(revision 184)
+++ /trunk/include/sh_string.h	(revision 185)
@@ -33,5 +33,5 @@
 
 #define sh_string_copy(a)  ((a) ? sh_string_new_from_lchar(((a)->str), ((a)->len)) : NULL)
-#define sh_string_add(a,b) ((a && b) ? sh_string_add_from_lchar((a), ((b)->str), ((b)->len)) : NULL)
+#define sh_string_add(a,b) ((a && b) ? sh_string_cat_lchar((a), ((b)->str), ((b)->len)) : NULL)
 
 /* create new sh_string from three arrays of given length
@@ -53,4 +53,11 @@
  */
 size_t sh_string_read(sh_string * s, FILE * fp, size_t maxlen);
+
+/* Read a string from a file, with maxlen. Return 0 on EOF,
+ * -1 on error, and -2 if a line exceeds maxlen.
+ * If 'cont' != NULL, continuation lines starting with a char
+ * in 'cont' are concatenated.
+ */
+size_t sh_string_read_cont(sh_string * s, FILE * fp, size_t maxlen, char *cont);
 
 /* Split array at delim in at most nfields fields. 
Index: /trunk/include/sh_utils.h
===================================================================
--- /trunk/include/sh_utils.h	(revision 184)
+++ /trunk/include/sh_utils.h	(revision 185)
@@ -178,4 +178,6 @@
 char * sh_util_safe_name (const char * name) SH_GNUC_MALLOC SH_GNUC_PURE;
 
+char * sh_util_safe_name_keepspace (const char * name) SH_GNUC_MALLOC SH_GNUC_PURE;
+
 /* check max size of printf result string
  */
Index: /trunk/src/sh_cat.c
===================================================================
--- /trunk/src/sh_cat.c	(revision 184)
+++ /trunk/src/sh_cat.c	(revision 185)
@@ -272,4 +272,5 @@
   { MSG_E_ACCESS,    SH_ERR_ERR,     ERR,   N_("msg=\"File not accessible\" userid=\"%ld\" path=\"%s\"")},
   { MSG_E_READ,      SH_ERR_ERR,     ERR,   N_("msg=\"Not accessible or not a regular file\" path=\"%s\"")},
+  { MSG_E_NOTREG,    SH_ERR_ERR,     ERR,   N_("msg=\"Not a regular file\" path=\"%s\"")},
   { MSG_E_TIMEOUT,   SH_ERR_ERR,     ERR,   N_("msg=\"Timeout (%d sec) while checksumming file\" path=\"%s\"")},
   { MSG_NODEV,       SH_ERR_ERR,     ERR,   N_("msg=\"Device not available or timeout during read attempt\" userid=\"%ld\" path=\"%s\"")},
@@ -599,4 +600,5 @@
   { MSG_E_ACCESS,    SH_ERR_ERR,     ERR,   N_("msg=<File not accessible>, userid=<%ld>, path=<%s>")},
   { MSG_E_READ,      SH_ERR_ERR,     ERR,   N_("msg=<Not accessible or not a regular file>, path=<%s>")},
+  { MSG_E_NOTREG,    SH_ERR_ERR,     ERR,   N_("msg=<Not a regular file>, path=<%s>")},
   { MSG_E_TIMEOUT,   SH_ERR_ERR,     ERR,   N_("msg=<Timeout (%d sec) while checksumming file>, path=<%s>")},
   { MSG_NODEV,       SH_ERR_ERR,     ERR,   N_("msg=<Device not available or timeout during read attempt>, userid=<%ld>, path=<%s>")},
Index: /trunk/src/sh_hash.c
===================================================================
--- /trunk/src/sh_hash.c	(revision 184)
+++ /trunk/src/sh_hash.c	(revision 185)
@@ -1139,4 +1139,7 @@
   char hashbuf[KEYBUF_SIZE];
 
+  int  retval  = 0;
+  int  exitval = EXIT_SUCCESS;
+
   SL_ENTER(_("sh_hash_init"));
 
@@ -1170,5 +1173,6 @@
 	  sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1, 
 			   sh.prg_name);
-	  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+	  retval = 1; exitval = EXIT_FAILURE;
+	  goto unlock_and_return;
 	}
       sl_rewind (fd);
@@ -1196,5 +1200,6 @@
 	    sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1, 
 			     sh.prg_name);
-	    aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+	    retval = 1; exitval = EXIT_FAILURE;
+	    goto unlock_and_return;
 	  }
 	
@@ -1216,5 +1221,6 @@
 			       file_path('D', 'R') )
 			     );
-	    aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+	    retval = 1; exitval = EXIT_FAILURE;
+	    goto unlock_and_return;
 	  }
 	sl_rewind (fd);
@@ -1226,5 +1232,6 @@
       TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
       --sig_raised; --sig_urgent;
-      aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+      retval = 1; exitval = EXIT_SUCCESS;
+      goto unlock_and_return;
     }
 
@@ -1251,5 +1258,6 @@
 	  TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
 	  --sig_raised; --sig_urgent;
-	  aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+	  retval = 1; exitval = EXIT_SUCCESS;
+	  goto unlock_and_return;
 	}
 
@@ -1307,5 +1315,6 @@
   if (0 != sh_gpg_check_sign (0, fd, 2))
     {
-      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+      retval = 1; exitval = EXIT_FAILURE;
+      goto unlock_and_return;
     }
   sl_rewind (fd);
@@ -1328,5 +1337,6 @@
 	  TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
 	  --sig_raised; --sig_urgent;
-	  aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+	  retval = 1; exitval = EXIT_SUCCESS;
+	  goto unlock_and_return;
 	}
 
@@ -1357,5 +1367,9 @@
   ; /* 'label at end of compound statement */
   SH_MUTEX_UNLOCK(mutex_hash);
-  SL_RET0(_("sh_hash_init"));
+  if (retval == 0)
+    {
+      SL_RET0(_("sh_hash_init"));
+    }
+  aud_exit (FIL__, __LINE__, exitval);
 }
   
Index: /trunk/src/sh_log_check.c
===================================================================
--- /trunk/src/sh_log_check.c	(revision 184)
+++ /trunk/src/sh_log_check.c	(revision 185)
@@ -29,8 +29,9 @@
  */
 struct sh_logfile_type sh_logtypes_def[] = {
-    {  "SYSLOG", NULL,          sh_parse_syslog, NULL },
-    {  "APACHE", NULL,          sh_parse_apache, sh_eval_fileinfo_apache },
+    {  "SYSLOG", NULL,            sh_parse_syslog, NULL },
+    {  "SAMBA",  sh_read_samba,   sh_parse_samba,  NULL },
+    {  "APACHE", NULL,            sh_parse_apache, sh_eval_fileinfo_apache },
 #if defined(HAVE_SYS_ACCT_H)
-    {  "PACCT",  sh_read_pacct, sh_parse_pacct,  NULL },
+    {  "PACCT",  sh_read_pacct,   sh_parse_pacct,  NULL },
 #endif
 };
@@ -369,6 +370,11 @@
 	      {
 		logrecord->filename = thisfile->filename;
-
-		sh_eval_process_msg(logrecord);
+		
+		/* Don't report if 'init', just set file pointer
+		 */
+		if (sh.flag.checkSum != SH_CHECK_INIT)
+		  {
+		    sh_eval_process_msg(logrecord);
+		  }
 
 		if (logrecord->message) 
@@ -378,4 +384,6 @@
 		if (logrecord->prefix)
 		  sh_string_destroy(&(logrecord->prefix));
+		if (logrecord->timestr)
+		  sh_string_destroy(&(logrecord->timestr));
 		SH_FREE(logrecord);
 	      }
@@ -383,5 +391,5 @@
 	else
 	  {
-	    (void) sh_string_truncate(record, 0);
+	    record = sh_string_new(0);
 	    break;
 	  }
@@ -617,4 +625,81 @@
 	  return NULL;
 	}
+      return s;
+    }
+
+  if (0 != sh_open_for_reader(logfile))
+    goto start_read;
+
+  return NULL;
+}
+
+/******************************************************
+ *  Reader for continued text files 
+ */
+sh_string * sh_cont_reader (sh_string * s, struct sh_logfile * logfile, char*cont)
+{
+  int         status;
+  char      * tmp;
+  sh_string * str;
+  int         remain = 8192;
+  int         count  = 0;
+
+  if (!sh_string_truncate(s, 0))
+    return NULL;
+
+ start_read:
+
+  if (logfile->fp)
+    {
+      str = sh_string_new(0);
+
+      /* Result cannot be larger than 8192, thus cast is ok
+       */
+      status = (int) sh_string_read(str, logfile->fp, 8192);
+
+      if (status > 0)
+	{
+	  
+	  do {
+	    s       = sh_string_add (s, str);
+	    count  += status;
+	    remain -= status;
+
+	    if (remain <= 0)
+	      {
+		return s;
+	      }
+
+	    status = (int) sh_string_read_cont(str, logfile->fp, count, cont);
+
+	    if (status == 0)
+	      {
+		return s;
+	      }
+	  }
+	  while (status > 0);
+	}
+
+      if (status <= 0)
+	{
+	  fgetpos(logfile->fp, &(logfile->offset));
+	  fclose(logfile->fp);
+	  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;
     }
Index: /trunk/src/sh_log_evalrule.c
===================================================================
--- /trunk/src/sh_log_evalrule.c	(revision 184)
+++ /trunk/src/sh_log_evalrule.c	(revision 185)
@@ -170,21 +170,10 @@
   ng->rule_extra  = group_extra;
   ng->ovector     = NULL;
+  ng->ovecnum     = 0;
   ng->captures    = 0;
   ng->counterlist = NULL;
   ng->queue       = NULL;
   ng->nextrule    = NULL;
-
-  /* 
-   * Insert at end, to keep user-defined order 
-   */ 
-  ng->next   = NULL;
-  if (grouplist) 
-    {
-      tmp = grouplist; 
-      while (tmp->next != NULL) { tmp = tmp->next; }
-      tmp->next = ng;
-    } else {
-      grouplist = ng;
-    }
+  ng->next        = NULL;
 
   if (!host_open)
@@ -202,9 +191,24 @@
 
   /* 
-   * If there is an open host group, add it to its
-   * rulegroups
-   */
+   * Insert at end, to keep user-defined order 
+   */ 
+
   if (host_open)
     {
+      if (grouplist) 
+	{
+	  tmp = grouplist; 
+	  while (tmp->next != NULL) { tmp = tmp->next; }
+	  tmp->next = ng;
+	} else {
+	  grouplist = ng;
+        }
+
+
+      /* 
+       * If there is an open host group, add it to its
+       * rulegroups
+       */
+
       if (host_open->rulegroups) 
 	{
@@ -214,5 +218,5 @@
 	} else {
 	  host_open->rulegroups = ng;
-	}
+        }
     }
 
@@ -427,4 +431,5 @@
   nr->captures    = captures;
   nr->ovector     = SH_ALLOC(sizeof(int) * (captures+1) * 3);
+  nr->ovecnum     = 0;
   nr->counterlist = NULL;
   nr->queue       = queue;
@@ -441,6 +446,6 @@
 	{
 	  tmp = group_open->nextrule; 
-	  while (tmp->next != NULL) { tmp = tmp->next; }
-	  tmp->next = nr;
+	  while (tmp->nextrule != NULL) { tmp = tmp->nextrule; } /* next -> nextrule */
+	  tmp->nextrule = nr;                                    /* next -> nextrule */
 	} else {
 	  group_open->nextrule = nr;
@@ -454,20 +459,9 @@
   else
     {
-      /* 
-       * Add rule as member to grouplist, to facilitate cleanup
-       */
-      if (grouplist) 
-	{
-	  tmp = grouplist; 
-	  while (tmp->next != NULL) { tmp = tmp->next; }
-	  tmp->next = nr;
-	} else {
-	  grouplist = nr;
-	}
-
       if (!host_open)
 	{
 	  if (0 != sh_eval_hadd("^.*"))
 	    {
+	      SH_FREE(nr->ovector);
 	      SH_FREE(nr);
 	      return -1;
@@ -475,9 +469,23 @@
 	}
 
-      /* 
-       * Add rule to host rulegroups
-       */
       if (host_open)
 	{
+	  /* 
+	   * Add rule as member to grouplist, to facilitate cleanup
+	   */
+#if 0
+	  if (grouplist) 
+	    {
+	      tmp = grouplist; 
+	      while (tmp->next != NULL) { tmp = tmp->next; }
+	      tmp->next = nr;
+	    } else {
+	      grouplist = nr;
+	    }
+#endif
+
+	  /* 
+	   * Add rule to host rulegroups
+	   */
 	  if (host_open->rulegroups) 
 	    {
@@ -488,5 +496,7 @@
 	      while (tmp->nextrule != NULL) { tmp = tmp->nextrule; }
 	      tmp->nextrule = nr;
-	    } else {
+	    } 
+	  else 
+	    {
 	      /* First rule goes to host_open->rulegroups */
 	      host_open->rulegroups = nr;
@@ -495,4 +505,5 @@
       else
 	{
+	  SH_FREE(nr->ovector);
 	  SH_FREE(nr);
 	  return -1;
@@ -505,5 +516,4 @@
 void sh_eval_cleanup()
 {
-  struct sh_geval * nr;
   struct sh_geval * tmp;
 
@@ -512,7 +522,9 @@
   struct sh_heval * htmp;
 
-  gtmp = grouplist;
-  while (gtmp)
-    {
+  while (grouplist)
+    {
+      gtmp      = grouplist;
+      grouplist = gtmp->next;
+
       if (gtmp->label)      sh_string_destroy(&(gtmp->label));
       if (gtmp->rule_extra) (*pcre_free)(gtmp->rule_extra);
@@ -522,22 +534,20 @@
       if (gtmp->ovector)
 	SH_FREE(gtmp->ovector);
-      if (gtmp->nextrule)
-	{
-	  tmp = gtmp->nextrule;
-	  do {
-	    nr  = tmp->nextrule;
-	    if (tmp->rule_extra) (*pcre_free)(tmp->rule_extra);
-	    if (tmp->rule)       (*pcre_free)(tmp->rule);
-	    if (tmp->counterlist)
-	      zAVLFreeTree(tmp->counterlist, sh_ceval_free);
-	    if (tmp->ovector)
-	      SH_FREE(tmp->ovector);
-	    SH_FREE(tmp);
-	    tmp = nr;
-	  } while (tmp);
-	}
-      grouplist = gtmp->next;
+
+      while (gtmp->nextrule)
+	{
+	  tmp            = gtmp->nextrule;
+	  gtmp->nextrule = tmp->nextrule;
+
+	  if (tmp->rule_extra) (*pcre_free)(tmp->rule_extra);
+	  if (tmp->rule)       (*pcre_free)(tmp->rule);
+	  if (tmp->counterlist)
+	    zAVLFreeTree(tmp->counterlist, sh_ceval_free);
+	  if (tmp->ovector)
+	    SH_FREE(tmp->ovector);
+	  SH_FREE(tmp);
+	}
+
       SH_FREE(gtmp);
-      gtmp = grouplist;
     }
 
@@ -678,6 +688,6 @@
   SH_MUTEX_LOCK(mutex_thread_nolog);
   tmp = sh_util_safe_name (record->filename);
-  msg = sh_util_safe_name (sh_string_str(record->message));
-  ttt = sh_util_safe_name (sh_string_str(record->timestr));
+  msg = sh_util_safe_name_keepspace (sh_string_str(record->message));
+  ttt = sh_util_safe_name_keepspace (sh_string_str(record->timestr));
   sh_error_handle (severity, FIL__, __LINE__, 0, MSG_LOGMON_REP,
 		   msg,
@@ -697,5 +707,5 @@
   SH_MUTEX_LOCK(mutex_thread_nolog);
   tmp = sh_util_safe_name (sh_string_str(path));
-  msg = sh_util_safe_name (sh_string_str(message));
+  msg = sh_util_safe_name_keepspace (sh_string_str(message));
   sh_error_handle (severity, FIL__, __LINE__, 0, MSG_LOGMON_SUM,
 		   msg,
Index: /trunk/src/sh_log_parse_apache.c
===================================================================
--- /trunk/src/sh_log_parse_apache.c	(revision 184)
+++ /trunk/src/sh_log_parse_apache.c	(revision 185)
@@ -47,6 +47,8 @@
   int    pos_status;
   int    pos_time;
+  int    format_time;
 };
 
+static const char lf_error0[]    = N_("%error");
 static const char lf_common0[]   = N_("%h %l %u %t \"%r\" %>s %b");
 static const char lf_combined0[] = N_("%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
@@ -73,4 +75,5 @@
   volatile int          p_status = -1;
   volatile int          p_time = -1;
+  volatile int          f_time = -1;
   const char * error;
   int          erroffset;
@@ -89,4 +92,8 @@
       new    = sh_util_strdup(_(lf_combined0));
     }
+  else if (0 == strncmp("error", str, 8))
+    {
+      new    = sh_util_strdup(_(lf_error0));
+    }
   else
     {
@@ -156,4 +163,22 @@
 	  sh_string_add_from_char(re_string, p);
 	  p_time = i+1;
+	  f_time = 1;
+	}
+      else if (token[0] == '%' && token[1] == 'e' && 0 == strcmp(token, _("%error"))) 
+	{
+	  p = _("\\[([^\\]]+)\\]");
+	  sh_string_add_from_char(re_string, p);
+	  p_time = i+1; f_time = 2; ++i;
+
+	  sh_string_add_from_char(re_string, " ");
+	  p = _("\\[([^\\]]+)\\]");
+	  sh_string_add_from_char(re_string, p);
+	  p_status = i+1;
+
+	  sh_string_add_from_char(re_string, " ");
+	  p = _("(.*)");
+	  sh_string_add_from_char(re_string, p);
+
+	  break;
 	}
       else
@@ -208,4 +233,5 @@
   result->pos_status    = p_status;
   result->pos_time      = p_time;
+  result->format_time   = f_time;
 
   SH_FREE(splits);
@@ -262,4 +288,5 @@
 	  res = 0;
 	  timestamp = 0;
+	  info->format_time = 1;
 	  sl_strlcpy(tstr, _("01/Jan/1970:00:00:00"), sizeof(tstr));
 	}
@@ -268,12 +295,20 @@
 	{
 	  struct tm btime;
-	  char * ptr, * q;
+	  char * ptr = NULL, * q;
 	  
 	  /* example: 01/Jun/2008:07:55:28 +0200 */
 
-	  q = strchr(tstr, ' ');
-	  if (q) *q = '\0';
-
-	  ptr = /*@i@*/strptime(tstr, "%d/%b/%Y:%T", &btime);
+	  if (info->format_time == 1)
+	    {
+	      q = strchr(tstr, ' ');
+	      if (q) *q = '\0';
+	      
+	      ptr = /*@i@*/strptime(tstr, "%d/%b/%Y:%T", &btime);
+	    }
+	  else if (info->format_time == 2)
+	    {
+	      ptr = /*@i@*/strptime(tstr, "%a %b %d %T %Y", &btime);
+	    }
+
 	  if (ptr && *ptr == '\0')
 	    {
@@ -294,5 +329,5 @@
       else
 	{
-	  sl_strlcpy(sstr, _("000"), sizeof(sstr)); /* FIXME API */
+	  sl_strlcpy(sstr, _("000"), sizeof(sstr));
 	}
 
Index: /trunk/src/sh_log_parse_pacct.c
===================================================================
--- /trunk/src/sh_log_parse_pacct.c	(revision 184)
+++ /trunk/src/sh_log_parse_pacct.c	(revision 185)
@@ -277,4 +277,6 @@
     }
 
+  if (record)
+    sh_string_destroy(&record);
   return NULL;
 }
Index: /trunk/src/sh_log_parse_samba.c
===================================================================
--- /trunk/src/sh_log_parse_samba.c	(revision 185)
+++ /trunk/src/sh_log_parse_samba.c	(revision 185)
@@ -0,0 +1,101 @@
+/**************************************
+ **
+ ** PARSER RULES
+ **
+ ** (a) must set record->host 
+ **     (eventually to dummy value)
+ **
+ ** (b) must set record->prefix
+ **     (command) 
+ **
+ **
+ **************************************/
+
+/* for strptime */
+#define _XOPEN_SOURCE
+
+#include "config_xor.h"
+#include <string.h>
+#include <time.h>
+
+#if defined(USE_LOGFILE_MONITOR)
+
+#include "samhain.h"
+#include "sh_pthread.h"
+#include "sh_log_check.h"
+#include "sh_string.h"
+
+#undef  FIL__
+#define FIL__  _("sh_log_parse_samba.c")
+
+
+sh_string * sh_read_samba (sh_string * record, struct sh_logfile * logfile)
+{
+  return sh_cont_reader (record, logfile, " \t");
+}
+
+struct sh_logrecord * sh_parse_samba (sh_string * logline, void * fileinfo)
+{
+  static struct tm old_tm;
+  static time_t    old_time;
+
+  struct sh_logrecord * record = NULL;
+
+  static const char *    format0_1 = N_("%Y/%m/%d %T");
+  static char   format_1[16]; 
+  static int    format_init = 0;
+
+  (void) fileinfo;
+
+  if (!format_init)
+    {
+      sl_strlcpy(format_1, _(format0_1), sizeof(format_1));
+      format_init = 1;
+    }
+
+  if (logline && sh_string_len(logline) > 0)
+    {
+      size_t lengths[3];
+      unsigned int  fields = 3;
+      char ** array;
+      char * p = strchr(sh_string_str(logline), ',');
+
+      *p = '\0'; ++p;
+      array = split_array_ws(p, &fields, lengths);
+
+      if (fields == 3)
+	{
+	  struct tm btime;
+	  char * ptr;
+
+	  memset(&btime, '\0', sizeof(struct tm));
+	  ptr = strptime(sh_string_str(logline), _("%Y/%m/%d %T"), &btime);
+
+	  if (ptr && *ptr == '\0') /* no error, whole string consumed */
+	    {
+
+	      record = SH_ALLOC(sizeof(struct sh_logrecord));
+
+	      record->timestamp = conv_timestamp(&btime, &old_tm, &old_time);
+
+	      p = sh_string_str(logline); ++p;
+	  
+	      record->timestr   = sh_string_new_from_lchar(p, strlen(p));
+	      
+	      record->message   = sh_string_new_from_lchar(array[2], lengths[2]);
+	  
+	      p = array[2]; while (*p != ' ' && *p != '\0') ++p;
+	      p = '\0';
+	      record->prefix    = sh_string_new_from_lchar(array[2], lengths[2]);
+
+	      record->pid       = 0;
+	      record->host      = sh_string_new_from_lchar(sh.host.name, 
+							   strlen(sh.host.name));
+	    }
+	}
+      SH_FREE(array);
+    }
+  return record;
+}
+
+#endif
Index: /trunk/src/sh_string.c
===================================================================
--- /trunk/src/sh_string.c	(revision 184)
+++ /trunk/src/sh_string.c	(revision 185)
@@ -204,6 +204,41 @@
 #define SH_STRING_PARCEL 120
 
+static
+size_t sh_string_read_int(sh_string * s, FILE * fp, size_t maxlen, char *start);
+
 size_t sh_string_read(sh_string * s, FILE * fp, size_t maxlen)
 {
+  return sh_string_read_int(s, fp, maxlen, NULL);
+}
+
+size_t sh_string_read_cont(sh_string * s, FILE * fp, size_t maxlen, char *cont)
+{
+  return sh_string_read_int(s, fp, maxlen, cont);
+}
+
+size_t sh_string_read_int(sh_string * s, FILE * fp, size_t maxlen, char *start)
+{
+
+  /* case 0) start != NULL and first char not in 'start'
+   */
+  if (start)
+    {
+      int first = fgetc(fp);
+
+      if (first == EOF)
+	{
+	  sh_string_truncate(s, 0);
+	  if (ferror(fp))
+	    return -1;
+	  return 0;
+	}
+
+      if (NULL == strchr(start, first))
+	{
+	  ungetc(first, fp);
+	  return 0;
+	}
+      ungetc(first, fp);
+    }
 
   /* case 1) EOF or error 
Index: /trunk/src/sh_unix.c
===================================================================
--- /trunk/src/sh_unix.c	(revision 184)
+++ /trunk/src/sh_unix.c	(revision 185)
@@ -3500,7 +3500,8 @@
    */
 
-  else    /* fstat_return != 0 or !S_ISREG(fbuf->st_mode) */
-    {
-      fstat_return = errno;
+  else    /* fstat_return != 0 or !S_ISREG(fbuf.st_mode) */
+    {
+      uid_t   euid;
+      int fstat_errval = errno;
       if (fileHash != NULL)
 	sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
@@ -3509,6 +3510,21 @@
 	{
 	  tmp2 = sh_util_safe_name (theFile->fullpath);
-	  sh_error_handle (level, FIL__, __LINE__, fstat_return, MSG_E_READ,
-			   tmp2);
+
+	  if (fstat_return != 0)
+	    {
+	      (void) sl_get_euid(&euid);
+	      sh_error_handle (level, FIL__, __LINE__, fstat_errval, 
+			       MSG_E_ACCESS, (long) euid, tmp2);
+	    }
+	  else if (!S_ISREG(fbuf.st_mode))
+	    {
+	      sh_error_handle (level, FIL__, __LINE__, fstat_errval, 
+			       MSG_E_NOTREG, tmp2);
+	    }
+	  else
+	    {
+	      sh_error_handle (level, FIL__, __LINE__, fstat_errval, 
+			       MSG_E_READ, tmp2);
+	    }
 	  SH_FREE(tmp2);
 	}
Index: /trunk/src/sh_utils.c
===================================================================
--- /trunk/src/sh_utils.c	(revision 184)
+++ /trunk/src/sh_utils.c	(revision 185)
@@ -1881,8 +1881,21 @@
 }
 
-    
+#define SH_ESCAPE_SPACE      1
+#define SH_DONT_ESCAPE_SPACE 0    
+char * sh_util_safe_name_int (const char * name, int escape_space);
+
+char * sh_util_safe_name (const char * name)
+{
+  return sh_util_safe_name_int (name, SH_ESCAPE_SPACE); 
+}
+
+char * sh_util_safe_name_keepspace (const char * name)
+{
+  return sh_util_safe_name_int (name, SH_DONT_ESCAPE_SPACE); 
+}
+
 /* returns freshly allocated memory, return value should be free'd
  */
-char * sh_util_safe_name (const char * name)
+char * sh_util_safe_name_int (const char * name, int escape_space)
 {
   register int  i = 0;
@@ -1971,6 +1984,11 @@
 #endif
     } else if ( (*p) == ' ') {     /* space            */
-      retval[i] = '\\'; ++i; 
-      retval[i] = ' ';
+      if (escape_space) {
+	retval[i] = '\\'; ++i; 
+	retval[i] = ' ';
+      }
+      else {
+	retval[i] = *p;
+      }
 #ifdef SH_USE_XML
     } else if ( (*p) == '"') {     /* double quote     */
Index: /trunk/test/testhash.sh
===================================================================
--- /trunk/test/testhash.sh	(revision 184)
+++ /trunk/test/testhash.sh	(revision 185)
@@ -37,5 +37,5 @@
 	fi
 	#
-	${TOP_SRCDIR}/configure --quiet $TRUST --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file 
+	${TOP_SRCDIR}/configure --quiet $TRUST --prefix=$PW_DIR --localstatedir=$PW_DIR --with-config-file=$RCFILE --with-log-file=$LOGFILE --with-pid-file=$PW_DIR/.samhain_lock --with-data-file=$PW_DIR/.samhain_file --enable-debug --enable-logfile-monitor --disable-dnmalloc
 	#
 	fail=0
