Index: trunk/src/cutest_sh_utils.c
===================================================================
--- trunk/src/cutest_sh_utils.c	(revision 67)
+++ trunk/src/cutest_sh_utils.c	(revision 68)
@@ -7,4 +7,28 @@
 #include "sh_utils.h"
 
+void Test_sh_util_acl_compact (CuTest *tc) {
+  char * ret = 0;
+  char   inp1[] = "user::r--\nuser:lisa:rwx\t\t#effective: r--\ngroup::r--\ngroup:toolies:rw-  #effective: r--\nmask::r--\nother::r--\n";
+  char   inp2[] = "use\n\nuser:lisa:rwx\t\t#effective: r--\ngroup::r--\ngroup:toolies:rw-  #effective: r--\nmask::r--\nother::r--\n";
+  char   inp3[] = "user:\177\145\177\122:r--\nuser:lisa:rwx\t\t#effective: r--\ngroup::r--\ngroup:toolies:rw-  #effective: r--\nmask::r--\nother::r--\n";
+  
+  ret = sh_util_acl_compact (inp1, strlen(inp1));
+  CuAssertPtrNotNull(tc, ret);
+  CuAssertStrEquals(tc, "u::r--,u:lisa:rwx,g::r--,g:toolies:rw-,m::r--,o::r--",
+		    ret); 
+
+  ret = sh_util_acl_compact (inp2, strlen(inp2));
+  CuAssertPtrNotNull(tc, ret);
+  CuAssertStrEquals(tc, "use,u:lisa:rwx,g::r--,g:toolies:rw-,m::r--,o::r--",
+		    ret); 
+
+  ret = sh_util_acl_compact (inp3, strlen(inp3));
+  CuAssertPtrNotNull(tc, ret);
+  CuAssertStrEquals(tc, "u:eR:r--,u:lisa:rwx,g::r--,g:toolies:rw-,m::r--,o::r--",
+		    ret); 
+
+  return;
+}
+
 void Test_sh_util_strdup_ok (CuTest *tc) {
   char * ret = 0;
@@ -108,4 +132,141 @@
 
   return;
+}
+
+void Test_sh_util_utf8_ok (CuTest *tc) {
+  int ret = 0;
+#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
+  unsigned char seq[16];
+  unsigned char input[16] = "foobar";
+
+  seq[0] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  seq[0] = 0xd7; seq[1] = 0x90; seq[2] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  seq[0] = 0xed; seq[1] = 0x9f; seq[2] = 0xbf; seq[3] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  seq[0] = 0xee; seq[1] = 0x80; seq[2] = 0x80; seq[3] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  seq[0] = 0xef; seq[1] = 0xbf; seq[2] = 0xbd; seq[3] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  seq[0] = 0xf4; seq[1] = 0x8f; seq[2] = 0xbf; seq[3] = 0xbf; seq[4] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  seq[0] = 0xf4; seq[1] = 0x90; seq[2] = 0x80; seq[3] = 0x80; seq[4] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  seq[0] = 0xd7; seq[1] = 0x90; seq[2] = 0xd7; seq[3] = 0x90; seq[4] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  /* cont. char */
+
+  seq[0] = 0x80; seq[1] = 0x00; 
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xbf; seq[1] = 0x00; 
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  /* overlong */
+
+  seq[0] = 0xc0; seq[1] = 0xaf; seq[2] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xe0; seq[1] = 0x8f; seq[2] = 0xaf;  seq[3] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xf0; seq[1] = 0x80; seq[2] = 0x80;  seq[3] = 0xaf; seq[4] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  /* overlong */
+
+  seq[0] = 0xc1; seq[1] = 0xbf; seq[2] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xe0; seq[1] = 0x9f; seq[2] = 0xbf;  seq[3] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xf0; seq[1] = 0x8f; seq[2] = 0xbf;  seq[3] = 0xbf; seq[4] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  /* overlong */
+
+  seq[0] = 0xc0; seq[1] = 0x80; seq[2] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xe0; seq[1] = 0x80; seq[2] = 0x80;  seq[3] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xf0; seq[1] = 0x80; seq[2] = 0x80;  seq[3] = 0x80; seq[4] = 0x00;  
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  /* cont missing */
+
+  seq[0] = 0xd7; seq[1] = 0x20; seq[3] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xee; seq[1] = 0x80; seq[2] = 0x20; seq[3] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  seq[0] = 0xf4; seq[1] = 0x8f; seq[2] = 0xbf; seq[3] = 0x20; seq[4] = 0x00;
+  ret = sh_util_valid_utf8(seq);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+
+  ret = sh_util_obscure_ok ("0x01,0x02,0x03");
+  CuAssertIntEquals(tc, ret, 0);
+
+  ret = sh_util_valid_utf8 (input);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  input[0] = '\t';
+  ret = sh_util_valid_utf8 (input);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+  input[0] = 0x01;
+  ret = sh_util_valid_utf8 (input);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  input[0] = 0x02;
+  ret = sh_util_valid_utf8 (input);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  input[0] = 0x03;
+  ret = sh_util_valid_utf8 (input);
+  CuAssertIntEquals(tc, ret, S_TRUE);
+
+  input[0] = 0x04;
+  ret = sh_util_valid_utf8 (input);
+  CuAssertIntEquals(tc, ret, S_FALSE);
+
+
+#else
+  CuAssertIntEquals(tc, ret, 0);
+#endif
 }
 
Index: trunk/src/sh_cat.c
===================================================================
--- trunk/src/sh_cat.c	(revision 67)
+++ trunk/src/sh_cat.c	(revision 68)
@@ -122,4 +122,16 @@
   { MSG_UT_ROT,      SH_ERR_WARN,    RUN,   N_("msg=\"Logfile size decreased\" path=\"%s\"")},
 
+#endif
+
+#ifdef SH_USE_PROCESSCHECK
+  { MSG_PCK_CHECK,   SH_ERR_NOTICE,  RUN,   N_("msg=\"Checking processes in pid interval [%ld,%ld]\"")},
+  { MSG_PCK_OK,      SH_ERR_ALL,     RUN,   N_("msg=\"PID %ld found with tests %s\"")},
+  { MSG_PCK_HIDDEN,  SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Process] Hidden pid: %ld tests: %s\"")},
+  { MSG_PCK_FAKE,    SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Process] Fake pid: %ld tests: %s\"")},
+  { MSG_PCK_MISS,    SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Process] Missing: %s\"")},
+#endif
+
+#ifdef SH_USE_PORTCHECK
+  { MSG_PORT_REPORT, SH_ERR_SEVERE,  EVENT, N_("msg=\"%s\"")},
 #endif
 
@@ -181,5 +193,5 @@
   { MSG_TCP_MISMATCH,SH_ERR_ERR,     TCP,   N_("msg=\"Protocol mismatch\"")},
   { MSG_TCP_MISENC,  SH_ERR_ERR,     TCP,   N_("msg=\"Encryption mismatch in %s: server: %s client: %s\"")},
-  { MSG_TCP_NONAME,  SH_ERR_ERR,     TCP,   N_("msg=\"No server name available\"")},
+  { MSG_TCP_NONAME,  SH_ERR_ERR,     TCP,   N_("msg=\"No server name known\"")},
   { MSG_TCP_UNEXP,   SH_ERR_ERR,     TCP,   N_("msg=\"Unexpected reply\"")},
   { MSG_TCP_EFIL,    SH_ERR_ERR,     TCP,   N_("msg=\"Could not open temporary file\"")},
@@ -424,4 +436,16 @@
   { MSG_UT_ROT,      SH_ERR_WARN,    RUN,   N_("msg=<Logfile size decreased>, path=<%s>")},
 
+#endif
+
+#ifdef SH_USE_PROCESSCHECK
+  { MSG_PCK_CHECK,   SH_ERR_NOTICE,  RUN,   N_("msg=<Checking processes in pid interval [%ld,%ld]>")},
+  { MSG_PCK_OK,      SH_ERR_ALL,     RUN,   N_("msg=<PID %ld found with tests %s>")},
+  { MSG_PCK_HIDDEN,  SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [Process] Hidden pid: %ld tests: %s>")},
+  { MSG_PCK_FAKE,    SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [Process] Fake pid: %ld tests: %s>")},
+  { MSG_PCK_MISS,    SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [Process] Missing: %s>")},
+#endif
+
+#ifdef SH_USE_PORTCHECK
+  { MSG_PORT_REPORT, SH_ERR_SEVERE,  EVENT, N_("msg=<%s>")},
 #endif
 
Index: trunk/src/sh_database.c
===================================================================
--- trunk/src/sh_database.c	(revision 67)
+++ trunk/src/sh_database.c	(revision 68)
@@ -109,4 +109,6 @@
   char            link_old[1024];
   char            link_new[1024];
+  char            acl_old[1024];
+  char            acl_new[1024];
 
   long            long_data[20];
@@ -204,4 +206,6 @@
   { NULL, N_("attr_old"),     0,  71,   16, 0, offsetof(struct dbins_, attr_old)},
   { NULL, N_("attr_new"),     0,  72,   16, 0, offsetof(struct dbins_, attr_new)},
+  { NULL, N_("acl_old"),      0,  73, 1024, 0, offsetof(struct dbins_, acl_old)},
+  { NULL, N_("acl_new"),      0,  74, 1024, 0, offsetof(struct dbins_, acl_new)},
 
   { NULL, NULL,      0,  0, 0, 0, 0 }
@@ -497,4 +501,5 @@
 static    OCIError  * o_error = NULL;
 static    OCIStmt   * o_statement;
+static    OCIBind   * o_bind = (OCIBind *) 0;
 static    text        o_errormsg[512];
 static    sb4         o_errorcode;
@@ -666,35 +671,17 @@
  oracle_connected:
 
-  /* 
-   * Insert
-   */
+  /* Get row index
+   */
+  sl_strlcpy (row_query, _("SELECT log_log_index_seq.NEXTVAL FROM dual"), 128);
+
 #ifdef DB_DEBUG
   sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		  query, 
+		  row_query, 
 		  _("sh_database_query"));
 #endif
 
   if (OCIStmtPrepare(o_statement, o_error, 
-		     (OraText*) query, sl_strlen(query), 
+		     (OraText*) row_query, sl_strlen(row_query), 
 		     OCI_NTV_SYNTAX, OCI_DEFAULT))
-    {
-      OCIErrorGet(o_error, 1, NULL, 
-		  &o_errorcode, o_errormsg, sizeof(o_errormsg), 
-		  OCI_HTYPE_ERROR);
-      sh_stripnl (o_errormsg);
-      sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
-		      o_errormsg, 
-		      _("sh_database_query"));
-      if (retry == 0 && 
-	  (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) 
-	{ 
-	  ++retry; sh_database_reset(); goto oracle_doconnect; 
-	}
-      goto err_out;
-    }
- 
-   if (OCIStmtExecute(o_servicecontext, 
-		      o_statement, o_error, 1,  0, 
-		      NULL, NULL, OCI_COMMIT_ON_SUCCESS))
     {
       OCIErrorGet(o_error, 1, NULL, 
@@ -713,24 +700,6 @@
     }
 
-#ifdef DB_DEBUG
-  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		  _("No error on insert"), 
-		  _("sh_database_query"));
-#endif
-
-  /* Get row index
-   */
-  sl_strlcpy (row_query, _("SELECT MAX(log_index) FROM "), 128);
-  sl_strlcat (row_query, db_table, 128);
-
-#ifdef DB_DEBUG
-  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		  row_query, 
-		  _("sh_database_query"));
-#endif
-
-  if (OCIStmtPrepare(o_statement, o_error, 
-		     (OraText*) row_query, sl_strlen(row_query), 
-		     OCI_NTV_SYNTAX, OCI_DEFAULT))
+  if (OCIStmtExecute(o_servicecontext, o_statement, o_error, 
+		     0, 0, NULL, NULL, OCI_DEFAULT))
     {
       OCIErrorGet(o_error, 1, NULL, 
@@ -749,6 +718,7 @@
     }
 
-  if (OCIStmtExecute(o_servicecontext, o_statement, o_error, 
-		     0, 0, NULL, NULL, OCI_DEFAULT))
+  if (OCIDefineByPos (o_statement, &o_define, o_error, 1, 
+		      &result, sizeof(result), 
+		      SQLT_INT, 0, 0, 0, OCI_DEFAULT))
     {
       OCIErrorGet(o_error, 1, NULL, 
@@ -766,8 +736,5 @@
       goto err_out;
     }
-
-  if (OCIDefineByPos (o_statement, &o_define, o_error, 1, 
-		      &result, sizeof(result), 
-		      SQLT_INT, 0, 0, 0, OCI_DEFAULT))
+  if (OCIStmtFetch (o_statement, o_error, 1, OCI_FETCH_NEXT, OCI_DEFAULT))
     {
       OCIErrorGet(o_error, 1, NULL, 
@@ -785,5 +752,44 @@
       goto err_out;
     }
-  if (OCIStmtFetch (o_statement, o_error, 1, OCI_FETCH_NEXT, OCI_DEFAULT))
+  
+#ifdef DB_DEBUG
+  sl_snprintf(row_query, 127, _("Returned value: %d"), result); 
+  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
+		  row_query, 
+		  _("sh_database_query"));
+#endif
+
+  *id = result;
+
+  /* do the insert
+   */
+#ifdef DB_DEBUG
+  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
+		  query, 
+		  _("sh_database_query"));
+#endif
+
+  if (OCIStmtPrepare(o_statement, o_error, 
+		     (OraText*) query, sl_strlen(query), 
+		     OCI_NTV_SYNTAX, OCI_DEFAULT))
+    {
+      OCIErrorGet(o_error, 1, NULL, 
+		  &o_errorcode, o_errormsg, sizeof(o_errormsg), 
+		  OCI_HTYPE_ERROR);
+      sh_stripnl (o_errormsg);
+      sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
+		      o_errormsg, 
+		      _("sh_database_query"));
+      if (retry == 0 && 
+	  (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) 
+	{ 
+	  ++retry; sh_database_reset(); goto oracle_doconnect; 
+	}
+      goto err_out;
+    }
+ 
+  if (OCIBindByPos(o_statement, &o_bind, o_error, 1,
+		   (dvoid *) &result, (sword) sizeof(result), SQLT_INT, 
+		   (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT))
     {
       OCIErrorGet(o_error, 1, NULL, 
@@ -801,13 +807,29 @@
       goto err_out;
     }
-  
+
+   if (OCIStmtExecute(o_servicecontext, 
+		      o_statement, o_error, 1,  0, 
+		      NULL, NULL, OCI_COMMIT_ON_SUCCESS))
+    {
+      OCIErrorGet(o_error, 1, NULL, 
+		  &o_errorcode, o_errormsg, sizeof(o_errormsg), 
+		  OCI_HTYPE_ERROR);
+      sh_stripnl (o_errormsg);
+      sh_error_handle((-1), FIL__, __LINE__, (long) o_errorcode, MSG_E_SUBGEN,
+		      o_errormsg, 
+		      _("sh_database_query"));
+      if (retry == 0 && 
+	  (3114 == o_errorcode || 0 == strncmp(o_errormsg, _("ORA-03114"), 9))) 
+	  { 
+	    ++retry; sh_database_reset(); goto oracle_doconnect; 
+	  }
+      goto err_out;
+    }
+
 #ifdef DB_DEBUG
-  sl_snprintf(row_query, 127, _("Returned value: %d"), result); 
   sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		  row_query, 
+		  _("No error on insert"), 
 		  _("sh_database_query"));
 #endif
-
-  *id = result;
 
   if (sh_persistent_dbconn == S_FALSE)
@@ -1254,5 +1276,5 @@
   (void)
   sl_snprintf (values, SH_QUERY_MAX,  
-	       _("(%s,%c%s%c,to_date(%c%s%c,'YYYY-MM-DD HH24:MI:SS'),%c%s%c,%c%s%c"),
+	       _("(:1,%s,%c%s%c,to_date(%c%s%c,'YYYY-MM-DD HH24:MI:SS'),%c%s%c,%c%s%c"),
                id >= 0 ? num : _("NULL"),
                '\'', db_entry->host,'\'', 
@@ -1263,5 +1285,5 @@
                '\'');
   (void) sl_snprintf (columns, 1023, 
-		      _("(log_ref,log_host,log_time,log_sev,log_msg"));
+		      _("(log_index,log_ref,log_host,log_time,log_sev,log_msg"));
 #elif defined(WITH_POSTGRES)
   /* Prepare query for PQexecParams
@@ -1495,8 +1517,9 @@
 }
 
-static int is_escaped(unsigned char * p) {
+static int is_escaped(char * p_in) {
 
   int    escp = 0;
   int    retv = S_TRUE;
+  unsigned char * p = (unsigned char *) p_in;
 
   while (*p != '\0') 
Index: trunk/src/sh_files.c
===================================================================
--- trunk/src/sh_files.c	(revision 67)
+++ trunk/src/sh_files.c	(revision 68)
@@ -1563,4 +1563,5 @@
    */
   sl_strlcpy (theFile.fullpath, iname, PATH_MAX);
+  theFile.attr_string = NULL;
 
   (void) relativeName;
@@ -1571,4 +1572,5 @@
   if ((sig_termfast == 1) || (sig_terminate == 1)) 
     {
+      if (theFile.attr_string) SH_FREE(theFile.attr_string);
       SL_RETURN((0), _("sh_files_checkdir"));
     }
@@ -1577,4 +1579,5 @@
     {
       SH_FREE(tmpname); 
+      if (theFile.attr_string) SH_FREE(theFile.attr_string);
       SL_RETURN((-1), _("sh_files_checkdir"));
     }
@@ -1586,4 +1589,5 @@
 		       tmpname);
       SH_FREE(tmpname); 
+      if (theFile.attr_string) SH_FREE(theFile.attr_string);
       SL_RETURN((-1), _("sh_files_checkdir"));
     }
@@ -1607,4 +1611,5 @@
       SH_FREE(tmpname); 
 
+      if (theFile.attr_string) SH_FREE(theFile.attr_string);
       SL_RETURN((-1), _("sh_files_checkdir"));
     }
@@ -1660,4 +1665,5 @@
     if (sig_termfast == 1) 
       {
+	if (theFile.attr_string) SH_FREE(theFile.attr_string);
 	SL_RETURN((0), _("sh_files_checkdir"));
       }
@@ -1850,4 +1856,5 @@
     if ((sig_termfast == 1) || (sig_terminate == 1)) 
       {
+	if (theFile.attr_string) SH_FREE(theFile.attr_string);
 	SL_RETURN((0), _("sh_files_checkdir"));
       }
@@ -1896,4 +1903,5 @@
 #endif
 
+  if (theFile.attr_string) SH_FREE(theFile.attr_string);
   SH_FREE(tmpname);
 
@@ -1986,6 +1994,7 @@
    */
   sl_strlcpy (theFile.fullpath, fullpath, PATH_MAX);
-  theFile.check_mask = sh_files_maskof(class);
-  theFile.reported   = (*reported);
+  theFile.check_mask  = sh_files_maskof(class);
+  theFile.reported    = (*reported);
+  theFile.attr_string = NULL;
 
   TPT(( 0, FIL__, __LINE__, _("msg=<checking file: %s>\n"),  fullpath));
@@ -2001,5 +2010,7 @@
 	    fullpath, status));
       if (class == SH_LEVEL_ALLIGNORE && sh.flag.checkSum != SH_CHECK_INIT)
-	  sh_hash_set_visited_true (fullpath);
+	sh_hash_set_visited_true (fullpath);
+      if (theFile.attr_string) 
+	SH_FREE(theFile.attr_string);
       SL_RETURN(SH_FILE_UNKNOWN, _("sh_files_filecheck"));
     }
@@ -2080,8 +2091,10 @@
     }
 #else
-      (void) rsrcflag; /* avoid compiler warning */
+  (void) rsrcflag; /* avoid compiler warning */
 #endif
 
  ret_point:
+
+  if (theFile.attr_string) SH_FREE(theFile.attr_string);
 
   switch (theFile.c_mode[0]) 
Index: trunk/src/sh_hash.c
===================================================================
--- trunk/src/sh_hash.c	(revision 67)
+++ trunk/src/sh_hash.c	(revision 68)
@@ -285,4 +285,5 @@
   char           * fullpath;
   char           * linkpath;
+  char           * attr_string;
   int              visited;
   int              reported;
@@ -337,4 +338,6 @@
 #endif
 
+#define REC_FLAGS_ATTR (1<<8)
+#define REC_FLAGS_MASK 0xFF00
 
 /**************************************************************
@@ -389,4 +392,9 @@
   theFile->hardlinks = p->theFile.hardlinks;
 
+  if (p->attr_string)
+    theFile->attr_string = sh_util_strdup(p->attr_string);
+  else
+    theFile->attr_string = NULL;
+
   SL_RETURN((theFile), _("sh_hash_create_ft"));
 }
@@ -440,4 +448,6 @@
   SH_FREE(tmp);
   SH_FREE(str);
+  if (theFile->attr_string)
+    SH_FREE(theFile->attr_string);
   SH_FREE(theFile);
   return 0;
@@ -517,4 +527,6 @@
 				   MSG_FI_MISS2, tmp, str);
 		  SH_FREE(str);
+		  if (theFile->attr_string)
+		    SH_FREE(theFile->attr_string);
 		  SH_FREE(theFile);
 
@@ -532,4 +544,6 @@
 	      theFile = sh_hash_create_ft (p, fileHash);
 	      sh_hash_pushdata (theFile, fileHash);
+	      if (theFile->attr_string)
+		SH_FREE(theFile->attr_string);
 	      SH_FREE(theFile);
 	    }
@@ -554,4 +568,9 @@
 		  p->linkpath = NULL;
 		}
+	      if (p->attr_string)
+		{
+		  SH_FREE(p->attr_string);
+		  p->attr_string = NULL;
+		}
 	      SH_FREE(p);
 	      p = NULL;
@@ -576,4 +595,6 @@
 			   MSG_FI_MISS2, tmp, str);
 	  SH_FREE(str);
+	  if (theFile->attr_string)
+	    SH_FREE(theFile->attr_string);
 	  SH_FREE(theFile);
 
@@ -635,4 +656,9 @@
       SH_FREE(p->linkpath);
       p->linkpath = NULL;
+    }
+  if (p->attr_string)
+    {
+      SH_FREE(p->attr_string);
+      p->attr_string = NULL;
     }
   SH_FREE(p);
@@ -696,4 +722,6 @@
 	      if(p->linkpath)
 		SH_FREE(p->linkpath);
+	      if(p->attr_string)
+		SH_FREE(p->attr_string);
 	      memcpy(p, s, sizeof(sh_file_t));
 	      p->next = q;
@@ -868,4 +896,5 @@
   char * fullpath;
   char * linkpath;
+  char * attr_string = NULL;
   char * tmp;
 
@@ -908,5 +937,5 @@
 #endif
 
-  if (ft.mark != REC_MAGIC)
+  if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
     {
       SH_FREE(p);
@@ -967,4 +996,36 @@
     linkpath[len-2] = '\0';
 
+  /* Read next record -- Part Four -- attr_string
+   */
+  if ((ft.mark & REC_FLAGS_ATTR) != 0)
+    {
+      i =  sh_hash_getline (sh_fin_fd, line, size);
+      if (i < 0 ) 
+	{
+	  SH_FREE(line);
+	  SH_FREE(fullpath);
+	  SH_FREE(linkpath);
+	  SH_FREE(p);
+	  dlog(1, FIL__, __LINE__, 
+	       _("There is a corrupt record in the file signature database: %s\nThe attribute string is missing.\n"),
+	       (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
+	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
+			   ( (NULL == file_path('D', 'R')) ? _("(null)") :
+			     file_path('D', 'R'))
+			   );
+	  aud_exit (FIL__, __LINE__,EXIT_FAILURE);
+	}
+
+      tmp = unquote_string (line);
+
+      len = sl_strlen(tmp)+1;
+      attr_string = SH_ALLOC(len);
+      (void) sl_strlcpy (attr_string, tmp, len);
+      if (tmp)
+	SH_FREE(tmp);
+      if (attr_string[len-2] == '\n')
+	attr_string[len-2] = '\0';
+    }
+
   /* Read next record -- Part Four -- Decode
    */
@@ -986,4 +1047,8 @@
       sh_do_decode(linkpath, sl_strlen(linkpath));
     }
+  if ((ft.mark & REC_FLAGS_ATTR) != 0)
+    {  
+      sh_do_decode(attr_string, sl_strlen(attr_string));
+    }
 #endif
 
@@ -995,4 +1060,6 @@
   p->fullpath  = fullpath;
   p->linkpath  = linkpath;
+
+  p->attr_string = attr_string;
 
   /* set to an invalid value 
@@ -1313,4 +1380,5 @@
   char *  fullpath = NULL;
   char *  linkpath = NULL;
+  char *  attr_string = NULL;
 
   char * line = NULL;
@@ -1518,6 +1586,26 @@
     }
 
+  if (buf != NULL && buf->attr_string != NULL) 
+    {
+      old_len = sl_strlen(buf->attr_string);
+#if defined(SH_STEALTH)
+      sh_do_encode(buf->attr_string, old_len);
+#endif
+      tmp = quote_string(buf->attr_string);
+      if (tmp)
+	{
+	  attr_string = tmp;
+	  tmp = NULL;
+	}
+#if defined(SH_STEALTH)
+      sh_do_decode(buf->attr_string, old_len);
+#endif
+    }
+
+
   if (buf != NULL) {
     p.mark = REC_MAGIC;
+    if (attr_string)
+      p.mark |= REC_FLAGS_ATTR;
     sl_strlcpy(p.c_mode,   buf->c_mode,   11);
     sl_strlcpy(p.c_group,  buf->c_group,  GROUP_MAX+1);
@@ -1640,8 +1728,12 @@
       sl_write_line (pushdata_fd, fullpath,    sl_strlen(fullpath));
       sl_write_line (pushdata_fd, linkpath,    sl_strlen(linkpath));
+      if (attr_string)
+	sl_write_line (pushdata_fd, attr_string,    sl_strlen(attr_string));
     } else {
       fwrite (&p, sizeof(sh_filestore_t), 1, stdout);
       printf ("%s\n", fullpath);
       printf ("%s\n", linkpath);
+      if (attr_string)
+	printf ("%s\n", attr_string);
     }
 
@@ -1656,4 +1748,6 @@
   SH_FREE(fullpath);
   SH_FREE(linkpath);
+  if (attr_string)
+    SH_FREE(attr_string);
 
   SL_RET0(_("sh_hash_pushdata"));
@@ -1689,4 +1783,6 @@
 	  f = sh_hash_create_ft (p, fileHash);
 	  sh_hash_pushdata (f, fileHash);
+	  if (f->attr_string)
+	    SH_FREE(f->attr_string);
 	  SH_FREE(f);
 	}
@@ -1757,4 +1853,6 @@
   tmpFile->mtime = p->theFile.mtime;
   tmpFile->ctime = p->theFile.ctime;
+
+  tmpFile->attr_string = NULL;
   return 0;
 }
@@ -1857,4 +1955,6 @@
   int         i = 0;
   char      * p;
+
+  tmpFile.attr_string = NULL;
 
   sl_strlcpy(tmpFile.fullpath, key, PATH_MAX);
@@ -1979,4 +2079,5 @@
   char * fullpath;
   char * linkpath;
+  char * attr_string = NULL;
 
   SL_ENTER(_("sh_hash_push_int"));
@@ -1985,4 +2086,6 @@
 
   p.mark = REC_MAGIC;
+  if (buf->attr_string)
+    p.mark |= REC_FLAGS_ATTR;
   sl_strlcpy(p.c_mode,   buf->c_mode,   11);
   sl_strlcpy(p.c_group,  buf->c_group,  GROUP_MAX+1);
@@ -2015,4 +2118,8 @@
   fp->modi_mask = 0L;
 
+  if (buf->attr_string)
+    attr_string = sh_util_strdup(buf->attr_string);
+  fp->attr_string = attr_string;
+
   len = sl_strlen(buf->fullpath);
   if (len <= MAX_PATH_STORE) 
@@ -2235,4 +2342,19 @@
 	} 
     }
+
+  if (theFile->attr_string)
+    {
+      tmp_lnk     = sh_util_safe_name(theFile->attr_string);
+      if (tmp_lnk)
+	{
+	  if (is_new)
+	    sl_snprintf(tmp, SH_BUFSIZE, _("acl_new=\"%s\" "), tmp_lnk);
+	  else
+	    sl_snprintf(tmp, SH_BUFSIZE, _("acl_old=\"%s\" "), tmp_lnk);
+	  SH_FREE(tmp_lnk);
+	  sl_strlcat(msg, tmp, SH_BUFSIZE);
+	} 
+    }
+
   
   SH_FREE(tmp);
@@ -2387,4 +2509,18 @@
     }
   
+  if (theFile->attr_string)
+    {
+      tmp_lnk     = sh_util_safe_name(theFile->attr_string);
+      if (tmp_lnk)
+	{
+	  if (is_new)
+	    sl_snprintf(tmp, SH_BUFSIZE, _(", acl_new=<%s> "), tmp_lnk);
+	  else
+	    sl_snprintf(tmp, SH_BUFSIZE, _(", acl_old=<%s> "), tmp_lnk);
+	  SH_FREE(tmp_lnk);
+	  sl_strlcat(msg, tmp, SH_BUFSIZE);
+	} 
+    }
+
   SH_FREE(tmp);
   return (msg);
@@ -2605,8 +2741,17 @@
 
   if ( (  (theFile->mode != p->theFile.mode)
+#if defined(USE_ACL) || defined(USE_XATTR)
+	  || ( (sh_unix_check_selinux|sh_unix_check_acl) &&
+	       ( 
+		(theFile->attr_string == NULL && p->attr_string != NULL) ||
+		(theFile->attr_string != NULL && p->attr_string == NULL) ||
+		(theFile->attr_string != NULL && 0 != strcmp(theFile->attr_string, p->attr_string))
+		)
+	       )
+#endif
 #if defined(__linux__) || defined(HAVE_STAT_FLAGS)
           || (theFile->attributes != p->theFile.attributes)
 #endif
-        )
+	  )
        && (theFile->check_mask & MODI_MOD) != 0)
     {
@@ -2652,6 +2797,6 @@
     } 
   
-  if ( theFile->atime != (time_t) p->theFile.atime &&
-       (theFile->check_mask & MODI_ATM) != 0)
+  if ( (theFile->check_mask & MODI_ATM) != 0 &&
+       theFile->atime != (time_t) p->theFile.atime)
     {
       modi_mask |= MODI_ATM;
@@ -2705,6 +2850,6 @@
       if (   ((modi_mask & MODI_MOD) != 0)
 #if defined(HAVE_LIBPRELUDE) && defined(HAVE_LIBPRELUDE_9)
-	  || ((modi_mask & MODI_USR) != 0)
-	  || ((modi_mask & MODI_GRP) != 0)
+	     || ((modi_mask & MODI_USR) != 0)
+	     || ((modi_mask & MODI_GRP) != 0)
 #endif
 	     )
@@ -2729,14 +2874,29 @@
 	  sl_snprintf(tmp, SH_BUFSIZE, 
 		      _("mode_old=\"%s\" mode_new=\"%s\" imode_old=\"%ld\" imode_new=\"%ld\" "),
-#else
-		      sl_snprintf(tmp, SH_BUFSIZE, _("mode_old=<%s>, mode_new=<%s>, "),
-#endif
-		      p->theFile.c_mode, theFile->c_mode
+		      p->theFile.c_mode, theFile->c_mode,
+		      (long) p->theFile.mode, (long) theFile->mode);
+#else
+	  sl_snprintf(tmp, SH_BUFSIZE, _("mode_old=<%s>, mode_new=<%s>, "),
+		      p->theFile.c_mode, theFile->c_mode);
+#endif
+#endif
+	  sl_strlcat(msg, tmp, SH_BUFSIZE);
+
+#if defined(USE_ACL) || defined(USE_XATTR)
+	  if (theFile->attr_string != NULL || p->attr_string != NULL)
+	    {
+	      sl_snprintf(tmp, SH_BUFSIZE, 
 #ifdef SH_USE_XML
-		      , (long) p->theFile.mode, (long) theFile->mode
-#endif
-		      );
-#endif
-	  sl_strlcat(msg, tmp, SH_BUFSIZE);
+			  _("acl_old=\"%s\" acl_new=\"%s\" "),
+#else
+			  _("acl_old=<%s>, acl_new=<%s>, "),
+#endif
+			  (p->attr_string)       ? p->attr_string       : _("none"), 
+			  (theFile->attr_string) ? theFile->attr_string : _("none"));
+	      
+	      sl_strlcat(msg, tmp, SH_BUFSIZE);
+	    }
+#endif
+
 #ifdef REPLACE_OLD
 	  if ((modi_mask & MODI_MOD) != 0)
@@ -2754,4 +2914,18 @@
 		  p->theFile.attributes = theFile->attributes;
 #endif
+#if defined(USE_ACL) || defined(USE_XATTR)
+		  if      (p->attr_string == NULL && theFile->attr_string != NULL)
+		    { p->attr_string = sh_util_strdup (theFile->attr_string); }
+		  else if (p->attr_string != NULL && theFile->attr_string == NULL)
+		    { SH_FREE(p->attr_string); p->attr_string = NULL; }
+		  else if (theFile->attr_string != NULL && p->attr_string != NULL)
+		    { 
+		      if (0 != strcmp(theFile->attr_string, p->attr_string))
+			{
+			  SH_FREE(p->attr_string);
+			  p->attr_string = sh_util_strdup (theFile->attr_string);
+			}
+		    }
+#endif
 		}
 	    }
@@ -3039,4 +3213,18 @@
 	      sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, 16);
 	      theFile->attributes =  p->theFile.attributes;
+#endif
+#if defined(USE_ACL) || defined(USE_XATTR)
+	      if      (theFile->attr_string == NULL && p->attr_string != NULL)
+		{ theFile->attr_string = sh_util_strdup (p->attr_string); }
+	      else if (theFile->attr_string != NULL && p->attr_string == NULL)
+		{ SH_FREE(theFile->attr_string); theFile->attr_string = NULL; }
+	      else if (theFile->attr_string != NULL && p->attr_string != NULL)
+		{ 
+		  if (0 != strcmp(theFile->attr_string, p->attr_string))
+		    {
+		      SH_FREE(theFile->attr_string);
+		      theFile->attr_string = sh_util_strdup (p->attr_string);
+		    }
+		}
 #endif
 	      
@@ -3084,4 +3272,18 @@
 	      p->theFile.attributes = theFile->attributes;
 #endif
+#if defined(USE_ACL) || defined(USE_XATTR)
+	      if      (p->attr_string == NULL && theFile->attr_string != NULL)
+		{ p->attr_string = sh_util_strdup (theFile->attr_string); }
+	      else if (p->attr_string != NULL && theFile->attr_string == NULL)
+		{ SH_FREE(p->attr_string); p->attr_string = NULL; }
+	      else if (theFile->attr_string != NULL && p->attr_string != NULL)
+		{ 
+		  if (0 != strcmp(theFile->attr_string, p->attr_string))
+		    {
+		      SH_FREE(p->attr_string);
+		      p->attr_string = sh_util_strdup (theFile->attr_string);
+		    }
+		}
+#endif
 	      
 	      if (theFile->c_mode[0] == 'l')
@@ -3216,4 +3418,5 @@
   char * tmp;
   char   str[81];
+  size_t i;
 
   if (ListWithDelimiter == S_TRUE)
@@ -3270,11 +3473,28 @@
       tmp = sh_util_safe_name(p->linkpath);
       if (ListWithDelimiter == S_TRUE)
-	printf(_(" %s\n"), tmp);
+	printf(_(" %s"), tmp);
       else
-	printf(_(" -> %s\n"), tmp);
+	printf(_(" -> %s"), tmp);
       SH_FREE(tmp);
     }
-  else
-    printf("\n");
+  if (ListWithDelimiter == S_TRUE)
+    putchar(',');
+
+  if (p->attr_string)
+    {
+      tmp = sh_util_safe_name(p->attr_string);
+      if (ListWithDelimiter == S_TRUE) {
+	for (i = 0; i < strlen(tmp); ++i) 
+	  if (tmp[i] == ',') tmp[i] = ';';
+      }
+      printf(_(" %s"), tmp);
+      SH_FREE(tmp);
+    }
+  else
+    {
+      if (ListWithDelimiter == S_TRUE)
+	printf(_(" no_attr"));
+    }
+  putchar('\n');
 
   return;
Index: trunk/src/sh_kern.c
===================================================================
--- trunk/src/sh_kern.c	(revision 67)
+++ trunk/src/sh_kern.c	(revision 68)
@@ -209,4 +209,6 @@
   int         i = 0;
   char      * p;
+
+  tmpFile.attr_string = NULL;
 
   sl_strlcpy(tmpFile.fullpath, name, PATH_MAX);
@@ -1790,5 +1792,5 @@
  *************/
 
-int sh_kern_set_severity  (char * c)
+int sh_kern_set_severity  (const char * c)
 {
   char tmp[32];
@@ -1799,5 +1801,5 @@
 }
 
-int sh_kern_set_timer (char * c)
+int sh_kern_set_timer (const char * c)
 {
   long val;
@@ -1816,5 +1818,5 @@
 }
 
-int sh_kern_set_activate (char * c)
+int sh_kern_set_activate (const char * c)
 {
   int i;
@@ -1824,5 +1826,5 @@
 }
 
-int sh_kern_set_idt (char * c)
+int sh_kern_set_idt (const char * c)
 {
   int i;
@@ -1832,5 +1834,5 @@
 }
 
-int sh_kern_set_sc_addr (char * c)
+int sh_kern_set_sc_addr (const char * c)
 {
   char * endptr;
@@ -1853,5 +1855,5 @@
 }
 
-int sh_kern_set_sct_addr (char * c)
+int sh_kern_set_sct_addr (const char * c)
 {
   char * endptr;
@@ -1874,5 +1876,5 @@
 }
 
-int sh_kern_set_proc_root (char * c)
+int sh_kern_set_proc_root (const char * c)
 {
   char * endptr;
@@ -1896,5 +1898,5 @@
 }
 
-int sh_kern_set_proc_root_iops (char * c)
+int sh_kern_set_proc_root_iops (const char * c)
 {
   char * endptr;
@@ -1918,5 +1920,5 @@
 }
 
-int sh_kern_set_proc_root_lookup (char * c)
+int sh_kern_set_proc_root_lookup (const char * c)
 {
   char * endptr;
@@ -1941,7 +1943,7 @@
 #endif
 
-/* #ifdef SH_USE_UTMP */
-#endif
-
-
-
+/* #ifdef SH_USE_KERN */
+#endif
+
+
+
Index: trunk/src/sh_modules.c
===================================================================
--- trunk/src/sh_modules.c	(revision 67)
+++ trunk/src/sh_modules.c	(revision 68)
@@ -13,4 +13,6 @@
 #include "sh_kern.h"
 #include "sh_suidchk.h"
+#include "sh_processcheck.h"
+#include "sh_portcheck.h"
 
 sh_mtype modList[] = {
@@ -74,4 +76,5 @@
   },
 #endif
+
 #ifdef SH_USE_SUIDCHK
   {
@@ -88,4 +91,35 @@
   },
 #endif
+
+#ifdef SH_USE_PROCESSCHECK
+  {
+    N_("PROCESSCHECK"),
+    0,
+    sh_prochk_init,
+    sh_prochk_timer,
+    sh_prochk_check,
+    sh_prochk_cleanup,
+    sh_prochk_reconf,
+
+    N_("[ProcessCheck]"),
+    sh_prochk_table,
+  },
+#endif
+
+#ifdef SH_USE_PORTCHECK
+  {
+    N_("PORTCHECK"),
+    0,
+    sh_portchk_init,
+    sh_portchk_timer,
+    sh_portchk_check,
+    sh_portchk_cleanup,
+    sh_portchk_reconf,
+
+    N_("[PortCheck]"),
+    sh_portchk_table,
+  },
+#endif
+
   {
     NULL,
Index: trunk/src/sh_mounts.c
===================================================================
--- trunk/src/sh_mounts.c	(revision 67)
+++ trunk/src/sh_mounts.c	(revision 68)
@@ -51,9 +51,9 @@
 
 /* Prototypes for configuration functions */
-int sh_mounts_config_activate (char * opt);
-int sh_mounts_config_timer    (char * opt);
-int sh_mounts_config_mount    (char * opt);
-int sh_mounts_config_sevmnt   (char * opt);
-int sh_mounts_config_sevopt   (char * opt);
+int sh_mounts_config_activate (const char * opt);
+int sh_mounts_config_timer    (const char * opt);
+int sh_mounts_config_mount    (const char * opt);
+int sh_mounts_config_sevmnt   (const char * opt);
+int sh_mounts_config_sevopt   (const char * opt);
 
 /* Prototype for the function to read info on mounted filesystems */
@@ -276,9 +276,9 @@
 
 /* Configure to check a particular mount */
-int sh_mounts_config_mount (char * opt)
+int sh_mounts_config_mount (const char * opt_in)
 {
   struct sh_mounts_mnt *m;
   struct sh_mounts_opt *o;
-  char *sp, *temp;
+  char *sp, *temp, *opt;
 
   SL_ENTER(_("sh_mounts_config_mount"));
@@ -286,9 +286,9 @@
   /* It's probably best to make a copy of opt before messing about with it
    * via string functions. Good practice and all that. */
-  temp = sh_util_strdup(opt);
+  temp = sh_util_strdup(opt_in);
 
   /* Since we're going to "consume" this new buffer, it'll be good to have a
    * reference to it's allocated memory so we can free it later. Let's use
-   * temp for that, and the now-unused "opt" for consumption */
+   * temp for that, and "opt" for consumption */
   opt = temp;
   
@@ -327,5 +327,5 @@
 
 /* Simply sets our boolean as to whether this module is active */
-int sh_mounts_config_activate (char * opt)
+int sh_mounts_config_activate (const char * opt)
 {
   int i;
@@ -336,5 +336,5 @@
 
 /* Sets up our timer */
-int sh_mounts_config_timer (char * opt)
+int sh_mounts_config_timer (const char * opt)
 {
   long val;
@@ -357,5 +357,5 @@
 
 /* Configure severity for "mount missing" messages */
-int sh_mounts_config_sevmnt  (char * opt)
+int sh_mounts_config_sevmnt  (const char * opt)
 {
   int retval = 0;
@@ -370,5 +370,5 @@
 }
 
-int sh_mounts_config_sevopt  (char * opt)
+int sh_mounts_config_sevopt  (const char * opt)
 {
   int retval = 0;
Index: trunk/src/sh_readconf.c
===================================================================
--- trunk/src/sh_readconf.c	(revision 67)
+++ trunk/src/sh_readconf.c	(revision 68)
@@ -857,6 +857,16 @@
   { N_("hardlinkoffset"),     SH_SECTION_MISC,   SH_SECTION_NONE,
     sh_files_hle_reg },
+#if defined(USE_XATTR)
+  { N_("useselinuxcheck"),    SH_SECTION_MISC,   SH_SECTION_NONE, 
+    sh_unix_setcheckselinux },
+#endif
+#if defined(USE_ACL)
+  { N_("useaclcheck"),        SH_SECTION_MISC,   SH_SECTION_NONE, 
+    sh_unix_setcheckacl },
+#endif
   { N_("addokchars"),         SH_SECTION_MISC,   SH_SECTION_NONE,
     sh_util_obscure_ok },
+  { N_("filenamesareutf8"),   SH_SECTION_MISC,   SH_SECTION_NONE, /* FIXME document this option */
+    sh_util_obscure_utf8 },
   { N_("setrecursionlevel"),  SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_files_setrecursion },
Index: trunk/src/sh_suidchk.c
===================================================================
--- trunk/src/sh_suidchk.c	(revision 67)
+++ trunk/src/sh_suidchk.c	(revision 68)
@@ -146,5 +146,5 @@
 static int     ShSuidchkSeverity = SH_ERR_SEVERE;
 static char *  ShSuidchkExclude  = NULL;
-static int     ExcludeLen        = 0;
+static size_t  ExcludeLen        = 0;
 
 static time_t  FileLimNow        = 0;
@@ -554,9 +554,11 @@
 		    )
 		   )
-	    {
+	    { /* way too long routine */
 	      
 	      (void) sl_strlcpy (theFile.fullpath, tmpcat, PATH_MAX);
-	      theFile.check_mask = sh_files_maskof(SH_LEVEL_READONLY);
-	      theFile.reported   = S_FALSE;
+	      theFile.check_mask  = sh_files_maskof(SH_LEVEL_READONLY);
+	      theFile.reported    = S_FALSE;
+	      theFile.attr_string = NULL;
+
 	      status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_RO], 
 					thisEntry->d_name,
@@ -971,9 +973,12 @@
 		}
 	      SH_FREE(tmp);
-
-	    }
+	      if (theFile.attr_string)
+		SH_FREE(theFile.attr_string);
+
+	    } /* end of way too long routine */
 	}
       SH_FREE(tmpcat);
     }
+
 #ifdef HAVE_SCHED_YIELD
     if (ShSuidchkYield == S_TRUE)
@@ -989,4 +994,5 @@
       }
 #endif
+
   }  while (thisEntry != NULL);
 
@@ -1087,5 +1093,5 @@
  *************/
 
-int sh_suidchk_set_severity  (char * c)
+int sh_suidchk_set_severity  (const char * c)
 {
   int retval;
@@ -1099,7 +1105,8 @@
 }
 
-int sh_suidchk_set_exclude (char * c)
+int sh_suidchk_set_exclude (const char * c)
 {
   SL_ENTER(_("sh_suidchk_set_exclude"));
+
   if (c == NULL || c[0] == '\0')
     {
@@ -1118,17 +1125,15 @@
     SH_FREE(ShSuidchkExclude);
 
-  ExcludeLen       = (int) sl_strlen(c);
-  if (c[ExcludeLen-1] == '/')
-    {
-      c[ExcludeLen-1] = '\0';
+  ShSuidchkExclude = sh_util_strdup (c);
+  ExcludeLen       = sl_strlen (ShSuidchkExclude);
+  if (ShSuidchkExclude[ExcludeLen-1] == '/')
+    {
+      ShSuidchkExclude[ExcludeLen-1] = '\0';
       ExcludeLen--;
     }
-  ShSuidchkExclude = SH_ALLOC((size_t) ExcludeLen + 1);
-  (void) sl_strlcpy(ShSuidchkExclude, c, (size_t)(ExcludeLen + 1));
-
   SL_RETURN(0, _("sh_suidchk_set_exclude"));
 }
 
-int sh_suidchk_set_timer (char * c)
+int sh_suidchk_set_timer (const char * c)
 {
   long val;
@@ -1163,5 +1168,5 @@
 }
 
-int sh_suidchk_set_schedule (char * str)
+int sh_suidchk_set_schedule (const char * str)
 {
   int status;
@@ -1201,5 +1206,5 @@
 
 
-int sh_suidchk_set_fps (char * c)
+int sh_suidchk_set_fps (const char * c)
 {
   long val;
@@ -1218,5 +1223,5 @@
 }
 
-int sh_suidchk_set_yield (char * c)
+int sh_suidchk_set_yield (const char * c)
 {
   int i;
@@ -1231,5 +1236,5 @@
 }
 
-int sh_suidchk_set_activate (char * c)
+int sh_suidchk_set_activate (const char * c)
 {
   int i;
@@ -1239,5 +1244,5 @@
 }
 
-int sh_suidchk_set_quarantine (char * c)
+int sh_suidchk_set_quarantine (const char * c)
 {
   int i;
@@ -1247,5 +1252,5 @@
 }
 
-int sh_suidchk_set_qdelete (char * c)
+int sh_suidchk_set_qdelete (const char * c)
 {
   int i;
@@ -1255,5 +1260,5 @@
 }
 
-int sh_suidchk_set_qmethod (char * c)
+int sh_suidchk_set_qmethod (const char * c)
 {
   long val;
Index: trunk/src/sh_unix.c
===================================================================
--- trunk/src/sh_unix.c	(revision 67)
+++ trunk/src/sh_unix.c	(revision 68)
@@ -2863,5 +2863,5 @@
 					alert_timeout),
 		 KEY_LEN+1);
-
+      
       /* return */
       SL_RETURN( 0, _("sh_unix_checksum_size"));
@@ -2874,4 +2874,187 @@
   SL_RETURN( -1, _("sh_unix_checksum_size"));
 }
+
+int sh_unix_check_selinux = S_FALSE;
+int sh_unix_check_acl     = S_FALSE;
+
+#ifdef USE_ACL
+
+#include <sys/acl.h>
+static char * sh_unix_getinfo_acl (char * path, int fd, struct stat * buf)
+{
+  /* system.posix_acl_access, system.posix_acl_default
+   */
+  char *  out  = NULL;
+  char *  collect = NULL;
+  char *  tmp;
+  char *  out_compact;
+  ssize_t len;
+  acl_t   result;
+
+  SL_ENTER(_("sh_unix_getinfo_acl"));
+
+  result = (fd == -1) ? 
+    acl_get_file (path, ACL_TYPE_ACCESS) :
+    acl_get_fd   (fd);
+
+  if (result)
+    {
+      out = acl_to_text (result, &len);
+      if (out && (len > 0)) {
+	out_compact = sh_util_acl_compact (out, len);
+	acl_free(out);
+	if (out_compact) 
+	  {
+	    collect = sh_util_strconcat (_("acl_access:"), out_compact, NULL);
+	    SH_FREE(out_compact);
+	  }
+      }
+      acl_free(result);
+    }
+  
+  
+  if ( S_ISDIR(buf->st_mode) ) 
+    {
+      result = acl_get_file (path, ACL_TYPE_DEFAULT);
+      
+      if (result)
+	{
+	  out = acl_to_text (result, &len);
+	  if (out && (len > 0)) {
+	    out_compact = sh_util_acl_compact (out, len);
+	    acl_free(out);
+	    if (out_compact) {
+	      if (collect) {
+		tmp = sh_util_strconcat (_("acl_default:"), 
+					 out_compact, ":", collect, NULL);
+		SH_FREE(collect);
+	      }
+	      else {
+		tmp = sh_util_strconcat (_("acl_default:"), out_compact, NULL);
+	      }
+	      SH_FREE(out_compact);
+	      collect = tmp;
+	    }
+	  }
+	  acl_free(result);
+	}
+    }
+  
+  SL_RETURN((collect),_("sh_unix_getinfo_acl"));
+}
+#endif
+
+#ifdef USE_XATTR
+
+#include <attr/xattr.h>
+static char * sh_unix_getinfo_xattr_int (char * path, int fd, char * name)
+{
+  char *  out   = NULL;
+  char *  tmp   = NULL;
+  size_t  size  = 256;
+  ssize_t result;
+
+  SL_ENTER(_("sh_unix_getinfo_xattr_int"));
+
+  out = SH_ALLOC(size);
+
+  result = (fd == -1) ? 
+    lgetxattr (path, name, out, size-1) :
+    fgetxattr (fd,   name, out, size-1);
+
+  if (result == -1 && errno == ERANGE) 
+    {
+      SH_FREE(out);
+      result = (fd == -1) ? 
+	lgetxattr (path, name, NULL, 0) :
+	fgetxattr (fd,   name, NULL, 0);
+      size = result + 1;
+      out  = SH_ALLOC(size);
+      result = (fd == -1) ? 
+	lgetxattr (path, name, out, size-1) :
+	fgetxattr (fd,   name, out, size-1);
+    }
+
+  if ((result > 0) && ((size_t)result < size))
+    {
+      out[size-1] = '\0';
+      tmp = out;
+    }
+  else
+    {
+      SH_FREE(out);
+    }
+
+  SL_RETURN((tmp),_("sh_unix_getinfo_xattr_int"));
+}
+
+
+static char * sh_unix_getinfo_xattr (char * path, int fd, struct stat * buf)
+{
+  /* system.posix_acl_access, system.posix_acl_default, security.selinux 
+   */
+  char *  tmp;
+  char *  out  = NULL;
+  char *  collect = NULL;
+
+  SL_ENTER(_("sh_unix_getinfo_xattr"));
+
+#ifdef USE_ACL
+  /*
+   * we need the acl_get_fd/acl_get_file functions, getxattr will only
+   * yield the raw bytes
+   */
+  if (sh_unix_check_acl == S_TRUE) 
+    {
+      out = sh_unix_getinfo_acl(path, fd, buf);
+      
+      if (out)
+	{
+	  collect = out;
+	}
+  }
+#endif
+
+  out = sh_unix_getinfo_xattr_int(path, fd, _("security.selinux"));
+
+  if (out)
+    {
+      if (collect) {
+	tmp = sh_util_strconcat(_("selinux:"), out, ":", collect, NULL);
+	SH_FREE(collect);
+      }
+      else {
+	tmp = sh_util_strconcat(_("selinux:"), out, NULL);
+      }
+      SH_FREE(out);
+      collect = tmp;
+    }
+
+  SL_RETURN((collect),_("sh_unix_getinfo_xattr"));
+}
+#endif
+
+#ifdef USE_XATTR
+int sh_unix_setcheckselinux (const char * c)
+{
+  int i;
+  SL_ENTER(_("sh_unix_setcheckselinux"));
+  i = sh_util_flagval(c, &(sh_unix_check_selinux));
+
+  SL_RETURN(i, _("sh_unix_setcheckselinux"));
+}
+#endif
+
+#ifdef USE_ACL
+int sh_unix_setcheckacl (const char * c)
+{
+  int i;
+  SL_ENTER(_("sh_unix_setcheckacl"));
+  i = sh_util_flagval(c, &(sh_unix_check_acl));
+
+  SL_RETURN(i, _("sh_unix_setcheckacl"));
+}
+#endif
+    
 
 int sh_unix_getinfo (int level, char * filename, file_type * theFile, 
@@ -3124,4 +3307,14 @@
 			 &theFile->attributes, theFile->c_attributes, 
 			 fd, &buf);
+#endif
+
+#if defined(USE_XATTR)
+  if (sh_unix_check_selinux == S_TRUE)
+    theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf);
+#elif defined(USE_ACL)
+  if (sh_unix_check_acl == S_TRUE)
+    theFile->attr_string = sh_unix_getinfo_acl (theFile->fullpath, fd, &buf);
+#else
+  theFile->attr_string = NULL;
 #endif
 
Index: trunk/src/sh_userfiles.c
===================================================================
--- trunk/src/sh_userfiles.c	(revision 67)
+++ trunk/src/sh_userfiles.c	(revision 68)
@@ -115,8 +115,8 @@
 }
   
-int sh_userfiles_set_uid (char * str)
+int sh_userfiles_set_uid (const char * str)
 {
   char * end;
-  char * p = str;
+  const  char * p = str;
   unsigned long lower;
   unsigned long upper = 0;
@@ -183,5 +183,5 @@
  * directory that should be checked. */
 
-int sh_userfiles_add_file(char *c) {
+int sh_userfiles_add_file(const char *c) {
     struct userfileslist *new;
     char *s, *orig;
@@ -232,21 +232,11 @@
 }
 
-/* Decide if we're active.  1 means yes, all else means no */
-
-int sh_userfiles_set_active(char *c) {
+/* Decide if we're active. 
+ */
+int sh_userfiles_set_active(const char *c) {
     int value;
     
     SL_ENTER(_("sh_userfiles_set_active"));
-
     value = sh_util_flagval(c, &ShUserfilesActive);
-
-    /*
-    if( value == 1 ) {
-        ShUserfilesActive = S_TRUE;
-    } else {
-        ShUserfilesActive = S_FALSE;
-    }
-    */
-
     SL_RETURN((value), _("sh_userfiles_set_active"));
 }
Index: trunk/src/sh_utils.c
===================================================================
--- trunk/src/sh_utils.c	(revision 67)
+++ trunk/src/sh_utils.c	(revision 68)
@@ -196,4 +196,75 @@
 
   SL_RETURN(i, _("sh_util_hidesetup"));
+}
+
+char * sh_util_acl_compact(char * buf, ssize_t len)
+{
+  unsigned char  * p = (unsigned char *) buf;
+  int       state = 0;
+  ssize_t   rem = 0;
+  char    * out;
+  
+  SH_VALIDATE_NE(buf, NULL);
+  SH_VALIDATE_GE(len, 0);
+
+  out = SH_ALLOC(len + 1);
+
+  while (*p != '\0')  {
+
+    /* -- not at start or after newline
+     */
+    if (state == 1) {
+      if (*p == '\n' || *p == ' ' || *p == '\t' || *p == '#') {
+	while (*p != '\n') {
+	  ++p;
+	  if (*p == '\0') {
+	    goto exit_it;
+	  }
+	}
+	out[rem] = ','; ++rem;
+	while (p[1] == '\n') ++p; /* scan over consecutive newlines */
+	state = 0;
+	if (p[1] == '\0') {
+	  if (rem > 0) out[rem-1] = '\0';
+	  break;
+	}
+      }
+      else {
+	if (*p <= 0x7F && isgraph((int) *p)) {
+	  out[rem] = (char) *p; ++rem;
+	}
+      }
+    }
+
+    /* -- at start or after newline
+     */
+    else /* if (state == 0) */ {
+      if        (0 == strncmp((char *) p, "user", 4)) {
+	out[rem] = 'u'; ++rem;
+	p += 3; state = 1;
+      } else if (0 == strncmp((char *) p, "group", 5)) {
+	out[rem] = 'g'; ++rem;
+	p += 4; state = 1; 
+      } else if (0 == strncmp((char *) p, "mask", 4)) {
+	out[rem] = 'm'; ++rem;
+	p += 3; state = 1;
+      } else if (0 == strncmp((char *) p, "other", 5)) {
+	out[rem] = 'o';
+	p += 4; state = 1; ++rem;
+      } else if (*p == '\0') {
+	if (rem > 0) { out[rem-1] = '\0'; }
+	break;
+      } else {
+	if (*p <= 0x7F && isprint((int) *p)) {
+	  out[rem] = (char) *p; ++rem;
+	}
+      }
+      state = 1;
+    }
+    ++p;
+  }
+ exit_it:
+  out[rem] = '\0';
+  return out;
 }
     
@@ -1343,4 +1414,65 @@
 static unsigned char sh_obscure_index[256];
 
+int sh_util_valid_utf8 (const unsigned char * str) 
+{
+  size_t        len = strlen((char *)str);
+  size_t        l   = 0;
+  unsigned char c;
+
+#define SH_VAL_UTF8_1 ((c != '\0') && ((c & 0x80) == 0x00))
+#define SH_VAL_UTF8_2 ((c != '\0') && ((c & 0xE0) == 0xC0)) /* 110x xxxx */
+#define SH_VAL_UTF8_3 ((c != '\0') && ((c & 0xF0) == 0xE0)) /* 1110 xxxx */
+#define SH_VAL_UTF8_4 ((c != '\0') && ((c & 0xF8) == 0xF0)) /* 1111 0xxx */
+#define SH_VAL_UTF8_N ((c != '\0') && ((c & 0xC0) == 0x80)) /* 10xx xxxx */
+#define SH_VAL_BAD    ((c == '"') || (c == '\t') || (c == '\b') || (c == '\f') || (c == '\n') || \
+                       (c == '\r') || (c == '\v') || iscntrl((int) c) || \
+                       (c != ' ' && !isgraph ((int) c)))
+   
+  while(l < len) 
+    {
+      c = str[l];
+
+      if      (SH_VAL_UTF8_1) 
+	{
+	  if (SH_VAL_BAD && (sh_obscure_index[c] != 1)) return S_FALSE;
+	  ++l; continue; /* ASCII character */
+	} 
+      else if (SH_VAL_UTF8_2) 
+	{ 
+	  if ((c & 0x3e) == 0x00) 
+	    return S_FALSE; /* overlong 2-byte seq. */
+	  ++l; if (l == len) return S_FALSE; c = str[l];
+	  if(!SH_VAL_UTF8_N) return S_FALSE; 
+	  ++l; continue;
+	  
+	} 
+      else if (SH_VAL_UTF8_3) 
+	{
+	  ++l; if (l == len) return S_FALSE; c = str[l];
+	  if(!SH_VAL_UTF8_N) return S_FALSE;
+	  if (((str[l-1] & 0x1F) == 0x00) && ((c & 0x60) == 0x00))
+	    return S_FALSE; /* overlong 3-byte seq. */
+	  ++l; if (l == len) return S_FALSE; c = str[l];
+	  if(!SH_VAL_UTF8_N) return S_FALSE;
+	  ++l; continue;
+	} 
+      else if (SH_VAL_UTF8_4) 
+	{
+	  ++l; if (l == len) return S_FALSE; c = str[l];
+	  if(!SH_VAL_UTF8_N) return S_FALSE;
+	  if (((str[l-1] & 0x0F) == 0x00) && ((c & 0x70) == 0x00))
+	    return S_FALSE; /* overlong 4-byte seq. */
+	  ++l; if (l == len) return S_FALSE; c = str[l];
+	  if(!SH_VAL_UTF8_N) return S_FALSE;
+	  ++l; if (l == len) return S_FALSE; c = str[l];
+	  if(!SH_VAL_UTF8_N) return S_FALSE;
+	  ++l; continue;
+	}
+      return S_FALSE;
+    }
+  return S_TRUE;
+}
+
+
 int sh_util_obscure_ok (const char * str)
 {
@@ -1387,4 +1519,16 @@
 }
 
+static int sh_obscure_check_utf8 = S_FALSE;
+
+int sh_util_obscure_utf8 (const char * c)
+{
+  int i;
+  SL_ENTER(_("sh_util_obscure_utf8"));
+  i = sh_util_flagval(c, &(sh_obscure_check_utf8));
+
+  SL_RETURN(i, _("sh_util_obscure_utf8"));
+}
+
+
 int sh_util_obscurename (ShErrLevel level, char * name_orig, int flag)
 {
@@ -1396,4 +1540,13 @@
 
   ASSERT_RET((name != NULL), _("name != NULL"), (0))
+
+  if (sh_obscure_check_utf8 == S_TRUE)
+    {
+      if (S_FALSE == sh_util_valid_utf8(name))
+	{
+	  goto err;
+	}
+      SL_RETURN((0),_("sh_util_obscurename"));
+    }
 
   /* -- Check name. --
@@ -1410,12 +1563,5 @@
 	  if (sh_obscure_index[i] != (unsigned char)1)
 	    {
-	      if (flag == S_TRUE)
-		{
-		  safe = sh_util_safe_name (name_orig);  
-		  sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_OBSC, 
-				   safe);
-		  SH_FREE(safe);
-		}
-	      SL_RETURN((-1),_("sh_util_obscurename"));
+	      goto err;
 	    }
 	}
@@ -1424,5 +1570,17 @@
 
   SL_RETURN((0),_("sh_util_obscurename"));
-}
+
+ err:
+
+  if (flag == S_TRUE)
+    {
+      safe = sh_util_safe_name (name_orig);  
+      sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_OBSC, 
+		       safe);
+      SH_FREE(safe);
+    }
+  SL_RETURN((-1),_("sh_util_obscurename"));
+}
+
 #endif
 
Index: trunk/src/sh_utmp.c
===================================================================
--- trunk/src/sh_utmp.c	(revision 67)
+++ trunk/src/sh_utmp.c	(revision 68)
@@ -547,5 +547,5 @@
  *************/
 
-int sh_utmp_set_login_solo  (char * c)
+int sh_utmp_set_login_solo  (const char * c)
 {
   int retval;
@@ -559,5 +559,5 @@
 }
 
-int sh_utmp_set_login_multi (char * c)
+int sh_utmp_set_login_multi (const char * c)
 {
   int retval;
@@ -571,5 +571,5 @@
 }
 
-int sh_utmp_set_logout_good (char * c)
+int sh_utmp_set_logout_good (const char * c)
 {
   int retval;
@@ -583,5 +583,5 @@
 }
 
-int sh_utmp_set_login_timer (char * c)
+int sh_utmp_set_login_timer (const char * c)
 {
   int retval = 0;
@@ -603,5 +603,5 @@
 }
 
-int sh_utmp_set_login_activate (char * c)
+int sh_utmp_set_login_activate (const char * c)
 {
   int i;
