Index: trunk/src/sh_audit.c
===================================================================
--- trunk/src/sh_audit.c	(revision 489)
+++ trunk/src/sh_audit.c	(revision 514)
@@ -180,8 +180,11 @@
   if (0 == strcmp(state.success, "yes"))
     {
+      char   time_str[81];
       char * tmp_exe = sh_util_safe_name(state.exe);
+
+      (void) sh_unix_gmttime (state.time, time_str, sizeof(time_str));
       sl_snprintf(result, rsize, 
-		  _("time=%lu.%u, syscall=%s, auid=%u, uid=%u, gid=%u, euid=%u, egid=%u, fsuid=%u, fsgid=%u, exe=%s"),
-		  (unsigned long) state.time, state.milli, 
+		  _("time=%lu.%u, timestamp=%s, syscall=%s, auid=%u, uid=%u, gid=%u, euid=%u, egid=%u, fsuid=%u, fsgid=%u, exe=%s"),
+		  (unsigned long) state.time, state.milli, time_str, 
 		  state.syscall,
 		  state.auid, state.uid, state.gid, state.euid, state.egid, 
@@ -196,4 +199,21 @@
   return NULL;
 }
+
+#define SH_AUDIT_DEF "wa"
+static char sh_audit_flags[32] = SH_AUDIT_DEF;
+
+int sh_audit_set_flags(const char * str)
+{
+  if (!str || strlen(str) >= sizeof(sh_audit_flags))
+    return -1;
+  sl_strlcpy(sh_audit_flags, str, sizeof(sh_audit_flags));
+  return 0;
+}
+static void reset_audit_flags()
+{
+  sl_strlcpy(sh_audit_flags, SH_AUDIT_DEF, sizeof(sh_audit_flags));
+  return;
+}
+
 
 static int sh_audit_checkdaemon();
@@ -207,18 +227,21 @@
   };
 
+static char * getflags (char * file);
 
 /* Public function to fetch an audit record for path 'file', time 'time'
  * The 'result' array should be sized ~256 char. 
  */
-char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize)
-{
-  char * res = NULL;
+char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, time_t atime, char * result, size_t rsize)
+{
+  char * res   = NULL;
+  char * flags = getflags(file);
 
   if (sh_audit_checkdaemon() >= 0)
     {
       time_t new;
-      
-      if (mtime >= ctime) { new = mtime; }
-      else                { new = ctime; }
+
+      if (flags && (strchr(flags, 'r') || strchr(flags, 'x')) && atime >= ctime && atime >= mtime) { new = atime; }
+      else if (mtime >= ctime) { new = mtime; }
+      else                     { new = ctime; }
 
       res = doAuparse (file, new, 1, result, rsize, S_FALSE);
@@ -251,4 +274,5 @@
       sh_ext_system(ctl, ctl, "-D", "-k", _("samhain"), NULL);
     }
+  reset_audit_flags();
   return;
 }
@@ -263,5 +287,5 @@
 }
 
-static void sh_audit_mark_int (const char * file)
+static void sh_audit_mark_int (const char * file, const char * flags)
 {
   static int flushRules = 0;
@@ -286,8 +310,8 @@
       char   a2[32];
       char   a3[32];
-
-      sl_snprintf(command, len, _("%s -w %s -p wa -k samhain"),
-		  _(actl_paths[p]),
-		  file);
+      char   a4[32];
+
+      sl_snprintf(command, len, _("%s -w %s -p %s -k samhain"),
+		  _(actl_paths[p]), file, flags);
 
       safe = sh_util_safe_name_keepspace(command);
@@ -303,5 +327,6 @@
 
       sl_strlcpy(a3, _("samhain"), sizeof(a3));
-      sh_ext_system(ctl, ctl, "-w", command, "-p", "wa", "-k", a3, NULL);
+      sl_strlcpy(a4, flags, sizeof(a4));
+      sh_ext_system(ctl, ctl, "-w", command, "-p", a4, "-k", a3, NULL);
 
       /* Placing a watch on a directory will not place a watch on the
@@ -319,5 +344,6 @@
 	  sl_strlcat(command, file, len);
 	  sl_strlcpy(a1, _("always,exit"), sizeof(a1));
-	  sl_strlcpy(a2, _("perm=wa"), sizeof(a2));
+	  sl_strlcpy(a2, _("perm="), sizeof(a2));
+	  sl_strlcat(a2, flags, sizeof(a2));
 	  sh_ext_system(ctl, ctl, "-a", a1, "-F", command, "-F", a2, "-k", a3, NULL);
 	}
@@ -327,10 +353,45 @@
 }
 
+#define SH_AU_FLAGS_SIZ 32
 struct aud_list {
   char * file;
+  char   flags[SH_AU_FLAGS_SIZ];
   struct aud_list * next;
 };
 
 struct aud_list * mark_these = NULL;
+static int marked_committed = 0;
+
+static void delete_listofmarked()
+{
+  struct aud_list * tmp;
+  struct aud_list * this = mark_these;
+
+  mark_these = NULL;
+  
+  while (this)
+    {
+      tmp  = this;
+      this = this->next;
+      
+      SH_FREE(tmp->file);
+      SH_FREE(tmp);
+    }
+  marked_committed = 0;
+}
+
+static char * getflags (char * file)
+{
+  struct aud_list * this = mark_these;
+
+  while (this)
+    {
+      if (0 == strcmp(file, this->file))
+	return this->flags;
+      this = this->next;
+    }
+  /* no explicit rule for this file */
+  return NULL;
+}
 
 static void add_this (char * file)
@@ -340,6 +401,10 @@
 
   this->file = sh_util_strdup(file);
+
+  /* strip trailing '/' */
   if ((len > 1) && (file[len-1] == '/'))
     this->file[len-1] = '\0';
+
+  sl_strlcpy(this->flags, sh_audit_flags, SH_AU_FLAGS_SIZ);
   
   this->next = mark_these;
@@ -362,30 +427,33 @@
   else
     {
-      char * s0 = SH_ALLOC(len0 + 2);
-      char * s1 = SH_ALLOC(len1 + 2);
-
-       sl_strlcpy(s0, this->file, len0 + 2); 
-       sl_strlcpy(s1, file,       len1 + 2); 
-
-       if (s0 < s1)
-	 {
-	   sl_strlcat(s0, "/", len0 + 2);
-	   ret = strncmp(s0, s1, len0 + 1);
-	 }
-       else
-	 {
-	   sl_strlcat(s1, "/", len1 + 2);
-	   if (0 == strncmp(s0, s1, len1 + 1))
-	     {
-	       size_t len = strlen(file);
-	       SH_FREE(this->file);
-	       this->file = sh_util_strdup(file);
-	       if ((len > 1) && (file[len-1] == '/'))
-		 this->file[len-1] = '\0';
-	       ret = 0;
-	     }
-	 }
-       SH_FREE(s0);
-       SH_FREE(s1);
+      if (0 == strcmp(this->flags, sh_audit_flags))
+	{
+	  char * s0 = SH_ALLOC(len0 + 2);
+	  char * s1 = SH_ALLOC(len1 + 2);
+	  
+	  sl_strlcpy(s0, this->file, len0 + 2); 
+	  sl_strlcpy(s1, file,       len1 + 2); 
+	  
+	  if (s0 < s1)
+	    {
+	      sl_strlcat(s0, "/", len0 + 2);
+	      ret = strncmp(s0, s1, len0 + 1);
+	    }
+	  else
+	    {
+	      sl_strlcat(s1, "/", len1 + 2);
+	      if (0 == strncmp(s0, s1, len1 + 1))
+		{
+		  size_t len = strlen(file);
+		  SH_FREE(this->file);
+		  this->file = sh_util_strdup(file);
+		  if ((len > 1) && (file[len-1] == '/'))
+		    this->file[len-1] = '\0';
+		  ret = 0;
+		}
+	    }
+	  SH_FREE(s0);
+	  SH_FREE(s1);
+	}
     }
   
@@ -397,10 +465,15 @@
 void sh_audit_mark (char * file)
 {
-  struct aud_list * this = mark_these;
-
+  struct aud_list * this;
+
+  if (marked_committed != 0) 
+    delete_listofmarked();
+  
   if (!mark_these) {
     add_this (file);
     return;
   }
+
+  this = mark_these;
 
   while (this)
@@ -411,4 +484,5 @@
       if (0 == test_exchange(this, file))
 	return;
+
       this = this->next;
     }
@@ -420,18 +494,12 @@
 void sh_audit_commit ()
 {
-  struct aud_list * next;
   struct aud_list * this = mark_these;
 
-  mark_these = NULL;
-
   while (this)
     {
-      sh_audit_mark_int (this->file);
-      next = this->next;
-      SH_FREE(this->file);
-      SH_FREE(this);
-      this = next;
-    }
-  
+      sh_audit_mark_int (this->file, this->flags);
+      this = this->next;
+    }
+  marked_committed = 1;
 }
 
@@ -538,9 +606,10 @@
 /* HAVE_AUPARSE_H */
 #else
-char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize)
+char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, time_t atime, char * result, size_t rsize)
 {
   (void) file;
   (void) mtime;
   (void) ctime;
+  (void) atime;
   (void) result;
   (void) rsize;
@@ -564,4 +633,9 @@
   return;
 }
+int sh_audit_set_flags(const char * str)
+{
+  (void) str;
+  return -1;
+}
 #endif
 
