Index: /trunk/Makefile.in
===================================================================
--- /trunk/Makefile.in	(revision 148)
+++ /trunk/Makefile.in	(revision 149)
@@ -1647,5 +1647,5 @@
 sh_tiger1_64.o: $(srcsrc)/sh_tiger1_64.c Makefile config_xor.h 
 sh_tiger2_64.o: $(srcsrc)/sh_tiger2_64.c Makefile config_xor.h 
-sh_hash.o: $(srcsrc)/sh_hash.c Makefile config_xor.h $(srcinc)/sh_hash.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_ignore.h $(srcinc)/sh_forward.h $(srcinc)/sh_hash.h 
+sh_hash.o: $(srcsrc)/sh_hash.c Makefile config_xor.h $(srcinc)/sh_hash.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_ignore.h $(srcinc)/sh_pthread.h $(srcinc)/sh_forward.h $(srcinc)/sh_hash.h 
 sh_mail.o: $(srcsrc)/sh_mail.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_mail.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_pthread.h $(srcinc)/sh_static.h $(srcinc)/sh_tools.h 
 sh_mem.o: $(srcsrc)/sh_mem.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_pthread.h 
Index: /trunk/configure.ac
===================================================================
--- /trunk/configure.ac	(revision 148)
+++ /trunk/configure.ac	(revision 149)
@@ -13,5 +13,5 @@
 dnl start
 dnl
-AM_INIT_AUTOMAKE(samhain, 2.4.1a)
+AM_INIT_AUTOMAKE(samhain, 2.4.2) 
 AC_CANONICAL_HOST
 
Index: /trunk/depend.dep
===================================================================
--- /trunk/depend.dep	(revision 148)
+++ /trunk/depend.dep	(revision 149)
@@ -13,5 +13,5 @@
 sh_tiger1_64.o: $(srcsrc)/sh_tiger1_64.c Makefile config_xor.h 
 sh_tiger2_64.o: $(srcsrc)/sh_tiger2_64.c Makefile config_xor.h 
-sh_hash.o: $(srcsrc)/sh_hash.c Makefile config_xor.h $(srcinc)/sh_hash.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_ignore.h $(srcinc)/sh_forward.h $(srcinc)/sh_hash.h 
+sh_hash.o: $(srcsrc)/sh_hash.c Makefile config_xor.h $(srcinc)/sh_hash.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_tiger.h $(srcinc)/sh_gpg.h $(srcinc)/sh_unix.h $(srcinc)/sh_files.h $(srcinc)/sh_ignore.h $(srcinc)/sh_pthread.h $(srcinc)/sh_forward.h $(srcinc)/sh_hash.h 
 sh_mail.o: $(srcsrc)/sh_mail.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_unix.h $(srcinc)/sh_tiger.h $(srcinc)/sh_mail.h $(srcinc)/sh_utils.h $(srcinc)/sh_fifo.h $(srcinc)/sh_tools.h $(srcinc)/sh_pthread.h $(srcinc)/sh_static.h $(srcinc)/sh_tools.h 
 sh_mem.o: $(srcsrc)/sh_mem.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_utils.h $(srcinc)/sh_mem.h $(srcinc)/sh_pthread.h 
@@ -58,8 +58,7 @@
 sh_prelink.o: $(srcsrc)/sh_prelink.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_tiger.h $(srcinc)/sh_extern.h $(srcinc)/sh_utils.h $(srcinc)/sh_unix.h 
 sh_static.o: $(srcsrc)/sh_static.c Makefile config_xor.h $(srcinc)/sh_pthread.h 
+sh_portcheck.o: $(srcsrc)/sh_portcheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_mem.h $(srcinc)/sh_calls.h $(srcinc)/sh_utils.h $(srcinc)/sh_modules.h $(srcinc)/sh_pthread.h $(srcinc)/CuTest.h 
+sh_processcheck.o: $(srcsrc)/sh_processcheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_modules.h $(srcinc)/sh_processcheck.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_extern.h $(srcinc)/sh_calls.h $(srcinc)/sh_pthread.h $(srcinc)/CuTest.h 
 sh_prelude_old.o: $(srcsrc)/sh_prelude_old.c Makefile config_xor.h $(srcinc)/slib.h $(srcinc)/sh_mem.h $(srcinc)/sh_cat.h $(srcinc)/sh_error_min.h $(srcinc)/sh_prelude.h $(srcinc)/sh_static.h $(srcinc)/sh_pthread.h 
+sh_pthread.o: $(srcsrc)/sh_pthread.c Makefile config_xor.h $(srcinc)/sh_pthread.h $(srcinc)/sh_calls.h $(srcinc)/sh_modules.h 
 kern_head.o: $(srcsrc)/kern_head.c Makefile config.h $(srcinc)/kern_head.h $(srcinc)/kern_head.h 
-sh_async.o: $(srcsrc)/sh_async.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_calls.h $(srcinc)/sh_error.h 
-sh_processcheck.o: $(srcsrc)/sh_processcheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_modules.h $(srcinc)/sh_processcheck.h $(srcinc)/sh_utils.h $(srcinc)/sh_error.h $(srcinc)/sh_extern.h $(srcinc)/sh_calls.h $(srcinc)/sh_pthread.h $(srcinc)/CuTest.h 
-sh_portcheck.o: $(srcsrc)/sh_portcheck.c Makefile config_xor.h $(srcinc)/samhain.h $(srcinc)/sh_error.h $(srcinc)/sh_mem.h $(srcinc)/sh_calls.h $(srcinc)/sh_utils.h $(srcinc)/sh_modules.h $(srcinc)/sh_pthread.h $(srcinc)/CuTest.h 
-sh_pthread.o: $(srcsrc)/sh_pthread.c Makefile config_xor.h $(srcinc)/sh_pthread.h $(srcinc)/sh_calls.h $(srcinc)/sh_modules.h 
Index: /trunk/depend.sum
===================================================================
--- /trunk/depend.sum	(revision 148)
+++ /trunk/depend.sum	(revision 149)
@@ -1,1 +1,1 @@
-1541314115
+1156805991
Index: /trunk/docs/Changelog
===================================================================
--- /trunk/docs/Changelog	(revision 148)
+++ /trunk/docs/Changelog	(revision 149)
@@ -1,2 +1,12 @@
+2.4.2:
+	* make sh_hash.c thread-safe
+	* remove plenty of tiny allocations
+	* improve sh_mem_dump
+	* modify port check to run as thread
+	* fix unsetting of sh_thread_pause_flag (was too early)
+
+2.4.1a:
+	* fix overwrite of ErrFlags (functionality bug)
+
 2.4.1:
 	* security fix: regression in the seeding routine for the PRNG 
Index: /trunk/include/samhain.h
===================================================================
--- /trunk/include/samhain.h	(revision 148)
+++ /trunk/include/samhain.h	(revision 149)
@@ -48,8 +48,12 @@
  */
 #define SOCKPASS_MAX 14
-#define USER_MAX  20
-#define GROUP_MAX 20
-#define TIM_MAX   32
-
+#define USER_MAX     20
+#define GROUP_MAX    20
+#define TIM_MAX      32
+
+#define CMODE_SIZE   11
+
+#define ATTRBUF_SIZE 16
+#define ATTRBUF_USED 12
 
 /* The number of bytes in a key,  
@@ -159,5 +163,4 @@
 #define SET_SH_FFLAG_SUIDCHK(a)     ((a) |= SH_FFLAG_SUIDCHK)
 #define CLEAR_SH_FFLAG_SUIDCHK(a)   ((a) &= ~SH_FFLAG_SUIDCHK)
-
 
 
@@ -340,8 +343,29 @@
 
 #if defined(__GNUC__) && (__GNUC__ >= 4)
-#define SH_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
-#else
-#define SH_GNUC_NULL_TERMINATED
-#endif
+#define SH_GNUC_SENTINEL __attribute__((__sentinel__))
+#else
+#define SH_GNUC_SENTINEL
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#undef  SH_GNUC_PURE
+#define SH_GNUC_PURE     __attribute__((pure))
+#undef  SH_GNUC_CONST
+#define SH_GNUC_CONST	 __attribute__((const))
+#undef  SH_GNUC_NORETURN
+#define SH_GNUC_NORETURN __attribute__((noreturn))
+#undef  SH_GNUC_MALLOC
+#define SH_GNUC_MALLOC   __attribute__((malloc))
+#else
+#undef  SH_GNUC_PURE
+#define SH_GNUC_PURE
+#undef  SH_GNUC_CONST
+#define SH_GNUC_CONST
+#undef  SH_GNUC_NORETURN
+#define SH_GNUC_NORETURN
+#undef  SH_GNUC_MALLOC
+#define SH_GNUC_MALLOC
+#endif
+
 
 /* The semantics of the built-in are that it is expected that expr == const
Index: /trunk/include/sh_mem.h
===================================================================
--- /trunk/include/sh_mem.h	(revision 148)
+++ /trunk/include/sh_mem.h	(revision 149)
@@ -38,7 +38,14 @@
 #else
 
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#undef  SH_GNUC_MALLOC
+#define SH_GNUC_MALLOC   __attribute__((malloc))
+#else
+#undef  SH_GNUC_MALLOC
+#define SH_GNUC_MALLOC
+#endif
 
 void   sh_mem_free (/*@only@*//*@out@*//*@null@*/ void * a);
-/*@only@*//*@notnull@*/void * sh_mem_malloc (size_t size);
+/*@only@*//*@notnull@*/void * sh_mem_malloc (size_t size) SH_GNUC_MALLOC;
 
 #define SH_FREE(a)   sh_mem_free(a)
Index: /trunk/include/sh_suidchk.h
===================================================================
--- /trunk/include/sh_suidchk.h	(revision 148)
+++ /trunk/include/sh_suidchk.h	(revision 149)
@@ -6,9 +6,9 @@
 
 #ifdef SH_USE_SUIDCHK
-int sh_suidchk_init  (struct mod_type * arg);
-int sh_suidchk_timer (time_t tcurrent);
-int sh_suidchk_check (void);
-int sh_suidchk_end   (void);
-int sh_suidchk_free_schedule (void);
+int sh_suidchk_init   (struct mod_type * arg);
+int sh_suidchk_timer  (time_t tcurrent);
+int sh_suidchk_check  (void);
+int sh_suidchk_end    (void);
+int sh_suidchk_reconf (void);
 
 int sh_suidchk_set_activate   (const char * c);
Index: /trunk/include/sh_unix.h
===================================================================
--- /trunk/include/sh_unix.h	(revision 148)
+++ /trunk/include/sh_unix.h	(revision 149)
@@ -120,7 +120,7 @@
 #if defined(__linux__) || defined(HAVE_STAT_FLAGS)
   unsigned long    attributes;
-  char             c_attributes[16];
-#endif
-  char             c_mode[11];
+  char             c_attributes[ATTRBUF_SIZE];
+#endif
+  char             c_mode[CMODE_SIZE];
   uid_t            owner;
   char             c_owner[USER_MAX+2];
Index: /trunk/include/sh_utils.h
===================================================================
--- /trunk/include/sh_utils.h	(revision 148)
+++ /trunk/include/sh_utils.h	(revision 149)
@@ -64,9 +64,9 @@
 /* returns allocated memory
  */
-char * sh_util_strdup (const char * str);
+char * sh_util_strdup (const char * str) SH_GNUC_MALLOC;
 
 /* returns allocated memory
  */
-char * sh_util_strdup_l (const char * str, size_t len);
+char * sh_util_strdup_l (const char * str, size_t len) SH_GNUC_MALLOC;
 
 /* returns pointer within str
@@ -119,5 +119,5 @@
 /* read a hexchar, return int value (0-15)
  */
-int sh_util_hexchar( char c );
+int sh_util_hexchar( char c ) SH_GNUC_CONST;
 
 /* change verifier 
@@ -159,9 +159,9 @@
  * Argument list must be NULL terminated.
  */
-char * sh_util_strconcat (const char * arg1, ...) SH_GNUC_NULL_TERMINATED;
+char * sh_util_strconcat (const char * arg1, ...) SH_GNUC_MALLOC SH_GNUC_SENTINEL;
 
 /* check if string is numeric only
  */
-int sh_util_isnum (char *str);
+int sh_util_isnum (const char *str) SH_GNUC_PURE;
 
 /* init a key w/random string
@@ -176,5 +176,5 @@
 /* returns freshly allocated memory, return value should be free'd
  */
-char * sh_util_safe_name (const char * name);
+char * sh_util_safe_name (const char * name) SH_GNUC_MALLOC SH_GNUC_PURE;
 
 /* check max size of printf result string
Index: /trunk/include/sh_utmp.h
===================================================================
--- /trunk/include/sh_utmp.h	(revision 148)
+++ /trunk/include/sh_utmp.h	(revision 149)
@@ -6,9 +6,9 @@
 
 #ifdef SH_USE_UTMP
-int sh_utmp_init  (struct mod_type * arg);
-int sh_utmp_timer (time_t tcurrent);
-int sh_utmp_check (void);
-int sh_utmp_end (void);
-int sh_utmp_null (void);
+int sh_utmp_init   (struct mod_type * arg);
+int sh_utmp_timer  (time_t tcurrent);
+int sh_utmp_check  (void);
+int sh_utmp_end    (void);
+int sh_utmp_reconf (void);
 
 int sh_utmp_set_login_activate (const char * c);
Index: /trunk/include/slib.h
===================================================================
--- /trunk/include/slib.h	(revision 148)
+++ /trunk/include/slib.h	(revision 149)
@@ -63,4 +63,12 @@
 #define SH_PWBUF_SIZE  4096
 
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#undef  SL_GNUC_CONST
+#define SL_GNUC_CONST   __attribute__((const))
+#else
+#undef  SH_GNUC_CONST
+#define SH_GNUC_CONST
+#endif
 
 /*
@@ -405,11 +413,11 @@
   /* Overflow tests
    */
-  int sl_ok_muli (int a, int b);
-  int sl_ok_divi (int a, int b);
-  int sl_ok_addi (int a, int b);
-  int sl_ok_subi (int a, int b);
-
-  int sl_ok_muls (size_t a, size_t b);
-  int sl_ok_adds (size_t a, size_t b);
+  int sl_ok_muli (int a, int b) SL_GNUC_CONST;
+  int sl_ok_divi (int a, int b) SL_GNUC_CONST;
+  int sl_ok_addi (int a, int b) SL_GNUC_CONST;
+  int sl_ok_subi (int a, int b) SL_GNUC_CONST;
+
+  int sl_ok_muls (size_t a, size_t b) SL_GNUC_CONST;
+  int sl_ok_adds (size_t a, size_t b) SL_GNUC_CONST;
 
 
Index: /trunk/src/cutest_sh_hash.c
===================================================================
--- /trunk/src/cutest_sh_hash.c	(revision 148)
+++ /trunk/src/cutest_sh_hash.c	(revision 149)
@@ -5,6 +5,6 @@
 #include "CuTest.h"
 
-extern char * quote_string   (const char * str);
-extern char * unquote_string (const char * str);
+extern char * quote_string   (const char * str, size_t len);
+extern char * unquote_string (const char * str, size_t len);
 
 void Test_quote_string_ok (CuTest *tc) {
@@ -19,9 +19,9 @@
   char   out2[] = "=0A=3Dfoo=0Aba=3Dr=0Atest=3D=0A";
 
-  ret = quote_string(inp1);
+  ret = quote_string(inp1, strlen(inp1));
   CuAssertPtrNotNull(tc, ret);
   CuAssertStrEquals(tc, out1, ret);
 
-  ret = quote_string(inp2);
+  ret = quote_string(inp2,strlen(inp2));
   CuAssertPtrNotNull(tc, ret);
   CuAssertStrEquals(tc, out2, ret);
@@ -45,13 +45,13 @@
   char   inp3[] = "=00=3Dfoo=0Aba=3Dr=0Atest=3D=0A";
 
-  ret = unquote_string(inp1);
+  ret = unquote_string(inp1, strlen(inp1));
   CuAssertPtrNotNull(tc, ret);
   CuAssertStrEquals(tc, out1, ret);
 
-  ret = unquote_string(inp2);
+  ret = unquote_string(inp2, strlen(inp2));
   CuAssertPtrNotNull(tc, ret);
   CuAssertStrEquals(tc, out2, ret);
 
-  ret = unquote_string(inp3);
+  ret = unquote_string(inp3, strlen(inp3));
   CuAssertPtrNotNull(tc, ret);
   CuAssertStrEquals(tc, out3, ret);
Index: /trunk/src/samhain.c
===================================================================
--- /trunk/src/samhain.c	(revision 148)
+++ /trunk/src/samhain.c	(revision 149)
@@ -818,5 +818,5 @@
   if (0 != stat(SH_INSTALL_PATH, &buf))
     {
-      dummy = pidlist;
+      dummy = (pid_t *)pidlist;
       free(dummy);
       return NULL;
@@ -827,5 +827,5 @@
   if (NULL == (dp = opendir("/proc")))
     {
-      dummy = pidlist;
+      dummy = (pid_t *)pidlist;
       free(dummy);
       return NULL;
@@ -858,5 +858,5 @@
 
   closedir(dp);
-  return pidlist;
+  return (pid_t *)pidlist;
 }
 #else
@@ -1755,6 +1755,10 @@
 	      for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
 		{
-		  if (modList[modnum].initval >= SH_MOD_ACTIVE)
-		    (void) modList[modnum].mod_reconf();
+		  /* sh_thread_pause_flag is true, and we block in lock
+		   * until check has returned, so we are sure check will
+		   * not run until sh_thread_pause_flag is set to false
+		   */
+		  /* if (modList[modnum].initval >= SH_MOD_ACTIVE) */
+		  (void) modList[modnum].mod_reconf();
 		}
 #endif
@@ -1801,5 +1805,4 @@
 		}
 
-	      sh_thread_pause_flag = S_FALSE;
 
 	      /* --- Initialize modules. ---
@@ -1832,4 +1835,8 @@
 		    }
 		}
+
+	      /* module is properly set up now
+	       */
+	      sh_thread_pause_flag = S_FALSE;
 	      
 	      --sig_raised;
@@ -2069,4 +2076,10 @@
 	sh_hash_writeout ();
 
+      /* no-op unless MEM_LOG is defined in sh_mem.c
+       */
+#ifdef MEM_DEBUG
+      sh_mem_dump ();
+#endif
+
       /* no loop if not daemon
        */
Index: /trunk/src/sh_hash.c
===================================================================
--- /trunk/src/sh_hash.c	(revision 148)
+++ /trunk/src/sh_hash.c	(revision 149)
@@ -57,4 +57,5 @@
 #include "sh_files.h"
 #include "sh_ignore.h"
+#include "sh_pthread.h"
 
 #if defined(SH_WITH_CLIENT)
@@ -69,13 +70,17 @@
 #define FIL__  _("sh_hash.c")
 
+SH_MUTEX_STATIC(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
+
+const char notalink[2] = { '-', '\0' };
+
 static char * all_items (file_type * theFile, char * fileHash, int is_new);
 
 #define QUOTE_CHAR '='
 
-char * unquote_string (const char * str)
+char * unquote_string (const char * str, size_t len)
 {
   int    i = 0, t1, t2;
   char * tmp = NULL;
-  size_t len, l2, j, k = 0;
+  size_t l2, j, k = 0;
 
   SL_ENTER(_("unquote_string"));
@@ -83,5 +88,4 @@
   if (str != NULL)
     {
-      len = sl_strlen(str);
       l2  = len - 2;
       tmp = SH_ALLOC(len + 1);
@@ -116,7 +120,6 @@
 }
 
-static char i2h[2];
-
-char * int2hex (unsigned char i)
+
+static char * int2hex (unsigned char i, char * i2h)
 {
   static char hexchars[] = "0123456789ABCDEF";
@@ -129,9 +132,10 @@
 
 
-char * quote_string (const char * str)
+char * quote_string (const char * str, size_t len)
 {
   char * tmp;
   char * tmp2;
-  size_t len, l2, j, i = 0, k = 0;
+  size_t l2, j, i = 0, k = 0;
+  char   i2h[2];
 
   SL_ENTER(_("quote_string"));
@@ -141,6 +145,4 @@
       SL_RETURN(NULL, _("quote_string"));
     }
-
-  len = sl_strlen(str);
 
   for (j = 0; j < len; ++j)
@@ -164,5 +166,5 @@
       if (str[j] == '\n')
 	{
-	  tmp2 = int2hex((unsigned char) '\n'); /* was 'n', fixed in 1.5.4 */
+	  tmp2 = int2hex((unsigned char) '\n', i2h); /* was 'n', fixed in 1.5.4 */
 	  tmp[k] = QUOTE_CHAR; ++k;
 	  tmp[k] = tmp2[0];    ++k;
@@ -171,5 +173,5 @@
       else if (str[j] == QUOTE_CHAR)
 	{
-	  tmp2 = int2hex((unsigned char) QUOTE_CHAR);
+	  tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h);
 	  tmp[k] = QUOTE_CHAR; ++k;
 	  tmp[k] = tmp2[0];    ++k;
@@ -249,8 +251,5 @@
 
 typedef struct store_info {
-  /*
-  char             fullpath[MAX_PATH_STORE+2];
-  char             linkpath[MAX_PATH_STORE+2];
-  */
+
   UINT32           mode;
   UINT32           linkmode;
@@ -270,10 +269,10 @@
 #if defined(__linux__)
   UINT32           attributes;
-  char             c_attributes[16];
+  char             c_attributes[ATTRBUF_SIZE];
 #endif
 #else
   /* #if defined(__linux__) */
   UINT32           attributes;
-  char             c_attributes[16];
+  char             c_attributes[ATTRBUF_SIZE];
   /* endif                  */
 #endif
@@ -281,5 +280,5 @@
   char             c_owner[USER_MAX+2];
   char             c_group[GROUP_MAX+2];
-  char             c_mode[11];
+  char             c_mode[CMODE_SIZE];
   char             checksum[KEY_LEN+1];
 } sh_filestore_t;
@@ -351,7 +350,4 @@
 {
   file_type * theFile;
-#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
-  int i = 16;
-#endif
 
   SL_ENTER(_("sh_hash_create_ft"));
@@ -362,5 +358,5 @@
   theFile->mode  =  p->theFile.mode;
 #if defined(__linux__) || defined(HAVE_STAT_FLAGS)
-  sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, i /* 16 */);
+  sl_strlcpy(theFile->c_attributes, p->theFile.c_attributes, ATTRBUF_SIZE);
   theFile->attributes =  p->theFile.attributes;
 #endif
@@ -431,6 +427,9 @@
   char * str;
   char hashbuf[KEYBUF_SIZE];
+  int  retval = 0;
 
   /* --------  find the entry for the file ----------------       */
+
+  SH_MUTEX_LOCK(mutex_hash);
 
   if (sl_strlen(fullpath) <= MAX_PATH_STORE) 
@@ -443,5 +442,8 @@
 		    );
   if (p == NULL)
-    return -1;
+    {
+      retval = -1;
+      goto unlock_and_return;
+    }
 
   theFile = sh_hash_create_ft (p, fileHash);
@@ -455,5 +457,8 @@
     SH_FREE(theFile->attr_string);
   SH_FREE(theFile);
-  return 0;
+
+ unlock_and_return:
+  SH_MUTEX_UNLOCK(mutex_hash);
+  return retval;
 }
 
@@ -564,5 +569,6 @@
 	      if (p->linkpath)
 		{
-		  SH_FREE(p->linkpath);
+		  if (p->linkpath != notalink)
+		    SH_FREE(p->linkpath);
 		  p->linkpath = NULL;
 		}
@@ -624,4 +630,6 @@
 
   SL_ENTER(_("sh_hash_unvisited"));
+
+  SH_MUTEX_LOCK(mutex_hash);
   for (i = 0; i < TABSIZE; ++i)
     {
@@ -629,4 +637,6 @@
 	hash_unvisited (i, tab[i], tab[i], level);
     }
+  SH_MUTEX_UNLOCK(mutex_hash);
+
   SL_RET0(_("hash_unvisited"));
 }
@@ -655,5 +665,6 @@
   if (p->linkpath)
     {
-      SH_FREE(p->linkpath);
+      if (p->linkpath != notalink)
+	SH_FREE(p->linkpath);
       p->linkpath = NULL;
     }
@@ -721,5 +732,5 @@
 	      q = p->next;
 	      SH_FREE(p->fullpath);
-	      if(p->linkpath)
+	      if(p->linkpath && p->linkpath != notalink)
 		SH_FREE(p->linkpath);
 	      if(p->attr_string)
@@ -768,5 +779,5 @@
     }
   n = strlen(line);
-  if (n > 1) {
+  if (n > 0) {
     --n;
     line[n] = '\0'; /* remove terminating '\n' */
@@ -947,5 +958,5 @@
    */
   i =  sh_hash_getline (sh_fin_fd, line, size);
-  if (i < 0 ) 
+  if (i <= 0 ) 
     {
       SH_FREE(line);
@@ -961,5 +972,5 @@
     }
 
-  tmp = unquote_string (line);
+  tmp = unquote_string (line, i);
   len = sl_strlen(tmp)+1;
   fullpath = SH_ALLOC(len);
@@ -973,5 +984,5 @@
    */
   i =  sh_hash_getline (sh_fin_fd, line, size);
-  if (i < 0 ) 
+  if (i <= 0 ) 
     {
       SH_FREE(line);
@@ -988,12 +999,22 @@
     }
 
-  tmp = unquote_string (line);
-  len = sl_strlen(tmp)+1;
-  linkpath = SH_ALLOC(len);
-  (void) sl_strlcpy (linkpath, tmp, len);
+  tmp = unquote_string (line, i);
+
+  if ( tmp && tmp[0] == '-' && 
+       (tmp[1] == '\0' || (tmp[1] == '\n' && tmp[2] == '\0')))
+    {
+      linkpath = (char *)notalink;
+    }
+  else
+    {
+      len = sl_strlen(tmp)+1;
+      linkpath = SH_ALLOC(len);
+      (void) sl_strlcpy (linkpath, tmp, len);
+      if (len > 1 && linkpath[len-2] == '\n')
+	linkpath[len-2] = '\0';
+    }
+
   if (tmp)
     SH_FREE(tmp);
-  if (linkpath[len-2] == '\n')
-    linkpath[len-2] = '\0';
 
   /* Read next record -- Part Four -- attr_string
@@ -1002,9 +1023,10 @@
     {
       i =  sh_hash_getline (sh_fin_fd, line, size);
-      if (i < 0 ) 
+      if (i <= 0 ) 
 	{
 	  SH_FREE(line);
 	  SH_FREE(fullpath);
-	  SH_FREE(linkpath);
+	  if (linkpath != notalink)
+	    SH_FREE(linkpath);
 	  SH_FREE(p);
 	  dlog(1, FIL__, __LINE__, 
@@ -1018,5 +1040,5 @@
 	}
 
-      tmp = unquote_string (line);
+      tmp = unquote_string (line, i);
 
       len = sl_strlen(tmp)+1;
@@ -1044,5 +1066,5 @@
   
   
-  if (ft.c_mode[0] == 'l') 
+  if (ft.c_mode[0] == 'l' && linkpath != notalink)
     {  
       sh_do_decode(linkpath, sl_strlen(linkpath));
@@ -1122,9 +1144,10 @@
   SL_ENTER(_("sh_hash_init"));
 
-  if (IsInit == 1) 
-    SL_RET0(_("sh_hash_init"));
-
-  for (i = 0; i < TABSIZE; ++i) 
-    tab[i] = NULL;
+  SH_MUTEX_LOCK(mutex_hash);
+
+  if (IsInit == 1)
+    { 
+      goto unlock_and_return;
+    }
 
 #if defined(SH_WITH_CLIENT)
@@ -1290,4 +1313,7 @@
   sh_hash_setdataent(fd, line, MAX_PATH_STORE, file_path('D', 'R'));
 
+  for (i = 0; i < TABSIZE; ++i) 
+    tab[i] = NULL;
+
   while (1) 
     {
@@ -1308,4 +1334,8 @@
 	break;
     }
+
+  /* Initialization completed.
+   */
+  IsInit = 1;
 
   if (line != NULL)
@@ -1318,7 +1348,6 @@
   fd = -1;
 
-  /* --- Initialization done successfully. ---
-   */
-  IsInit = 1;
+ unlock_and_return:
+  SH_MUTEX_UNLOCK(mutex_hash);
   SL_RET0(_("sh_hash_init"));
 }
@@ -1334,7 +1363,9 @@
 
   SL_ENTER(_("sh_hash_hashdelete"));
+  SH_MUTEX_LOCK(mutex_hash);
 
   if (IsInit == 0) 
-    SL_RET0(_("sh_hash_hashdelete"));
+    goto unlock_and_exit;
+
   for (i = 0; i < TABSIZE; ++i) 
     if (tab[i] != NULL)
@@ -1344,4 +1375,7 @@
       }
   IsInit = 0;
+
+ unlock_and_exit:
+  SH_MUTEX_UNLOCK(mutex_hash);
   SL_RET0(_("sh_hash_hashdelete"));
 }
@@ -1385,5 +1419,5 @@
 
 
-void sh_hash_pushdata (file_type * buf, char * fileHash)
+static void sh_hash_pushdata_int (file_type * buf, char * fileHash)
 {
   static long p_count = 0;
@@ -1394,4 +1428,5 @@
   size_t      tmp_len = 0;
   size_t      old_len = 0;
+  size_t      path_len = 0;
 
   sh_filestore_t p;
@@ -1411,5 +1446,5 @@
 #endif
 
-  SL_ENTER(_("sh_hash_pushdata"));
+  SL_ENTER(_("sh_hash_pushdata_int"));
 
   fullpath = SH_ALLOC(MAX_PATH_STORE+1);
@@ -1432,5 +1467,5 @@
 		      _("Writing database to stdout with update"), 
 		      sh.prg_name, 
-		      _("sh_hash_pushdata"));
+		      _("sh_hash_pushdata_int"));
       aud_exit(FIL__, __LINE__, EXIT_FAILURE);
     }
@@ -1443,10 +1478,10 @@
 		      _("Writing database to stdout when suid"), 
 		      sh.prg_name, 
-		      _("sh_hash_pushdata"));
+		      _("sh_hash_pushdata_int"));
       aud_exit(FIL__, __LINE__, EXIT_FAILURE);
     }
 
 
-  if ((pushdata_stdout == S_FALSE) && 
+  if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) && 
       ( (NULL == file_path('D', 'W')) || 
 	(0 == sl_strcmp(file_path('D', 'W'), _("REQ_FROM_SERVER"))) ))
@@ -1457,10 +1492,10 @@
 		      _("No local path for database specified"), 
 		      sh.prg_name, 
-		      _("sh_hash_pushdata"));
+		      _("sh_hash_pushdata_int"));
       aud_exit(FIL__, __LINE__, EXIT_FAILURE);
     }
 
 
-  if ((pushdata_stdout == S_FALSE) && (pushdata_isfirst == 1))  
+  if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))  
     {
       /* Warn that file already exists; file_path != NULL here because
@@ -1488,5 +1523,5 @@
 	      sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
 			      geteuid(), file_path('D', 'W'));
-	      SL_RET0(_("sh_hash_pushdata"));
+	      SL_RET0(_("sh_hash_pushdata_int"));
 	    }
 	  if ( SL_ISERROR(status = sl_forward(pushdata_fd))) 
@@ -1495,7 +1530,7 @@
 	      SH_FREE(linkpath);
 	      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
-			      _("Fast forward failed"), _("sh_hash_pushdata"),
+			      _("Fast forward failed"), _("sh_hash_pushdata_int"),
 			      file_path('D', 'W'));
-	      SL_RET0(_("sh_hash_pushdata"));
+	      SL_RET0(_("sh_hash_pushdata_int"));
 	    }
 	}
@@ -1511,5 +1546,5 @@
 	    sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
 			    geteuid(), file_path('D', 'W'));
-	    SL_RET0(_("sh_hash_pushdata"));
+	    SL_RET0(_("sh_hash_pushdata_int"));
 	  }
 	  line = SH_ALLOC(MAX_PATH_STORE+1);
@@ -1521,5 +1556,5 @@
 	      SH_FREE(linkpath);
 	      SH_FREE(line);
-	      SL_RET0(_("sh_hash_pushdata"));
+	      SL_RET0(_("sh_hash_pushdata_int"));
 	    }
 	  SH_FREE(line);
@@ -1533,5 +1568,5 @@
     sh_do_encode(buf->fullpath, old_len);
 #endif
-    tmp = quote_string(buf->fullpath);
+    tmp = quote_string(buf->fullpath, old_len);
     tmp_len = sl_strlen(tmp);
 #if defined(SH_STEALTH)
@@ -1563,9 +1598,10 @@
   }
 
+  path_len = sl_strlen(fullpath);
 #if defined(SH_STEALTH)
-  sh_do_encode(fullpath, sl_strlen(fullpath));
-#endif
-
-  tmp = quote_string(fullpath);
+  sh_do_encode(fullpath, path_len);
+#endif
+
+  tmp = quote_string(fullpath, path_len);
   if (tmp) {
     sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
@@ -1580,5 +1616,5 @@
       sh_do_encode(buf->linkpath, old_len);
 #endif
-      tmp = quote_string(buf->linkpath);
+      tmp = quote_string(buf->linkpath, old_len);
       tmp_len = sl_strlen(tmp);
 #if defined(SH_STEALTH)
@@ -1601,8 +1637,9 @@
       if (tmp) SH_FREE(tmp);
 
+      path_len = sl_strlen(linkpath);
 #if defined(SH_STEALTH)
-      sh_do_encode(linkpath, sl_strlen(linkpath));
-#endif
-      tmp = quote_string(linkpath);
+      sh_do_encode(linkpath, path_len);
+#endif
+      tmp = quote_string(linkpath, path_len);
       if (tmp)
 	{
@@ -1618,5 +1655,5 @@
       sh_do_encode(buf->attr_string, old_len);
 #endif
-      tmp = quote_string(buf->attr_string);
+      tmp = quote_string(buf->attr_string, old_len);
       if (tmp)
 	{
@@ -1634,5 +1671,5 @@
     if (attr_string)
       p.mark |= REC_FLAGS_ATTR;
-    sl_strlcpy(p.c_mode,   buf->c_mode,   11);
+    sl_strlcpy(p.c_mode,   buf->c_mode,   CMODE_SIZE);
     sl_strlcpy(p.c_group,  buf->c_group,  GROUP_MAX+1);
     sl_strlcpy(p.c_owner,  buf->c_owner,  USER_MAX+1);
@@ -1641,8 +1678,8 @@
     }
 #if defined(__linux__) || defined(HAVE_STAT_FLAGS)
-    sl_strlcpy(p.c_attributes, buf->c_attributes, 13);
-#else
-    for (i = 0; i < 12; ++i) p.c_attributes[i] = '-';
-    p.c_attributes[12] = '\0';
+    sl_strlcpy(p.c_attributes, buf->c_attributes, ATTRBUF_SIZE);
+#else
+    for (i = 0; i < ATTRBUF_USED; ++i) p.c_attributes[i] = '-';
+    p.c_attributes[ATTRBUF_USED] = '\0';
 #endif
     
@@ -1778,6 +1815,17 @@
     SH_FREE(attr_string);
 
-  SL_RET0(_("sh_hash_pushdata"));
-}
+  SL_RET0(_("sh_hash_pushdata_int"));
+}
+
+SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
+
+void sh_hash_pushdata (file_type * buf, char * fileHash)
+{
+  SH_MUTEX_LOCK(mutex_writeout); 
+  sh_hash_pushdata_int (buf, fileHash);
+  SH_MUTEX_UNLOCK(mutex_writeout); 
+  return;
+}
+
 
 int sh_hash_writeout()
@@ -1797,4 +1845,5 @@
     }
 
+  SH_MUTEX_LOCK(mutex_writeout); 
   if (!SL_ISERROR(pushdata_fd))
     {
@@ -1804,4 +1853,6 @@
   pushdata_isfirst =  1;
 
+
+  SH_MUTEX_LOCK(mutex_hash);
   for (i = 0; i < TABSIZE; ++i)
     {
@@ -1809,5 +1860,5 @@
 	{
 	  f = sh_hash_create_ft (p, fileHash);
-	  sh_hash_pushdata (f, fileHash);
+	  sh_hash_pushdata_int (f, fileHash);
 	  if (f->attr_string)
 	    SH_FREE(f->attr_string);
@@ -1815,4 +1866,5 @@
 	}
     }
+  SH_MUTEX_UNLOCK(mutex_hash);
 
   if (!SL_ISERROR(pushdata_fd))
@@ -1822,4 +1874,5 @@
     }
   pushdata_isfirst =  1;
+  SH_MUTEX_UNLOCK(mutex_writeout); 
 
   SL_RETURN (0, _("sh_hash_writeout"));
@@ -1842,6 +1895,4 @@
     SL_RETURN( (NULL), _("sh_hash_have_it_int"));
 
-  if (IsInit != 1) 
-    sh_hash_init();
   if (sl_strlen(newname) <= MAX_PATH_STORE) 
     p = hashsearch(newname);
@@ -1851,10 +1902,5 @@
   if (p == NULL) 
      SL_RETURN( (NULL), _("sh_hash_have_it_int"));
-  /*
-  if (p->allignore == S_FALSE && 
-      (p->modi_mask & MODI_CHK) != 0 &&
-      (p->modi_mask & MODI_MOD) != 0)
-    SL_RETURN( (1), _("sh_hash_have_it"));
-  */
+
   SL_RETURN( (p), _("sh_hash_have_it_int"));
 }
@@ -1862,44 +1908,82 @@
 int sh_hash_have_it (char * newname)
 {
-  sh_file_t * p = sh_hash_have_it_int (newname);
-
-  if (!p) return (-1);
-  if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) && 
-      (p->modi_mask & MODI_CHK) != 0 &&
-      (p->modi_mask & MODI_MOD) != 0)
-    return 1;
-  return 0;
+  sh_file_t * p;
+  int retval = 0;
+
+  if (IsInit != 1) 
+    sh_hash_init();
+
+  SH_MUTEX_LOCK(mutex_hash);
+  p = sh_hash_have_it_int (newname);
+
+  if (!p) 
+    retval = (-1);
+  else if ((!SH_FFLAG_ALLIGNORE_SET(p->fflags)) && 
+	   (p->modi_mask & MODI_CHK) != 0 &&
+	   (p->modi_mask & MODI_MOD) != 0)
+    retval = 1;
+  SH_MUTEX_UNLOCK(mutex_hash);
+
+  return retval;
 }
 
 int sh_hash_get_it (char * newname, file_type * tmpFile)
 {
-  sh_file_t * p = sh_hash_have_it_int (newname);
-  if (!p)
-    return (-1);
-  sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
-  sl_strlcpy(tmpFile->linkpath, p->linkpath, PATH_MAX);
-  tmpFile->size  = p->theFile.size;
-  tmpFile->mtime = p->theFile.mtime;
-  tmpFile->ctime = p->theFile.ctime;
-
-  tmpFile->attr_string = NULL;
-  return 0;
+  sh_file_t * p;
+  int retval = -1;
+
+  if (IsInit != 1) 
+    sh_hash_init();
+
+  SH_MUTEX_LOCK(mutex_hash);
+  p = sh_hash_have_it_int (newname);
+  if (p)
+    {
+      sl_strlcpy(tmpFile->fullpath, p->fullpath, PATH_MAX);
+      sl_strlcpy(tmpFile->linkpath, p->linkpath, PATH_MAX);
+      tmpFile->size  = p->theFile.size;
+      tmpFile->mtime = p->theFile.mtime;
+      tmpFile->ctime = p->theFile.ctime;
+      tmpFile->attr_string = NULL;
+      retval = 0;
+    }
+  SH_MUTEX_UNLOCK(mutex_hash);
+
+  return retval;
 }
 
 int sh_hash_getflags (char * filename)
 {
-  sh_file_t * p = sh_hash_have_it_int (filename);
-  if (!p)
-    return (-1);
-  return (p->fflags);
+  sh_file_t * p;
+  int retval = -1;
+
+  if (IsInit != 1) 
+    sh_hash_init();
+
+  SH_MUTEX_LOCK(mutex_hash);
+  p = sh_hash_have_it_int (filename);
+  if (p)
+    retval = p->fflags;
+  SH_MUTEX_UNLOCK(mutex_hash);
+  return retval;
 }
 
 int sh_hash_setflags (char * filename, int flags)
 {
-  sh_file_t * p = sh_hash_have_it_int (filename);
-  if (!p)
-    return (-1);
-  p->fflags = flags;
-  return 0;
+  sh_file_t * p;
+  int retval = -1;
+
+  if (IsInit != 1) 
+    sh_hash_init();
+
+  SH_MUTEX_LOCK(mutex_hash);
+  p = sh_hash_have_it_int (filename);
+  if (p)
+    {
+      p->fflags = flags;
+      retval = 0;
+    }
+  SH_MUTEX_UNLOCK(mutex_hash);
+  return retval;
 }
 
@@ -1908,11 +1992,16 @@
 void sh_hash_addflag (char * filename, int flag_to_set)
 {
-  int fflags = sh_hash_getflags(filename);
-
-  if (fflags >= 0)
-    {
-      fflags |= flag_to_set;
-      sh_hash_setflags(filename, fflags);
-    }
+  sh_file_t * p;
+
+  if (IsInit != 1) 
+    sh_hash_init();
+
+  SH_MUTEX_LOCK(mutex_hash);
+  p = sh_hash_have_it_int (filename);
+  if (p)
+    {
+      p->fflags |= flag_to_set;
+    }
+  SH_MUTEX_UNLOCK(mutex_hash);
   return;
 }
@@ -1929,4 +2018,5 @@
   sh_file_t * p;
   char hashbuf[KEYBUF_SIZE];
+  int  retval = -1;
 
   SL_ENTER(_("sh_hash_set_visited_int"));
@@ -1934,6 +2024,9 @@
   if (newname == NULL)
     SL_RETURN((-1), _("sh_hash_set_visited_int"));
+
   if (IsInit != 1) 
     sh_hash_init();
+
+  SH_MUTEX_LOCK(mutex_hash);
 
   if (sl_strlen(newname) <= MAX_PATH_STORE) 
@@ -1943,23 +2036,26 @@
 				  hashbuf, sizeof(hashbuf)));
   
-  if (p == NULL) 
-    SL_RETURN((-1), _("sh_hash_set_visited_int"));
-
-  if (flag == SH_FFLAG_CHECKED)
-    {
-      CLEAR_SH_FFLAG_REPORTED(p->fflags);
-      CLEAR_SH_FFLAG_VISITED(p->fflags);
-      SET_SH_FFLAG_CHECKED(p->fflags);
-    }
-  else
-    {
-      SET_SH_FFLAG_VISITED(p->fflags);
-      CLEAR_SH_FFLAG_CHECKED(p->fflags);
-      if (flag == SH_FFLAG_REPORTED)
-	SET_SH_FFLAG_REPORTED(p->fflags);
+  if (p)
+    {
+      if (flag == SH_FFLAG_CHECKED)
+	{
+	  CLEAR_SH_FFLAG_REPORTED(p->fflags);
+	  CLEAR_SH_FFLAG_VISITED(p->fflags);
+	  SET_SH_FFLAG_CHECKED(p->fflags);
+	}
       else
-	CLEAR_SH_FFLAG_REPORTED(p->fflags);
-    }
-  SL_RETURN((0), _("sh_hash_set_visited_int"));
+	{
+	  SET_SH_FFLAG_VISITED(p->fflags);
+	  CLEAR_SH_FFLAG_CHECKED(p->fflags);
+	  if (flag == SH_FFLAG_REPORTED)
+	    SET_SH_FFLAG_REPORTED(p->fflags);
+	  else
+	    CLEAR_SH_FFLAG_REPORTED(p->fflags);
+	}
+      retval = 0;
+    }
+
+  SH_MUTEX_UNLOCK(mutex_hash);
+  SL_RETURN((retval), _("sh_hash_set_visited_int"));
 }
 
@@ -2590,6 +2686,8 @@
   if (p) 
     {
+      SH_MUTEX_LOCK(mutex_hash);
       hashinsert (p);
       p->modi_mask = theFile->check_mask;
+      SH_MUTEX_UNLOCK(mutex_hash);
     }
 
@@ -2633,4 +2731,6 @@
   char hashbuf[KEYBUF_SIZE];
 
+  int  retval = 0;
+
   SL_ENTER(_("sh_hash_compdata"));
 
@@ -2646,4 +2746,6 @@
 
   /* --------  find the entry for the file ----------------       */
+
+  SH_MUTEX_LOCK(mutex_hash);
 
   if (sl_strlen(theFile->fullpath) <= MAX_PATH_STORE) 
@@ -2675,10 +2777,4 @@
 	}
 
-      if (p)
-	{
-	  SET_SH_FFLAG_VISITED(p->fflags);
-	  CLEAR_SH_FFLAG_CHECKED(p->fflags);
-	}
-
       if (sh.flag.reportonce == S_TRUE)
 	SET_SH_FFLAG_REPORTED(theFile->file_reported);
@@ -2687,7 +2783,9 @@
 	{
 	  p = sh_hash_push_int(theFile, fileHash);
-	  hashinsert (p);
 	  if (p)
-	    p->modi_mask = theFile->check_mask;
+	    {
+	      hashinsert (p);
+	      p->modi_mask = theFile->check_mask;
+	    }
 	}
 
@@ -2697,20 +2795,21 @@
 	    {
 	      p = sh_hash_push_int(theFile, fileHash);
-	      hashinsert (p);
 	      if (p)
-		p->modi_mask = theFile->check_mask;
+		{
+		  hashinsert (p);
+		  p->modi_mask = theFile->check_mask;
+		}
 	    }
 	  else
 	    {
-	      SL_RETURN(1, _("sh_hash_compdata"));
+	      retval = 1;
+	      goto unlock_and_return;
 	    }
 	}
-	
-      SL_RETURN(0, _("sh_hash_compdata"));
-    }
-  else
-    {
-      p->modi_mask = theFile->check_mask;
-    }
+
+      goto unlock_and_return;
+    }
+
+  p->modi_mask = theFile->check_mask;
 
   /* initialize change_code */
@@ -3251,7 +3350,10 @@
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    {
-	      if (p->linkpath != NULL)
+	      if (p->linkpath != NULL && p->linkpath != notalink)
 		SH_FREE(p->linkpath);
-	      p->linkpath = sh_util_strdup(theFile->linkpath);
+	      if (theFile->linkpath[0] == '-' && theFile->linkpath[1] == '\0')
+		p->linkpath = (char *)notalink;
+	      else
+		p->linkpath = sh_util_strdup(theFile->linkpath);
 	    }
 #endif
@@ -3331,5 +3433,6 @@
 	      SET_SH_FFLAG_VISITED(p->fflags);
 	      CLEAR_SH_FFLAG_CHECKED(p->fflags);
-	      SL_RETURN(1, _("sh_hash_compdata"));
+	      retval = 1;
+	      goto unlock_and_return;
 	    }
 	  else /* if (sh.flag.reportonce == S_TRUE) */
@@ -3362,5 +3465,5 @@
 	      if (theFile->c_mode[0] == 'l')
 		{
-                  if (p->linkpath != NULL)
+                  if (p->linkpath != NULL && p->linkpath != notalink)
 		    SH_FREE(p->linkpath);
 		  p->linkpath = sh_util_strdup(theFile->linkpath);
@@ -3368,11 +3471,9 @@
 	      else
 		{
-	          if (p->linkpath != NULL) {
+	          if (p->linkpath != NULL && p->linkpath != notalink) {
 		    p->linkpath[0] = '-';
 		    p->linkpath[1] = '\0';
                   } else {
-		    p->linkpath = SH_ALLOC(2);
-		    p->linkpath[0] = '-';
-                    p->linkpath[1] = '\0';
+		    p->linkpath = (char *)notalink;
                   }
 		}
@@ -3402,5 +3503,8 @@
   CLEAR_SH_FFLAG_CHECKED(p->fflags);
 
-  SL_RETURN(0, _("sh_hash_compdata"));
+ unlock_and_return:
+
+  SH_MUTEX_UNLOCK(mutex_hash);
+  SL_RETURN(retval, _("sh_hash_compdata"));
 }
 
@@ -3415,4 +3519,5 @@
     SL_RETURN(0, _("sh_hash_compdata"));
 
+  SH_MUTEX_LOCK_UNSAFE(mutex_hash);
   for (i = 0; i < TABSIZE; ++i)
     {
@@ -3420,4 +3525,5 @@
 	CLEAR_SH_FFLAG_ALLIGNORE(p->fflags);
     }
+  SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
   SL_RETURN (0, _("sh_hash_compdata"));
 } 
@@ -3440,4 +3546,5 @@
     sh_hash_init();
 
+  SH_MUTEX_LOCK_UNSAFE(mutex_hash);
   for (i = 0; i < TABSIZE; ++i)
     {
@@ -3450,4 +3557,5 @@
 	}
     }
+  SH_MUTEX_UNLOCK_UNSAFE(mutex_hash);
   SL_RETURN ((0), _("hash_remove_tree"));
 } 
@@ -3469,24 +3577,18 @@
 int set_full_detail (const char * c)
 {
+  (void) c;
   ListFullDetail = S_TRUE;
-  /* warning: unused parameter `c' */
-  if (c)
-    return 0;
-  else
-    return 0;
+  return 0;
 }
  
 int set_list_delimited (const char * c)
 {
+  (void) c;
   ListFullDetail = S_TRUE;
   ListWithDelimiter = S_TRUE;
-  /* warning: unused parameter `c' */
-  if (c)
-    return 0;
-  else
-    return 0;
-}
-
-/* Always quote the string, except if it is empty. Qoute quotes by
+  return 0;
+}
+
+/* Always quote the string, except if it is empty. Quote quotes by
  * doubling them.
  */
Index: /trunk/src/sh_mem.c
===================================================================
--- /trunk/src/sh_mem.c	(revision 148)
+++ /trunk/src/sh_mem.c	(revision 149)
@@ -47,5 +47,4 @@
 #undef  FIL__
 #define FIL__  _("sh_mem.c")
-static int eblock = 0;
 
 #ifdef MEM_DEBUG
@@ -74,47 +73,13 @@
 unsigned long Mem_Current = 0, Mem_Max = 0;
 
-#if 0
-#define MEM_DETAILS 
-#endif
-
-#ifdef MEM_DETAILS
-int           max_upto_032 = 0;
-int           max_upto_064 = 0;
-int           max_upto_128 = 0;
-int           max_upto_256 = 0;
-int           max_upto_512 = 0;
-int           max_upto_1024 = 0;
-int           max_upto_4096 = 0;
-int           max_upto_inf = 0;
-
-int           now_upto_032 = 0;
-int           now_upto_064 = 0;
-int           now_upto_128 = 0;
-int           now_upto_256 = 0;
-int           now_upto_512 = 0;
-int           now_upto_1024 = 0;
-int           now_upto_4096 = 0;
-int           now_upto_inf = 0;
-
-int           tot_upto_032 = 0;
-int           tot_upto_064 = 0;
-int           tot_upto_128 = 0;
-int           tot_upto_256 = 0;
-int           tot_upto_512 = 0;
-int           tot_upto_1024 = 0;
-int           tot_upto_4096 = 0;
-int           tot_upto_inf = 0;
-#endif
-
 #ifdef HAVE_PTHREAD
 SH_MUTEX_RECURSIVE(mutex_mem);
 #endif
 
+/* define MEM_LOG to an absolute filename to enable this */
 #ifdef MEM_LOG
 void sh_mem_dump ()
 {
   memlist_t   * this = memlist;
-
-
   FILE * fd;
 
@@ -123,13 +88,20 @@
 
   fd = fopen(MEM_LOG, "w");
+  if (!fd)
+    {
+      perror(MEM_LOG);
+      _exit(EXIT_FAILURE);
+    }
 
   while (this != NULL)
     {
-      fprintf (fd, "%20s %5d %ld\n",  this->file, this->line, this->size);
+      fprintf (fd, "## %20s %5d %ld\n",  this->file, this->line, this->size);
+      fprintf (fd, "%10p %8ld\n", (void *)this->address, this->size);
       this = this->next;
     }
   fclose(fd);
-  SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
-  return;
+
+  SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
+  _exit(EXIT_SUCCESS);
 }
 #else
@@ -162,18 +134,4 @@
 		   Mem_Max, Mem_Current);
 
-#ifdef MEM_DETAILS
-  fprintf(stderr, "\n");
-  fprintf(stderr, "__SIZE_____TOTAL___MAXIMUM___\n");
-  fprintf(stderr, "    32    %6d    %6d\n", tot_upto_032, max_upto_032);
-  fprintf(stderr, "    64    %6d    %6d\n", tot_upto_064, max_upto_064);
-  fprintf(stderr, "   128    %6d    %6d\n", tot_upto_128, max_upto_128);
-  fprintf(stderr, "   256    %6d    %6d\n", tot_upto_256, max_upto_256);
-  fprintf(stderr, "   512    %6d    %6d\n", tot_upto_512, max_upto_512);
-  fprintf(stderr, "  1024    %6d    %6d\n", tot_upto_1024, max_upto_1024);
-  fprintf(stderr, "  4096    %6d    %6d\n", tot_upto_4096, max_upto_4096);
-  fprintf(stderr, "   inf    %6d    %6d\n", tot_upto_inf, max_upto_inf);
-  fprintf(stderr, "\n");
-#endif
-
   this = memlist;
 
@@ -199,4 +157,5 @@
   SH_MUTEX_RECURSIVE_INIT(mutex_mem);
   SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
+
   sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MSTAMP,
 		   Mem_Max, Mem_Current);
@@ -229,5 +188,4 @@
     }
 
-  /* if (nerr > 0) abort(); */
 
   SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
@@ -249,13 +207,9 @@
   if ( the_realAddress  == NULL ) 
     {
-      if (eblock == 0)
-	{
-	  eblock = 1;
-	  (void) safe_logger (0, 0, NULL);
-	  eblock = 0;
-	}
+      (void) safe_logger (0, 0, NULL);
+
       /* use _exit() rather than exit() - we malloc() in atexit() functions 
        */
-      _exit (42);
+      _exit (EXIT_FAILURE);
     }
   
@@ -274,60 +228,4 @@
     Max_Alloc_Count = Now_Alloc_Count;
 
-#ifdef MEM_DETAILS
-  if (size <= 32)
-    { 
-      ++now_upto_032;
-      ++tot_upto_032;
-      if (now_upto_032 > max_upto_032) max_upto_032 = now_upto_032;
-    }
-  else if  (size <= 64)
-    { 
-      ++now_upto_064;
-      ++tot_upto_064;
-      if (now_upto_064 > max_upto_064) max_upto_064 = now_upto_064;
-    }
-  else if  (size <= 128)
-    { 
-      ++now_upto_128;
-      ++tot_upto_128;
-      if (now_upto_128 > max_upto_128) max_upto_128 = now_upto_128;
-    }
-  else if  (size <= 256)
-    { 
-      ++now_upto_256;
-      ++tot_upto_256;
-      if (now_upto_256 > max_upto_256) max_upto_256 = now_upto_256;
-    }
-  else if  (size <= 512)
-    { 
-      ++now_upto_512;
-      ++tot_upto_512;
-      if (now_upto_512 > max_upto_512) max_upto_512 = now_upto_512;
-    }
-  else if  (size <= 1024)
-    { 
-      ++now_upto_1024;
-      ++tot_upto_1024;
-      if (now_upto_1024 > max_upto_1024) max_upto_1024 = now_upto_1024;
-    }
-  else if  (size <= 4096)
-    { 
-      ++now_upto_4096;
-      ++tot_upto_4096;
-      if (now_upto_4096 > max_upto_4096) max_upto_4096 = now_upto_4096;
-    }
-  else 
-    { 
-      ++now_upto_inf;
-      ++tot_upto_inf;
-      if (now_upto_inf > max_upto_inf) max_upto_inf = now_upto_inf;
-
-      fprintf(stderr, "\n___BIGSIZE___");
-      fprintf(stderr, "   %6d  -> %16s  %10d \n", size, file, line);
-      fprintf(stderr, "\n");
-
-    }
-#endif
-
   Mem_Current += size;
   Mem_Max = ( (Mem_Current > Mem_Max) ? Mem_Current : Mem_Max);
@@ -337,11 +235,7 @@
   if ( this == NULL) 
     {
-      if (eblock == 0)
-	{
-	  eblock = 1;
-	  (void) safe_logger(0, 0, NULL);
-	  eblock = 0;
-	}
-      _exit(42);
+      (void) safe_logger(0, 0, NULL);
+
+      _exit(EXIT_FAILURE);
     }
   else
@@ -374,4 +268,5 @@
   SH_MUTEX_RECURSIVE_INIT(mutex_mem);
   SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
+
   if ( a == NULL ) 
     {
@@ -424,23 +319,4 @@
   --Now_Alloc_Count;
 
-#ifdef MEM_DETAILS
-  if (size <= 32)
-    --now_upto_032;
-  else if  (size <= 64)
-    --now_upto_064;
-  else if  (size <= 128)
-    --now_upto_128;
-  else if  (size <= 256)
-    --now_upto_256;
-  else if  (size <= 512)
-    --now_upto_512;
-  else if  (size <= 1024)
-    --now_upto_1024;
-  else if  (size <= 4096)
-    --now_upto_4096;
-  else 
-    --now_upto_inf;
-#endif
-
   Mem_Current -= size;
  out:
@@ -475,19 +351,16 @@
   theAddress = malloc(size);
 
-  if ( theAddress == NULL ) 
-    {
-      if (eblock == 0)
-	{
-	  eblock = 1;
-	  (void) safe_logger(0, 0, NULL);
-	  eblock = 0;
-	}
+  if ( theAddress != NULL ) 
+    {
+      SL_RETURN( theAddress, _("sh_mem_malloc"));
+    }
+  else
+    {
+      (void) safe_logger(0, 0, NULL);
+
       /* use _exit() rather than exit() - we malloc() in atexit()  
        */
-      _exit (42);
-    }
-  /* memset (theAddress, 0, 1); *//* needs testing */
-
-  SL_RETURN( theAddress, _("sh_mem_malloc"));
-}
-#endif
+      _exit (EXIT_FAILURE);
+    }
+}
+#endif
Index: /trunk/src/sh_modules.c
===================================================================
--- /trunk/src/sh_modules.c	(revision 148)
+++ /trunk/src/sh_modules.c	(revision 149)
@@ -26,5 +26,5 @@
     sh_utmp_check,
     sh_utmp_end,
-    sh_utmp_null,
+    sh_utmp_reconf,
 
     N_("[Utmp]"),
@@ -90,5 +90,5 @@
     sh_suidchk_check,
     sh_suidchk_end,
-    sh_suidchk_free_schedule,
+    sh_suidchk_reconf,
 
     N_("[SuidCheck]"),
Index: /trunk/src/sh_mounts.c
===================================================================
--- /trunk/src/sh_mounts.c	(revision 148)
+++ /trunk/src/sh_mounts.c	(revision 149)
@@ -263,6 +263,6 @@
 
 /* Module reconfiguration
- * Run on receipt of a HUP. Right now this is identical to _end(), but it may
- * not always be. */
+ * Run on receipt of a HUP.
+ */
 int sh_mounts_reconf()
 {
@@ -270,4 +270,12 @@
   sh_mounts_mnt_free(mountlist);
   mountlist = NULL;
+
+  /* re-set defaults
+   */
+  ShMountsActive    = S_FALSE;
+  ShMountsInterval  = 86400;
+  ShMountsSevMnt    = 7;
+  ShMountsSevOpt    = 7;
+
   SL_RETURN( (0), _("sh_mounts_null"));
 }
Index: /trunk/src/sh_portcheck.c
===================================================================
--- /trunk/src/sh_portcheck.c	(revision 148)
+++ /trunk/src/sh_portcheck.c	(revision 149)
@@ -80,4 +80,5 @@
 #define SH_PORT_OPT 2
 #define SH_PORT_IGN 3
+#define SH_PORT_BLACKLIST 4
 
 #define SH_PORT_MISS 0
@@ -87,4 +88,8 @@
 #define SH_PORT_NOREPT 0
 #define SH_PORT_REPORT 1
+
+#define SH_PROTO_TCP 0
+#define SH_PROTO_UDP 1
+#define SH_PROTO_STR(a) (((a) == IPPROTO_TCP) ? _("tcp") : _("udp"))
 
 struct sh_portentry {
@@ -101,4 +106,13 @@
 static struct sh_portentry * portlist_udp = NULL;
 
+struct sh_port {
+  int              port;
+  struct in_addr   haddr;
+  struct sh_port * next;
+};
+
+static struct sh_port * blacklist_tcp = NULL;
+static struct sh_port * blacklist_udp = NULL;
+
 #define SH_PORTCHK_INTERVAL 300
 
@@ -117,4 +131,6 @@
 #include "sh_pthread.h"
 
+SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
+
 static int sh_portchk_severity  = SH_ERR_SEVERE;
 #endif
@@ -132,8 +148,15 @@
 static int sh_portchk_add_optional (const char * str);
 
+/* Exported interface to add blacklisted ports as 'iface:portlist'
+ */
+static int sh_portchk_add_blacklist (const char * str);
+
 /* Exported interface to add an ethernet interface
  */
 static int sh_portchk_add_interface (const char * str);
 
+/* verify whether port/interface is blacklisted (do not check)
+ */
+static int sh_portchk_is_blacklisted(int port, struct in_addr haddr, int proto);
 
 #ifndef TEST_ONLY
@@ -148,6 +171,8 @@
   if (val <= 0)
     {
+      SH_MUTEX_LOCK(mutex_thread_nolog);
       sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
 		       _("port check interval"), c);
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
       retval = -1;
     }
@@ -196,4 +221,8 @@
     },
     {
+        N_("portcheckskip"),
+        sh_portchk_add_blacklist,
+    },
+    {
         N_("portcheckactive"),
         sh_portchk_set_active,
@@ -232,5 +261,5 @@
 
 
-static char * check_services (int port, char * proto);
+static char * check_services (int port, int proto);
 
 #ifdef TEST_ONLY
@@ -249,5 +278,5 @@
 #endif
 
-static void sh_portchk_add_to_list (char * proto, 
+static void sh_portchk_add_to_list (int proto, 
 				    int port, struct in_addr haddr, char * service,
 				    int flag, int status)
@@ -257,5 +286,5 @@
   if (portchk_debug)
     fprintf(stderr, _("add to list: port %d/%s %d %d (%s)\n"),
-	    port, proto, flag, status, service ? service : _("undef"));
+	    port, SH_PROTO_STR(proto), flag, status, service ? service : _("undef"));
 
   new->port = port;
@@ -270,5 +299,5 @@
   else
     new->service = NULL;
-  if (0 == strcmp(proto, "tcp"))
+  if (proto == IPPROTO_TCP)
     {
       new->next = portlist_tcp;
@@ -322,7 +351,19 @@
 }
   
+static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head)
+{
+  if (head)
+    {
+      if (head->next)
+	sh_portchk_kill_blacklist (head->next);
+
+      SH_FREE(head);
+    }
+  return NULL;
+}
+  
 /* check the list of open ports for any that are marked as UNKN
  */
-static void sh_portchk_check_list (struct sh_portentry ** head, char * proto, int report)
+static void sh_portchk_check_list (struct sh_portentry ** head, int proto, int report)
 {
   struct sh_portentry * ptr = *head;
@@ -334,5 +375,5 @@
       if (portchk_debug && report)
 	fprintf(stderr, _("check list: port %d/%s %d %d\n"),
-		ptr->port, proto, ptr->flag, ptr->status);
+		ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
 
       if (ptr->status == SH_PORT_UNKN)
@@ -343,5 +384,5 @@
 	    {
 	      snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceMissing] port %s:%d/%s (%s)"), 
-			ptr->interface, ptr->port, proto, 
+			ptr->interface, ptr->port, SH_PROTO_STR(proto), 
 			ptr->service ? ptr->service : check_services(ptr->port, proto));
 #ifdef TEST_ONLY
@@ -350,6 +391,10 @@
 #else
 	      if (report == SH_PORT_REPORT)
-		sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-				MSG_PORT_REPORT, errbuf);
+		{
+		  SH_MUTEX_LOCK(mutex_thread_nolog);
+		  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
+				  MSG_PORT_REPORT, errbuf);
+		  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+		}
 #endif
 	    }
@@ -361,5 +406,5 @@
 	      if (portchk_debug && report)
 		fprintf(stderr, _("removing: port %d/%s %d %d\n"),
-			ptr->port, proto, ptr->flag, ptr->status);
+			ptr->port, SH_PROTO_STR(proto), ptr->flag, ptr->status);
 	      
 	      if (ptr == *head)
@@ -399,5 +444,5 @@
 
 
-static struct sh_portentry * sh_portchk_get_from_list (char * proto, int port, 
+static struct sh_portentry * sh_portchk_get_from_list (int proto, int port, 
 						       struct in_addr haddr, char * service)
 {
@@ -407,5 +452,5 @@
   sl_strlcpy (iface_all, _("0.0.0.0"), sizeof(iface_all));
   
-  if (0 == strcmp(proto, "tcp"))
+  if (proto == IPPROTO_TCP)
     portlist = portlist_tcp;
   else
@@ -439,5 +484,5 @@
       
 
-static void sh_portchk_cmp_to_list (char * proto, int port, struct in_addr haddr, char * service)
+static void sh_portchk_cmp_to_list (int proto, int port, struct in_addr haddr, char * service)
 {
   struct sh_portentry * portent;
@@ -452,11 +497,13 @@
 	{
 	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceNew] port %s:%d/%s (%s)"), 
-		    inet_ntoa(haddr), port, proto, service);
+		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), service);
 #ifdef TEST_ONLY
 	  fprintf(stderr, _("open port: %s:%d/%s (%s)\n"), 
-		  inet_ntoa(haddr), port, proto, service);
-#else
+		  inet_ntoa(haddr), port, SH_PROTO_STR(proto), service);
+#else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
 			  MSG_PORT_REPORT, errbuf);
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 	  /* 
@@ -468,10 +515,12 @@
 	{
 	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceRestarted] port %s:%d/%s to %d/%s (%s)"), 
-		    inet_ntoa(haddr), portent->port, proto, port, proto, service);
+		    inet_ntoa(haddr), portent->port, SH_PROTO_STR(proto), port, SH_PROTO_STR(proto), service);
 #ifdef TEST_ONLY
 	  fprintf(stderr, _("service: %s\n"), errbuf);
 #else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
 			  MSG_PORT_REPORT, errbuf);
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 
@@ -481,10 +530,12 @@
 	{
 	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServicePortSwitch] port %s:%d/%s to %d/%s (%s)"), 
-		    inet_ntoa(haddr), portent->port, proto, port, proto, service);
+		    inet_ntoa(haddr), portent->port, SH_PROTO_STR(proto), port, SH_PROTO_STR(proto), service);
 #ifdef TEST_ONLY
 	  fprintf(stderr, _("service: %s\n"), errbuf);
 #else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
 			  MSG_PORT_REPORT, errbuf);
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 	  portent->port   = port;
@@ -501,11 +552,13 @@
 	{
 	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceNew] port %s:%d/%s (%s)"), 
-		    inet_ntoa(haddr), port, proto, check_services(port, proto));
+		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
 #ifdef TEST_ONLY
 	  fprintf(stderr, _("open port: %s:%d/%s (%s)\n"), 
-		  inet_ntoa(haddr), port, proto, check_services(port, proto));
-#else
+		  inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
+#else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
 			  MSG_PORT_REPORT, errbuf);
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 
@@ -517,10 +570,12 @@
 	{
 	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceRestarted] port %s:%d/%s (%s)"), 
-		    inet_ntoa(haddr), port, proto, check_services(port, proto));
+		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
 #ifdef TEST_ONLY
 	  fprintf(stderr, _("port   : %s\n"), errbuf);
 #else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
 			  MSG_PORT_REPORT, errbuf);
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 
@@ -541,8 +596,8 @@
  * Returns NULL on failure
  */
-static char * check_services (int port, char * proto)
+static char * check_services (int port, int proto)
 {
   static char buf[256];
-  struct servent * service = getservbyport(htons(port), proto);
+  struct servent * service = getservbyport(htons(port), SH_PROTO_STR(proto));
 
   if (service && service->s_name && service->s_name[0] != '\0')
@@ -630,6 +685,8 @@
       sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/udp on %15s: %s"),
 		  port, inet_ntoa(haddr), sh_error_message(errno, errbuf, sizeof(errbuf)));
+      SH_MUTEX_LOCK(mutex_thread_nolog);
       sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
 		      errmsg, _("connect"));
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
     }
@@ -666,10 +723,10 @@
 	      p = check_rpc_list (port, &sinr, IPPROTO_UDP);
 	      
-	      sh_portchk_cmp_to_list ("udp", port, haddr, p ? p : NULL);
+	      sh_portchk_cmp_to_list (IPPROTO_UDP, port, haddr, p ? p : NULL);
 	      
 	      /* If not an RPC service, try to get name from /etc/services
 	       */
 	      if (!p)
-		p = check_services(port, "udp");
+		p = check_services(port, IPPROTO_UDP);
 	      
 	      if (portchk_debug)
@@ -722,6 +779,8 @@
       sl_snprintf(errmsg, sizeof(errmsg), _("check port: %5d/tcp on %15s: %s"),
 		  port, inet_ntoa(haddr), sh_error_message(errno, errbuf, sizeof(errbuf)));
+      SH_MUTEX_LOCK(mutex_thread_nolog);
       sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, 
 		      errmsg, _("connect"));
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
     }
@@ -732,10 +791,10 @@
       p = check_rpc_list (port, &sinr, IPPROTO_TCP);
 
-      sh_portchk_cmp_to_list ("tcp", port, haddr, p ? p : NULL);
+      sh_portchk_cmp_to_list (IPPROTO_TCP, port, haddr, p ? p : NULL);
 
       /* If not an RPC service, try to get name from /etc/services
        */
       if (!p)
-	p = check_services(port, "tcp");
+	p = check_services(port, IPPROTO_TCP);
 
       if (portchk_debug)
@@ -815,10 +874,9 @@
 #endif
 
-int sh_portchk_init (struct mod_type * arg)
+static int sh_portchk_init_internal (void)
 {
   struct hostent * hent;
   int              i = 0;
   char errbuf[256];
-  (void) arg;
 
   if (portchk_debug)
@@ -831,4 +889,5 @@
     return -1;
 
+  SH_MUTEX_LOCK(mutex_port_check);
   if (iface_initialized == 0)
     {
@@ -852,21 +911,51 @@
       sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), 
 		  inet_ntoa(iface_list.iface[i]));
+      SH_MUTEX_LOCK(mutex_thread_nolog);
       sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
 		      errbuf, _("sh_portchk_init"));
-    }
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
+    }
+  SH_MUTEX_UNLOCK(mutex_port_check);
 
   return 0;
 }
+
+int sh_portchk_init (struct mod_type * arg)
+{
+  if (sh_portchk_active == S_FALSE)
+    return SH_MOD_FAILED;
+  if (!portchk_hostname)
+    return SH_MOD_FAILED;
+
+#ifdef HAVE_PTHREAD
+  if (arg != NULL && arg->initval < 0 &&
+      (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
+    {
+      if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
+	return SH_MOD_THREAD;
+      else
+	return SH_MOD_FAILED;
+    }
+#endif
+  return sh_portchk_init_internal();
+}
+
+
 
 #if !defined(TEST_ONLY)
 int sh_portchk_reconf ()
 {
+  SH_MUTEX_LOCK(mutex_port_check);
   iface_initialized    = 0;
-
   sh_portchk_active    = 1;
   sh_portchk_check_udp = 1;
+  sh_portchk_interval  = SH_PORTCHK_INTERVAL;
 
   portlist_udp = sh_portchk_kill_list (portlist_udp);
   portlist_tcp = sh_portchk_kill_list (portlist_tcp);
+
+  blacklist_udp = sh_portchk_kill_blacklist (blacklist_udp);
+  blacklist_tcp = sh_portchk_kill_blacklist (blacklist_tcp);
+  SH_MUTEX_UNLOCK(mutex_port_check);
   return 0;
 }
@@ -903,4 +992,11 @@
   while (i < iface_list.used)
     {
+      haddr.s_addr = iface_list.iface[i].s_addr;
+
+      if (0 != sh_portchk_is_blacklisted(port, haddr, protocol))
+	{
+	  ++i; continue;
+	}
+
       if ((sock = socket(AF_INET, type, protocol)) < 0 )
 	{
@@ -909,6 +1005,10 @@
 	    perror(_("socket"));
 #else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
 			  sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	  ++i;
+	  continue;
 #endif
 	}
@@ -920,10 +1020,13 @@
 	    perror(_("setsockopt"));
 #else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
 			  sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
-#endif
-	}
-
-      memcpy (&(haddr.s_addr), &(iface_list.iface[i].s_addr), sizeof(in_addr_t));
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+#endif
+	  ++i;
+	  continue;
+	}
+
 
       if (protocol == IPPROTO_TCP)
@@ -982,7 +1085,10 @@
 	    perror(_("socket"));
 #else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
 			  sh_error_message(errno, errbuf, sizeof(errbuf)), _("socket"));
-#endif
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+#endif
+	  continue;
 	}
       if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
@@ -993,7 +1099,10 @@
 	    perror(_("setsockopt"));
 #else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
 			  sh_error_message(errno, errbuf, sizeof(errbuf)),_("setsockopt"));
-#endif
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
+#endif
+	  continue;
 	}
 
@@ -1027,6 +1136,8 @@
 		perror(_("bind"));
 #else
+	      SH_MUTEX_LOCK(mutex_thread_nolog);
 	      sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN, 
 			      sh_error_message(errno, errbuf, sizeof(errbuf)), _("bind"));
+	      SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 	    }
@@ -1067,6 +1178,8 @@
 
   sl_snprintf(errbuf, sizeof(errbuf), _("interface: %s"), inet_ntoa(haddr));
+  SH_MUTEX_LOCK(mutex_thread_nolog);
   sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
 		  errbuf, _("sh_portchk_add_interface"));
+  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 
   memcpy (&(iface_list.iface[iface_list.used].s_addr), &(haddr.s_addr), sizeof(in_addr_t));
@@ -1076,4 +1189,60 @@
 }
 
+/* verify whether port/interface is blacklisted (do not check)
+ */
+static int sh_portchk_is_blacklisted(int port, struct in_addr haddr, int proto)
+{
+  struct sh_port * head;
+
+  if (proto == IPPROTO_TCP)
+    head = blacklist_tcp;
+  else
+    head = blacklist_udp;
+
+  while (head)
+    {
+      if (head->port == port)
+	{
+	  if ((head->haddr.s_addr == 0) || (head->haddr.s_addr == haddr.s_addr))
+	    return 1;
+	  else
+	    return 0;
+	}
+      head = head->next;
+    }
+  return 0;
+}
+
+
+static int sh_portchk_blacklist(int port, struct in_addr haddr, int proto)
+{
+  struct sh_port * black;
+  struct sh_port * head;
+
+  if (proto == IPPROTO_TCP)
+    head = blacklist_tcp;
+  else
+    head = blacklist_udp;
+
+  black = head;
+
+  while (black)
+    {
+      if (black->port == port && head->haddr.s_addr == haddr.s_addr)
+	return -1;
+      black = black->next;
+    }
+  black = SH_ALLOC (sizeof(struct sh_port));
+  black->port  = port;
+  black->haddr.s_addr = haddr.s_addr;
+  black->next  = head;
+
+  if (proto == IPPROTO_TCP)
+    blacklist_tcp = black;
+  else
+    blacklist_udp = black;
+  return 0;
+}
+  
  
 /* Subroutine to add a required or optional port/service
@@ -1082,5 +1251,5 @@
 {
   char buf[256];
-  char proto[4];
+  int proto;
   char * p;
   char * endptr;
@@ -1098,7 +1267,7 @@
     return -1;
   if (0 == strcmp(p, _("/tcp")))
-    sl_strlcpy(proto, _("tcp"), sizeof(proto));
-  else if  (0 == strcmp(p, _("/udp")))   
-    sl_strlcpy(proto, _("udp"), sizeof(proto));
+    proto = IPPROTO_TCP;
+  else if  (0 == strcmp(p, _("/udp")))
+    proto = IPPROTO_UDP;
   else
     return -1;
@@ -1106,4 +1275,9 @@
   *p = '\0';
   port = strtoul(buf, &endptr, 0);
+
+  /* Blacklisted ports
+   */
+  if (*endptr == '\0' && port <= 65535 && type == SH_PORT_BLACKLIST)
+    return (sh_portchk_blacklist(port, haddr, proto));
 
   if (*endptr != '\0')
@@ -1115,8 +1289,10 @@
 	{
 #ifdef TEST_ONLY
-	  fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, proto);
-#else
+	  fprintf(stderr, "** WARNING: duplicate port definition %s/%s\n", buf, SH_PROTO_STR(proto));
+#else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
 			  _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 	  return -1;
@@ -1131,8 +1307,10 @@
 	{
 #ifdef TEST_ONLY
-	  fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, proto);
-#else
+	  fprintf(stderr, "** WARNING: duplicate port definition %lu/%s\n", port, SH_PROTO_STR(proto));
+#else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
 			  _("duplicate port definition"), _("sh_portchk_add_required_port_generic"));
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 	  return -1;
@@ -1151,4 +1329,5 @@
   size_t len;
   size_t ll = 0;
+  int    status;
 
   char * interface = NULL;
@@ -1213,5 +1392,7 @@
   while (p)
     {
-      if (-1 == sh_portchk_add_required_port_generic (p, interface, type))
+      status = sh_portchk_add_required_port_generic (p, interface, type);
+
+      if (-1 == status)
 	{
 	  SH_FREE(interface);
@@ -1251,4 +1432,11 @@
 }
 
+/* User interface to add ports that should not be checked as 'iface:portlist'
+ */
+static int sh_portchk_add_blacklist (const char * str)
+{
+  return sh_portchk_add_required_generic (str, SH_PORT_BLACKLIST); 
+}
+
 /* Interface to run port check
  */
@@ -1257,4 +1445,5 @@
   int min_port = 0;
 
+  SH_MUTEX_LOCK(mutex_port_check);
   if (sh_portchk_active != S_FALSE)
     {
@@ -1266,6 +1455,8 @@
 	  fprintf(stderr, "** WARNING not scanning ports < 1024\n");
 #else
+	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
 			  _("not scanning ports below 1024"), _("sh_portchk_check"));
+	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
 	}
@@ -1273,8 +1464,9 @@
 	sh_portchk_scan_ports_udp(min_port, -1);
       sh_portchk_scan_ports_tcp(min_port, -1);
-      sh_portchk_check_list (&portlist_tcp, "tcp", SH_PORT_REPORT);
+      sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_REPORT);
       if (sh_portchk_check_udp == 1)
-	sh_portchk_check_list (&portlist_udp, "udp", SH_PORT_REPORT);
-    }
+	sh_portchk_check_list (&portlist_udp, IPPROTO_UDP, SH_PORT_REPORT);
+    }
+  SH_MUTEX_UNLOCK(mutex_port_check);
   return 0;
 }
@@ -1292,7 +1484,7 @@
   CuAssertTrue(tc, 0 != inet_aton("127.0.0.1", &haddr_local));
 
-  sh_portchk_add_to_list ("tcp",  8000, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
-
-  portent = sh_portchk_get_from_list("tcp",  8000, haddr_local, NULL);
+  sh_portchk_add_to_list (IPPROTO_TCP,  8000, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
+
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, haddr_local, NULL);
   CuAssertPtrNotNull(tc, portent);
 
@@ -1302,55 +1494,74 @@
   CuAssertTrue(tc, portent->flag == SH_PORT_NOT);
 
-  sh_portchk_check_list (&portlist_tcp, "tcp", SH_PORT_NOREPT);
+  sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
 
   CuAssertTrue(tc, NULL == portlist_tcp);
 
-  sh_portchk_add_to_list ("tcp",  8000, haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",  8001, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",  8002, haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",  8003, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",  8004, haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",    -1, haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",    -1, haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",    -1, haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",    -1, haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN);
-  sh_portchk_add_to_list ("tcp",    -1, haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN);
-
-  sh_portchk_check_list (&portlist_tcp, "tcp", SH_PORT_NOREPT);
+  sh_portchk_add_to_list (IPPROTO_TCP,  8000, haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,  8001, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,  8002, haddr_local, NULL, SH_PORT_REQ, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,  8003, haddr_local, NULL, SH_PORT_NOT, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,  8004, haddr_local, NULL, SH_PORT_IGN, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,    -1, haddr_local, "foo1", SH_PORT_NOT, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,    -1, haddr_local, "foo2", SH_PORT_REQ, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,    -1, haddr_local, "foo3", SH_PORT_NOT, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,    -1, haddr_local, "foo4", SH_PORT_REQ, SH_PORT_UNKN);
+  sh_portchk_add_to_list (IPPROTO_TCP,    -1, haddr_local, "foo5", SH_PORT_IGN, SH_PORT_UNKN);
+
+  sh_portchk_check_list (&portlist_tcp, IPPROTO_TCP, SH_PORT_NOREPT);
 
   CuAssertPtrNotNull(tc, portlist_tcp);
 
-  portent = sh_portchk_get_from_list("tcp",  8000, haddr_local, NULL);
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, haddr_local, NULL);
   CuAssertPtrNotNull(tc, portent);
 
-  portent = sh_portchk_get_from_list("tcp",  8001, haddr_local, NULL);
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8001, haddr_local, NULL);
   CuAssertTrue(tc, NULL == portent);
 
-  portent = sh_portchk_get_from_list("tcp",  8002, haddr_local, NULL);
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8002, haddr_local, NULL);
   CuAssertPtrNotNull(tc, portent);
 
-  portent = sh_portchk_get_from_list("tcp",  8003, haddr_local, NULL);
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8003, haddr_local, NULL);
   CuAssertTrue(tc, NULL == portent);
 
-  portent = sh_portchk_get_from_list("tcp",  8004, haddr_local, NULL);
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8004, haddr_local, NULL);
   CuAssertPtrNotNull(tc, portent);
 
-  portent = sh_portchk_get_from_list("tcp",  8000, haddr_local, "foo1");
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, haddr_local, "foo1");
   CuAssertTrue(tc, NULL == portent);
 
-  portent = sh_portchk_get_from_list("tcp",  8000, haddr_local, "foo2");
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, haddr_local, "foo2");
   CuAssertPtrNotNull(tc, portent);
   CuAssertTrue(tc, 0 == strcmp(portent->service, "foo2"));
 
-  portent = sh_portchk_get_from_list("tcp",  8000, haddr_local, "foo3");
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, haddr_local, "foo3");
   CuAssertTrue(tc, NULL == portent);
 
-  portent = sh_portchk_get_from_list("tcp",  8000, haddr_local, "foo4");
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, haddr_local, "foo4");
   CuAssertPtrNotNull(tc, portent);
   CuAssertTrue(tc, 0 == strcmp(portent->service, "foo4"));
 
-  portent = sh_portchk_get_from_list("tcp",  8000, haddr_local, "foo5");
+  portent = sh_portchk_get_from_list(IPPROTO_TCP,  8000, haddr_local, "foo5");
   CuAssertPtrNotNull(tc, portent);
   CuAssertTrue(tc, 0 == strcmp(portent->service, "foo5"));
+
+  CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, haddr_local, IPPROTO_TCP));
+  CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, haddr_local, IPPROTO_TCP));
+  CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, haddr_local, IPPROTO_TCP));
+  CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, haddr_local, IPPROTO_TCP));
+  CuAssertTrue(tc, 0 == sh_portchk_blacklist(666, haddr_local, IPPROTO_UDP));
+  CuAssertTrue(tc, 0 != sh_portchk_blacklist(666, haddr_local, IPPROTO_UDP));
+  CuAssertTrue(tc, 0 == sh_portchk_blacklist(667, haddr_local, IPPROTO_UDP));
+  CuAssertTrue(tc, 0 == sh_portchk_blacklist(668, haddr_local, IPPROTO_UDP));
+
+  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, haddr_local, IPPROTO_UDP));
+  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, haddr_local, IPPROTO_UDP));
+  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, haddr_local, IPPROTO_UDP));
+  CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, haddr_local, IPPROTO_UDP));
+
+  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(668, haddr_local, IPPROTO_TCP));
+  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(667, haddr_local, IPPROTO_TCP));
+  CuAssertTrue(tc, 0 != sh_portchk_is_blacklisted(666, haddr_local, IPPROTO_TCP));
+  CuAssertTrue(tc, 0 == sh_portchk_is_blacklisted(665, haddr_local, IPPROTO_TCP));
 #else
   (void) tc; /* fix compiler warning */
Index: /trunk/src/sh_suidchk.c
===================================================================
--- /trunk/src/sh_suidchk.c	(revision 148)
+++ /trunk/src/sh_suidchk.c	(revision 149)
@@ -164,4 +164,28 @@
 
 extern unsigned long sh_files_maskof (int class);
+
+static void set_defaults (void)
+{
+  ShSuidchkActive   = S_TRUE;
+  ShSuidchkInterval = 7200;
+  ShSuidchkFps      = 0;
+  ShSuidchkNosuid   = S_FALSE;
+  ShSuidchkYield    = S_FALSE;
+  ShSuidchkQEnable  = S_FALSE;
+  ShSuidchkQMethod  = SH_Q_CHANGEPERM;
+  ShSuidchkQDelete  = S_FALSE;
+  ShSuidchkSeverity = SH_ERR_SEVERE;
+  if (ShSuidchkExclude != NULL)
+    SH_FREE(ShSuidchkExclude);
+  ShSuidchkExclude  = NULL;
+  ExcludeLen        = 0;
+
+  FileLimNow        = 0;
+  FileLimStart      = 0;
+  FileLimNum        = 0;
+  FileLimTotal      = 0;
+
+  return;
+}
 
 /* Recursively descend into the directory to make sure that
@@ -1320,5 +1344,5 @@
 
 
-int sh_suidchk_free_schedule ()
+static void sh_suidchk_free_schedule ()
 {
   sh_schedule_t * current = ShSuidchkSched;
@@ -1332,5 +1356,11 @@
     }
   ShSuidchkSched = NULL;
-  return 0;
+  return;
+}
+
+int sh_suidchk_reconf ()
+{
+  sh_suidchk_free_schedule();
+  set_defaults();
 }
 
Index: /trunk/src/sh_unix.c
===================================================================
--- /trunk/src/sh_unix.c	(revision 148)
+++ /trunk/src/sh_unix.c	(revision 149)
@@ -2881,5 +2881,5 @@
 int sh_unix_get_ftype(char * fullpath)
 {
-  char        c_mode[16];
+  char        c_mode[CMODE_SIZE];
   struct stat buf;
   ShFileType  type;
@@ -3449,9 +3449,9 @@
   /* --- Determine file type. ---
    */
-  memset (theFile->c_mode, '-', 10);
-  theFile->c_mode[10] = '\0';
-
-  memset (theFile->link_c_mode, '-', 10);
-  theFile->link_c_mode[10] = '\0';
+  memset (theFile->c_mode, '-', CMODE_SIZE-1);
+  theFile->c_mode[CMODE_SIZE-1] = '\0';
+
+  memset (theFile->link_c_mode, '-', CMODE_SIZE-1);
+  theFile->link_c_mode[CMODE_SIZE-1] = '\0';
 
   sh_unix_getinfo_type (&buf, &type, theFile->c_mode);
@@ -3462,6 +3462,6 @@
   /* --- Determine file attributes. ---
    */
-  memset (theFile->c_attributes, '-', 12);
-  theFile->c_attributes[12] = '\0';
+  memset (theFile->c_attributes, '-', ATTRBUF_SIZE);
+  theFile->c_attributes[ATTRBUF_USED] = '\0';
   theFile->attributes      =    0;
 
Index: /trunk/src/sh_userfiles.c
===================================================================
--- /trunk/src/sh_userfiles.c	(revision 148)
+++ /trunk/src/sh_userfiles.c	(revision 149)
@@ -390,4 +390,6 @@
     userFiles = NULL;
 
+    ShUserfilesActive   = S_TRUE;
+
     SL_RETURN(0, _("sh_userfiles_reconf"));
 }
Index: /trunk/src/sh_utils.c
===================================================================
--- /trunk/src/sh_utils.c	(revision 148)
+++ /trunk/src/sh_utils.c	(revision 149)
@@ -2020,7 +2020,7 @@
 }
 
-int sh_util_isnum (char *str)
-{
-  char *p = str;
+int sh_util_isnum (const char *str)
+{
+  const char *p = str;
 
   SL_ENTER(_("sh_util_isnum"));
@@ -2036,5 +2036,5 @@
 }
 
-char * sh_util_strconcat (const char * arg1, ...) 
+char * sh_util_strconcat (const char * arg1, ...)
 {
   size_t    length, l2;
Index: /trunk/src/sh_utmp.c
===================================================================
--- /trunk/src/sh_utmp.c	(revision 148)
+++ /trunk/src/sh_utmp.c	(revision 149)
@@ -227,10 +227,13 @@
 };
 
-int sh_utmp_null()
-{
-  return 0;
-}
-
-
+static void set_defaults(void)
+{
+  ShUtmpLoginSolo    = SH_ERR_INFO;
+  ShUtmpLoginMulti   = SH_ERR_WARN;
+  ShUtmpLogout       = SH_ERR_INFO;
+  ShUtmpActive       = S_TRUE;
+  ShUtmpInterval     = 300;
+  return;
+}
 
 
@@ -535,7 +538,13 @@
    * can be re-enabled.
    */
-  ShUtmpActive       = S_TRUE;
+  set_defaults();
   init_done          = 0;
   SL_RETURN( (0), _("sh_utmp_end"));
+}
+
+int sh_utmp_reconf()
+{
+  set_defaults();
+  return 0;
 }
 
Index: /trunk/test/testrun_1e.sh
===================================================================
--- /trunk/test/testrun_1e.sh	(revision 148)
+++ /trunk/test/testrun_1e.sh	(revision 149)
@@ -23,5 +23,36 @@
 export BUILDOPTS
 
-MAXTEST=3; export MAXTEST
+MAXTEST=4; export MAXTEST
+
+PORTPOLICY_4="
+[ReadOnly]
+file=${BASE}
+[PortCheck]
+PortCheckActive = yes
+PortCheckUDP = no
+"
+
+chk_portdata_4 () {
+    one_sec_sleep
+
+    egrep 'CRIT.*POLICY \[ServiceNew\]' $LOGFILE >/dev/null 2>&1
+    if [ $? -eq 0 ]; then
+	
+	[ -z "$verbose" ] || log_msg_fail "Open ports";
+	return 1
+    fi
+}
+
+refine_portpolicy_4 ()
+{
+    cat "$LOGFILE" | grep ServiceNew | sed 's/.*port //' | awk '{ print $1 }' | \
+    while read line; do
+	echo "PortCheckSkip=$line" >>"${RCFILE}"
+    done
+    echo "PortCheckIgnore=2026/tcp" >>"${RCFILE}"
+    echo "PortCheckIgnore=2027/udp" >>"${RCFILE}"
+    echo "PortCheckIgnore=2028/tcp" >>"${RCFILE}"
+    echo "PortCheckIgnore=2029/udp" >>"${RCFILE}"
+}
 
 PORTPOLICY_3="
@@ -50,8 +81,8 @@
 	echo "PortCheckIgnore=$line" >>"${RCFILE}"
     done
-    echo "PortCheckIgnore=2026" >>"${RCFILE}"
-    echo "PortCheckIgnore=2027" >>"${RCFILE}"
-    echo "PortCheckIgnore=2028" >>"${RCFILE}"
-    echo "PortCheckIgnore=2029" >>"${RCFILE}"
+    echo "PortCheckIgnore=2026/tcp" >>"${RCFILE}"
+    echo "PortCheckIgnore=2027/udp" >>"${RCFILE}"
+    echo "PortCheckIgnore=2028/tcp" >>"${RCFILE}"
+    echo "PortCheckIgnore=2029/udp" >>"${RCFILE}"
 }
 
