Index: trunk/src/cutest_slib.c
===================================================================
--- trunk/src/cutest_slib.c	(revision 167)
+++ trunk/src/cutest_slib.c	(revision 169)
@@ -24,3 +24,57 @@
 }
 
+void Test_sl_strcasecmp (CuTest *tc) {
+  char one[64], two[64];
+  int  res;
 
+  strcpy(one, "foo");
+  strcpy(two, "foo");
+  res = sl_strcasecmp(one, two);
+  CuAssertIntEquals(tc, 0, res);
+
+  strcpy(one, "fo");
+  strcpy(two, "foo");
+  res = sl_strcasecmp(one, two);
+  CuAssertIntEquals(tc, -1, res);
+
+  strcpy(one, "foo");
+  strcpy(two, "fo");
+  res = sl_strcasecmp(one, two);
+  CuAssertIntEquals(tc, 1, res);
+
+  strcpy(one, "1234");
+  strcpy(two, "2345");
+  res = sl_strcasecmp(one, two);
+  CuAssertIntEquals(tc, -1, res);
+
+  strcpy(one, "234");
+  strcpy(two, "123");
+  res = sl_strcasecmp(one, two);
+  CuAssertIntEquals(tc, 1, res);
+
+  strcpy(one, "");
+  strcpy(two, "123");
+  res = sl_strcasecmp(one, two);
+  CuAssertIntEquals(tc, -1, res);
+
+  strcpy(one, "234");
+  strcpy(two, "");
+  res = sl_strcasecmp(one, two);
+  CuAssertIntEquals(tc, 1, res);
+
+  strcpy(one, "");
+  strcpy(two, "");
+  res = sl_strcasecmp(one, two);
+  CuAssertTrue(tc, res == 0);
+
+#ifndef SL_FAIL_ON_ERROR
+  res = sl_strcasecmp(NULL, two);
+  CuAssertIntEquals(tc, -1, res);
+
+  res = sl_strcasecmp(one, NULL);
+  CuAssertIntEquals(tc, 1, res);
+
+  res = sl_strcasecmp(NULL, NULL);
+  CuAssertTrue(tc, res != 0);
+#endif
+}
Index: trunk/src/samhain.c
===================================================================
--- trunk/src/samhain.c	(revision 167)
+++ trunk/src/samhain.c	(revision 169)
@@ -775,5 +775,6 @@
    */
   (void) sh_unix_rm_lock_file (sh.srvlog.name);
-  (void) sh_unix_rm_pid_file ();
+  if (sh.flag.isdaemon == S_TRUE)
+    (void) sh_unix_rm_pid_file ();
   if (skey != NULL)
     memset (skey, (int) '\0', sizeof(sh_key_t));
Index: trunk/src/sh_calls.c
===================================================================
--- trunk/src/sh_calls.c	(revision 167)
+++ trunk/src/sh_calls.c	(revision 169)
@@ -341,5 +341,5 @@
 #endif
 
-  SL_ENTER(_("retry_fcntl"));
+  SL_ENTER(_("retry_msleep"));
 
   errno  = 0;
Index: trunk/src/sh_cat.c
===================================================================
--- trunk/src/sh_cat.c	(revision 167)
+++ trunk/src/sh_cat.c	(revision 169)
@@ -134,5 +134,8 @@
 
 #ifdef SH_USE_PORTCHECK
-  { MSG_PORT_REPORT, SH_ERR_SEVERE,  EVENT, N_("msg=\"%s\"")},
+  { MSG_PORT_MISS,   SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServiceMissing] %s\"")},
+  { MSG_PORT_NEW,    SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServiceNew] %s\"")},
+  { MSG_PORT_RESTART,SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServiceRestarted] %s\"")},
+  { MSG_PORT_NEWPORT,SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [ServicePortSwitch] %s\"")},
 #endif
 
@@ -449,5 +452,8 @@
 
 #ifdef SH_USE_PORTCHECK
-  { MSG_PORT_REPORT, SH_ERR_SEVERE,  EVENT, N_("msg=<%s>")},
+  { MSG_PORT_MISS,   SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServiceMissing] %s>")},
+  { MSG_PORT_NEW,    SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServiceNew] %s>")},
+  { MSG_PORT_RESTART,SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServiceRestarted] %s>")},
+  { MSG_PORT_NEWPORT,SH_ERR_SEVERE,  EVENT, N_("msg=<POLICY [ServicePortSwitch] %s>")},
 #endif
 
Index: trunk/src/sh_extern.c
===================================================================
--- trunk/src/sh_extern.c	(revision 167)
+++ trunk/src/sh_extern.c	(revision 169)
@@ -143,8 +143,11 @@
    * --  check whether path is trustworthy
    */
+  status = sl_trustfile(task->command, NULL, NULL);
+#if 0
   if ((uid_t) -1 != task->trusted_users[0])
     {
       status = sl_trustfile(task->command, task->trusted_users, NULL);
     }
+#endif
 
   PDBG_OPEN;
@@ -647,5 +650,7 @@
       tas->argv[i]          = NULL;
       tas->envv[i]          = NULL;
+#if 0
       tas->trusted_users[i] = (uid_t) -1;
+#endif
     }
 
@@ -826,6 +831,8 @@
 
   (void) sl_get_euid(&ff_euid);
+#if 0
   ext_com->tas.trusted_users[0] = (uid_t) 0;
   ext_com->tas.trusted_users[1] = (uid_t) (ff_euid);
+#endif
 
   /* ------------------------------------------------- */
Index: trunk/src/sh_getopt.c
===================================================================
--- trunk/src/sh_getopt.c	(revision 167)
+++ trunk/src/sh_getopt.c	(revision 169)
@@ -225,4 +225,9 @@
     HAS_ARG_NO, 
     sh_getopt_forever},
+  { N_("list-file"),  
+    '-', 
+    N_("Modify -d to list content of a single file"),  
+    HAS_ARG_YES, 
+    set_list_file},
   { N_("full-detail"),  
     'a', 
@@ -417,5 +422,5 @@
 #if defined(SL_DEBUG)
   if (num > 0) fputc ('\n', stdout);
-  fputs (_(" debug build"), stdout); ++num;
+  fputs (_(" debug build (don't use for production)"), stdout); ++num;
 #endif
 #if defined(SCREW_IT_UP)
@@ -433,4 +438,8 @@
 
 #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
+#if defined(HAVE_LIBZ)
+  if (num > 0) fputc ('\n', stdout);
+  fputs (_(" optionally store full text for files"), stdout); ++num;
+#endif
 #if defined(USE_XATTR)
   if (num > 0) fputc ('\n', stdout);
Index: trunk/src/sh_hash.c
===================================================================
--- trunk/src/sh_hash.c	(revision 167)
+++ trunk/src/sh_hash.c	(revision 169)
@@ -2497,5 +2497,6 @@
   sl_strlcat(msg, tmp, SH_BUFSIZE); 
 
-  if (theFile->c_mode[0] == 'l' || theFile->link_path != NULL)
+  if (theFile->c_mode[0] == 'l' || 
+      (theFile->link_path != NULL && theFile->link_path[0] != '-'))
     {
       tmp_lnk     = sh_util_safe_name(theFile->link_path);
@@ -2663,5 +2664,6 @@
   sl_strlcat(msg, tmp, SH_BUFSIZE); 
 
-  if (theFile->c_mode[0] == 'l' || theFile->link_path != NULL)
+  if (theFile->c_mode[0] == 'l' || 
+      (theFile->link_path != NULL && theFile->link_path[0] != '-'))
     {
       tmp_lnk     = sh_util_safe_name(theFile->link_path);
@@ -2739,4 +2741,5 @@
   char timstr2m[32];
   char linkHash[KEY_LEN+1];
+  char * linkComp;
   int  maxcomp;
 
@@ -2869,28 +2872,39 @@
   if (p->theFile.c_mode[0] == 'l') 
     {
-      if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE) 
-	{
-	  sl_strlcpy(linkHash, 
-		     sh_tiger_hash(theFile->link_path, 
-				   TIGER_DATA,
-				   sl_strlen(theFile->link_path),
-				   hashbuf, sizeof(hashbuf)), 
-		     MAX_PATH_STORE+1);
-	  maxcomp = MAX_PATH_STORE;
-	} 
-      else 
-	{
-	  sl_strlcpy(linkHash, theFile->link_path, KEY_LEN + 1);
-	  maxcomp = KEY_LEN;
-	}
-      
-
-      if ( sl_strncmp (linkHash, p->linkpath, maxcomp) != 0 &&
-	   (theFile->check_mask & MODI_LNK) != 0)
-	{
+      if (!(theFile->link_path) &&
+	  (theFile->check_mask & MODI_LNK) != 0)
+	{
+	  linkComp = NULL;
 	  modi_mask |= MODI_LNK;
 	  change_code[1] = 'L';
 	  TPT ((0, FIL__, __LINE__, _("mod=<link>")));
-	} 
+	}
+      else
+	{
+	  if (sl_strlen(theFile->link_path) >= MAX_PATH_STORE) 
+	    {
+	      sl_strlcpy(linkHash, 
+			 sh_tiger_hash(theFile->link_path, 
+				       TIGER_DATA,
+				       sl_strlen(theFile->link_path),
+				       hashbuf, sizeof(hashbuf)), 
+			 MAX_PATH_STORE+1);
+	      linkComp = linkHash;
+	      maxcomp  = KEY_LEN;
+	    } 
+	  else 
+	    {
+	      linkComp = theFile->link_path;
+	      maxcomp  = MAX_PATH_STORE;
+	    }
+	  
+	  if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
+	       (theFile->check_mask & MODI_LNK) != 0)
+	    {
+	      modi_mask |= MODI_LNK;
+	      change_code[1] = 'L';
+	      TPT ((0, FIL__, __LINE__, _("mod=<link>")));
+	    } 
+	}
     }
 
@@ -3349,11 +3363,21 @@
 	    }
 #endif
-	}
-
-
-      if ((modi_mask & MODI_LNK) != 0 && theFile->c_mode[0] == 'l')
-	{
-	  tmp_lnk     = sh_util_safe_name(theFile->link_path);
-	  tmp_lnk_old = sh_util_safe_name(p->linkpath);
+	  /* FIXME is this correct? */
+	  if (theFile->c_mode[0] != 'l' && theFile->link_path &&
+	      strlen(theFile->link_path) > 2)
+	    modi_mask |= MODI_LNK;
+	}
+
+
+      if ((modi_mask & MODI_LNK) != 0 /* && theFile->c_mode[0] == 'l' */)
+	{
+	  if (theFile->link_path)
+	    tmp_lnk     = sh_util_safe_name(theFile->link_path);
+	  else
+	    tmp_lnk     = sh_util_strdup("-");
+	  if (p->linkpath)
+	    tmp_lnk_old = sh_util_safe_name(p->linkpath);
+	  else
+	    tmp_lnk_old = sh_util_strdup("-");
 #ifdef SH_USE_XML
 	  sl_snprintf(tmp, SH_BUFSIZE, _("link_old=\"%s\" link_new=\"%s\" "),
@@ -3599,6 +3623,13 @@
 #endif
 
-static int ListFullDetail = S_FALSE;
+static int ListFullDetail    = S_FALSE;
 static int ListWithDelimiter = S_FALSE;
+static char * ListFile       = NULL;
+
+int set_list_file (const char * c)
+{
+  ListFile = sh_util_strdup(c);
+  return 0;
+}
 
 int set_full_detail (const char * c)
@@ -3858,4 +3889,46 @@
 }
 
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif    
+
+int sh_hash_printcontent(char * linkpath)
+{
+#ifdef HAVE_LIBZ
+  unsigned char * decoded;
+  unsigned char * decompressed = NULL;
+  size_t dlen;
+  unsigned long clen;
+  unsigned long clen_o;
+  int    res;
+
+  if (linkpath && *linkpath != '-')
+    {
+      dlen = sh_util_base64_dec_alloc (&decoded, 
+				       (unsigned char *)linkpath, 
+				       strlen(linkpath));
+      clen = dlen * 2 + 1;
+      do {
+	if (decompressed)
+	  SH_FREE(decompressed);
+	clen += dlen; clen_o = clen;
+	decompressed = SH_ALLOC(clen);
+	res = uncompress(decompressed, &clen, decoded, dlen);
+	if (res == Z_MEM_ERROR)
+	  { fprintf(stderr, _("Error: Not enough memory\n")); return -1; }
+	if (res == Z_DATA_ERROR)
+	  { fprintf(stderr, _("Error: Data corrupt or incomplete\n")); return -1; }
+      } while (res == Z_BUF_ERROR || clen == clen_o);
+      decompressed[clen] = '\0';
+      fputs( (char*) decompressed, stdout);
+      return 0;
+    }
+#else
+  (void) linkpath;
+#endif
+  fprintf(stderr, _("Error: No data available\n")); 
+  return -1;
+}
+
 int sh_hash_list_db (const char * db_file)
 {
@@ -3863,4 +3936,5 @@
   SL_TICKET fd;
   char * line;
+  int  flag = 0;
 
   if (!db_file)
@@ -3900,10 +3974,37 @@
     {
       p = sh_hash_getdataent (fd, line, MAX_PATH_STORE);
-      if ((p != NULL) && (p->fullpath[0] != 'K'))
-	{
-	  if (ListFullDetail == S_FALSE)
-	    sh_hash_list_db_entry (p); 
+      if ((p != NULL) && (p->fullpath[0] == '/'))
+	{
+	  if (!ListFile)
+	    {
+	      flag = 1;
+	      if (ListFullDetail == S_FALSE)
+		sh_hash_list_db_entry (p); 
+	      else
+		sh_hash_list_db_entry_full_detail (p);
+	    }
 	  else
-	    sh_hash_list_db_entry_full_detail (p); 
+	    {
+	      if (0 != sl_strcmp(ListFile, p->fullpath))
+		{
+		  continue;
+		}
+	      flag = 1;
+	      if ('l' != p->theFile.c_mode[0])
+		{
+		  if (sh_hash_printcontent(p->linkpath) < 0)
+		    {
+		      _exit(EXIT_FAILURE);
+		      return -1;
+		    }
+		}
+	      else
+		{
+		  fprintf(stderr, _("File is a link\n"));
+		  _exit(EXIT_FAILURE);
+		  return -1;
+		}
+	      break;
+	    }
 	}
       else if (p == NULL)
@@ -3919,4 +4020,9 @@
   fflush(NULL);
 
+  if (flag == 0)
+    {
+      fprintf(stderr, _("No file found\n"));
+      _exit(EXIT_FAILURE);
+    }
   _exit(EXIT_SUCCESS);
   return 0; 
Index: trunk/src/sh_mounts.c
===================================================================
--- trunk/src/sh_mounts.c	(revision 167)
+++ trunk/src/sh_mounts.c	(revision 169)
@@ -180,6 +180,4 @@
   }
 
-  lastcheck = time(NULL);
-
   SL_RETURN(0, _("sh_mounts_init"));
 }
@@ -197,5 +195,5 @@
     SL_RETURN(-1, _("sh_mounts_timer"));
   }
-  
+ 
   SL_RETURN(0, _("sh_mounts_timer"));
 }
@@ -400,5 +398,5 @@
 
 /* FreeBSD includes */
-#ifdef HOST_IS_FREEBSD
+#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD) 
 #include <sys/param.h>
 #include <sys/ucred.h>
@@ -577,5 +575,5 @@
 #endif
 
-#if defined(HOST_IS_FREEBSD)
+#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD)
 
 /* FreeBSD returns flags instead of strings as mount options, so we'll convert
@@ -595,4 +593,7 @@
 		{"local",	MNT_LOCAL},
 		{"quota",	MNT_QUOTA},
+#ifdef MNT_NOATIME
+		{"noatime",	MNT_NOATIME},
+#endif
 		{"bound",	-1}
 	};
@@ -665,6 +666,6 @@
 	list = m;
 
-/* The FreeBSD way */
-#ifdef HOST_IS_FREEBSD
+/* The Open/FreeBSD way */
+#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD)
 {
 	struct statfs *fsp;
Index: trunk/src/sh_portcheck.c
===================================================================
--- trunk/src/sh_portcheck.c	(revision 167)
+++ trunk/src/sh_portcheck.c	(revision 169)
@@ -384,5 +384,5 @@
 	  if (ptr->flag != SH_PORT_OPT && ptr->flag != SH_PORT_IGN)
 	    {
-	      snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceMissing] port %s:%d/%s (%s)"), 
+	      snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
 			ptr->interface, ptr->port, SH_PROTO_STR(proto), 
 			ptr->service ? ptr->service : check_services(ptr->port, proto));
@@ -395,5 +395,5 @@
 		  SH_MUTEX_LOCK(mutex_thread_nolog);
 		  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-				  MSG_PORT_REPORT, errbuf);
+				  MSG_PORT_MISS, errbuf);
 		  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 		}
@@ -497,5 +497,5 @@
       if (!portent)
 	{
-	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceNew] port %s:%d/%s (%s)"), 
+	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
 		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), service);
 #ifdef TEST_ONLY
@@ -505,5 +505,5 @@
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_REPORT, errbuf);
+			  MSG_PORT_NEW, errbuf);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
@@ -515,6 +515,6 @@
       else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
 	{
-	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceRestarted] port %s:%d/%s to %d/%s (%s)"), 
-		    inet_ntoa(haddr), portent->port, SH_PROTO_STR(proto), port, SH_PROTO_STR(proto), service);
+	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
+		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
 #ifdef TEST_ONLY
 	  fprintf(stderr, _("service: %s\n"), errbuf);
@@ -522,5 +522,5 @@
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_REPORT, errbuf);
+			  MSG_PORT_RESTART, errbuf);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
@@ -530,6 +530,6 @@
       else if (port != portent->port && (-1) != portent->port)
 	{
-	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServicePortSwitch] port %s:%d/%s to %d/%s (%s)"), 
-		    inet_ntoa(haddr), portent->port, SH_PROTO_STR(proto), port, SH_PROTO_STR(proto), service);
+	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s), was %d/%s"), 
+		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), service, portent->port, SH_PROTO_STR(proto));
 #ifdef TEST_ONLY
 	  fprintf(stderr, _("service: %s\n"), errbuf);
@@ -537,5 +537,5 @@
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_REPORT, errbuf);
+			  MSG_PORT_NEWPORT, errbuf);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
@@ -552,5 +552,5 @@
       if (!portent)
 	{
-	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceNew] port %s:%d/%s (%s)"), 
+	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
 		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
 #ifdef TEST_ONLY
@@ -560,5 +560,5 @@
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_REPORT, errbuf);
+			  MSG_PORT_NEW, errbuf);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
@@ -570,5 +570,5 @@
       else if (portent->status == SH_PORT_MISS && portent->flag != SH_PORT_IGN)
 	{
-	  snprintf (errbuf, sizeof(errbuf), _("POLICY [ServiceRestarted] port %s:%d/%s (%s)"), 
+	  snprintf (errbuf, sizeof(errbuf), _("port: %s:%d/%s (%s)"), 
 		    inet_ntoa(haddr), port, SH_PROTO_STR(proto), check_services(port, proto));
 #ifdef TEST_ONLY
@@ -577,5 +577,5 @@
 	  SH_MUTEX_LOCK(mutex_thread_nolog);
 	  sh_error_handle(sh_portchk_severity, FIL__, __LINE__, 0, 
-			  MSG_PORT_REPORT, errbuf);
+			  MSG_PORT_RESTART, errbuf);
 	  SH_MUTEX_UNLOCK(mutex_thread_nolog);
 #endif
Index: trunk/src/sh_prelude.c
===================================================================
--- trunk/src/sh_prelude.c	(revision 167)
+++ trunk/src/sh_prelude.c	(revision 169)
@@ -85,5 +85,5 @@
 #define SH_NEED_PWD_GRP 1
 #include "sh_static.h"
-
+char * sh_util_strdup (const char * str) SH_GNUC_MALLOC;
 /*
  * When SH_USE_XML is set, value are formated using name="value".
@@ -651,4 +651,11 @@
 #endif
 
+#ifdef SH_USE_PORTCHECK
+		{ MSG_PORT_MISS, N_("Service closed"), IDMEF_IMPACT_TYPE_OTHER },
+		{ MSG_PORT_NEW, N_("Service opened"), IDMEF_IMPACT_TYPE_OTHER },
+		{ MSG_PORT_RESTART, N_("Service restarted"), IDMEF_IMPACT_TYPE_OTHER },
+		{ MSG_PORT_NEWPORT, N_("Service restarted"), IDMEF_IMPACT_TYPE_OTHER },
+#endif
+
 #ifdef SH_USE_SUIDCHK
                 { MSG_SUID_POLICY, N_("SUID/SGID File Detected"), IDMEF_IMPACT_TYPE_FILE },
@@ -684,4 +691,158 @@
 
 
+#ifdef SH_USE_PORTCHECK
+static int get_service_info(char *msg, idmef_alert_t *alert)
+{
+        int ret;
+	long port;
+	char *ptr, *new, *tmp, *ip, *srv, *end;
+        prelude_string_t *str;
+        idmef_address_t *address;
+        idmef_node_t *node;
+        idmef_service_t *service;
+        idmef_source_t *source = idmef_alert_get_next_source(alert, NULL);
+
+        new = sh_util_strdup(msg);
+ 
+        ptr = strstr(new, _("port: "));
+        if ( ! ptr ) {
+                sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+                                _("malformed Samhain port check message"), _("get_service_info"));
+		SH_FREE( new );
+                return -1;
+        }
+
+        ptr += 6; /* skip 'port: ', position on first byte of interface */
+        tmp = strchr(ptr, ':');
+        if ( ! tmp ) {
+                sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+                                _("malformed Samhain port check message (no port)"), _("get_service_info"));
+		SH_FREE( new );
+                return -1;
+        }
+	*tmp = '\0';
+
+	ip = strdup(ptr);
+        if ( ip ) {
+                if ( ! source ) {
+                        ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
+                        if ( ret < 0 ) {
+                                free(ip);
+				SH_FREE( new );
+                                return ret;
+                        }
+                }
+
+                ret = idmef_source_new_node(source, &node);
+                if ( ret < 0 ) {
+                        free(ip);
+			SH_FREE( new );
+                        return ret;
+                }
+                
+                ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
+                if ( ret < 0 ) {
+                        free(ip);
+			SH_FREE( new );
+                        return ret;
+                }
+                
+                ret = idmef_address_new_address(address, &str);
+                if ( ret < 0 ) {
+                        free(ip);
+			SH_FREE( new );
+                        return ret;
+                }
+                
+                prelude_string_set_nodup(str, ip);
+        }
+
+	ptr = tmp;
+	++ptr;
+        tmp = strchr(ptr, '/');
+        if ( ! tmp ) {
+                sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+                                _("malformed Samhain port check message (no protocol)"), _("get_service_info"));
+		SH_FREE( new );
+                return -1;
+        }
+	*tmp = '\0';
+
+	port = strtol(ptr, &end, 0);
+        if ( *ptr && *end == '\0' && port >= 0 && port < 65536) {
+
+                if ( ! source ) {
+                        ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
+                        if ( ret < 0 ) {
+                                free(srv);
+				SH_FREE( new );
+                                return ret;
+                        }
+                }
+
+                ret = idmef_source_new_service(source, &service);
+                if ( ret < 0 ) {
+                        free(srv);
+			SH_FREE( new );
+                        return ret;
+                }
+
+		idmef_service_set_port(service, port);
+	}
+
+	ptr = tmp;
+	++ptr;
+        ptr = strchr(ptr, '(');
+        if ( ! ptr ) {
+                sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+                                _("malformed Samhain port check message (no service)"), _("get_service_info"));
+		SH_FREE( new );
+                return -1;
+        }
+	++ptr;
+        tmp = strchr(ptr, ')');
+        if ( ! tmp ) {
+                sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+                                _("malformed Samhain port check message (service not closed)"), _("get_service_info"));
+		SH_FREE( new );
+                return -1;
+        }
+	*tmp = '\0';
+
+	srv = strdup(ptr);
+        if ( srv ) {
+                if ( ! source ) {
+                        ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
+                        if ( ret < 0 ) {
+                                free(srv);
+				SH_FREE( new );
+                                return ret;
+                        }
+                }
+
+		if ( ! service ) {
+                        ret = idmef_source_new_service(source, &service);
+			if ( ret < 0 ) {
+                                free(srv);
+				SH_FREE( new );
+				return ret;
+			}
+                }
+
+                ret = idmef_service_new_ident(service, &str);
+                if ( ret < 0 ) {
+                        free(srv);
+			SH_FREE( new );
+                        return ret;
+                }
+                
+                prelude_string_set_nodup(str, srv);
+        }
+
+	SH_FREE( new );
+
+	return 0;
+}
+#endif
 
 static int get_login_info(char *msg, idmef_alert_t *alert)
@@ -902,4 +1063,12 @@
                 goto err;
         
+#ifdef SH_USE_PORTCHECK
+	if (msgid == MSG_PORT_MISS || msgid == MSG_PORT_NEW || msgid == MSG_PORT_RESTART || msgid == MSG_PORT_NEWPORT) {
+	        ret = get_service_info(message, alert);
+		if ( ret < 0 )
+		        goto err;
+        }
+#endif
+   
         map_policy_to_class(message, msgid, impact, str);
 
Index: trunk/src/sh_processcheck.c
===================================================================
--- trunk/src/sh_processcheck.c	(revision 167)
+++ trunk/src/sh_processcheck.c	(revision 169)
@@ -837,6 +837,14 @@
 	  else if (errno == EAGAIN)
 	    {
+	      clearerr(in);
 	      continue;
 	    }
+#ifdef HOST_IS_OPENBSD
+	  else if (errno == ENODEV)
+	    {
+	      clearerr(in);
+	      continue;
+	    }
+#endif
 	  else
 	    {
@@ -1049,4 +1057,5 @@
   size_t i, j;
   char  tests[512];
+  int   retval;
 
   pid_t this_pid;
@@ -1060,5 +1069,5 @@
       SH_MUTEX_LOCK(mutex_thread_nolog);
       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      _("Internal error: NULL argument"), 
+		      _("Internal error: NULL argument, switching off"), 
 		      _("sh_process_check_int"));
       SH_MUTEX_UNLOCK(mutex_thread_nolog);
@@ -1067,5 +1076,5 @@
 
   SH_MUTEX_LOCK(mutex_thread_nolog);
-  sh_processes_runps (res, NULL, 0, SH_PR_PS, 0);
+  retval = sh_processes_runps (res, NULL, 0, SH_PR_PS, 0);
   SH_MUTEX_UNLOCK(mutex_thread_nolog);
   for (i = sh_prochk_minpid; i != sh_prochk_maxpid; ++i)
@@ -1075,6 +1084,16 @@
     }
   SH_MUTEX_LOCK(mutex_thread_nolog);
-  sh_processes_runps (res, NULL, 0, SH_PR_PS2, 0);
+  retval += sh_processes_runps (res, NULL, 0, SH_PR_PS2, 0);
   SH_MUTEX_UNLOCK(mutex_thread_nolog);
+
+  if (retval != 0)
+    {
+      SH_MUTEX_LOCK(mutex_thread_nolog);
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Failed to run ps, switching off"), 
+		      _("sh_process_check_int"));
+      SH_MUTEX_UNLOCK(mutex_thread_nolog);
+      SL_RETURN ((-1), _("sh_process_check_int"));
+    }
 
   /* Evaluate results
Index: trunk/src/sh_readconf.c
===================================================================
--- trunk/src/sh_readconf.c	(revision 167)
+++ trunk/src/sh_readconf.c	(revision 169)
@@ -573,5 +573,4 @@
    */
   sl_rewind (fd);
-  sh_error_only_stderr (S_FALSE);
   if (0 != sh_gpg_check_sign (fd, 0, 1))
     aud_exit (FIL__, __LINE__, EXIT_FAILURE);
Index: trunk/src/sh_string.c
===================================================================
--- trunk/src/sh_string.c	(revision 169)
+++ trunk/src/sh_string.c	(revision 169)
@@ -0,0 +1,825 @@
+
+#include "config_xor.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#include "sh_string.h"
+#include "sh_mem.h"
+
+#undef  FIL__
+#define FIL__  _("sh_string.c")
+
+extern int sl_ok_adds (size_t a, size_t b);
+#define SL_TRUE  1
+#define SL_FALSE 0
+
+#include <ctype.h>
+/* Split array at delim in at most nfields fields. 
+ * Empty fields are returned as empty (zero-length) strings. 
+ * Leading and trailing WS are removed from token. 
+ * The number of fields is returned in 'nfields', their
+ * lengths in 'lengths'.
+ * A single delimiter will return two empty fields.
+ */
+char ** split_array(char *line, unsigned int * nfields, 
+                    char delim, size_t * lengths)
+{
+  char *a, *e, *s;
+  unsigned int i = 0;
+  int flag = 0;
+  char **arr;
+  unsigned int maxfields = (*nfields);
+
+  arr = SH_ALLOC((maxfields+1) * sizeof (char*));
+
+  e = line;
+
+  do
+    {
+      /* skip leading WS 
+       */
+      for (s=e; *s && isspace(*s); ++s) /* nothing */;
+
+      if (*s) 
+        {
+          a = s;
+
+          /* move a to next delim
+           */
+          for (a=s; *a && *a != delim; ++a) /* nothing */;
+          
+          /* set e to next after delim
+           */
+          if (*a == delim)
+            {
+              e    = a+1;
+              flag = 1;
+            }
+          else /* (!*a) */
+            {
+              e    = a;
+              flag = 0;
+            }
+
+          if (a != line)
+            {
+              /* chop off trailing WS 
+               */
+              for (a--; isspace(*a) && a > s; a--) /* do nothing */;
+              
+              /* terminate string
+               */
+              ++a; *a = '\0';
+            }
+          else
+            {
+              *a = '\0';
+            }
+        }
+      else /* (!*s) */
+        {
+          a = s;
+	  /* (i == 0) handles the special case of splitting the empty string */
+          if (flag || i == 0) 
+            {
+              flag = 0;
+              goto setnext;
+            }
+          break;
+        }
+
+    setnext:
+      lengths[i] = (a-s);
+      arr[i] = s;
+      ++i;
+
+    } while (i < maxfields);
+
+  *nfields = i;
+  arr[i]   = NULL;
+
+  return arr;
+}
+
+/* Split array at whitespace in at most nfields fields.
+ * Multiple whitespaces are collapsed. 
+ * Empty fields are returned as empty (zero-length) strings.
+ * The number of fields is returned in nfields.
+ * An empty string will return zero fields.
+ * If nfields < actual fields, last string will be remainder.
+ */
+char ** split_array_ws(char *line, unsigned int * nfields, size_t * lengths)
+{
+  char *a, *e, *s;
+  unsigned int i = 0;
+  char **arr;
+  unsigned int maxfields = (*nfields);
+
+  arr = SH_ALLOC((maxfields+1) * sizeof (char*));
+
+  e = line;
+
+  do
+    {
+      s = e;
+
+      /* skip leading WS 
+       */
+      if ( *s && isspace(*s) )
+        {
+          do {
+            ++s;
+          } while ( *s && isspace(*s) );
+        }
+
+      if (*s)
+        {
+
+          /* s is at non-ws, move a to next ws
+           */
+          a = s;
+          do {
+            a++;
+          } while ( *a && (!isspace(*a)) );
+
+          /* next token, *a is either ws or '\0' 
+           */
+          e = ( (*a) ? a+1 : a);
+          
+          /* terminate and set arr[i]
+           */
+          if (i < (maxfields-1))
+	    {
+              *a = '\0'; 
+	    }
+	  else
+	    {
+	      /* If nfields < actual fields, last 
+	       * string will be remainder. Therefore
+	       * skip to end.
+	       */
+	      if ( *a )
+		{
+		  do {
+		    a++;
+		  } while ( *a );
+		}
+	    }
+          lengths[i] = (a-s);
+          arr[i]     = s; 
+          ++i;
+        }
+      else /* if (!*s) */
+        {
+          break;
+        }
+
+    } while (i < maxfields);
+
+  *nfields = i;
+  arr[i]   = NULL;
+
+  return arr;
+}
+
+
+#define SH_STRING_PARCEL 120
+
+size_t sh_string_read(sh_string * s, FILE * fp, size_t maxlen)
+{
+
+  /* case 1) EOF or error 
+   */
+  if (fgets(s->str, s->siz, fp) == NULL)
+    {
+      sh_string_truncate(s, 0);
+      if (ferror(fp))
+        return -1;
+      return 0;
+    }
+
+  /* case 2) end of line reached. strlen should always be > 0
+   *         because of the '\n', but we check.
+   */
+  s->len = strlen(s->str);
+  if (s->len > 0 && (s->str)[s->len-1] == '\n') 
+    {
+      (s->str)[s->len-1] = '\0';
+      --(s->len);
+      return (s->len + 1);
+    }
+      
+  /* case 3) incomplete string
+   */
+  for (;;) {
+    
+    if (maxlen > 0 && (s->siz+SH_STRING_PARCEL) > maxlen)
+      {
+        if (s->siz < maxlen)
+          sh_string_grow(s, (maxlen-s->siz));
+        else
+          return -2;
+      }
+    else
+      {
+        sh_string_grow(s, 0);
+      }
+    
+    if (fgets(&(s->str[s->len]), (s->siz - s->len), fp) == NULL) 
+      {
+        if (ferror(fp))
+          {
+            sh_string_truncate(s, 0);
+            return -1;
+          }
+        return s->len;
+      }
+    
+    s->len += strlen( &(s->str[s->len]) );
+    if (s->len > 0 && s->str[s->len-1] == '\n')
+      {
+        (s->str)[s->len-1] = '\0';
+        --(s->len);
+        return (s->len + 1);
+      }
+  }
+
+  /* notreached */
+}
+
+sh_string * sh_string_cat_lchar(sh_string * s, char * str, size_t len)
+{
+  if (sl_ok_adds(len, s->siz) == SL_TRUE)
+    {
+      if ((len + 1 + s->len) > s->siz)
+	{
+	  sh_string_grow(s, ((len+1+s->len) - s->siz) );
+	}
+      memcpy(&(s->str[s->len]), str, len);
+      s->len += len;
+      s->str[s->len] = '\0';
+      return s;
+    }
+
+  return NULL;
+}
+
+sh_string * sh_string_set_from_char(sh_string * s, char * str)
+{
+  size_t len = strlen(str);
+
+  if ((len+1) > s->siz)
+    {
+      sh_string_grow(s, ((len+1) - s->siz) );
+    }
+  memcpy(s->str, str, (len+1));
+  return s;
+}
+
+sh_string * sh_string_new_from_lchar(char * str, size_t len)
+{
+  sh_string * s;
+  s      = SH_ALLOC(sizeof(sh_string));
+  s->str = SH_ALLOC(len+1);
+  memcpy(s->str, str, len);
+  s->str[len] = '\0';
+  s->siz = len+1;
+  s->len = len;
+  return s;
+}
+
+sh_string * sh_string_new_from_lchar3(char * str1, size_t len1,
+                                      char * str2, size_t len2,
+                                      char * str3, size_t len3)
+{
+  sh_string * s;
+  size_t len = 0;
+
+  if (sl_ok_adds(len1, len2) == SL_TRUE)
+    len    = len1 + len2;
+  else
+    return NULL;
+  if (sl_ok_adds( len, len3) == SL_TRUE)
+    len    = len  + len3;
+  else
+    return NULL;
+
+  s      = SH_ALLOC(sizeof(sh_string));
+  s->str = SH_ALLOC(len+1);
+
+  memcpy(s->str, str1, len1);
+  memcpy(&s->str[len1], str2, len2);
+  memcpy(&s->str[len1+len2], str3, len3);
+
+  s->str[len] = '\0';
+  s->siz = len+1;
+  s->len = len;
+  return s;
+}
+
+sh_string * sh_string_grow(sh_string * s, size_t increase)
+{
+  char * new;
+
+  if (increase == 0)
+    increase = SH_STRING_PARCEL;
+  
+  if (s && sl_ok_adds(s->siz, increase) == SL_TRUE)
+    {
+      new = SH_ALLOC(s->siz + increase);
+
+      if (s->str)
+        {
+          memcpy(new, s->str, s->len+1);
+          SH_FREE(s->str);
+        }
+      else
+        {
+          new[0] = '\0';
+        }
+      s->str  = new;
+      s->siz += increase;
+      return s;
+    }
+  return NULL;
+}
+
+sh_string * sh_string_truncate(sh_string * s, size_t len)
+{
+  if (s)
+    {
+      if (s->str && (s->len > len) )
+        {
+          s->len            = len;
+          (s->str)[len]     = '\0';
+        }
+      return s;
+    }
+  return NULL;
+}
+
+void sh_string_destroy(sh_string ** s)
+{
+  if (s)
+    {
+      if ((*s) && (*s)->str)
+        SH_FREE ((*s)->str);
+      SH_FREE(*s);
+      *s = NULL;
+    }
+  return;
+}
+
+sh_string * sh_string_new(size_t size)
+{
+  sh_string * s;
+  s      = SH_ALLOC (sizeof(sh_string));
+  if (size == 0)
+    size = SH_STRING_PARCEL;
+  s->str = SH_ALLOC (size);
+  s->str[0] = '\0';
+  s->siz = size;
+  s->len = 0;
+  return s;
+}
+
+/* Replaces fields in s with 'replacement'. Fields are given
+ * in the ordered array ovector, comprising ovecnum pairs 
+ * ovector[i], ovector[i+1] which list offset of first char
+ * of field, offset of first char after field (this is how
+ * the pcre library does it).
+ */  
+sh_string * sh_string_replace(const sh_string * s, 
+                              const int * ovector, int ovecnum, 
+                              const char * replacement, size_t rlen)
+{
+  sh_string * r = NULL;
+  char * p;
+  size_t len;
+  int    end    = 0;
+  int    start  = 0;
+  size_t oldlen = 0;
+  size_t newlen = 0;
+  long   diff;
+  int    i;
+
+
+  for (i = 0; i < ovecnum; ++i)
+    {
+      start = ovector[2*i];       /* offset of first char of substring       */
+      if (start >= end)
+        {
+          end   = ovector[2*i+1]; /* offset of first char after substring end*/
+
+          if (end > start && (unsigned int)end <= (s->len + 1))
+            {
+              oldlen += (end - start);
+              newlen += rlen;
+            }
+          else                    /* inconsistency detected                  */
+            {
+              return NULL;
+            }
+        }
+      else                        /* overlap detected                        */
+        {
+          return NULL;
+        }
+    }
+
+  diff = newlen - oldlen;
+
+  if ((diff > 0) && ((s->len + 1 + diff) > s->siz))
+    {
+      r = sh_string_new_from_lchar(sh_string_str(s), 
+                                   sh_string_len(s));
+      r = sh_string_grow(r, diff);
+    }
+  else
+    {
+      r = sh_string_new_from_lchar(sh_string_str(s), 
+                                   sh_string_len(s));
+    }
+
+  if (r && ovecnum > 0)
+    {
+      r->len = 0; r->str[0] = '\0'; p = r->str;
+
+      /* First part, until start of first replacement 
+       */
+      memcpy(p, s->str,      ovector[0]); p += ovector[0];
+      memcpy(p, replacement, rlen);       p += rlen;
+      *p = '\0'; r->len += (ovector[0] + rlen);
+
+      for (i = 1; i < ovecnum; ++i)
+        {
+          /* From end of last replacement to start of this */
+          len = ovector[2*i] - ovector[2*i -1];
+          memcpy(p, &(s->str[ovector[2*i -1]]), len);
+          p += len;
+
+          /* The replacement */
+          memcpy(p, replacement, rlen);       
+          p += rlen;
+
+          /* null terminate */
+          *p = '\0'; r->len += (len + rlen);
+        }
+
+      /* Last part, after last replacement; includes terminating null 
+       */
+      len = (s->len + 1) - ovector[2*i -1];
+      memcpy(p, &(s->str[ovector[2*i -1]]), len);
+      p += len; *p = '\0'; r->len += (len - 1);
+    }
+  return r;
+}
+
+
+#ifdef SH_CUTEST
+#include <stdlib.h>
+#include "CuTest.h"
+
+void Test_string (CuTest *tc) {
+  int status, i, max = 120;
+  FILE * fp;
+  sh_string * s = NULL;
+  sh_string * t;
+  static char template[] = "/tmp/xtest.XXXXXX";
+  char ** array;
+  char test[128];
+  size_t lengths[16];
+  unsigned int iarr;
+  int ovector[16];
+  int ovecnum;
+
+  s = sh_string_new(0);
+  CuAssertPtrNotNull(tc, s);
+  sh_string_destroy(&s);
+  CuAssertTrue(tc, s == NULL);
+
+  s = sh_string_new(0);
+  CuAssertPtrNotNull(tc, s);
+
+  status = mkstemp(template);
+  CuAssertTrue(tc, status >= 0);
+
+  fp = fdopen(status, "r+");
+  CuAssertPtrNotNull(tc, fp);
+
+  for (i = 0; i <  80; ++i) { fputc ('a', fp); } fputc ('\n', fp); // 0
+  for (i = 0; i < 118; ++i) { fputc ('a', fp); } fputc ('\n', fp); // 1
+  for (i = 0; i < 119; ++i) { fputc ('a', fp); } fputc ('\n', fp); // 2
+  for (i = 0; i < 120; ++i) { fputc ('a', fp); } fputc ('\n', fp); // 3
+  for (i = 0; i < 121; ++i) { fputc ('a', fp); } fputc ('\n', fp); // 4
+  for (i = 0; i < 238; ++i) { fputc ('a', fp); } fputc ('\n', fp);
+  for (i = 0; i < 239; ++i) { fputc ('a', fp); } fputc ('\n', fp);
+  for (i = 0; i < 240; ++i) { fputc ('a', fp); } fputc ('\n', fp);
+  for (i = 0; i < 241; ++i) { fputc ('a', fp); } fputc ('\n', fp);
+
+  rewind(fp);
+
+  for (i = 0; i < 9; ++i)
+    {
+      status = sh_string_read(s, fp, max);
+
+      switch (i) {
+      case 0:
+	CuAssertTrue(tc, s->len ==  80);
+	CuAssertTrue(tc, s->siz == 120);
+	CuAssertTrue(tc, status ==  81);
+	break;
+      case 1:
+	CuAssertTrue(tc, s->len == 118);
+	CuAssertTrue(tc, s->siz == 120);
+	CuAssertTrue(tc, status == 119);
+	break;
+      case 2:
+	CuAssertTrue(tc, s->len == 119);
+	CuAssertTrue(tc, s->siz == 120);
+	CuAssertTrue(tc, status ==  -2); /* no terminating '\n', truncated */
+	break;
+      case 3:
+	CuAssertTrue(tc, s->len == 120);
+	CuAssertTrue(tc, s->siz == 240);
+	CuAssertTrue(tc, status == 121);
+	break;
+      case 4:
+	CuAssertTrue(tc, s->len == 121);
+	CuAssertTrue(tc, s->siz == 240);
+	CuAssertTrue(tc, status == 122);
+	break;
+      case 5:
+	CuAssertTrue(tc, s->len == 238);
+	CuAssertTrue(tc, s->siz == 240);
+	CuAssertTrue(tc, status == 239);
+	break;
+      case 6:
+	CuAssertTrue(tc, s->len == 239);
+	CuAssertTrue(tc, s->siz == 240);
+	CuAssertTrue(tc, status ==  -2); /* no terminating '\n', truncated */
+	break;
+      default:
+	CuAssertTrue(tc, s->len == 239);
+	CuAssertTrue(tc, s->siz == 240);
+	CuAssertTrue(tc, status ==  -2);
+      }
+      if (status == -2) /* read in rest of string */
+        { max = 240; sh_string_read(s, fp, max); }
+    }
+
+  rewind(fp);
+
+  sh_string_truncate(s, 0);
+  CuAssertTrue(tc, s->len == 0);
+
+  for (i = 0; i < 9; ++i)
+    {
+      status = sh_string_read(s, fp, 240);
+      if (status == -2)
+        sh_string_read(s, fp, 240);
+      else
+        {
+          for (status = 0; status < (int)s->len; ++status)
+            {
+              if (s->str[status] != 'a')
+                {
+                  CuFail(tc, "unexpected character");
+                }
+            }
+        }
+    }
+
+  status = fclose(fp); 
+  CuAssertTrue(tc, status == 0);
+  status = remove(template);
+  CuAssertTrue(tc, status == 0);
+
+  iarr = 10; strcpy(test, "|a1|| a2| |a3 |a4|a5|");
+  array  = split_array(test, &iarr, '|', lengths);
+  CuAssertIntEquals(tc,9,(int)iarr);
+  CuAssertStrEquals(tc,"",   array[0]);
+  CuAssertStrEquals(tc,"a1", array[1]);
+  CuAssertStrEquals(tc,"",   array[2]);
+  CuAssertStrEquals(tc,"a2", array[3]);
+  CuAssertStrEquals(tc,"",   array[4]);
+  CuAssertStrEquals(tc,"a3", array[5]);
+  CuAssertStrEquals(tc,"a4", array[6]);
+  CuAssertStrEquals(tc,"a5", array[7]);
+  CuAssertStrEquals(tc,"",   array[8]);
+
+  CuAssertIntEquals(tc, 0, (int)lengths[0]);
+  CuAssertIntEquals(tc, 2, (int)lengths[1]);
+  CuAssertIntEquals(tc, 0, (int)lengths[2]);
+  CuAssertIntEquals(tc, 2, (int)lengths[3]);
+  CuAssertIntEquals(tc, 0, (int)lengths[4]);
+  CuAssertIntEquals(tc, 2, (int)lengths[5]);
+  CuAssertIntEquals(tc, 2, (int)lengths[6]);
+  CuAssertIntEquals(tc, 2, (int)lengths[7]);
+  CuAssertIntEquals(tc, 0, (int)lengths[8]);
+
+  iarr = 10; strcpy(test, "a1|| a2| |a3 |a4|a5|");
+  array  = split_array(test, &iarr, '|', lengths);
+  CuAssertIntEquals(tc,8,(int)iarr);
+  CuAssertStrEquals(tc,"a1", array[0]);
+  CuAssertStrEquals(tc,"",   array[1]);
+  CuAssertStrEquals(tc,"a2", array[2]);
+  CuAssertStrEquals(tc,"",   array[3]);
+  CuAssertStrEquals(tc,"a3", array[4]);
+  CuAssertStrEquals(tc,"a4", array[5]);
+  CuAssertStrEquals(tc,"a5", array[6]);
+  CuAssertStrEquals(tc,"",   array[7]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+  CuAssertIntEquals(tc, 0, (int)lengths[1]);
+  CuAssertIntEquals(tc, 2, (int)lengths[2]);
+  CuAssertIntEquals(tc, 0, (int)lengths[3]);
+  CuAssertIntEquals(tc, 2, (int)lengths[4]);
+  CuAssertIntEquals(tc, 2, (int)lengths[5]);
+  CuAssertIntEquals(tc, 2, (int)lengths[6]);
+  CuAssertIntEquals(tc, 0, (int)lengths[7]);
+
+  iarr = 10; strcpy(test, "  a1|| a2  | |a3 |a4|a5");
+  array  = split_array(test, &iarr, '|', lengths);
+  CuAssertIntEquals(tc,7,(int)iarr);
+  CuAssertStrEquals(tc,"a1", array[0]);
+  CuAssertStrEquals(tc,"",   array[1]);
+  CuAssertStrEquals(tc,"a2", array[2]);
+  CuAssertStrEquals(tc,"",   array[3]);
+  CuAssertStrEquals(tc,"a3", array[4]);
+  CuAssertStrEquals(tc,"a4", array[5]);
+  CuAssertStrEquals(tc,"a5", array[6]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+  CuAssertIntEquals(tc, 0, (int)lengths[1]);
+  CuAssertIntEquals(tc, 2, (int)lengths[2]);
+  CuAssertIntEquals(tc, 0, (int)lengths[3]);
+  CuAssertIntEquals(tc, 2, (int)lengths[4]);
+  CuAssertIntEquals(tc, 2, (int)lengths[5]);
+  CuAssertIntEquals(tc, 2, (int)lengths[6]);
+
+  iarr = 10; strcpy(test, "a1|| a2  | |a3 |a4|a5  ");
+  array  = split_array(test, &iarr, '|', lengths);
+  CuAssertIntEquals(tc,7,(int)iarr);
+  CuAssertStrEquals(tc,"a1", array[0]);
+  CuAssertStrEquals(tc,"",   array[1]);
+  CuAssertStrEquals(tc,"a2", array[2]);
+  CuAssertStrEquals(tc,"",   array[3]);
+  CuAssertStrEquals(tc,"a3", array[4]);
+  CuAssertStrEquals(tc,"a4", array[5]);
+  CuAssertStrEquals(tc,"a5", array[6]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+  CuAssertIntEquals(tc, 0, (int)lengths[1]);
+  CuAssertIntEquals(tc, 2, (int)lengths[2]);
+  CuAssertIntEquals(tc, 0, (int)lengths[3]);
+  CuAssertIntEquals(tc, 2, (int)lengths[4]);
+  CuAssertIntEquals(tc, 2, (int)lengths[5]);
+  CuAssertIntEquals(tc, 2, (int)lengths[6]);
+
+  iarr = 10; strcpy(test, "|");
+  array  = split_array(test, &iarr, '|', lengths);
+  CuAssertIntEquals(tc,2,(int)iarr);
+  CuAssertStrEquals(tc,"",   array[0]);
+  CuAssertStrEquals(tc,"",   array[1]);
+
+  CuAssertIntEquals(tc, 0, (int)lengths[0]);
+  CuAssertIntEquals(tc, 0, (int)lengths[1]);
+
+  iarr = 10; strcpy(test, "|||");
+  array  = split_array(test, &iarr, '|', lengths);
+  CuAssertIntEquals(tc,4,(int)iarr);
+  CuAssertStrEquals(tc,"",   array[0]);
+  CuAssertStrEquals(tc,"",   array[1]);
+  CuAssertStrEquals(tc,"",   array[2]);
+  CuAssertStrEquals(tc,"",   array[3]);
+
+  CuAssertIntEquals(tc, 0, (int)lengths[0]);
+  CuAssertIntEquals(tc, 0, (int)lengths[1]);
+  CuAssertIntEquals(tc, 0, (int)lengths[2]);
+  CuAssertIntEquals(tc, 0, (int)lengths[3]);
+
+  iarr = 10; strcpy(test, " a1 ");
+  array  = split_array(test, &iarr, '|', lengths);
+  CuAssertIntEquals(tc,1,(int)iarr);
+  CuAssertStrEquals(tc,"a1",   array[0]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+
+  iarr = 10; strcpy(test, "");
+  array  = split_array(test, &iarr, '|', lengths);
+  CuAssertIntEquals(tc,1,(int)iarr);
+  CuAssertStrEquals(tc,"",   array[0]);
+
+  CuAssertIntEquals(tc, 0, (int)lengths[0]);
+
+  /* WS separated */
+
+  iarr = 10; strcpy(test, "a1");
+  array  = split_array_ws (test, &iarr, lengths);
+  CuAssertIntEquals(tc,1,(int)iarr);
+  CuAssertStrEquals(tc,"a1",   array[0]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+
+  iarr = 10; strcpy(test, " a1");
+  array  = split_array_ws (test, &iarr, lengths);
+  CuAssertIntEquals(tc,1,(int)iarr);
+  CuAssertStrEquals(tc,"a1",   array[0]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+
+  iarr = 10; strcpy(test, " a1 ");
+  array  = split_array_ws (test, &iarr, lengths);
+  CuAssertIntEquals(tc,1,(int)iarr);
+  CuAssertStrEquals(tc,"a1",   array[0]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+
+  iarr = 10; strcpy(test, "   ");
+  array  = split_array_ws (test, &iarr, lengths);
+  CuAssertIntEquals(tc,0,(int)iarr);
+  CuAssertTrue(tc, array[0] == NULL);
+
+  iarr = 10; strcpy(test, " a1 a2");
+  array  = split_array_ws (test, &iarr, lengths);
+  CuAssertIntEquals(tc,2,(int)iarr);
+  CuAssertStrEquals(tc,"a1",   array[0]);
+  CuAssertStrEquals(tc,"a2",   array[1]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+  CuAssertIntEquals(tc, 2, (int)lengths[1]);
+
+  iarr = 10; strcpy(test, " a1  a2  ");
+  array  = split_array_ws (test, &iarr, lengths);
+  CuAssertIntEquals(tc,2,(int)iarr);
+  CuAssertStrEquals(tc,"a1",   array[0]);
+  CuAssertStrEquals(tc,"a2",   array[1]);
+
+  CuAssertIntEquals(tc, 2, (int)lengths[0]);
+  CuAssertIntEquals(tc, 2, (int)lengths[1]);
+
+  iarr = 10; strcpy(test, "");
+  array  = split_array_ws (test, &iarr, lengths);
+  CuAssertIntEquals(tc,0,(int)iarr);
+  CuAssertTrue(tc, array[0] == NULL);
+
+  iarr = 3; strcpy(test, " this is a test for remainder");
+  array  = split_array_ws (test, &iarr, lengths);
+  CuAssertIntEquals(tc,3,(int)iarr);
+  CuAssertStrEquals(tc,"this",   array[0]);
+  CuAssertStrEquals(tc,"is",     array[1]);
+  CuAssertStrEquals(tc,"a test for remainder",     array[2]);
+  for (i = 0; i < 3; ++i)
+    {
+      CuAssertIntEquals(tc, (int)strlen(array[i]), lengths[i] );
+    }
+
+  /* string replace */
+  s = sh_string_new_from_lchar3 ("abc ", 4, "def ", 4, "ghi ", 4);
+  ovecnum = 2;
+  ovector[0] = 0;  ovector[1] = 2;
+  ovector[2] = 4;  ovector[3] = 11;
+
+  t = sh_string_replace(s, ovector, ovecnum, 
+                        "___", 3);
+  CuAssertStrEquals(tc, "___c ___ ",   t->str);
+  CuAssertIntEquals(tc, 9, (int)t->len);
+
+  ovector[0] = 0;  ovector[1] = 2;
+  ovector[2] = 4;  ovector[3] = 12; 
+  t = sh_string_replace(s, ovector, ovecnum, 
+                        "___", 3);
+  CuAssertStrEquals(tc, "___c ___",   t->str);
+  CuAssertIntEquals(tc, 8, (int)t->len);
+
+  ovector[0] = 0;  ovector[1] = 0;
+  ovector[2] = 0;  ovector[3] = 0; 
+  t = sh_string_replace(s, ovector, ovecnum, 
+                        "___", 3);
+  CuAssertTrue(tc, t == NULL);
+
+  ovector[0] = 0;  ovector[1] = 3;
+  ovector[2] = 3;  ovector[3] = 6; 
+  t = sh_string_replace(s, ovector, ovecnum, 
+                        "___", 3);
+  
+  CuAssertStrEquals(tc, "______f ghi ",   t->str);
+  CuAssertIntEquals(tc, 12, (int)t->len);
+
+  ovector[0] = 4;  ovector[1] = 5;
+  ovector[2] = 11;  ovector[3] = 12; 
+  t = sh_string_replace(s, ovector, ovecnum, 
+                        "___", 3);
+  CuAssertStrEquals(tc, "abc ___ef ghi___",   t->str);
+  CuAssertIntEquals(tc, 16, (int)t->len);
+
+  t = sh_string_replace(s, ovector, 0, 
+                        "___", 3);
+  CuAssertStrEquals(tc, s->str,   t->str);
+  CuAssertIntEquals(tc, (int)s->len, (int)t->len);
+
+}
+
+#endif
Index: trunk/src/sh_tools.c
===================================================================
--- trunk/src/sh_tools.c	(revision 167)
+++ trunk/src/sh_tools.c	(revision 169)
@@ -582,5 +582,5 @@
 		      *errnum = 0;
 		      if (sl_strlen(host_entry->h_name) == 0 || 
-			  (*errnum = sl_strcmp(host_name,host_entry->h_name)) != 0)
+			  (*errnum = sl_strcasecmp(host_name,host_entry->h_name)) != 0)
 			{ 
 			  if (*errnum)
@@ -1663,4 +1663,6 @@
 	SH_FREE (file);
 	SH_FREE(my_tmp_dir);
+	sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, 
+			_("Error (lstat) while opening temporary file"), _("open_tmp"));
 	TPT(( 0, FIL__, __LINE__, _("msg=<Unexpected error %d>\n"), error));
 	SL_RETURN((-1), _("open_tmp"));
Index: trunk/src/sh_unix.c
===================================================================
--- trunk/src/sh_unix.c	(revision 167)
+++ trunk/src/sh_unix.c	(revision 169)
@@ -43,4 +43,10 @@
 #include <fcntl.h>
 #include <unistd.h>
+/* need to undef these, since the #define's may be picked up from
+ * linux/wait.h, and will clash with a typedef in sys/wait.h
+ */
+#undef P_ALL
+#undef P_PID
+#undef P_PGID
 #include <sys/wait.h>
 
@@ -2993,5 +2999,4 @@
 	      someval *= 1000;  /* milliseconds in a second */
 	      sometime = (unsigned long) someval;
-	      /* fprintf(stderr, "FIXME PAUSE %ld\n", sometime); */
 	      retry_msleep(0, sometime);
 	    }
@@ -2999,5 +3004,4 @@
 	    {
 	      sometime = (unsigned long) someval;
-	      /* fprintf(stderr, "FIXME PAUSE %ld sec\n", sometime); */
 	      retry_msleep (sometime, 0);
 	    }
@@ -3037,4 +3041,6 @@
 
   SL_ENTER(_("sh_unix_checksum_size"));
+
+  tmpFile.link_path = NULL;
 
   if (sh.flag.checkSum != SH_CHECK_INIT)
@@ -3256,5 +3262,8 @@
 }
 #endif
-    
+
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif    
 
 int sh_unix_getinfo (int level, char * filename, file_type * theFile, 
@@ -3402,5 +3411,5 @@
 	      UINT64 length_nolim = TIGER_NOLIM;
 
-	      if ((theFile->check_mask & MODI_TXT) != 0 && fbuf.st_size < SH_TXT_MAX)
+	      if ((theFile->check_mask & MODI_TXT) != 0 && fbuf.st_size < (10 * SH_TXT_MAX))
 		{
 		  sl_init_content (rval_open, fbuf.st_size);
@@ -3415,4 +3424,5 @@
 
 	      content = sl_get_content(rval_open);
+	      content = sh_string_copy(content);
 
 	      if ((theFile->check_mask & MODI_SGROW) != 0)
@@ -3454,5 +3464,5 @@
 	      UINT64 length_nolim = TIGER_NOLIM;
 
-	      if ((theFile->check_mask & MODI_TXT) != 0 && fbuf.st_size < SH_TXT_MAX)
+	      if ((theFile->check_mask & MODI_TXT) != 0 && fbuf.st_size < (10 * SH_TXT_MAX))
 		{
 		  sl_init_content (rval_open, fbuf.st_size);
@@ -3467,4 +3477,5 @@
 
 	      content = sl_get_content(rval_open);
+	      content = sh_string_copy(content);
 
 	      if ((theFile->check_mask & MODI_SGROW) != 0) 
@@ -3759,7 +3770,32 @@
       if (content)
 	{
-	  sh_util_base64_enc_alloc (&(theFile->link_path), 
-				    sh_string_str(content), 
-				    sh_string_len(content));
+#ifdef HAVE_LIBZ
+	  unsigned long   clen = compressBound(sh_string_len(content));
+	  unsigned char * compressed = SH_ALLOC(clen);
+	  if (Z_OK == compress(compressed, &clen, 
+			       (unsigned char *) sh_string_str(content), 
+			       sh_string_len(content)))
+	      {
+		if (clen < SH_TXT_MAX)
+		  {
+		    sh_util_base64_enc_alloc (&(theFile->link_path), 
+					      (char *) compressed, clen);
+		  }
+		else
+		  {
+		    char tmsg[128];
+		    char * tpath = sh_util_safe_name (theFile->fullpath);
+		    sl_snprintf(tmsg, sizeof(tmsg), 
+				_("compressed file too large (%lu bytes)"),
+				clen);
+		    sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, -1, 
+				     MSG_E_SUBGPATH, tmsg, 
+				     _("sh_unix_getinfo"), tpath);
+		    SH_FREE(tpath);
+		  }
+	      }
+	  SH_FREE(compressed);
+#endif
+	  sh_string_destroy(&content);
 	}
     } 
@@ -3770,6 +3806,81 @@
 #endif
 
-int sh_unix_unlock (char * lockfile, char * flag);
-int sh_unix_lock   (char * lockfile, char * flag);
+int sh_unix_unlock(char * lockfile, char * flag)
+{
+  int         error = 0;
+  
+  SL_ENTER(_("sh_unix_unlock"));
+
+  if (sh.flag.isdaemon == S_FALSE && flag == NULL)
+    SL_RETURN((0),_("sh_unix_unlock"));
+
+  /* --- Logfile is not locked to us. ---
+   */
+  if (sh.flag.islocked == BAD && flag != NULL) 
+    SL_RETURN((-1),_("sh_unix_unlock"));
+
+  /* --- Check whether the directory is secure. ---
+   */
+  if (0 != tf_trust_check (lockfile, SL_YESPRIV))
+    SL_RETURN((-1),_("sh_unix_unlock"));
+
+  /* --- Delete the lock file. --- 
+   */
+  error = retry_aud_unlink (FIL__, __LINE__, lockfile);
+  
+  if (error == 0)
+    {
+      if (flag != NULL)
+	sh.flag.islocked = BAD; /* not locked anymore */
+    }
+  else if (flag != NULL)
+    {
+      char errbuf[SH_ERRBUF_SIZE];
+      error = errno;
+      sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_UNLNK,
+		       sh_error_message(error, errbuf, sizeof(errbuf)), 
+		       lockfile);
+      SL_RETURN((-1),_("sh_unix_unlock"));
+    }
+  SL_RETURN((0),_("sh_unix_unlock"));
+}
+
+int sh_unix_lock (char * lockfile, char * flag)
+{
+  int filed;
+  int errnum;
+  char myPid[64];
+  SL_TICKET  fd;
+  extern int get_the_fd (SL_TICKET ticket);
+
+  SL_ENTER(_("sh_unix_lock"));
+
+  sprintf (myPid, "%ld\n", (long) sh.pid);             /* known to fit  */
+
+  fd = sl_open_safe_rdwr (lockfile, SL_YESPRIV);       /* fails if file exists */
+
+  if (!SL_ISERROR(fd))
+    {
+      errnum = sl_write (fd, myPid, sl_strlen(myPid));
+      filed = get_the_fd(fd);
+      fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+      sl_close (fd);
+
+      if (!SL_ISERROR(errnum))
+	{
+	  if (flag != NULL)
+	    sh.flag.islocked = GOOD;
+	  SL_RETURN((0),_("sh_unix_lock"));
+	}
+    }
+
+  TPT((0, FIL__, __LINE__, _("msg=<open pid file failed>\n")));
+  if (flag != NULL)
+    sh.flag.islocked       = BAD;
+  SL_RETURN((-1),_("sh_unix_lock"));
+
+  /* notreached */
+}
+
 
 /* check whether file is locked
@@ -3964,41 +4075,4 @@
 }
 
-int sh_unix_unlock(char * lockfile, char * flag)
-{
-  int         error = 0;
-  
-  SL_ENTER(_("sh_unix_unlock"));
-
-  /* --- Logfile is not locked to us. ---
-   */
-  if (sh.flag.islocked == BAD && flag != NULL) 
-    SL_RETURN((-1),_("sh_unix_unlock"));
-
-  /* --- Check whether the directory is secure. ---
-   */
-  if (0 != tf_trust_check (lockfile, SL_YESPRIV))
-    SL_RETURN((-1),_("sh_unix_unlock"));
-
-  /* --- Delete the lock file. --- 
-   */
-  error = retry_aud_unlink (FIL__, __LINE__, lockfile);
-  
-  if (error == 0)
-    {
-      if (flag != NULL)
-	sh.flag.islocked = BAD; /* not locked anymore */
-    }
-  else if (flag != NULL)
-    {
-      char errbuf[SH_ERRBUF_SIZE];
-      error = errno;
-      sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_UNLNK,
-		       sh_error_message(error, errbuf, sizeof(errbuf)), 
-		       lockfile);
-      SL_RETURN((-1),_("sh_unix_unlock"));
-    }
-  SL_RETURN((0),_("sh_unix_unlock"));
-}
-
 /* rm lock for filename
  */
@@ -4029,41 +4103,4 @@
 {
   return sh_unix_unlock(sh.srvlog.alt, NULL);
-}
-
-int sh_unix_lock (char * lockfile, char * flag)
-{
-  int filed;
-  int errnum;
-  char myPid[64];
-  SL_TICKET  fd;
-  extern int get_the_fd (SL_TICKET ticket);
-
-  SL_ENTER(_("sh_unix_lock"));
-
-  sprintf (myPid, "%ld\n", (long) sh.pid);             /* known to fit  */
-
-  fd = sl_open_safe_rdwr (lockfile, SL_YESPRIV);       /* fails if file exists */
-
-  if (!SL_ISERROR(fd))
-    {
-      errnum = sl_write (fd, myPid, sl_strlen(myPid));
-      filed = get_the_fd(fd);
-      fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
-      sl_close (fd);
-
-      if (!SL_ISERROR(errnum))
-	{
-	  if (flag != NULL)
-	    sh.flag.islocked = GOOD;
-	  SL_RETURN((0),_("sh_unix_lock"));
-	}
-    }
-
-  TPT((0, FIL__, __LINE__, _("msg=<open pid file failed>\n")));
-  if (flag != NULL)
-    sh.flag.islocked       = BAD;
-  SL_RETURN((-1),_("sh_unix_lock"));
-
-  /* notreached */
 }
 
Index: trunk/src/slib.c
===================================================================
--- trunk/src/slib.c	(revision 167)
+++ trunk/src/slib.c	(revision 169)
@@ -108,8 +108,6 @@
 int  sl_trace_use (const char * dummy)
 {
-  if (dummy)
-    slib_do_trace = 1;
-  else
-    slib_do_trace = 1;
+  (void) dummy;
+  slib_do_trace = 1;
   return 0;
 }
@@ -156,4 +154,5 @@
 	  fprintf(trace_fp, "[%2d] %s \t - File %c%s%c at line %d\n", 
 		 trace_level, str, 0x22, file, 0x22, line);
+	  fflush(trace_fp);
 	}
       else
@@ -191,4 +190,5 @@
 	  fprintf(trace_fp, _("[%2d] %s \t - File %c%s%c at line %d\n"), 
 		 trace_level, str, 0x22, file, 0x22, line);
+	  fflush(trace_fp);
 	}
       else
@@ -1007,4 +1007,41 @@
 }
 
+#include <ctype.h>
+int sl_strcasecmp(const char * one, const char * two)
+{
+#ifdef SL_FAIL_ON_ERROR
+  SL_REQUIRE (one != NULL, _("one != NULL"));
+  SL_REQUIRE (two != NULL, _("two != NULL"));
+#endif
+
+  if (one && two)
+    {
+      do {
+	if (*one && *two)
+	  {
+	    if (tolower(*one) == tolower(*two))
+	      {
+		++one; ++two;
+	      }
+	    else if (tolower(*one) < tolower(*two))
+	      return -1;
+	    else
+	      return 1;
+	  }
+	else if (*one == '\0' && *two == '\0')
+	  return 0;
+	else if (*one == '\0')
+	  return -1;
+	else
+	  return 1;
+      } while (1 == 1);
+    }
+  else if (one == NULL && two != NULL)
+    return -1;
+  else if (one != NULL && two == NULL)
+    return 1;
+  else
+    return -7; /* default to not equal */
+}
 
 int sl_strcmp(const char * a, const char * b)
@@ -1022,5 +1059,5 @@
     return (1);
   else
-    return (-7); /* arbitrary */
+    return (-7); /* default to not equal */
 }
 
@@ -1040,5 +1077,5 @@
     return (1);
   else
-    return (-7); /* arbitrary */
+    return (-7); /* default to not equal */
 }
 
@@ -2232,4 +2269,5 @@
 		  if (is_nonblocking == SL_FALSE)
 		      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
+		  TPT(( 0, FIL__, __LINE__, _("msg=<read error>")));
 		  return (SL_EREAD);
 		}
@@ -2247,4 +2285,5 @@
 	  if (is_nonblocking == SL_FALSE)
 	      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
+	  TPT(( 0, FIL__, __LINE__, _("msg=<timeout>")));
 	  return (SL_TIMEOUT);
 	}
@@ -2253,4 +2292,5 @@
 	  if (is_nonblocking == SL_FALSE)
 	      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
+	  TPT(( 0, FIL__, __LINE__, _("msg=<timeout>")));
 	  return (SL_EREAD);
 	}
@@ -2260,4 +2300,5 @@
 	  if (is_nonblocking == SL_FALSE)
 	      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
+	  TPT(( 0, FIL__, __LINE__, _("msg=<terminated>")));
 	  return (SL_EREAD);
 	}
@@ -2270,4 +2311,5 @@
 	  if (is_nonblocking == SL_FALSE)
 	      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
+	  TPT(( 0, FIL__, __LINE__, _("msg=<timeout>")));
 	  return (SL_TIMEOUT);
 	}
@@ -2282,6 +2324,8 @@
 		     int timeout, int is_nonblocking)
 {
-  int    fd;
+  int    fd, retval;
  
+  SL_ENTER(_("sl_read_timeout"));
+
   if (buf_in == NULL || SL_ISERROR(fd = get_the_fd(ticket)))
     {
@@ -2289,14 +2333,15 @@
 	{
 	  TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
-	  return (SL_ENULL);
+	  SL_IRETURN((SL_ENULL), _("sl_read_timeout"));
 	}
       if (SL_ISERROR(fd = get_the_fd(ticket)))
 	{
 	  TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
-	  return (fd);
+	  SL_IRETURN((fd),  _("sl_read_timeout"));
 	}
     }
 
-  return sl_read_timeout_fd (fd, buf_in, count, timeout, is_nonblocking);
+  retval = sl_read_timeout_fd (fd, buf_in, count, timeout, is_nonblocking);
+  SL_IRETURN((retval), _("sl_read_timeout"));
 }
 
@@ -2310,13 +2355,15 @@
   char * buf;
 
+  SL_ENTER(_("sl_read"));
+
   if (count < 1)
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<range error>")));
-      return(SL_ERANGE);
+      SL_IRETURN((SL_ERANGE), _("sl_read"));
     }
   if (buf_in == NULL)
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
-      return (SL_ENULL);
+      SL_IRETURN((SL_ENULL), _("sl_read"));
     }
 
@@ -2324,5 +2371,5 @@
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
-      return (fd);
+      SL_IRETURN((fd), _("sl_read"));
     }
 
@@ -2345,7 +2392,7 @@
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<read error> errno=<%d>\n"), errno));
-      return (SL_EREAD);
-    }
-  return (bytes);
+      SL_IRETURN((SL_EREAD), _("sl_read"));
+    }
+  SL_IRETURN((bytes), _("sl_read"));
 }
 
@@ -2357,13 +2404,15 @@
   char * buf;
 
+  SL_ENTER(_("sl_read_fast"));
+
   if (count < 1)
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<range error>")));
-      return(SL_ERANGE);
+      SL_IRETURN((SL_ERANGE), _("sl_read_fast"));
     }
   if (buf_in == NULL)
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
-      return (SL_ENULL);
+      SL_IRETURN((SL_ENULL), _("sl_read_fast"));
     }
 
@@ -2371,5 +2420,5 @@
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
-      return (fd);
+      SL_IRETURN((fd), _("sl_read_fast"));
     }
 
@@ -2381,5 +2430,5 @@
       if (byteread >= 0) 
 	{
-	  return (byteread);
+	  SL_IRETURN((byteread), _("sl_read_fast"));
 	}  
     } while ( byteread == -1 && (errno == EINTR || errno == EAGAIN));
@@ -2389,7 +2438,7 @@
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<read error> errno=<%d>\n"), errno));
-      return (SL_EREAD);
-    }
-  return (0);
+      SL_IRETURN((SL_EREAD), _("sl_read_fast"));
+    }
+  SL_IRETURN((0), _("sl_read_fast"));
 }
 
