Index: trunk/src/samhain.c
===================================================================
--- trunk/src/samhain.c	(revision 403)
+++ trunk/src/samhain.c	(revision 405)
@@ -422,6 +422,10 @@
   /* The stats.
    */
-  sh.statistics.bytes_speed  = 0;
-  sh.statistics.bytes_hashed = 0;
+  sh.statistics.bytes_speed   = 0;
+  sh.statistics.bytes_hashed  = 0;
+  sh.statistics.files_report  = 0;
+  sh.statistics.files_error   = 0;
+  sh.statistics.files_nodir   = 0;
+
   sh.statistics.mail_success = 0;
   sh.statistics.mail_failed  = 0;
@@ -1727,6 +1731,9 @@
   /*  --------  MAIN LOOP  ---------
    */
-  sh.statistics.bytes_speed  = 0;
-  sh.statistics.bytes_hashed = 0;
+  sh.statistics.bytes_speed   = 0;
+  sh.statistics.bytes_hashed  = 0;
+  sh.statistics.files_report  = 0;
+  sh.statistics.files_error   = 0;
+  sh.statistics.files_nodir   = 0;
 
   while (1 == 1) 
@@ -2016,4 +2023,7 @@
 	  sh.statistics.dirs_checked   = 0;
 	  sh.statistics.files_checked  = 0;
+	  sh.statistics.files_report   = 0;
+	  sh.statistics.files_error    = 0;
+	  sh.statistics.files_nodir    = 0;
 
 	  TPT((0, FIL__, __LINE__, _("msg=<Check directories.>\n")))
@@ -2097,4 +2107,7 @@
 			       (long) runtim, 
 			       0.001 * st_1);
+
+	      if (sh.flag.checkSum != SH_CHECK_INIT)
+		sh_efile_report();
 	    }
 	  sh.fileCheck.alarm_last = time (NULL);
Index: trunk/src/sh_err_log.c
===================================================================
--- trunk/src/sh_err_log.c	(revision 403)
+++ trunk/src/sh_err_log.c	(revision 405)
@@ -24,4 +24,5 @@
 #include <sys/types.h>
 #include <unistd.h>
+#include <time.h>
 
 #include "samhain.h"
@@ -1053,2 +1054,213 @@
 }
 
+/* >>>>>>>>>>>>>>>>>>>>>>>>>>>> efile <<<<<<<<<<<<<<<<<< */
+
+static char * gEfile = NULL;
+static int    gFail  = 0;
+
+int sh_efile_path(const char * str) 
+{
+  if (!str || !strcmp(str, _("none")))
+    {
+      if (gEfile)
+	SH_FREE(gEfile);
+      gEfile = NULL;
+    }
+  else if (str[0] != '/')
+    {
+      return -1;
+    }
+  else
+    {
+      if (gEfile)
+	SH_FREE(gEfile);
+      gEfile = sh_util_strdup(str);
+    }
+  gFail = 0;
+  return 0;
+}
+
+/* write lock for filename
+ */
+static int sh_efile_lock (char * filename, int flag)
+{
+  extern int get_the_fd (SL_TICKET ticket);
+  size_t len;
+  int    res = -1;
+  char myPid[64];
+  SL_TICKET  fd;
+  char * lockfile;
+  int    status;
+
+  sprintf (myPid, "%ld\n", (long) sh.pid);             /* known to fit  */
+
+  if (filename == NULL)
+    return res;
+
+  len = sl_strlen(filename);
+  if (sl_ok_adds(len, 6))
+    len += 6;
+  lockfile = SH_ALLOC(len);
+  sl_strlcpy(lockfile, filename,   len);
+  sl_strlcat(lockfile, _(".lock"), len);
+
+  if (  0 !=  (status = tf_trust_check (lockfile, SL_YESPRIV))
+	&& gFail == 0)
+    {
+      char * tmp  = sh_util_safe_name (lockfile);
+      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST,
+			   (long) sh.effective.uid, tmp);
+      ++gFail;
+      SH_FREE(tmp);
+    }
+
+  if (status == 0)
+    {
+      if (flag == 0)
+	{
+	  /* --- Delete the lock file. --- 
+	   */
+	  res = retry_aud_unlink (FIL__, __LINE__, lockfile);
+	}
+      else
+	{
+	  unsigned int count = 0;
+
+	  /* fails if file exists 
+	   */
+	  do {
+	    fd = sl_open_safe_rdwr (FIL__, __LINE__, 
+				    lockfile, SL_YESPRIV);
+	    if (SL_ISERROR(fd))
+	      {
+		retry_msleep(0, 100);
+		++count;
+	      }
+
+	  } while (SL_ISERROR(fd) && count < 3);
+      
+	  if (!SL_ISERROR(fd))
+	    {
+	      int filed;
+
+	      res = sl_write (fd, myPid, sl_strlen(myPid));
+	      filed = get_the_fd(fd);
+	      fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+	      sl_close (fd);
+	    }
+	}
+    }
+
+  SH_FREE(lockfile);
+  return res;
+}
+
+static size_t gSave[6] = { 0 };
+
+static void sh_efile_clear()
+{
+  int i;
+
+  for (i = 0; i < 6; ++i)
+    gSave[i] = 0;
+  return;
+}
+
+static void sh_efile_load(size_t * tmp)
+{
+  int i;
+
+  if (SL_TRUE == sl_ok_adds (gSave[0], sh.statistics.bytes_hashed))
+    gSave[0] += sh.statistics.bytes_hashed;
+  if (SL_TRUE == sl_ok_adds (gSave[1], sh.statistics.dirs_checked))
+    gSave[1] += sh.statistics.dirs_checked;
+  if (SL_TRUE == sl_ok_adds (gSave[2], sh.statistics.files_checked))
+    gSave[2] += sh.statistics.files_checked;
+  if (SL_TRUE == sl_ok_adds (gSave[3], sh.statistics.files_report))
+    gSave[3] += sh.statistics.files_report;
+  if (SL_TRUE == sl_ok_adds (gSave[4], sh.statistics.files_error))
+    gSave[4] += sh.statistics.files_error;
+  if (SL_TRUE == sl_ok_adds (gSave[5], sh.statistics.files_nodir))
+    gSave[5] += sh.statistics.files_nodir;
+
+  for (i = 0; i < 6; ++i)
+    tmp[i] = gSave[i];
+  return;
+}
+
+void sh_efile_report()
+{
+  SL_TICKET     fd;
+  char         *efile;
+  int           status = -1;
+
+  if (gEfile)
+    {
+      size_t tmp[6];
+
+      sh_efile_load(tmp);
+
+      efile = sh_util_strdup(gEfile);
+      
+      if (sh_efile_lock (efile, 1) < 0)
+	goto end;
+
+      if (  0 !=  (status = tf_trust_check (efile, SL_YESPRIV))
+	    && gFail == 0)
+	{
+	  char * tmp  = sh_util_safe_name (efile);
+	  sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_TRUST,
+			   (long) sh.effective.uid, tmp);
+	  ++gFail;
+	  SH_FREE(tmp);
+	}
+      
+      if (status == 0)
+	{
+	  fd = sl_open_write (FIL__, __LINE__, efile, SL_YESPRIV);
+
+	  if (!SL_ISERROR(fd))
+	    {
+	      char report[511];
+	      char tstamp[TIM_MAX];
+
+	      time_t now = time(NULL);
+
+	      (void) sh_unix_time (now, tstamp, sizeof(tstamp));
+#ifdef HAVE_LONG_LONG
+	      sl_snprintf(report, sizeof(report), 
+			  _("%s %lld %ld %ld %ld %ld %ld %ld\n"),
+			  tstamp,
+			  (long long) now,
+			  tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]);
+#else
+	      sl_snprintf(report, sizeof(report), 
+			  _("%s %ld %ld %ld %ld %ld %ld %ld\n"),
+			  tstamp,
+			  (long) now,
+			  tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5]);
+#endif
+			  
+	      status = sl_forward(fd);
+	      if (!SL_ISERROR(status))
+		status = sl_write (fd, report,  strlen(report));
+	      (void) sl_sync(fd);
+	      (void) sl_close(fd);
+	    }
+	  else
+	    {
+	      status = -1;
+	    }
+	}
+  
+      (void) sh_efile_lock (efile, 0);
+    end:
+      SH_FREE(efile);
+
+      if (!SL_ISERROR(status))
+	{
+	  sh_efile_clear();
+	}
+    }
+  return;
+}
Index: trunk/src/sh_error.c
===================================================================
--- trunk/src/sh_error.c	(revision 403)
+++ trunk/src/sh_error.c	(revision 405)
@@ -999,4 +999,14 @@
     severity = sev;
 
+  /* --- Some statistics. ---
+   */
+#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
+  if ( ((1 << class) & ERROR_CLA) && 
+       (severity & (SH_ERR_ERR|SH_ERR_SEVERE|SH_ERR_FATAL)))
+    {
+      ++sh.statistics.files_error;
+    }
+#endif
+
   /* these are messages from remote sources
    */
Index: trunk/src/sh_fInotify.c
===================================================================
--- trunk/src/sh_fInotify.c	(revision 403)
+++ trunk/src/sh_fInotify.c	(revision 405)
@@ -515,5 +515,5 @@
   sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_MISS, tmp);
   SH_MUTEX_UNLOCK(mutex_thread_nolog);
-
+  ++sh.statistics.files_report;
   SH_FREE(tmp);
   return;
Index: trunk/src/sh_files.c
===================================================================
--- trunk/src/sh_files.c	(revision 403)
+++ trunk/src/sh_files.c	(revision 405)
@@ -417,4 +417,5 @@
 					 FIL__, __LINE__, 0, MSG_FI_MISS,
 					 tmp);
+			++sh.statistics.files_report;
 		      }
 		    }
@@ -476,4 +477,5 @@
 					     FIL__, __LINE__, 0, MSG_FI_MISS,
 					     tmp);
+			    ++sh.statistics.files_report;
 			  }
 			}
@@ -1437,4 +1439,5 @@
 				     ShDFLevel[SH_ERR_T_DIR], FIL__, __LINE__,
 				     0, MSG_FI_MISS, tmp);
+		    ++sh.statistics.files_report;
 		    SH_FREE(tmp);
 		  }
@@ -1460,4 +1463,5 @@
 				   FIL__, __LINE__, 0, MSG_FI_ADD,
 				   tmp);
+		  ++sh.statistics.files_report;
 		  SH_FREE(tmp);
 #endif
@@ -2023,4 +2027,5 @@
 		       MSG_FI_NODIR,
 		       tmpname);
+      ++sh.statistics.files_nodir;
       SH_FREE(tmpname); 
       if (theFile->attr_string) SH_FREE(theFile->attr_string);
Index: trunk/src/sh_hash.c
===================================================================
--- trunk/src/sh_hash.c	(revision 403)
+++ trunk/src/sh_hash.c	(revision 405)
@@ -464,4 +464,5 @@
 		   MSG_FI_MISS2, tmp, str);
   SH_MUTEX_UNLOCK(mutex_thread_nolog);
+  ++sh.statistics.files_report;
 
   SH_FREE(tmp);
@@ -576,4 +577,5 @@
 		  sh_error_handle (level, FIL__, __LINE__, 0, 
 				   MSG_FI_MISS2, tmp, str);
+		  ++sh.statistics.files_report;
 		  SH_FREE(str);
 		  if (theFile->attr_string) SH_FREE(theFile->attr_string);
@@ -621,4 +623,5 @@
 	  sh_error_handle (level, FIL__, __LINE__, 0, 
 			   MSG_FI_MISS2, tmp, str);
+	  ++sh.statistics.files_report;
 	  SH_FREE(str);
 	  if (theFile->attr_string)
@@ -2992,4 +2995,5 @@
 			   MSG_FI_ADD2, 
 			   tmp, str);
+	  ++sh.statistics.files_report;
 	  SH_FREE(str);
 
@@ -3638,4 +3642,5 @@
 		      (policy_override == NULL) ? _(policy[class]):log_policy,
 		      change_code, tmp_path, msg);
+      ++sh.statistics.files_report;
 
       SH_FREE(tmp_path);
Index: trunk/src/sh_inotify.c
===================================================================
--- trunk/src/sh_inotify.c	(revision 403)
+++ trunk/src/sh_inotify.c	(revision 405)
@@ -468,10 +468,15 @@
 }
 
+#if !defined(IN_DONT_FOLLOW)
+#define IN_DONT_FOLLOW 0
+#endif
+
 #define SH_INOTIFY_FILEFLAGS \
-  (IN_ATTRIB|IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT)
+  (IN_ATTRIB|IN_MODIFY|IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|IN_DONT_FOLLOW)
 #define SH_INOTIFY_DIRFLAGS \
   (SH_INOTIFY_FILEFLAGS|IN_DELETE|IN_CREATE|IN_MOVED_FROM|IN_MOVED_TO)
 
 #define SH_INOTIFY_FLAGS (SH_INOTIFY_FILEFLAGS|SH_INOTIFY_DIRFLAGS)
+
 
 /* Create an item and put it on the 'dormant' list for later watch creation 
@@ -639,5 +644,8 @@
 	      if (*errnum != 0)
 		{
-		  (*errnum == -1) ? *errnum = ENOMEM : EEXIST;
+		  /* zAVLInsert returns -1 on malloc() error and 3 if
+		   * the node already exists. 
+		   */
+		  *errnum = (*errnum == -1) ? ENOMEM : EEXIST;
 		  sh_inotify_free_watch(item);
 		  retval = -1;
Index: trunk/src/sh_login_track.c
===================================================================
--- trunk/src/sh_login_track.c	(revision 403)
+++ trunk/src/sh_login_track.c	(revision 405)
@@ -296,8 +296,8 @@
 	  struct sh_track_entry * entry = urecord->list;
 	  
-	  while (entry)
+	  while (entry && (n > 0))
 	    {
-	      fwrite(&(entry->data), sizeof(struct sh_track_entry_data), 
-		     1, fp);
+	      n = fwrite(&(entry->data), sizeof(struct sh_track_entry_data), 
+			 1, fp);
 	      entry = entry->next;
 	    }
Index: trunk/src/sh_portcheck.c
===================================================================
--- trunk/src/sh_portcheck.c	(revision 403)
+++ trunk/src/sh_portcheck.c	(revision 405)
@@ -1832,7 +1832,9 @@
   if (sh_portchk_active != S_FALSE)
     {
+      SH_MUTEX_LOCK(mutex_thread_nolog);
       sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
 		      _("Checking for open ports"),
 		      _("sh_portchk_check"));
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
 
       sh_portchk_reset_lists();
Index: trunk/src/sh_pthread.c
===================================================================
--- trunk/src/sh_pthread.c	(revision 403)
+++ trunk/src/sh_pthread.c	(revision 405)
@@ -85,4 +85,12 @@
    */
   sigfillset( &signal_set );
+#if defined(SCREW_IT_UP)
+  /*
+   * raise(SIGTRAP) sends to same thread, like 
+   * pthread_kill(pthread_self(), sig); so we need to unblock the
+   * signal. 
+   */
+  sigdelset( &signal_set, SIGTRAP );
+#endif 
   pthread_sigmask( SIG_BLOCK, &signal_set, NULL );
 
Index: trunk/src/sh_readconf.c
===================================================================
--- trunk/src/sh_readconf.c	(revision 403)
+++ trunk/src/sh_readconf.c	(revision 405)
@@ -1216,4 +1216,7 @@
     sh_log_set_console },
 
+  { N_("setreportfile"),     SH_SECTION_MISC,  SH_SECTION_NONE, 
+    sh_efile_path },
+
 #ifdef WITH_MESSAGE_QUEUE
   { N_("messagequeueactive"),SH_SECTION_MISC,  SH_SECTION_NONE, 
Index: trunk/src/sh_suidchk.c
===================================================================
--- trunk/src/sh_suidchk.c	(revision 403)
+++ trunk/src/sh_suidchk.c	(revision 405)
@@ -265,7 +265,9 @@
       if (0 != retry_lstat_ns(FIL__, __LINE__, ".", &two))
 	{ 
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle ((-1), FIL__, __LINE__, errno,
 			   MSG_SUID_ERROR,
 			   sh_error_message(errno, errbuf, sizeof(errbuf)));
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 	  return -1; 
 	}
