Index: trunk/src/caps.ac
===================================================================
--- trunk/src/caps.ac	(revision 476)
+++ 	(revision )
@@ -1,23 +1,0 @@
-        case "$host_os" in
-        *linux*)
-        if test x"${sh_use_lcaps}" = xyes
-        then
-            echo
-            echo "Using Linux capabilities to drop unnecessary root capabilities."
-            echo "Please make sure that directories used for writing have write permission"
-            echo "for root, because root will be a mere mortal in that respect:"
-            echo "  Baseline database in: ${mydataroot}"
-            echo "  Logfile in:           ${localstatedir}/log"
-            echo "  PID file in:          ${localstatedir}/run"
-            echo "(directories not existent yet will be created upon installation, root-owned"
-            echo "if make install is executed by root.)"
-            echo
-        fi
-        if test x"${sh_use_lcaps}" = xno
-        then
-            echo
-            echo "Not using Linux capabilities (capability.h or libcap not found)"
-            echo
-        fi
-        ;;
-        esac
Index: trunk/src/cutest_sh_tiger0.c
===================================================================
--- trunk/src/cutest_sh_tiger0.c	(revision 476)
+++ trunk/src/cutest_sh_tiger0.c	(revision 481)
@@ -28,5 +28,5 @@
   if (skey != NULL) 
     {
-      skey->mlock_failed = SL_FALSE;
+      skey->mlock_failed = S_FALSE;
       skey->rngI         = BAD;
       /* properly initialized later 
Index: trunk/src/cutest_sh_unix.c
===================================================================
--- trunk/src/cutest_sh_unix.c	(revision 476)
+++ trunk/src/cutest_sh_unix.c	(revision 481)
@@ -14,5 +14,7 @@
   int j, i;
   int sum;
+#ifndef USE_SYSTEM_MALLOC
   int i_malloc =  malloc_count;
+#endif
 
   char * buf;
@@ -35,5 +37,7 @@
   CuAssertStrEquals(tc, "testing realloctesting realloc", buf);
 
+#ifndef USE_SYSTEM_MALLOC
   i_malloc = malloc_count;
+#endif
 
   for (j = 0; j < 64; ++j)
@@ -60,5 +64,7 @@
   CuAssertStrEquals(tc, "testing realloctesting realloc", buf);
 
+#ifndef USE_SYSTEM_MALLOC
   i_malloc = malloc_count;
+#endif
 
   for (j = 0; j < 64; ++j)
@@ -97,5 +103,7 @@
     }
 
+#ifndef USE_SYSTEM_MALLOC
   i_malloc =  malloc_count;
+#endif
 
   for (j = 0; j < nalloc; ++j)
@@ -122,5 +130,7 @@
   for (j = 0; j < 32; ++j)
     {
+#ifndef USE_SYSTEM_MALLOC
       i_malloc =  malloc_count;
+#endif
       buf = malloc((j+1) * 1024 * 1024);
       CuAssertPtrNotNull(tc, buf);
Index: trunk/src/cutest_sh_utils.c
===================================================================
--- trunk/src/cutest_sh_utils.c	(revision 476)
+++ trunk/src/cutest_sh_utils.c	(revision 481)
@@ -531,3 +531,2 @@
 }
 
-
Index: trunk/src/cutest_zAVLTree.c
===================================================================
--- trunk/src/cutest_zAVLTree.c	(revision 476)
+++ trunk/src/cutest_zAVLTree.c	(revision 481)
@@ -21,5 +21,5 @@
 static zAVLKey ztest_intkey(void const *item)
 {
-  return (&((struct ztest *)item)->iname);
+  return (&((const struct ztest *)item)->iname);
 }
 
Index: trunk/src/dnmalloc.c
===================================================================
--- trunk/src/dnmalloc.c	(revision 476)
+++ trunk/src/dnmalloc.c	(revision 481)
@@ -220,5 +220,5 @@
 #ifdef linux
 #define HAVE_MREMAP 1
-#define _GNU_SOURCE
+#define _GNU_SOURCE 1
 #else
 #define HAVE_MREMAP 0
@@ -310,11 +310,16 @@
   char * i3 = "): ";
   char * i5 = "\n";
-  int   res = 0;
-
-  iov[0].iov_base = i1;               iov[0].iov_len = strlen(i1); 
-  iov[1].iov_base = (char*) file;     iov[1].iov_len = strlen(file); 
-  iov[2].iov_base = i3;               iov[2].iov_len = strlen(i3); 
-  iov[3].iov_base = (char*) error;    iov[3].iov_len = strlen(error); 
-  iov[4].iov_base = i5;               iov[4].iov_len = strlen(i5);
+  int    res = 0;
+  char   ifile[128];
+  char   ierr[128];
+
+  strncpy(ifile, file, sizeof(ifile)); ifile[sizeof(ifile)-1] = '\0';
+  strncpy(ierr, error, sizeof(ierr));  ierr[sizeof(ierr)-1]   = '\0';
+
+  iov[0].iov_base = i1;     iov[0].iov_len = strlen(i1); 
+  iov[1].iov_base = ifile;  iov[1].iov_len = strlen(ifile); 
+  iov[2].iov_base = i3;     iov[2].iov_len = strlen(i3); 
+  iov[3].iov_base = ierr;   iov[3].iov_len = strlen(ierr); 
+  iov[4].iov_base = i5;     iov[4].iov_len = strlen(i5);
   do {
     res = writev(STDERR_FILENO, iov, 5);
@@ -343,5 +348,7 @@
 
 static assert_handler_tp *assert_handler = NULL;
+#ifndef NDEBUG
 #define NDEBUG
+#endif
 #define assert(x) ((void)0)
 
@@ -3764,5 +3771,5 @@
     } /* not extended previous region */
     
-    /* Update statistics */ /* FIXME check this */
+    /* Update statistics */
     sum = av->sbrked_mem;
     if (sum > (CHUNK_SIZE_T)(av->max_sbrked_mem))
Index: trunk/src/kern_head.c
===================================================================
--- trunk/src/kern_head.c	(revision 476)
+++ 	(revision )
@@ -1,997 +1,0 @@
-/* 
- * need to #define SH_USE_KERN
- *
- */
-#define SH_SYSCALL_CODE
-
-#include "config.h"
-
-#if defined(HOST_IS_I86LINUX) || defined(HOST_IS_64LINUX)
-#define SH_IDT_TABLE
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#if defined(SH_USE_KERN) 
-
-#undef _
-#define _(string)  string
-#undef N_
-#define N_(string) string
-
-void usage(int flag)
-{
-  printf("\n");
-  printf("Usage: kern_head [-v | --verbose]\n");
-  printf("       kern_head [-h | --help]\n");
-  printf("\n");
-  /*
-   * printf("       You need superuser privileges to use this program,\n");
-   * printf("       because only the superuser can read from /dev/kmem.\n");
-   * printf("\n");
-   */
-  exit(flag);
-}
-
-#if defined(HOST_IS_LINUX)
-
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/utsname.h>
-#include <sys/mman.h>
-
-/* number of system calls */
-#define SH_MAXCALLS 512
-
-#include "kern_head.h"
-
-static int verbose = 0;
-
-typedef struct _smap_entry {
-#ifdef SH_SYSCALL_CODE
-  unsigned int  code[2];  /* 8 bytes */
-#endif
-  unsigned long addr;
-  char          name[64];
-} smap_entry;
-
-union {
-  unsigned long addr_sys_call_table;
-  unsigned char str_sys_call_table[sizeof(unsigned long)];
-} sh_sys_call;
-
-#define SYS_CODE_SIZE 1024
-
-static unsigned long addr_system_call;
-static unsigned char system_call_code[SYS_CODE_SIZE];
-
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-
-static int kmem_read (int fd, unsigned long addr, unsigned char * buf, int len)
-{
-  if (lseek(fd, addr, SEEK_SET) == (off_t) (-1))
-    {
-      if (verbose)
-	perror("kmem_read: lseek");
-      return -1;
-    }
-  if (read(fd, buf, len) < 0)
-    {
-      if (verbose)
-	perror("kmem_read: read");
-      return -1;
-    }
-  return 0;
-}
-
-static int kmem_mmap (int fd, unsigned long addr, unsigned char * buf, int len)
-{
-  size_t    moff, roff;
-  size_t    sz;
-  char    * kmap;
-
-  sz = getpagesize(); /* unistd.h */
-
-  moff = ((size_t)(addr/sz)) * sz;                 /* lower page boundary */
-  roff = addr - moff;    /* off relative to lower address of mmapped area */
-  kmap = mmap(0, len+sz, PROT_READ, MAP_PRIVATE, fd, moff);/* sys/mman.h */
-
-  if (kmap == MAP_FAILED)
-    {
-      /* then, try read()
-       */
-      if (verbose)
-	fprintf(stderr, "kmem_mmap: mmap() failed, now trying read()\n");
-
-      if (0 == kmem_read (fd, addr, buf, len))
-	return 0;
-
-      perror("kmem_mmap: mmap");
-      return -1;
-    }
-
-  memcpy (buf, &kmap[roff], len);
-      
-  if (munmap(kmap, len+sz) != 0)
-    {
-      perror("kmem_mmap: munmap");
-      return -1;
-    }
-
-  return 0;
-}
-
-int read_kcode (unsigned long addr, unsigned char * buf, int len)
-{
-  int fd;
-
-  if (addr == 0UL)
-    {
-      perror("read_kcode: invalid input");
-      return -1;
-    }
-
-  fd = open ("/dev/kmem", O_RDONLY);
-
-  if (fd < 0)
-    {
-      if (verbose)
-	fprintf(stderr, "read_kcode: /dev/kmem failed, now trying /proc/kmem\n");
-
-      if (0 != access("/proc/kmem", R_OK)) 
-	{
-	  perror("read_kcode: access /proc/kmem");
-
-	  fprintf(stderr, "\n");
-      
-	  fprintf(stderr, "NOTE:  kern_head: apparently you have no /dev/kmem, and the\n");
-	  fprintf(stderr, "       samhain_kmem module is not loaded\n");
-	  fprintf(stderr, "       If you get this message, please proceed as follows:\n");
-	  fprintf(stderr, "       $ make samhain_kmem.ko\n");
-	  fprintf(stderr, "       $ sudo /sbin/insmod samhain_kmem.ko; sudo ./kern_head > sh_ks.h; sudo /sbin/rmmod samhain_kmem\n");
-	  fprintf(stderr, "       $ make\n\n");
-	  exit (EXIT_FAILURE);
-	}
-      fd = open ("/proc/kmem", O_RDONLY);
-    }
-
-  if (fd < 0)
-    {
-      perror("read_kcode: open /dev/kmem and /proc/kmem");
-      return -1;
-    }
-
-  if (kmem_mmap(fd, addr, buf, len) < 0)
-    {
-      close (fd);
-      return -1;
-    }
-
-  close (fd);
-
-  return 0;
-}
-
-int get_dispatch (int * qq)
-{
-  int i;
-
-  if (addr_system_call == 0L || sh_sys_call.addr_sys_call_table == 0L)
-    {
-      fprintf(stderr, "get_dispatch: invalid data\n");
-      return -1;
-    }
-
-  if (0 != read_kcode (addr_system_call, system_call_code, SYS_CODE_SIZE))
-    {
-      fprintf(stderr, "get_dispatch: could not read system_call code\n");
-      return -1;
-    }
-
-  for (i = 0; i < (SYS_CODE_SIZE - 4); ++i)
-    {
-      if (system_call_code[i]   == sh_sys_call.str_sys_call_table[0] &&
-	  system_call_code[i+1] == sh_sys_call.str_sys_call_table[1] &&
-	  system_call_code[i+2] == sh_sys_call.str_sys_call_table[2] &&
-	  system_call_code[i+3] == sh_sys_call.str_sys_call_table[3])
-	{
-	  /*
-	    fprintf(stderr, "INFO: get_dispatch: found sys_call_table in "\
-		    "system_call code at %d\n", i);
-	  */
-	  *qq = i;
-	  return 0;
-	}
-    }
-  fprintf(stderr, 
-	  "get_dispatch: did not find sys_call_table in system_call code\n");
-  fprintf(stderr, 
-	  "** This indicates that either your System.map does not match\n");
-  fprintf(stderr,
-	  "** the currently running kernel, or that your System.map does\n");
-  fprintf(stderr,
-	  "** not provide the required information, and thus use of\n");
-  fprintf(stderr,
-	  "** the --with-kcheck option is not possible\n");
-  return -1;
-}
-
-unsigned long get_symbol_from_systemmap (char * systemmap, 
-                                         char * symbol, char flag)
-{
-  FILE * fp;
-  char buf[512], addr[32], * p;
-  unsigned long retval = 0;
-#if defined(__x86_64__) || defined(__amd64__)
-  int off = 8;
-#else
-  int off = 0;
-#endif
-
-  fp = fopen (systemmap, "r");
-
-  if (!fp)
-    {
-      fprintf(stderr, "error opening <%s>\n", systemmap);
-      perror("get_symbol_from_systemmap: fopen");
-      return -1;
-    }
-  while (fgets(buf, 512, fp) != NULL)
-    {
-      if (buf[9+off] != flag)
-        continue;
-
-      p = strchr(buf, '\n');
-      if (p != NULL)
-        *p = '\0';
-
-      if (0 != strcmp(&buf[11+off], symbol))
-        continue;
-
-      addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
-      strncat(&addr[2], buf, 8+off);
-
-      retval = strtoul(addr, NULL, 0);
-      if (retval == ULONG_MAX)
-        {
-          perror("get_symbol_from_systemmap");
-          return -1;
-        }
-    }
-  fclose(fp);
-  return retval;
-}
-
-
-/* returns the number N of entries in syscall table
- * (0 .. N-1) with valid syscalls
- */
-int fill_smap(smap_entry * sh_smap, int num)
-{
-  FILE * fp;
-  char buf[512], addr[32], name[128];
-  int  i, j, count = 0, maxcall = 0;
-#if defined(__x86_64__) || defined(__amd64__)
-  int off = 8;
-#else
-  int off = 0;
-#endif
-
-  fp = fopen (SYSTEMMAP, "r");
-
-  if (!fp)
-    {
-      perror("fill_smap: fopen");
-      fprintf(stderr, "fill_smap: error opening <%s>\n", SYSTEMMAP);
-      return -1;
-    }
-
-  /* initialize
-   */
-  sh_sys_call.addr_sys_call_table = 0L;
-
-  while (fgets(buf, 512, fp) != NULL)
-    {
-      
-      if ( ( (buf[9+off] == 'D') || (buf[9+off] == 'd') || 
-	     (buf[9+off] == 'R') || (buf[9+off] == 'r')) && 
-	   0 == strncmp("sys_call_table", &buf[11+off], 14))
-	{
-	  printf("/* found sys_call_table */\n");
-	  /* --- copy symbol address ---
-	   */
-	  addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
-	  strncat(&addr[2], buf, 8+off);
-	  addr[10+off] = '\0';
-
-	  sh_sys_call.addr_sys_call_table = strtoul(addr, NULL, 0);
-	  if (sh_sys_call.addr_sys_call_table == ULONG_MAX)
-	    {
-	      perror("fill_smap");
-	      return -1;
-	    }
-	  else
-	    {
-	      printf("#define SH_SYS_CALL_TABLE %s\n", addr);
-	    }
-	}
-
-      if (buf[9+off] != 'T')
-	continue;
-
-      if (0 == strncmp("system_call", &buf[11+off], 11))
-	{
-	  printf("/* found system_call */\n");
-	  /* --- copy symbol address ---
-	   */
-	  addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
-	  strncat(&addr[2], buf, 8+off);
-	  addr[10+off] = '\0';
-	  addr_system_call = strtoul(addr, NULL, 0);
-	  if (addr_system_call == ULONG_MAX)
-	    {
-	      perror("fill_smap");
-	      return -1;
-	    }
-	}
-
-
-      if ( (buf[11+off]!='s' || buf[12+off]!='y' || 
-	    buf[13+off]!='s' || buf[14+off]!='_') &&
-	   (buf[11+off]!='o' || buf[12+off]!='l' || 
-	    buf[13+off]!='d' || buf[14+off]!='_'))
-	continue;
-
-      for (i = 0; i < num; ++i)
-	{
-	  for (j = 0; j < 127; ++j)
-	    {
-	      if (buf[11+off+j] == '\n' || buf[11+off+j] == '\0')
-		{
-		  name[j] = '\0';
-		  break;
-		}
-	      name[j] = buf[11+off+j];
-	    }
-
-
-	  if (0 == strcmp(name, sh_smap[i].name)) 
-	    {
-	      
-	      /* --- copy symbol address ---
-	       */
-	      addr[0] = '0'; addr[1] = 'x'; addr[2] = '\0';
-	      strncat(&addr[2], buf, 8+off);
-	      addr[10+off] = '\0';
-	      sh_smap[i].addr = strtoul(addr, NULL, 0);
-	      if (sh_smap[i].addr == ULONG_MAX)
-		{
-		  perror("fill_smap");
-		  return -1;
-		}
-	      ++count;
-	      if (i > maxcall) maxcall = i;
-	      /* printf("maxcall = %d\n", maxcall); */
-	      /* break; */
-      	    }
-	}
-    }
-  fclose(fp);
-
-  if ((count > 0) && (maxcall > 0))
-    return maxcall+1;
-  else
-    return count;
-}
-
-
-int main(int argc, char * argv[])
-{
-  int i, count, maxcall, qq;
-  smap_entry sh_smap[SH_MAXCALLS];
-  struct utsname utbuf;
-  char *p = NULL;
-
-  unsigned long proc_root;
-  unsigned long proc_root_iops;
-  unsigned long proc_root_lookup;
-
-  unsigned long addr_ni_syscall = 0;
-
-  int major, minor, micro, is64 = 0;
-
-  if (argc > 1)
-    {
-      if (strcmp(argv[1], "-h") == 0 ||  strcmp(argv[1], "--help") == 0)
-	usage(EXIT_SUCCESS);
-      else if (strcmp(argv[1], "-v") == 0 ||
-	       strcmp(argv[1], "--verbose") == 0)
-	verbose = 1;
-    }
-
-  if (0 != uname(&utbuf))
-    {
-      perror("kern_head: uname");
-      exit (EXIT_FAILURE);
-    }
-
-  if (strncmp(utbuf.release, SH_KERNEL_VERSION, 3) != 0)
-    {
-      fprintf(stderr, "kern_head: current kernel version %s does not match\n",
-	      utbuf.release);
-      fprintf(stderr, "kern_head: %s from config.h\n", SH_KERNEL_VERSION);
-      fprintf(stderr, "kern_head: continuing with %s\n", SH_KERNEL_VERSION);
-
-      p = SH_KERNEL_VERSION;
-    } else {
-      p = utbuf.release;
-    }
-
-  if (3 != sscanf(p, "%d.%d.%d", &major, &minor, &micro))
-    {
-      perror("kern_head: sscanf");
-      exit (EXIT_FAILURE);
-    }
-
-  if (major == 2)
-    {
-      if (minor != 4 && minor != 6)
-	{
-	  fprintf(stderr, "kern_head: kernel %s not supported\n", p);
-	  exit (EXIT_FAILURE);
-	}
-    }
-
-  
-  if (utbuf.machine[0] != 'i' || utbuf.machine[2] != '8' || 
-      utbuf.machine[3] != '6')
-    {
-      if (0 != strcmp(utbuf.machine, "x86_64"))
-	{
-	  fprintf(stderr, "kern_head: machine %s not supported\n", utbuf.machine);
-	  exit (EXIT_FAILURE);
-	}
-      else
-	{
-	  is64 = 1;
-	}
-    }
-
-  if (0 != getuid())
-    {
-      fprintf(stderr, "\n");
-      
-      fprintf(stderr, "NOTE:  kern_head: must run as 'root' (need to read from /dev/kmem)\n");
-      fprintf(stderr, "       If you get this message, then proceed as follows:\n");
-      fprintf(stderr, "       $ sudo ./kern_head > sh_ks.h\n");
-      fprintf(stderr, "       $ make\n\n");
-      exit (EXIT_FAILURE);
-    }
-      
-  printf("#ifndef SH_KERN_CALLS_H\n");
-  printf("#define SH_KERN_CALLS_H\n\n");
-
-  printf("\n/* Kernel %s, machine %s, %d bit -- use table callz_2p4 */\n\n", 
-	 p, utbuf.machine,
-	 (is64 == 0) ? 32 : 64,
-	 (is64 == 0) ? "syscalls_32" : "syscalls_64");
-
-  /* initiate the system call table 
-   */
-  if (is64 == 0)
-    {
-      for (i = 0; i < SH_MAXCALLS; ++i)
-	{
-	  if (syscalls_32[i] == NULL)
-	    break;
-	  strcpy(sh_smap[i].name, syscalls_32[i]);
-	  sh_smap[i].addr    = 0UL;
-	}
-      if (major > 2 || minor == 6) /* fix syscall map for 2.6 */
-	{
-	  strcpy(sh_smap[0].name,   "sys_restart_syscall");
-	  strcpy(sh_smap[180].name, "sys_pread64");
-	  strcpy(sh_smap[181].name, "sys_pwrite64");
-	}
-    }
-  else /* x86_64 */
-    {
-      for (i = 0; i < SH_MAXCALLS; ++i)
-	{
-	  if (syscalls_64[i] == NULL)
-	    break;
-	  strcpy(sh_smap[i].name, syscalls_64[i]);
-	  sh_smap[i].addr    = 0UL;
-	}
-    }
-
-  count = i;
-
-  /* get the actual number of the highest syscall and use no more.
-   * get sys_call_table and system_call
-   */
-  maxcall = fill_smap(sh_smap, count);
-  if ( maxcall < 0)
-    {
-      printf("#endif\n");
-      fprintf(stderr, "kern_head: fill_smap failed\n");
-      exit (EXIT_FAILURE);
-    }
-
-  if (addr_system_call == 0L) 
-    {
-      printf("#endif\n");
-      fprintf(stderr, 
-	      "kern_head: address of system_call not found in System.map\n");
-      fprintf(stderr, 
-	      "** This indicates that your System.map does not provide\n");
-      fprintf(stderr, 
-	      "** the required information, and thus use of the\n");
-      fprintf(stderr, 
-	      "** --with-kcheck option is not possible\n");
-      exit (EXIT_FAILURE);
-    }
-
-  for (i = 0; i < maxcall; ++i)
-    {
-      if (0 == strcmp(sh_smap[i].name, "sys_ni_syscall"))
-        {
-          addr_ni_syscall = sh_smap[i].addr;
-          break;
-        }
-    }
-
-  if (minor < 6)
-    {
-      maxcall = (maxcall > 256) ? 256 : maxcall;
-    }
-
-  for (i = 0; i < maxcall; ++i)
-    {
-      if (sh_smap[i].addr == 0UL)
-        {
-          if (verbose > 0)
-            fprintf(stderr, "** unknown syscall **: [%s]\n", sh_smap[i].name);
-          strcpy(sh_smap[i].name, "sys_ni_syscall");
-          sh_smap[i].addr = addr_ni_syscall;
-        }
-    }
-
-
-  /* get the location of the syscall table address within system_call
-   */
-  if ( get_dispatch (&qq) < 0)
-    {
-      printf("#endif\n");
-      fprintf(stderr, "kern_head: get_dispatch failed\n");
-      exit (EXIT_FAILURE);
-    }
-
-  if (qq <= 252)
-    printf("#define SYS_CALL_LOC  %d\n", qq);
-  else
-    {
-      printf("#endif\n");
-      fprintf(stderr, "kern_head: SYS_CALL_LOC (%d) too large\n", qq);
-      exit(EXIT_FAILURE);
-    }
-  printf("#define SH_SYS_CALL_ADDR %#lx\n\n", addr_system_call);
-
-  printf("static unsigned char system_call_code[256] = { 0 };\n");
-
-  printf("#define SH_MAXCALLS %d\n\n", maxcall);
-
-#ifdef SH_IDT_TABLE
-  printf("static unsigned char idt_table[2048] = { 0 };\n");
-#endif
-
-  printf("typedef struct _sh_syscall_t {\n");
-#ifdef SH_SYSCALL_CODE
-  printf("  unsigned int  code[2];  /* 8 bytes */\n");
-#endif
-  printf("  unsigned long addr;\n");
-  printf("  char *        name;\n");
-  printf("} sh_syscall_t;\n\n");
-
-  printf("static sh_syscall_t sh_syscalls[] = {\n");
-
-  for (i = 0; i < maxcall; ++i) 
-    {
-#ifdef SH_SYSCALL_CODE
-      printf(" /* %03d */   { { 0, 0 }, 0, N_(%c%s%c) },\n", 
-	     i, '"', sh_smap[i].name, '"');
-#else
-      printf(" /* %03d */   { 0, N_(%c%s%c) },\n", 
-	     i, '"', sh_smap[i].name, '"');
-#endif
-    }
-#ifdef SH_SYSCALL_CODE
-  printf(" /* eof */   { { 0x00000000, 0x00000000 }, 0x00000000,  NULL }\n");
-#else
-  printf(" /* eof */   { 0x00000000,  NULL }\n");
-#endif
-  printf("};\n\n");
-
-
-  /* get proc addresses
-   */
-  proc_root =  get_symbol_from_systemmap (SYSTEMMAP, 
-                                          "proc_root", 'D');
-  if (proc_root == 0) 
-    {
-      proc_root =  get_symbol_from_systemmap (SYSTEMMAP, 
-                                              "proc_root", 'd');
-    }
-  if (proc_root == 0) 
-    {
-      proc_root =  get_symbol_from_systemmap (SYSTEMMAP, 
-                                              "proc_root", 'R');
-    }
-  if (proc_root != 0) {
-    printf("#define PROC_ROOT_LOC %#lx\n\n", proc_root);
-  }
-
-  proc_root_lookup =  get_symbol_from_systemmap (SYSTEMMAP, 
-                                                 "proc_root_lookup", 't');
-  if (proc_root_lookup == 0) 
-    {
-      proc_root_lookup =  get_symbol_from_systemmap (SYSTEMMAP, 
-                                                     "proc_root_lookup", 'T');
-    }
-  if (proc_root_lookup != 0) {
-    printf("#define PROC_ROOT_LOOKUP_LOC %#lx\n\n", proc_root_lookup);
-  }
-
-  proc_root_iops =  get_symbol_from_systemmap (SYSTEMMAP, 
-                                               "proc_root_inode_operations", 
-                                               'd');
-  if (proc_root_iops == 0) 
-    {
-      proc_root_iops = get_symbol_from_systemmap (SYSTEMMAP, 
-                                                  "proc_root_inode_operations",
-                                                  'D');
-    }
-  if (proc_root_iops == 0) 
-    {
-      proc_root_iops = get_symbol_from_systemmap (SYSTEMMAP, 
-                                                  "proc_root_inode_operations",
-                                                  'R');
-    }
-  if (proc_root_iops != 0) {
-    printf("#define PROC_ROOT_IOPS_LOC %#lx\n\n", proc_root_iops);
-  }
-
-  if (KERNEL_VERSION(major,minor,micro) >= KERNEL_VERSION(2,6,17)) 
-    {
-      printf("#define TWO_SIX_SEVENTEEN_PLUS 1\n\n");
-    }
-
-  printf("#endif\n");
-
-  exit (EXIT_SUCCESS);
-}
-
-/* if defined(HOST_IS_LINUX) */
-#endif
-
-/************************************************************
- *
- *
- *  FreeBSD Implementation
- *
- ************************************************************/
-
-#if defined(HOST_IS_FREEBSD) || defined(__OpenBSD__)
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <err.h>
-#include <kvm.h>
-#include <fcntl.h>
-#include <nlist.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/utsname.h>
-
-#ifdef __FreeBSD__
-#include <sys/sysent.h>
-#endif
-
-#include <sys/syscall.h>
-
-#ifndef  SYS_MAXSYSCALL
-#define  SYS_MAXSYSCALL	512
-#endif
-
-/* number of system calls */
-#define SH_MAXCALLS 512
-#include "kern_head.h"
-static int verbose = 0;
-
-#ifdef __OpenBSD__
-struct proc;
-struct sysent {
-	short sy_narg;
-	short sy_argsize;
-	int   (*sy_call)(struct proc *, void *, register_t *);
-};
-#endif
-
-typedef struct _smap_entry {
-  unsigned int  code[2];  /* 8 bytes */
-  unsigned long addr;
-  char          name[64];
-} smap_entry;
-
-union {
-  unsigned long addr_sys_call_table;
-  unsigned char str_sys_call_table[sizeof(unsigned long)];
-} sh_sys_call;
-
-struct nlist sys_list[SYS_MAXSYSCALL+1];
-
-struct  nlist   list[2];
-
-
-int main(int argc, char * argv[])
-{
-  int i, count, which;
-  smap_entry sh_smap[SYS_MAXSYSCALL];
-  struct utsname utbuf;
-  char errbuf[_POSIX2_LINE_MAX];
-
-  struct sysent  sy;
-  unsigned long offset = 0L;
-  kvm_t *kd;
-
-  list[0].n_name = "_sysent";
-  list[1].n_name = NULL;
-
-  if (argc > 1)
-    {
-      if (strcmp(argv[1], "-h") == 0 ||  strcmp(argv[1], "--help") == 0)
-	usage(EXIT_SUCCESS);
-      else if (strcmp(argv[1], "-v") == 0 ||
-	       strcmp(argv[1], "--verbose") == 0)
-	verbose = 1;
-    }
-
-  if (0 != uname(&utbuf))
-    {
-      perror("kern_head: uname");
-      exit (EXIT_FAILURE);
-    }
-
-#ifdef __OpenBSD__
-  if      (utbuf.release[0] == '3')
-    which = 38;
-  else if (utbuf.release[0] == '4')
-    which = 40;
-#else
-  if      (utbuf.release[0] == '4')
-    which = 4;
-  else if (utbuf.release[0] == '5')
-    which = 5;
-  else if (utbuf.release[0] == '6')
-    which = 5;
-#endif
-  else
-    {
-      fprintf(stderr, "kern_head: kernel %s not supported\n", utbuf.release);
-      exit (EXIT_FAILURE);
-    }
-
-  if (utbuf.machine[0] != 'i' || utbuf.machine[2] != '8' || 
-      utbuf.machine[3] != '6')
-    {
-      fprintf(stderr, "kern_head: machine %s not supported\n", utbuf.machine);
-      exit (EXIT_FAILURE);
-    }
-
-  if (0 != getuid())
-    {
-      fprintf(stderr, "\n");
-      fprintf(stderr, "NOTE:  kern_head: must run as 'root' ");
-      fprintf(stderr, "(need to read from kernel)\n");
-      fprintf(stderr, "       If you get this message, then proceed ");
-      fprintf(stderr, "as follows:\n");
-      fprintf(stderr, "       $ su\n");
-      fprintf(stderr, "       $ ./kern_head > sh_ks.h\n");
-      fprintf(stderr, "       $ exit\n");
-      fprintf(stderr, "       $ make\n\n");
-      exit (EXIT_FAILURE);
-    }
-
-  kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
-  if (!kd)
-    {
-      fprintf(stderr, "check_sysent: kvm_openfiles: %s\n", errbuf);
-      exit(EXIT_FAILURE);
-    }
-
-  i = kvm_nlist(kd, list);
-  if (i == -1)
-    {
-      fprintf(stderr, "check_sysent: kvm_nlist: %s\n", kvm_geterr(kd));
-      exit(EXIT_FAILURE);
-    }
-  else if (i == 1)
-    {
-      fprintf(stderr, "check_sysent: kvm_nlist: _sysent not found\n");
-      exit(EXIT_FAILURE);
-    }
-  else if (list[0].n_value == 0)
-    {
-      fprintf(stderr, "check_sysent: kvm_nlist: zero address for _sysent\n");
-      exit(EXIT_FAILURE);
-    }
-
-  if (which == 4)
-    printf("\n/* Kernel %s, machine %s -- use table %s */\n\n", 
-        	 utbuf.release, utbuf.machine, "callz_fbsd");
-  else if (which == 5 || which == 6)
-    printf("\n/* Kernel %s, machine %s -- use table %s */\n\n",
-                 utbuf.release, utbuf.machine, "callz_fbsd5");
-  else if (which == 38 || which == 40)
-    printf("\n/* Kernel %s, machine %s -- use table %s */\n\n",
-                 utbuf.release, utbuf.machine, "callz_obsd");
-      
-      
-  i = 0;
-  if (which == 4) {
-    while ((callz_fbsd[i] != NULL) && (i < SYS_MAXSYSCALL))
-      {
-	sys_list[i].n_name = callz_fbsd[i];
-	/* fprintf(stderr, "sys_list[%d] = %s\n", i, sys_list[i].n_name); */
-	++i;
-      }
-    if ((utbuf.release[1] == '.') && (utbuf.release[2] == '1') && 
-	(utbuf.release[3] == '0'))
-      {
-	sys_list[336].n_name = callz_fbsd[151]; /* sendfile -> nosys */
-      }
-  } else if (which == 5 || which == 6) {
-    while ((callz_fbsd5[i] != NULL) && (i < SYS_MAXSYSCALL))
-      {
-	sys_list[i].n_name = callz_fbsd5[i];
-	/* fprintf(stderr, "sys_list[%d] = %s\n", i, sys_list[i].n_name); */
-	++i;
-      }
-  }
-  else if (which == 38 || which == 40) {
-    while ((callz_obsd[i] != NULL) && (i < SYS_MAXSYSCALL))
-      {
-	sys_list[i].n_name = callz_obsd[i];
-	/* fprintf(stderr, "sys_list[%d] = %s\n", i, sys_list[i].n_name); */
-	++i;
-      }
-  }
-  
-  count = i;
-  sys_list[i].n_name = NULL;
-   
-  i = kvm_nlist(kd, sys_list);
-  if (i == -1)
-    {
-      fprintf(stderr, "check_sysent: kvm_nlist: %s\n", kvm_geterr(kd));
-      /* exit(EXIT_FAILURE); */
-    }
-  else if (i != 0 && verbose != 0)
-     {
-	fprintf(stderr, "check_sysent: kvm_nlist: %d out of %d invalid.\n",
-		i, count);
-	fprintf(stderr, "              Probably the table in kern_head.h\n");
-	fprintf(stderr, "              is not for your kernel version.\n");
-	fprintf(stderr, "              (No reason to worry, kcheck will "\
-                                       "work anyway)\n\n");
-     }
-
-  for (i = 0; i < count /* SYS_MAXSYSCALL */; i++) 
-    {
-       if (NULL == sys_list[i].n_name)
-	 break;
-       if (!sys_list[i].n_value && 0 != strcmp(sys_list[i].n_name, "_nosys")
-	   && verbose != 0)
-	{
-	  fprintf(stderr,"check_sysent: not found: slot %03d [%s]\n", 
-		  i, sys_list[i].n_name);
-	  /* exit(EXIT_FAILURE); */
-	}
-      offset = list[0].n_value + (i*sizeof(struct sysent));
-      if (kvm_read(kd, offset, &sy, sizeof(struct sysent)) < 0)
-	{
-	  fprintf(stderr,"check_sysent: kvm_read: %s\n", kvm_geterr(kd));
-	  exit(EXIT_FAILURE);
-	}
-
-      if (verbose > 0)
-	fprintf(stderr, "(kvm_nlist) %#lx   %#lx (sysent[%03d])  %03d [%s]\n",
-		(unsigned long) sys_list[i].n_value,
-		(unsigned long) sy.sy_call,
-		i, i, sys_list[i].n_name);
-
-      if((unsigned long)sy.sy_call != sys_list[i].n_value && 
-	 sys_list[i].n_value != 0 &&
-	 0 != strcmp(sys_list[i].n_name, "_nosys") &&
-	 (unsigned long)sy.sy_call != sys_list[151].n_value)  
-	{
-          fprintf(stderr,
-                  "WARNING: (kvm_nlist) %#lx != %#lx (sysent[%03d])  %03d [%s]\n",
-		  (unsigned long) sys_list[i].n_value,
-		  (unsigned long) sy.sy_call,
-		  i, i, sys_list[i].n_name);
-	}
-      sh_smap[i].addr = (unsigned long) sy.sy_call;
-      strncpy(sh_smap[i].name, sys_list[i].n_name, 64);
-      if(kvm_read(kd, (unsigned int) sy.sy_call, &(sh_smap[i].code[0]), 
-		  2 * sizeof(unsigned int)) < 0)
-	{
-	  fprintf(stderr,"check_sysent: kvm_read: %s\n", kvm_geterr(kd));
-	  exit(EXIT_FAILURE);
-	}
-    }
-
-  if(kvm_close(kd) < 0) 
-    {
-      fprintf(stderr,"check_sysent: kvm_nlist: %s\n", kvm_geterr(kd));
-      exit(EXIT_FAILURE);
-    }
- 
-  printf("#ifndef SH_KERN_CALLS_H\n");
-  printf("#define SH_KERN_CALLS_H\n\n");
-
-  printf("#define SH_MAXCALLS %d\n\n", count);
-
-  printf("typedef struct _sh_syscall_t {\n");
-  printf("  unsigned int  code[2];  /* 8 bytes */\n");
-  printf("  unsigned long addr;\n");
-  printf("  char *        name;\n");
-  printf("} sh_syscall_t;\n\n");
-
-  printf("static sh_syscall_t sh_syscalls[] = {\n");
-  for (i = 0; i < count; ++i) {
-    printf(" /* %03d */ {{ 0x%-8.8x, 0x%-8.8x }, 0x%-8.8lx, N_(%c%s%c) },\n", 
-	   i, sh_smap[i].code[0], sh_smap[i].code[1], 
-	   sh_smap[i].addr, '"', sh_smap[i].name, '"');
-  }
-  printf(" /* eof */   { { 0x00000000, 0x00000000 }, 0x00000000,  NULL }\n");
-  printf("};\n\n");
-  printf("#endif\n");
-  return 0;
-}
-/* if defined(HOST_IS_FREEBSD) */
-#endif
-
-/* #if defined(SH_USE_KERN) */
-#else
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int main()
-{
-  printf("#ifndef SH_KERN_CALLS_H\n");
-  printf("#define SH_KERN_CALLS_H\n\n");
-
-  printf("/* Dummy header. */\n\n");
-
-  printf("typedef struct _sh_syscall_t {\n");
-  printf("  unsigned long addr;\n");
-  printf("  char *        name;\n");
-  printf("} sh_syscall_t;\n\n");
-
-  printf("#endif\n");
-
-  return (EXIT_SUCCESS);
-}
-
-/* #ifdef SH_USE_KERN */
-#endif
Index: trunk/src/rijndael-alg-fst.c
===================================================================
--- trunk/src/rijndael-alg-fst.c	(revision 476)
+++ trunk/src/rijndael-alg-fst.c	(revision 481)
@@ -1,465 +1,1235 @@
+/*	$NetBSD: rijndael-alg-fst.c,v 1.7 2005/12/11 12:20:52 christos Exp $	*/
+/*	$KAME: rijndael-alg-fst.c,v 1.10 2003/07/15 10:47:16 itojun Exp $	*/
+/**
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config_xor.h"
+
+#include <sys/types.h>
+#include <string.h>
+
+#ifdef SH_ENCRYPT
+
+typedef unsigned char u8;
+#if defined(HAVE_INT_32)
+typedef unsigned int u32;
+#elif defined(HAVE_LONG_32)
+typedef unsigned long u32;
+#elif defined(HAVE_SHORT_32)
+typedef unsigned short u32;
+#else
+#error "No 32 bit integer type found"
+#endif
+
+#include "rijndael-alg-fst.h"
+
+#define FULL_UNROLL 1
 /*
- * rijndael-alg-fst.c   v2.3   April '2000
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+static const u32 Te0[256] = {
+    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+static const u32 Te1[256] = {
+    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const u32 Te2[256] = {
+    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const u32 Te3[256] = {
+
+    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+static const u32 Te4[256] = {
+    0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+    0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+    0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+    0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+    0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+    0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+    0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+    0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+    0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+    0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+    0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+    0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+    0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+    0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+    0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+    0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+    0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+    0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+    0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+    0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+    0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+    0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+    0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+    0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+    0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+    0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+    0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+    0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+    0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+    0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+    0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+    0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+    0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+    0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+    0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+    0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+    0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+    0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+    0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+    0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+    0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+    0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+    0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+    0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+    0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+    0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+    0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+    0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+    0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+    0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+    0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+    0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+    0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+    0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+    0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+    0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+    0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+    0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+    0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+    0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+    0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+    0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+    0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+    0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+static const u32 Td0[256] = {
+    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+static const u32 Td1[256] = {
+    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+static const u32 Td2[256] = {
+    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+static const u32 Td3[256] = {
+    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+static const u32 Td4[256] = {
+    0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+    0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+    0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+    0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+    0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+    0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+    0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+    0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+    0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+    0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+    0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+    0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+    0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+    0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+    0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+    0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+    0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+    0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+    0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+    0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+    0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+    0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+    0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+    0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+    0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+    0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+    0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+    0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+    0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+    0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+    0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+    0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+    0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+    0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+    0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+    0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+    0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+    0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+    0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+    0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+    0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+    0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+    0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+    0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+    0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+    0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+    0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+    0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+    0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+    0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+    0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+    0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+    0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+    0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+    0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+    0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+    0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+    0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+    0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+    0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+    0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+    0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+    0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+    0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+static const u32 rcon[] = {
+	0x01000000, 0x02000000, 0x04000000, 0x08000000,
+	0x10000000, 0x20000000, 0x40000000, 0x80000000,
+	0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+
+#ifdef _MSC_VER
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+#define GETU32(p) SWAP(*((u32 *)(p)))
+#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
+#endif
+
+/**
+ * Expand the cipher key into the encryption key schedule.
  *
- * Optimised ANSI C code
- *
- * authors: v1.0: Antoon Bosselaers
- *          v2.0: Vincent Rijmen
- *          v2.3: Paulo Barreto
- *
- * This code is placed in the public domain.
+ * @return	the number of rounds for the given cipher key size.
  */
-
-#include "config_xor.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef SH_ENCRYPT
-
-#include "rijndael-alg-fst.h"
-
-#include "rijndael-boxes-fst.h"
-
-#if defined(GCC_VERSION_MAJOR)
-#if (GCC_VERSION_MAJOR > 4) || ((GCC_VERSION_MAJOR == 4) && (GCC_VERSION_MINOR > 4))
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
-#endif
-
-int rijndaelKeySched(word8 k[MAXKC][4], word8 W[MAXROUNDS+1][4][4], int ROUNDS) {
-	/* Calculate the necessary round keys
-	 * The number of calculations depends on keyBits and blockBits
-	 */ 
-	int j, r, t, rconpointer = 0;
-	word8 tk[MAXKC][4] = { { 0 } }; /* init for llvm/clang analyzer */
-	int KC = ROUNDS - 6;
-	word32 tmp;
-
-	for (j = KC-1; j >= 0; j--) {
-	  memmove( &(tk[j]), &(k[j]), sizeof(word32));
-	}
-	r = 0;
-	t = 0;
-
-	/* copy values into round key array */
-	for (j = 0; (j < KC) && (r < ROUNDS + 1); ) {
-		for (; (j < KC) && (t < 4); j++, t++) {
-		  memmove( &(W[r][t]), &(tk[j]), sizeof(word32));
- 		}
-		if (t == 4) {
-			r++;
-			t = 0;
+int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+   	int i = 0;
+	u32 temp;
+
+	rk[0] = GETU32(cipherKey     );
+	rk[1] = GETU32(cipherKey +  4);
+	rk[2] = GETU32(cipherKey +  8);
+	rk[3] = GETU32(cipherKey + 12);
+	if (keyBits == 128) {
+		for (;;) {
+			temp  = rk[3];
+			rk[4] = rk[0] ^
+				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+				(Te4[(temp >> 24)       ] & 0x000000ff) ^
+				rcon[i];
+			rk[5] = rk[1] ^ rk[4];
+			rk[6] = rk[2] ^ rk[5];
+			rk[7] = rk[3] ^ rk[6];
+			if (++i == 10) {
+				return 10;
+			}
+			rk += 4;
 		}
 	}
-		
-	while (r < ROUNDS + 1) { /* while not enough round key material calculated */
-		/* calculate new values */
-		tk[0][0] ^= S[tk[KC-1][1]];
-		tk[0][1] ^= S[tk[KC-1][2]];
-		tk[0][2] ^= S[tk[KC-1][3]];
-		tk[0][3] ^= S[tk[KC-1][0]];
-		tk[0][0] ^= rcon[rconpointer++];
-
-		if (KC != 8) {
-			for (j = 1; j < KC; j++) {
-			  tmp = *((word32*)tk[j-1]);
-			  *((word32*)tk[j]) ^= tmp;
+	rk[4] = GETU32(cipherKey + 16);
+	rk[5] = GETU32(cipherKey + 20);
+	if (keyBits == 192) {
+		for (;;) {
+			temp = rk[ 5];
+			rk[ 6] = rk[ 0] ^
+				(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+				(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+				(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+				(Te4[(temp >> 24)       ] & 0x000000ff) ^
+				rcon[i];
+			rk[ 7] = rk[ 1] ^ rk[ 6];
+			rk[ 8] = rk[ 2] ^ rk[ 7];
+			rk[ 9] = rk[ 3] ^ rk[ 8];
+			if (++i == 8) {
+				return 12;
 			}
-		} else {
-			for (j = 1; j < KC/2; j++) {
-			  tmp = *((word32*)tk[j-1]);
-			  *((word32*)tk[j]) ^= tmp;
+			rk[10] = rk[ 4] ^ rk[ 9];
+			rk[11] = rk[ 5] ^ rk[10];
+			rk += 6;
+		}
+	}
+	rk[6] = GETU32(cipherKey + 24);
+	rk[7] = GETU32(cipherKey + 28);
+	if (keyBits == 256) {
+        for (;;) {
+        	temp = rk[ 7];
+        	rk[ 8] = rk[ 0] ^
+        		(Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+        		(Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+        		(Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+        		(Te4[(temp >> 24)       ] & 0x000000ff) ^
+        		rcon[i];
+        	rk[ 9] = rk[ 1] ^ rk[ 8];
+        	rk[10] = rk[ 2] ^ rk[ 9];
+        	rk[11] = rk[ 3] ^ rk[10];
+			if (++i == 7) {
+				return 14;
 			}
-			tk[KC/2][0] ^= S[tk[KC/2 - 1][0]];
-			tk[KC/2][1] ^= S[tk[KC/2 - 1][1]];
-			tk[KC/2][2] ^= S[tk[KC/2 - 1][2]];
-			tk[KC/2][3] ^= S[tk[KC/2 - 1][3]];
-			for (j = KC/2 + 1; j < KC; j++) {
-			        tmp = *((word32*)tk[j-1]);
-				*((word32*)tk[j]) ^= tmp;
-			}
-		}
-		/* copy values into round key array */
-		for (j = 0; (j < KC) && (r < ROUNDS + 1); ) {
-			for (; (j < KC) && (t < 4); j++, t++) {
-			  memmove( &(W[r][t]), &(tk[j]), sizeof(word32));
-			}
-			if (t == 4) {
-				r++;
-				t = 0;
-			}
-		}
-	}		
+        	temp = rk[11];
+        	rk[12] = rk[ 4] ^
+        		(Te4[(temp >> 24)       ] & 0xff000000) ^
+        		(Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
+        		(Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
+        		(Te4[(temp      ) & 0xff] & 0x000000ff);
+        	rk[13] = rk[ 5] ^ rk[12];
+        	rk[14] = rk[ 6] ^ rk[13];
+        	rk[15] = rk[ 7] ^ rk[14];
+
+			rk += 8;
+        }
+	}
 	return 0;
 }
 
-int rijndaelKeyEncToDec(word8 W[MAXROUNDS+1][4][4], int ROUNDS) {
-	int r;
-	word8 *w;
-
-	for (r = 1; r < ROUNDS; r++) {
-		w = W[r][0];
-		*((word32*)w) =
-			  *((word32*)U1[w[0]])
-			^ *((word32*)U2[w[1]])
-			^ *((word32*)U3[w[2]])
-			^ *((word32*)U4[w[3]]);
-
-		w = W[r][1];
-		*((word32*)w) =
-			  *((word32*)U1[w[0]])
-			^ *((word32*)U2[w[1]])
-			^ *((word32*)U3[w[2]])
-			^ *((word32*)U4[w[3]]);
-
-		w = W[r][2];
-		*((word32*)w) =
-			  *((word32*)U1[w[0]])
-			^ *((word32*)U2[w[1]])
-			^ *((word32*)U3[w[2]])
-			^ *((word32*)U4[w[3]]);
-
-		w = W[r][3];
-		*((word32*)w) =
-			  *((word32*)U1[w[0]])
-			^ *((word32*)U2[w[1]])
-			^ *((word32*)U3[w[2]])
-			^ *((word32*)U4[w[3]]);
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return	the number of rounds for the given cipher key size.
+ */
+int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+	int Nr, i, j;
+	u32 temp;
+
+	/* expand the cipher key: */
+	Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+	/* invert the order of the round keys: */
+	for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
+		temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+		temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+		temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
 	}
-	return 0;
-}	
-
-/**
- * Encrypt a single block. 
- */
-int rijndaelEncrypt(word8 a[16], word8 b[16], word8 rk[MAXROUNDS+1][4][4], int ROUNDS) {
-	int r;
-	union {
-	  word32 tem4[4];
-	  word8  temp[4][4];
-	} tmpU;
-	tmpU.tem4[0] = tmpU.tem4[1] = tmpU.tem4[2] = tmpU.tem4[3] = 0;
-
-    tmpU.tem4[0] = *((word32*)(a   )) ^ *((word32*)rk[0][0]);
-    tmpU.tem4[1] = *((word32*)(a+ 4)) ^ *((word32*)rk[0][1]);
-    tmpU.tem4[2] = *((word32*)(a+ 8)) ^ *((word32*)rk[0][2]);
-    tmpU.tem4[3] = *((word32*)(a+12)) ^ *((word32*)rk[0][3]);
-    *((word32*)(b    )) = *((word32*)T1[tmpU.temp[0][0]])
-						^ *((word32*)T2[tmpU.temp[1][1]])
-						^ *((word32*)T3[tmpU.temp[2][2]]) 
-						^ *((word32*)T4[tmpU.temp[3][3]]);
-    *((word32*)(b + 4)) = *((word32*)T1[tmpU.temp[1][0]])
-						^ *((word32*)T2[tmpU.temp[2][1]])
-						^ *((word32*)T3[tmpU.temp[3][2]]) 
-						^ *((word32*)T4[tmpU.temp[0][3]]);
-    *((word32*)(b + 8)) = *((word32*)T1[tmpU.temp[2][0]])
-						^ *((word32*)T2[tmpU.temp[3][1]])
-						^ *((word32*)T3[tmpU.temp[0][2]]) 
-						^ *((word32*)T4[tmpU.temp[1][3]]);
-    *((word32*)(b +12)) = *((word32*)T1[tmpU.temp[3][0]])
-						^ *((word32*)T2[tmpU.temp[0][1]])
-						^ *((word32*)T3[tmpU.temp[1][2]]) 
-						^ *((word32*)T4[tmpU.temp[2][3]]);
-	for (r = 1; r < ROUNDS-1; r++) {
-		tmpU.tem4[0] = *((word32*)(b   )) ^ *((word32*)rk[r][0]);
-		tmpU.tem4[1] = *((word32*)(b+ 4)) ^ *((word32*)rk[r][1]);
-		tmpU.tem4[2] = *((word32*)(b+ 8)) ^ *((word32*)rk[r][2]);
-		tmpU.tem4[3] = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
-
-		*((word32*)(b    )) = *((word32*)T1[tmpU.temp[0][0]])
-							^ *((word32*)T2[tmpU.temp[1][1]])
-							^ *((word32*)T3[tmpU.temp[2][2]]) 
-							^ *((word32*)T4[tmpU.temp[3][3]]);
-		*((word32*)(b + 4)) = *((word32*)T1[tmpU.temp[1][0]])
-							^ *((word32*)T2[tmpU.temp[2][1]])
-							^ *((word32*)T3[tmpU.temp[3][2]]) 
-							^ *((word32*)T4[tmpU.temp[0][3]]);
-		*((word32*)(b + 8)) = *((word32*)T1[tmpU.temp[2][0]])
-							^ *((word32*)T2[tmpU.temp[3][1]])
-							^ *((word32*)T3[tmpU.temp[0][2]]) 
-							^ *((word32*)T4[tmpU.temp[1][3]]);
-		*((word32*)(b +12)) = *((word32*)T1[tmpU.temp[3][0]])
-							^ *((word32*)T2[tmpU.temp[0][1]])
-							^ *((word32*)T3[tmpU.temp[1][2]]) 
-							^ *((word32*)T4[tmpU.temp[2][3]]);
+	/* apply the inverse MixColumn transform to all round keys but the first and the last: */
+	for (i = 1; i < Nr; i++) {
+		rk += 4;
+		rk[0] =
+			Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
+			Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
+			Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
+			Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
+		rk[1] =
+			Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
+			Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
+			Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
+			Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
+		rk[2] =
+			Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
+			Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
+			Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
+			Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
+		rk[3] =
+			Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
+			Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
+			Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
+			Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
 	}
-	/* last round is special */   
-	tmpU.tem4[0] = *((word32*)(b   )) ^ *((word32*)rk[ROUNDS-1][0]);
-	tmpU.tem4[1] = *((word32*)(b+ 4)) ^ *((word32*)rk[ROUNDS-1][1]);
-	tmpU.tem4[2] = *((word32*)(b+ 8)) ^ *((word32*)rk[ROUNDS-1][2]);
-	tmpU.tem4[3] = *((word32*)(b+12)) ^ *((word32*)rk[ROUNDS-1][3]);
-	b[ 0] = T1[tmpU.temp[0][0]][1];
-	b[ 1] = T1[tmpU.temp[1][1]][1];
-	b[ 2] = T1[tmpU.temp[2][2]][1];
-	b[ 3] = T1[tmpU.temp[3][3]][1];
-	b[ 4] = T1[tmpU.temp[1][0]][1];
-	b[ 5] = T1[tmpU.temp[2][1]][1];
-	b[ 6] = T1[tmpU.temp[3][2]][1];
-	b[ 7] = T1[tmpU.temp[0][3]][1];
-	b[ 8] = T1[tmpU.temp[2][0]][1];
-	b[ 9] = T1[tmpU.temp[3][1]][1];
-	b[10] = T1[tmpU.temp[0][2]][1];
-	b[11] = T1[tmpU.temp[1][3]][1];
-	b[12] = T1[tmpU.temp[3][0]][1];
-	b[13] = T1[tmpU.temp[0][1]][1];
-	b[14] = T1[tmpU.temp[1][2]][1];
-	b[15] = T1[tmpU.temp[2][3]][1];
-	*((word32*)(b   )) ^= *((word32*)rk[ROUNDS][0]);
-	*((word32*)(b+ 4)) ^= *((word32*)rk[ROUNDS][1]);
-	*((word32*)(b+ 8)) ^= *((word32*)rk[ROUNDS][2]);
-	*((word32*)(b+12)) ^= *((word32*)rk[ROUNDS][3]);
-
-	return 0;
+	return Nr;
 }
 
-/**
- * Decrypt a single block.
- */
-int rijndaelDecrypt(word8 a[16], word8 b[16], word8 rk[MAXROUNDS+1][4][4], int ROUNDS) {
-	int r;
-	union {
-	  word32 tem4[4];
-	  word8  temp[4][4];
-	} tmpU;
-	tmpU.tem4[0] = tmpU.tem4[1] = tmpU.tem4[2] = tmpU.tem4[3] = 0;
-	
-    tmpU.tem4[0] = *((word32*)(a   )) ^ *((word32*)rk[ROUNDS][0]);
-    tmpU.tem4[1] = *((word32*)(a+ 4)) ^ *((word32*)rk[ROUNDS][1]);
-    tmpU.tem4[2] = *((word32*)(a+ 8)) ^ *((word32*)rk[ROUNDS][2]);
-    tmpU.tem4[3] = *((word32*)(a+12)) ^ *((word32*)rk[ROUNDS][3]);
-
-    *((word32*)(b   )) = *((word32*)T5[tmpU.temp[0][0]])
-           ^ *((word32*)T6[tmpU.temp[3][1]])
-           ^ *((word32*)T7[tmpU.temp[2][2]]) 
-           ^ *((word32*)T8[tmpU.temp[1][3]]);
-	*((word32*)(b+ 4)) = *((word32*)T5[tmpU.temp[1][0]])
-           ^ *((word32*)T6[tmpU.temp[0][1]])
-           ^ *((word32*)T7[tmpU.temp[3][2]]) 
-           ^ *((word32*)T8[tmpU.temp[2][3]]);
-	*((word32*)(b+ 8)) = *((word32*)T5[tmpU.temp[2][0]])
-           ^ *((word32*)T6[tmpU.temp[1][1]])
-           ^ *((word32*)T7[tmpU.temp[0][2]]) 
-           ^ *((word32*)T8[tmpU.temp[3][3]]);
-	*((word32*)(b+12)) = *((word32*)T5[tmpU.temp[3][0]])
-           ^ *((word32*)T6[tmpU.temp[2][1]])
-           ^ *((word32*)T7[tmpU.temp[1][2]]) 
-           ^ *((word32*)T8[tmpU.temp[0][3]]);
-	for (r = ROUNDS-1; r > 1; r--) {
-		tmpU.tem4[0] = *((word32*)(b   )) ^ *((word32*)rk[r][0]);
-		tmpU.tem4[1] = *((word32*)(b+ 4)) ^ *((word32*)rk[r][1]);
-		tmpU.tem4[2] = *((word32*)(b+ 8)) ^ *((word32*)rk[r][2]);
-		tmpU.tem4[3] = *((word32*)(b+12)) ^ *((word32*)rk[r][3]);
-		*((word32*)(b   )) = *((word32*)T5[tmpU.temp[0][0]])
-           ^ *((word32*)T6[tmpU.temp[3][1]])
-           ^ *((word32*)T7[tmpU.temp[2][2]]) 
-           ^ *((word32*)T8[tmpU.temp[1][3]]);
-		*((word32*)(b+ 4)) = *((word32*)T5[tmpU.temp[1][0]])
-           ^ *((word32*)T6[tmpU.temp[0][1]])
-           ^ *((word32*)T7[tmpU.temp[3][2]]) 
-           ^ *((word32*)T8[tmpU.temp[2][3]]);
-		*((word32*)(b+ 8)) = *((word32*)T5[tmpU.temp[2][0]])
-           ^ *((word32*)T6[tmpU.temp[1][1]])
-           ^ *((word32*)T7[tmpU.temp[0][2]]) 
-           ^ *((word32*)T8[tmpU.temp[3][3]]);
-		*((word32*)(b+12)) = *((word32*)T5[tmpU.temp[3][0]])
-           ^ *((word32*)T6[tmpU.temp[2][1]])
-           ^ *((word32*)T7[tmpU.temp[1][2]]) 
-           ^ *((word32*)T8[tmpU.temp[0][3]]);
-	}
-	/* last round is special */   
-	tmpU.tem4[0] = *((word32*)(b   )) ^ *((word32*)rk[1][0]);
-	tmpU.tem4[1] = *((word32*)(b+ 4)) ^ *((word32*)rk[1][1]);
-	tmpU.tem4[2] = *((word32*)(b+ 8)) ^ *((word32*)rk[1][2]);
-	tmpU.tem4[3] = *((word32*)(b+12)) ^ *((word32*)rk[1][3]);
-	b[ 0] = S5[tmpU.temp[0][0]];
-	b[ 1] = S5[tmpU.temp[3][1]];
-	b[ 2] = S5[tmpU.temp[2][2]];
-	b[ 3] = S5[tmpU.temp[1][3]];
-	b[ 4] = S5[tmpU.temp[1][0]];
-	b[ 5] = S5[tmpU.temp[0][1]];
-	b[ 6] = S5[tmpU.temp[3][2]];
-	b[ 7] = S5[tmpU.temp[2][3]];
-	b[ 8] = S5[tmpU.temp[2][0]];
-	b[ 9] = S5[tmpU.temp[1][1]];
-	b[10] = S5[tmpU.temp[0][2]];
-	b[11] = S5[tmpU.temp[3][3]];
-	b[12] = S5[tmpU.temp[3][0]];
-	b[13] = S5[tmpU.temp[2][1]];
-	b[14] = S5[tmpU.temp[1][2]];
-	b[15] = S5[tmpU.temp[0][3]];
-	*((word32*)(b   )) ^= *((word32*)rk[0][0]);
-	*((word32*)(b+ 4)) ^= *((word32*)rk[0][1]);
-	*((word32*)(b+ 8)) ^= *((word32*)rk[0][2]);
-	*((word32*)(b+12)) ^= *((word32*)rk[0][3]);
-
-	return 0;
+void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(pt     ) ^ rk[0];
+	s1 = GETU32(pt +  4) ^ rk[1];
+	s2 = GETU32(pt +  8) ^ rk[2];
+	s3 = GETU32(pt + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+    /* round 1: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
+   	/* round 2: */
+   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
+   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
+   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
+   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
+    /* round 3: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
+   	/* round 4: */
+   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
+   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
+   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
+   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
+    /* round 5: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
+   	/* round 6: */
+   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
+   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
+   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
+   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
+    /* round 7: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
+   	/* round 8: */
+   	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
+   	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
+   	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
+   	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
+    /* round 9: */
+   	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
+   	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
+   	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
+   	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
+    if (Nr > 10) {
+        /* round 10: */
+        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+        /* round 11: */
+        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+        if (Nr > 12) {
+            /* round 12: */
+            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+            /* round 13: */
+            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+        }
+    }
+    rk += Nr << 2;
+#else  /* !FULL_UNROLL */
+    /*
+	 * Nr - 1 full rounds:
+	 */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Te0[(s0 >> 24)       ] ^
+            Te1[(s1 >> 16) & 0xff] ^
+            Te2[(s2 >>  8) & 0xff] ^
+            Te3[(s3      ) & 0xff] ^
+            rk[4];
+        t1 =
+            Te0[(s1 >> 24)       ] ^
+            Te1[(s2 >> 16) & 0xff] ^
+            Te2[(s3 >>  8) & 0xff] ^
+            Te3[(s0      ) & 0xff] ^
+            rk[5];
+        t2 =
+            Te0[(s2 >> 24)       ] ^
+            Te1[(s3 >> 16) & 0xff] ^
+            Te2[(s0 >>  8) & 0xff] ^
+            Te3[(s1      ) & 0xff] ^
+            rk[6];
+        t3 =
+            Te0[(s3 >> 24)       ] ^
+            Te1[(s0 >> 16) & 0xff] ^
+            Te2[(s1 >>  8) & 0xff] ^
+            Te3[(s2      ) & 0xff] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Te0[(t0 >> 24)       ] ^
+            Te1[(t1 >> 16) & 0xff] ^
+            Te2[(t2 >>  8) & 0xff] ^
+            Te3[(t3      ) & 0xff] ^
+            rk[0];
+        s1 =
+            Te0[(t1 >> 24)       ] ^
+            Te1[(t2 >> 16) & 0xff] ^
+            Te2[(t3 >>  8) & 0xff] ^
+            Te3[(t0      ) & 0xff] ^
+            rk[1];
+        s2 =
+            Te0[(t2 >> 24)       ] ^
+            Te1[(t3 >> 16) & 0xff] ^
+            Te2[(t0 >>  8) & 0xff] ^
+            Te3[(t1      ) & 0xff] ^
+            rk[2];
+        s3 =
+            Te0[(t3 >> 24)       ] ^
+            Te1[(t0 >> 16) & 0xff] ^
+            Te2[(t1 >>  8) & 0xff] ^
+            Te3[(t2      ) & 0xff] ^
+            rk[3];
+    }
+#endif /* ?FULL_UNROLL */
+    /*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+	s0 =
+		(Te4[(t0 >> 24)       ] & 0xff000000) ^
+		(Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+		(Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+		(Te4[(t3      ) & 0xff] & 0x000000ff) ^
+		rk[0];
+	PUTU32(ct     , s0);
+	s1 =
+		(Te4[(t1 >> 24)       ] & 0xff000000) ^
+		(Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+		(Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+		(Te4[(t0      ) & 0xff] & 0x000000ff) ^
+		rk[1];
+	PUTU32(ct +  4, s1);
+	s2 =
+		(Te4[(t2 >> 24)       ] & 0xff000000) ^
+		(Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+		(Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+		(Te4[(t1      ) & 0xff] & 0x000000ff) ^
+		rk[2];
+	PUTU32(ct +  8, s2);
+	s3 =
+		(Te4[(t3 >> 24)       ] & 0xff000000) ^
+		(Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+		(Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+		(Te4[(t2      ) & 0xff] & 0x000000ff) ^
+		rk[3];
+	PUTU32(ct + 12, s3);
 }
 
-#ifdef INTERMEDIATE_VALUE_KAT
-/**
- * Encrypt only a certain number of rounds.
- * Only used in the Intermediate Value Known Answer Test.
- */
-int rijndaelEncryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds) {
-	int r;
-	word8 temp[4][4];
-
-	/* make number of rounds sane */
-	if (rounds > ROUNDS) {
-		rounds = ROUNDS;
-	}
-
-	*((word32*)a[0]) = *((word32*)a[0]) ^ *((word32*)rk[0][0]);
-	*((word32*)a[1]) = *((word32*)a[1]) ^ *((word32*)rk[0][1]);
-	*((word32*)a[2]) = *((word32*)a[2]) ^ *((word32*)rk[0][2]);
-	*((word32*)a[3]) = *((word32*)a[3]) ^ *((word32*)rk[0][3]);
-
-	for (r = 1; (r <= rounds) && (r < ROUNDS); r++) {
-		*((word32*)temp[0]) = *((word32*)T1[a[0][0]])
-           ^ *((word32*)T2[a[1][1]])
-           ^ *((word32*)T3[a[2][2]]) 
-           ^ *((word32*)T4[a[3][3]]);
-		*((word32*)temp[1]) = *((word32*)T1[a[1][0]])
-           ^ *((word32*)T2[a[2][1]])
-           ^ *((word32*)T3[a[3][2]]) 
-           ^ *((word32*)T4[a[0][3]]);
-		*((word32*)temp[2]) = *((word32*)T1[a[2][0]])
-           ^ *((word32*)T2[a[3][1]])
-           ^ *((word32*)T3[a[0][2]]) 
-           ^ *((word32*)T4[a[1][3]]);
-		*((word32*)temp[3]) = *((word32*)T1[a[3][0]])
-           ^ *((word32*)T2[a[0][1]])
-           ^ *((word32*)T3[a[1][2]]) 
-           ^ *((word32*)T4[a[2][3]]);
-		*((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[r][0]);
-		*((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[r][1]);
-		*((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[r][2]);
-		*((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[r][3]);
-	}
-	if (rounds == ROUNDS) {
-	   	/* last round is special */   
-	   	temp[0][0] = T1[a[0][0]][1];
-	   	temp[0][1] = T1[a[1][1]][1];
-	   	temp[0][2] = T1[a[2][2]][1]; 
-	   	temp[0][3] = T1[a[3][3]][1];
-	   	temp[1][0] = T1[a[1][0]][1];
-	   	temp[1][1] = T1[a[2][1]][1];
-	   	temp[1][2] = T1[a[3][2]][1]; 
-	   	temp[1][3] = T1[a[0][3]][1];
-	   	temp[2][0] = T1[a[2][0]][1];
-	   	temp[2][1] = T1[a[3][1]][1];
-	   	temp[2][2] = T1[a[0][2]][1]; 
-	   	temp[2][3] = T1[a[1][3]][1];
-	   	temp[3][0] = T1[a[3][0]][1];
-	   	temp[3][1] = T1[a[0][1]][1];
-	   	temp[3][2] = T1[a[1][2]][1]; 
-	   	temp[3][3] = T1[a[2][3]][1];
-		*((word32*)a[0]) = *((word32*)temp[0]) ^ *((word32*)rk[ROUNDS][0]);
-		*((word32*)a[1]) = *((word32*)temp[1]) ^ *((word32*)rk[ROUNDS][1]);
-		*((word32*)a[2]) = *((word32*)temp[2]) ^ *((word32*)rk[ROUNDS][2]);
-		*((word32*)a[3]) = *((word32*)temp[3]) ^ *((word32*)rk[ROUNDS][3]);
-	}
-
-	return 0;
-}   
-#endif /* INTERMEDIATE_VALUE_KAT */
-
-#ifdef INTERMEDIATE_VALUE_KAT
-/**
- * Decrypt only a certain number of rounds.
- * Only used in the Intermediate Value Known Answer Test.
- * Operations rearranged such that the intermediate values
- * of decryption correspond with the intermediate values
- * of encryption.
- */
-int rijndaelDecryptRound(word8 a[4][4], word8 rk[MAXROUNDS+1][4][4], int ROUNDS, int rounds) {
-	int r, i;
-	word8 temp[4], shift;
-
-	/* make number of rounds sane */
-	if (rounds > ROUNDS) {
-		rounds = ROUNDS;
-	}
-    /* first round is special: */
-	*(word32 *)a[0] ^= *(word32 *)rk[ROUNDS][0];
-	*(word32 *)a[1] ^= *(word32 *)rk[ROUNDS][1];
-	*(word32 *)a[2] ^= *(word32 *)rk[ROUNDS][2];
-	*(word32 *)a[3] ^= *(word32 *)rk[ROUNDS][3];
-	for (i = 0; i < 4; i++) {
-		a[i][0] = Si[a[i][0]];
-		a[i][1] = Si[a[i][1]];
-		a[i][2] = Si[a[i][2]];
-		a[i][3] = Si[a[i][3]];
-	}
-	for (i = 1; i < 4; i++) {
-		shift = (4 - i) & 3;
-		temp[0] = a[(0 + shift) & 3][i];
-		temp[1] = a[(1 + shift) & 3][i];
-		temp[2] = a[(2 + shift) & 3][i];
-		temp[3] = a[(3 + shift) & 3][i];
-		a[0][i] = temp[0];
-		a[1][i] = temp[1];
-		a[2][i] = temp[2];
-		a[3][i] = temp[3];
-	}
-	/* ROUNDS-1 ordinary rounds */
-	for (r = ROUNDS-1; r > rounds; r--) {
-		*(word32 *)a[0] ^= *(word32 *)rk[r][0];
-		*(word32 *)a[1] ^= *(word32 *)rk[r][1];
-		*(word32 *)a[2] ^= *(word32 *)rk[r][2];
-		*(word32 *)a[3] ^= *(word32 *)rk[r][3];
-
-		*((word32*)a[0]) =
-			  *((word32*)U1[a[0][0]])
-			^ *((word32*)U2[a[0][1]])
-			^ *((word32*)U3[a[0][2]])
-			^ *((word32*)U4[a[0][3]]);
-
-		*((word32*)a[1]) =
-			  *((word32*)U1[a[1][0]])
-			^ *((word32*)U2[a[1][1]])
-			^ *((word32*)U3[a[1][2]])
-			^ *((word32*)U4[a[1][3]]);
-
-		*((word32*)a[2]) =
-			  *((word32*)U1[a[2][0]])
-			^ *((word32*)U2[a[2][1]])
-			^ *((word32*)U3[a[2][2]])
-			^ *((word32*)U4[a[2][3]]);
-
-		*((word32*)a[3]) =
-			  *((word32*)U1[a[3][0]])
-			^ *((word32*)U2[a[3][1]])
-			^ *((word32*)U3[a[3][2]])
-			^ *((word32*)U4[a[3][3]]);
-		for (i = 0; i < 4; i++) {
-			a[i][0] = Si[a[i][0]];
-			a[i][1] = Si[a[i][1]];
-			a[i][2] = Si[a[i][2]];
-			a[i][3] = Si[a[i][3]];
-		}
-		for (i = 1; i < 4; i++) {
-			shift = (4 - i) & 3;
-			temp[0] = a[(0 + shift) & 3][i];
-			temp[1] = a[(1 + shift) & 3][i];
-			temp[2] = a[(2 + shift) & 3][i];
-			temp[3] = a[(3 + shift) & 3][i];
-			a[0][i] = temp[0];
-			a[1][i] = temp[1];
-			a[2][i] = temp[2];
-			a[3][i] = temp[3];
-		}
-	}
-	if (rounds == 0) {
-		/* End with the extra key addition */	
-		*(word32 *)a[0] ^= *(word32 *)rk[0][0];
-		*(word32 *)a[1] ^= *(word32 *)rk[0][1];
-		*(word32 *)a[2] ^= *(word32 *)rk[0][2];
-		*(word32 *)a[3] ^= *(word32 *)rk[0][3];
-	}    
-	return 0;
+void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+    s0 = GETU32(ct     ) ^ rk[0];
+    s1 = GETU32(ct +  4) ^ rk[1];
+    s2 = GETU32(ct +  8) ^ rk[2];
+    s3 = GETU32(ct + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+    /* round 1: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
+    /* round 2: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
+    /* round 3: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
+    /* round 4: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
+    /* round 5: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
+    /* round 6: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
+    /* round 7: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
+    /* round 8: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
+    /* round 9: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+    if (Nr > 10) {
+        /* round 10: */
+        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
+        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
+        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
+        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
+        /* round 11: */
+        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
+        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
+        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
+        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
+        if (Nr > 12) {
+            /* round 12: */
+            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
+            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
+            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
+            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
+            /* round 13: */
+            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
+            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
+            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
+            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
+        }
+    }
+	rk += Nr << 2;
+#else  /* !FULL_UNROLL */
+    /*
+     * Nr - 1 full rounds:
+     */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Td0[(s0 >> 24)       ] ^
+            Td1[(s3 >> 16) & 0xff] ^
+            Td2[(s2 >>  8) & 0xff] ^
+            Td3[(s1      ) & 0xff] ^
+            rk[4];
+        t1 =
+            Td0[(s1 >> 24)       ] ^
+            Td1[(s0 >> 16) & 0xff] ^
+            Td2[(s3 >>  8) & 0xff] ^
+            Td3[(s2      ) & 0xff] ^
+            rk[5];
+        t2 =
+            Td0[(s2 >> 24)       ] ^
+            Td1[(s1 >> 16) & 0xff] ^
+            Td2[(s0 >>  8) & 0xff] ^
+            Td3[(s3      ) & 0xff] ^
+            rk[6];
+        t3 =
+            Td0[(s3 >> 24)       ] ^
+            Td1[(s2 >> 16) & 0xff] ^
+            Td2[(s1 >>  8) & 0xff] ^
+            Td3[(s0      ) & 0xff] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Td0[(t0 >> 24)       ] ^
+            Td1[(t3 >> 16) & 0xff] ^
+            Td2[(t2 >>  8) & 0xff] ^
+            Td3[(t1      ) & 0xff] ^
+            rk[0];
+        s1 =
+            Td0[(t1 >> 24)       ] ^
+            Td1[(t0 >> 16) & 0xff] ^
+            Td2[(t3 >>  8) & 0xff] ^
+            Td3[(t2      ) & 0xff] ^
+            rk[1];
+        s2 =
+            Td0[(t2 >> 24)       ] ^
+            Td1[(t1 >> 16) & 0xff] ^
+            Td2[(t0 >>  8) & 0xff] ^
+            Td3[(t3      ) & 0xff] ^
+            rk[2];
+        s3 =
+            Td0[(t3 >> 24)       ] ^
+            Td1[(t2 >> 16) & 0xff] ^
+            Td2[(t1 >>  8) & 0xff] ^
+            Td3[(t0      ) & 0xff] ^
+            rk[3];
+    }
+#endif /* ?FULL_UNROLL */
+    /*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+   	s0 =
+   		(Td4[(t0 >> 24)       ] & 0xff000000) ^
+   		(Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+   		(Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+   		(Td4[(t1      ) & 0xff] & 0x000000ff) ^
+   		rk[0];
+	PUTU32(pt     , s0);
+   	s1 =
+   		(Td4[(t1 >> 24)       ] & 0xff000000) ^
+   		(Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+   		(Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+   		(Td4[(t2      ) & 0xff] & 0x000000ff) ^
+   		rk[1];
+	PUTU32(pt +  4, s1);
+   	s2 =
+   		(Td4[(t2 >> 24)       ] & 0xff000000) ^
+   		(Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+   		(Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+   		(Td4[(t3      ) & 0xff] & 0x000000ff) ^
+   		rk[2];
+	PUTU32(pt +  8, s2);
+   	s3 =
+   		(Td4[(t3 >> 24)       ] & 0xff000000) ^
+   		(Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+   		(Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+   		(Td4[(t0      ) & 0xff] & 0x000000ff) ^
+   		rk[3];
+	PUTU32(pt + 12, s3);
 }
-#endif /* INTERMEDIATE_VALUE_KAT */
+
 #endif
Index: trunk/src/rijndael-api-fst.c
===================================================================
--- trunk/src/rijndael-api-fst.c	(revision 476)
+++ trunk/src/rijndael-api-fst.c	(revision 481)
@@ -1,377 +1,407 @@
-/*
- * rijndael-api-fst.c   v2.3   April '2000
- *
- * Optimised ANSI C code
- *
- * authors: v1.0: Antoon Bosselaers
- *          v2.0: Vincent Rijmen
- *          v2.1: Vincent Rijmen
- *          v2.2: Vincent Rijmen
- *          v2.3: Paulo Barreto
- *          v2.4: Vincent Rijmen
- *
- * This code is placed in the public domain.
+/*	$NetBSD: rijndael-api-fst.c,v 1.24 2011/05/14 16:46:55 jmmv Exp $	*/
+
+/**
+ * rijndael-api-fst.c
+ *
+ * @version 2.9 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Acknowledgements:
+ *
+ * We are deeply indebted to the following people for their bug reports,
+ * fixes, and improvement suggestions to this implementation. Though we
+ * tried to list all contributions, we apologise in advance for any
+ * missing reference.
+ *
+ * Andrew Bales <Andrew.Bales@Honeywell.com>
+ * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
+ * John Skodon <skodonj@webquill.com>
  */
-
 #include "config_xor.h"
 
-#include <stdio.h>
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
+
 #ifdef SH_ENCRYPT
 
 #include "rijndael-api-fst.h"
 
-int makeKey(keyInstance *key, RIJ_BYTE direction, int keyLen, char *keyMaterial) {
-  word8 k[MAXKC][4];
-  int i;
-  char *keyMat;
-  
-  if (key == NULL) {
-    return BAD_KEY_INSTANCE;
-  }
-  
-  if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
-    key->direction = direction;
-  } else {
-    return BAD_KEY_DIR;
-  }
-  
-  if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 
-    key->keyLen = keyLen;
-  } else {
-    return BAD_KEY_MAT;
-  }
-  
-  if (keyMaterial != NULL) {
-    strncpy(key->keyMaterial, keyMaterial, keyLen/4);
-  }
-  
-  key->ROUNDS = keyLen/32 + 6;
-  
-  /* initialize key schedule: */
-  keyMat = key->keyMaterial;
-#ifndef BINARY_KEY_MATERIAL
-  for (i = 0; i < key->keyLen/8; i++) {
-    int t, j;
-    
-    t = *keyMat++;
-    if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
-    else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4; 
-    else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4; 
-    else return BAD_KEY_MAT;
-    
-    t = *keyMat++;
-    if ((t >= '0') && (t <= '9')) j ^= (t - '0');
-    else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10); 
-    else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10); 
-    else return BAD_KEY_MAT;
-    
-    k[i >> 2][i & 3] = (word8)j; 
-  }
-#else
-  for (i = 0; i < key->keyLen/8; i++) {
-    k[i >> 2][i & 3] = (word8)keyMat[i]; 
-  }
-#endif /* ?BINARY_KEY_MATERIAL */
-  rijndaelKeySched(k, key->keySched, key->ROUNDS);
-  if (direction == DIR_DECRYPT) {
-    rijndaelKeyEncToDec(key->keySched, key->ROUNDS);
-  }
-  
-  return TRUE;
-}
-
-int cipherInit(cipherInstance *cipher, RIJ_BYTE mode, char *IV) {
-  if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
-    cipher->mode = mode;
-  } else {
-    return BAD_CIPHER_MODE;
-  }
-  if (IV != NULL) {
-#ifndef BINARY_KEY_MATERIAL
-    int i;
-    for (i = 0; i < MAX_IV_SIZE; i++) {
-      int t, j;
-      
-      t = IV[2*i];
-      if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
-      else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4; 
-      else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4; 
-      else return BAD_CIPHER_INSTANCE;
-      
-      t = IV[2*i+1];
-      if ((t >= '0') && (t <= '9')) j ^= (t - '0');
-      else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10); 
-      else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10); 
-      else return BAD_CIPHER_INSTANCE;
-      
-      cipher->IV[i] = (word8)j;
-    }
-#else
-    memcpy(cipher->IV, IV, MAX_IV_SIZE);
-#endif /* ?BINARY_KEY_MATERIAL */
-  } else {
-    memset(cipher->IV, 0, MAX_IV_SIZE);
-  }
-  return TRUE;
-}
-
-int blockEncrypt(cipherInstance *cipher, keyInstance *key,
-		 RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer) {
-  int i, k, numBlocks;
-  union {
-    word32 bloc4[4];
-    word8  block[16];
-  } bb;
-  union {
-    word32 i4[4];
-    word8  iv[4][4];
-  } iu;
-  
-  if (cipher == NULL ||
-      key == NULL ||
-      key->direction == DIR_DECRYPT) {
-    return BAD_CIPHER_STATE;
-  }
-  if (input == NULL || inputLen <= 0) {
-    return 0; /* nothing to do */
-  }
-  
-  numBlocks = inputLen/128;
-  
-  switch (cipher->mode) {
-  case MODE_ECB: 
-    for (i = numBlocks; i > 0; i--) {
-      rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
-      input += 16;
-      outBuffer += 16;
-    }
-    break;
-    
-  case MODE_CBC:
-    /* fix the memory alignment for HP-UX 10.20 
-     * R. Wichmann  Mon Jun 18 22:36:55 CEST 2001
-     */
-#if STRICT_ALIGN 
-    memcpy(iu.iv, cipher->IV, 16); 
-    bb.bloc4[0] = iu.i4[0] ^ ((word32*)input)[0];
-    bb.bloc4[1] = iu.i4[1] ^ ((word32*)input)[1];
-    bb.bloc4[2] = iu.i4[2] ^ ((word32*)input)[2];
-    bb.bloc4[3] = iu.i4[3] ^ ((word32*)input)[3];
-#else  /* !STRICT_ALIGN */
-    ((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0];
-    ((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1];
-    ((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2];
-    ((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3];
-#endif /* ?STRICT_ALIGN */
-    rijndaelEncrypt(bb.block, outBuffer, key->keySched, key->ROUNDS);
-    input += 16;
-    for (i = numBlocks - 1; i > 0; i--) {
-      bb.bloc4[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0];
-      bb.bloc4[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1];
-      bb.bloc4[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2];
-      bb.bloc4[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3];
-      outBuffer += 16;
-      rijndaelEncrypt(bb.block, outBuffer, key->keySched, key->ROUNDS);
-      input += 16;
-    }
-    break;
-    
-  case MODE_CFB1:
-#if STRICT_ALIGN 
-    memcpy(iu.iv, cipher->IV, 16); 
-#else  /* !STRICT_ALIGN */
-    *((word32*)iv[0]) = *((word32*)(cipher->IV   ));
-    *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
-    *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
-    *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
-#endif /* ?STRICT_ALIGN */
-    for (i = numBlocks; i > 0; i--) {
-      for (k = 0; k < 128; k++) {
-	bb.bloc4[0] = iu.i4[0];
-	bb.bloc4[1] = iu.i4[1];
-	bb.bloc4[2] = iu.i4[2];
-	bb.bloc4[3] = iu.i4[3];
-	rijndaelEncrypt(bb.block, bb.block, key->keySched, key->ROUNDS);
-	outBuffer[k/8] ^= (bb.block[0] & 0x80) >> (k & 7);
-	iu.iv[0][0] = (iu.iv[0][0] << 1) | (iu.iv[0][1] >> 7);
-	iu.iv[0][1] = (iu.iv[0][1] << 1) | (iu.iv[0][2] >> 7);
-	iu.iv[0][2] = (iu.iv[0][2] << 1) | (iu.iv[0][3] >> 7);
-	iu.iv[0][3] = (iu.iv[0][3] << 1) | (iu.iv[1][0] >> 7);
-	iu.iv[1][0] = (iu.iv[1][0] << 1) | (iu.iv[1][1] >> 7);
-	iu.iv[1][1] = (iu.iv[1][1] << 1) | (iu.iv[1][2] >> 7);
-	iu.iv[1][2] = (iu.iv[1][2] << 1) | (iu.iv[1][3] >> 7);
-	iu.iv[1][3] = (iu.iv[1][3] << 1) | (iu.iv[2][0] >> 7);
-	iu.iv[2][0] = (iu.iv[2][0] << 1) | (iu.iv[2][1] >> 7);
-	iu.iv[2][1] = (iu.iv[2][1] << 1) | (iu.iv[2][2] >> 7);
-	iu.iv[2][2] = (iu.iv[2][2] << 1) | (iu.iv[2][3] >> 7);
-	iu.iv[2][3] = (iu.iv[2][3] << 1) | (iu.iv[3][0] >> 7);
-	iu.iv[3][0] = (iu.iv[3][0] << 1) | (iu.iv[3][1] >> 7);
-	iu.iv[3][1] = (iu.iv[3][1] << 1) | (iu.iv[3][2] >> 7);
-	iu.iv[3][2] = (iu.iv[3][2] << 1) | (iu.iv[3][3] >> 7);
-	iu.iv[3][3] = (iu.iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
-      }
-    }
-    break;
-    
-  default:
-    return BAD_CIPHER_STATE;
-  }
-  
-  return 128*numBlocks;
-}
-
-int blockDecrypt(cipherInstance *cipher, keyInstance *key,
-		 RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer) {
-  int i, k, numBlocks;
-  union {
-    word32 bloc4[4];
-    word8  block[16];
-  } bb;
-  union {
-    word32 i4[4];
-    word8  iv[4][4];
-  } iu;
-  
-  if (cipher == NULL ||
-      key == NULL ||
-      ((cipher->mode != MODE_CFB1) && (key->direction == DIR_ENCRYPT))) {
-    return BAD_CIPHER_STATE;
-  }
-  if (input == NULL || inputLen <= 0) {
-    return 0; /* nothing to do */
-  }
-  
-  numBlocks = inputLen/128;
-  
-  switch (cipher->mode) {
-  case MODE_ECB: 
-    for (i = numBlocks; i > 0; i--) { 
-      rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
-      input += 16;
-      outBuffer += 16;
-    }
-    break;
-    
-  case MODE_CBC:
-#if STRICT_ALIGN 
-    memcpy(iu.iv, cipher->IV, 16); 
-#else
-    *((word32*)iu.i4[0]) = *((word32*)(cipher->IV   ));
-    *((word32*)iu.i4[1]) = *((word32*)(cipher->IV+ 4));
-    *((word32*)iu.i4[2]) = *((word32*)(cipher->IV+ 8));
-    *((word32*)iu.i4[3]) = *((word32*)(cipher->IV+12));
+static void xor16(u8 *d, const u8 *a, const u8* b)
+{
+  size_t i;
+
+	for (i = 0; i < 4; i++) {
+		*d++ = *a++ ^ *b++;
+		*d++ = *a++ ^ *b++;
+		*d++ = *a++ ^ *b++;
+		*d++ = *a++ ^ *b++;
+	}
+}
+
+int
+rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen,
+    const char *keyMaterial)
+{
+	u8 cipherKey[RIJNDAEL_MAXKB];
+	int i;
+
+	if (key == NULL) {
+		return BAD_KEY_INSTANCE;
+	}
+
+	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
+		key->direction = direction;
+	} else {
+		return BAD_KEY_DIR;
+	}
+
+	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
+		key->keyLen = keyLen;
+	} else {
+		return BAD_KEY_MAT;
+	}
+
+	if (keyMaterial != NULL) {
+	        char temp[RIJNDAEL_MAX_KEY_SIZE];
+		for (i = 0; i < key->keyLen/8; i++) {
+		  int t, j;
+		  
+		  t = *keyMaterial++;
+		  if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
+		  else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4; 
+		  else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4; 
+		  else return BAD_KEY_MAT;
+		  
+		  t = *keyMaterial++;
+		  if ((t >= '0') && (t <= '9')) j ^= (t - '0');
+		  else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10); 
+		  else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10); 
+		  else return BAD_KEY_MAT;
+		  
+		  temp[i] = (u8)j; 
+		}
+
+		/* memcpy(key->keyMaterial, keyMaterial, keyLen/8); */
+		memcpy(key->keyMaterial, temp, keyLen/8);
+	}
+
+	/* initialize key schedule: */
+	memcpy(cipherKey, key->keyMaterial, keyLen/8);
+	if (direction == DIR_ENCRYPT) {
+		key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
+	} else {
+		key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
+	}
+	rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
+	return TRUE;
+}
+
+int
+rijndael_cipherInit(cipherInstance *cipher, BYTE mode, const char *IV)
+{
+	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
+		cipher->mode = mode;
+	} else {
+		return BAD_CIPHER_MODE;
+	}
+	if (IV != NULL) {
+		memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
+	} else {
+		memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
+	}
+	return TRUE;
+}
+
+int
+rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
+    const BYTE *input, int inputLen, BYTE *outBuffer)
+{
+	int i, k, t, numBlocks;
+	u8 block[16], *iv;
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_DECRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputLen <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputLen/128;
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+
+	case MODE_CBC:
+		iv = (u8 *)cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			xor16(block, input, iv);
+			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
+			iv = outBuffer;
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+
+	case MODE_CFB1:
+		iv = (u8 *)cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			memcpy(outBuffer, input, 16);
+			for (k = 0; k < 128; k++) {
+				rijndaelEncrypt(key->ek, key->Nr, iv, block);
+				outBuffer[k >> 3] ^=
+				    (block[0] & 0x80U) >> (k & 7);
+				for (t = 0; t < 15; t++) {
+					iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
+				}
+				iv[15] = (iv[15] << 1) |
+				    ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
+			}
+			outBuffer += 16;
+			input += 16;
+		}
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+
+	return 128 * numBlocks;
+}
+
+/**
+ * Encrypt data partitioned in octets, using RFC 2040-like padding.
+ *
+ * @param   input           data to be encrypted (octet sequence)
+ * @param   inputOctets		input length in octets (not bits)
+ * @param   outBuffer       encrypted output data
+ *
+ * @return	length in octets (not bits) of the encrypted output buffer.
+ */
+int
+rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
+    const BYTE *input, int inputOctets, BYTE *outBuffer)
+{
+	int i, numBlocks, padLen;
+	u8 block[16], *iv;
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_DECRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputOctets <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputOctets / 16;
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
+			input += 16;
+			outBuffer += 16;
+		}
+		padLen = 16 - (inputOctets - 16*numBlocks);
+		memcpy(block, input, 16 - padLen);
+		memset(block + 16 - padLen, padLen, padLen);
+		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
+		break;
+
+	case MODE_CBC:
+		iv = (u8 *)cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			xor16(block, input, iv);
+			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
+			iv = outBuffer;
+			input += 16;
+			outBuffer += 16;
+		}
+		padLen = 16 - (inputOctets - 16*numBlocks);
+		for (i = 0; i < 16 - padLen; i++) {
+			block[i] = input[i] ^ iv[i];
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			block[i] = (BYTE)padLen ^ iv[i];
+		}
+		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+
+	return 16 * (numBlocks + 1);
+}
+
+int
+rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
+    const BYTE *input, int inputLen, BYTE *outBuffer)
+{
+	int i, k, t, numBlocks;
+	u8 block[16], *iv;
+
+	if (cipher == NULL ||
+		key == NULL ||
+		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputLen <= 0) {
+		return 0; /* nothing to do */
+	}
+
+	numBlocks = inputLen/128;
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+
+	case MODE_CBC:
+		iv = (u8 *)cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			rijndaelDecrypt(key->rk, key->Nr, input, block);
+			xor16(block, block, iv);
+			if (numBlocks > 1)
+			  memcpy(cipher->IV, input, 16);
+			memcpy(outBuffer, block, 16);
+			input += 16;
+			outBuffer += 16;
+		}
+		break;
+
+    case MODE_CFB1:
+		iv = (u8 *)cipher->IV;
+		for (i = numBlocks; i > 0; i--) {
+			memcpy(outBuffer, input, 16);
+			for (k = 0; k < 128; k++) {
+				rijndaelEncrypt(key->ek, key->Nr, iv, block);
+				for (t = 0; t < 15; t++) {
+					iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
+				}
+				iv[15] = (iv[15] << 1) |
+				    ((input[k >> 3] >> (7 - (k & 7))) & 1);
+				outBuffer[k >> 3] ^= (block[0] & 0x80U) >>
+				    (k & 7);
+			}
+			outBuffer += 16;
+			input += 16;
+		}
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+
+	return 128 * numBlocks;
+}
+
+int
+rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
+    const BYTE *input, int inputOctets, BYTE *outBuffer)
+{
+	int i, numBlocks, padLen;
+	u8 block[16], *iv;
+
+	if (cipher == NULL ||
+		key == NULL ||
+		key->direction == DIR_ENCRYPT) {
+		return BAD_CIPHER_STATE;
+	}
+	if (input == NULL || inputOctets <= 0) {
+		return 0; /* nothing to do */
+	}
+	if (inputOctets % 16 != 0) {
+		return BAD_DATA;
+	}
+
+	numBlocks = inputOctets/16;
+
+	switch (cipher->mode) {
+	case MODE_ECB:
+		/* all blocks but last */
+		for (i = numBlocks - 1; i > 0; i--) {
+			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
+			input += 16;
+			outBuffer += 16;
+		}
+		/* last block */
+		rijndaelDecrypt(key->rk, key->Nr, input, block);
+		padLen = block[15];
+		if (padLen >= 16) {
+			return BAD_DATA;
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			if (block[i] != padLen) {
+				return BAD_DATA;
+			}
+		}
+		memcpy(outBuffer, block, 16 - padLen);
+		break;
+
+	case MODE_CBC:
+		iv = (u8 *)cipher->IV;
+		/* all blocks but last */
+		for (i = numBlocks - 1; i > 0; i--) {
+			rijndaelDecrypt(key->rk, key->Nr, input, block);
+			xor16(block, block, iv);
+			memcpy(cipher->IV, input, 16);
+			memcpy(outBuffer, block, 16);
+			input += 16;
+			outBuffer += 16;
+		}
+		/* last block */
+		rijndaelDecrypt(key->rk, key->Nr, input, block);
+		xor16(block, block, iv);
+		padLen = block[15];
+		if (padLen <= 0 || padLen > 16) {
+			return BAD_DATA;
+		}
+		for (i = 16 - padLen; i < 16; i++) {
+			if (block[i] != padLen) {
+				return BAD_DATA;
+			}
+		}
+		memcpy(outBuffer, block, 16 - padLen);
+		break;
+
+	default:
+		return BAD_CIPHER_STATE;
+	}
+
+	return 16 * numBlocks - padLen;
+}
+
 #endif
-    for (i = numBlocks; i > 0; i--) {
-      rijndaelDecrypt(input, bb.block, key->keySched, key->ROUNDS);
-      bb.bloc4[0] ^= iu.i4[0];
-      bb.bloc4[1] ^= iu.i4[1];
-      bb.bloc4[2] ^= iu.i4[2];
-      bb.bloc4[3] ^= iu.i4[3];
-#if STRICT_ALIGN
-      memcpy(iu.iv, input, 16);
-      memcpy(outBuffer, bb.block, 16);
-#else
-      *((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0];
-      *((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1];
-      *((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2];
-      *((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3];
-#endif
-      input += 16;
-      outBuffer += 16;
-    }
-    break;
-    
-  case MODE_CFB1:
-#if STRICT_ALIGN 
-    memcpy(iu.iv, cipher->IV, 16); 
-#else
-    *((word32*)iv[0]) = *((word32*)(cipher->IV));
-    *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
-    *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
-    *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
-#endif
-    for (i = numBlocks; i > 0; i--) {
-      for (k = 0; k < 128; k++) {
-	bb.bloc4[0] = iu.i4[0];
-	bb.bloc4[1] = iu.i4[1];
-	bb.bloc4[2] = iu.i4[2];
-	bb.bloc4[3] = iu.i4[3];
-	rijndaelEncrypt(bb.block, bb.block, key->keySched, key->ROUNDS);
-	iu.iv[0][0] = (iu.iv[0][0] << 1) | (iu.iv[0][1] >> 7);
-	iu.iv[0][1] = (iu.iv[0][1] << 1) | (iu.iv[0][2] >> 7);
-	iu.iv[0][2] = (iu.iv[0][2] << 1) | (iu.iv[0][3] >> 7);
-	iu.iv[0][3] = (iu.iv[0][3] << 1) | (iu.iv[1][0] >> 7);
-	iu.iv[1][0] = (iu.iv[1][0] << 1) | (iu.iv[1][1] >> 7);
-	iu.iv[1][1] = (iu.iv[1][1] << 1) | (iu.iv[1][2] >> 7);
-	iu.iv[1][2] = (iu.iv[1][2] << 1) | (iu.iv[1][3] >> 7);
-	iu.iv[1][3] = (iu.iv[1][3] << 1) | (iu.iv[2][0] >> 7);
-	iu.iv[2][0] = (iu.iv[2][0] << 1) | (iu.iv[2][1] >> 7);
-	iu.iv[2][1] = (iu.iv[2][1] << 1) | (iu.iv[2][2] >> 7);
-	iu.iv[2][2] = (iu.iv[2][2] << 1) | (iu.iv[2][3] >> 7);
-	iu.iv[2][3] = (iu.iv[2][3] << 1) | (iu.iv[3][0] >> 7);
-	iu.iv[3][0] = (iu.iv[3][0] << 1) | (iu.iv[3][1] >> 7);
-	iu.iv[3][1] = (iu.iv[3][1] << 1) | (iu.iv[3][2] >> 7);
-	iu.iv[3][2] = (iu.iv[3][2] << 1) | (iu.iv[3][3] >> 7);
-	iu.iv[3][3] = (iu.iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
-	outBuffer[k/8] ^= (bb.block[0] & 0x80) >> (k & 7);
-      }
-    }
-    break;
-    
-  default:
-    return BAD_CIPHER_STATE;
-  }
-  
-  return 128*numBlocks;
-}
-#ifdef INTERMEDIATE_VALUE_KAT
-/**
- *	cipherUpdateRounds:
- *
- *	Encrypts/Decrypts exactly one full block a specified number of rounds.
- *	Only used in the Intermediate Value Known Answer Test.	
- *
- *	Returns:
- *		TRUE - on success
- *		BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
- */
-int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
-		RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer, int rounds) {
-	int j;
-	word8 block[4][4];
-
-	if (cipher == NULL || key == NULL) {
-		return BAD_CIPHER_STATE;
-	}
-
-	for (j = 3; j >= 0; j--) {
-		/* parse input stream into rectangular array */
-  		*((word32*)block[j]) = *((word32*)(input+4*j));
-	}
-
-	switch (key->direction) {
-	case DIR_ENCRYPT:
-		rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds);
-		break;
-		
-	case DIR_DECRYPT:
-		rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds);
-		break;
-		
-	default:
-		return BAD_KEY_DIR;
-	} 
-
-	for (j = 3; j >= 0; j--) {
-		/* parse rectangular array into output ciphertext bytes */
-		*((word32*)(outBuffer+4*j)) = *((word32*)block[j]);
-	}
-	
-	return TRUE;
-}
-#endif /* INTERMEDIATE_VALUE_KAT */
-#endif
Index: trunk/src/samhain.c
===================================================================
--- trunk/src/samhain.c	(revision 476)
+++ trunk/src/samhain.c	(revision 481)
@@ -71,4 +71,5 @@
 #include "sh_readconf.h"
 #include "sh_hash.h"
+#include "sh_dbIO.h"
 #include "sh_restrict.h"
 
@@ -78,5 +79,5 @@
 #include "sh_gpg.h"
 #include "sh_mem.h"
-#include "sh_forward.h"
+#include "sh_xfer.h"
 #include "sh_tools.h"
 #include "sh_hash.h"
@@ -88,4 +89,5 @@
 #include "sh_ignore.h"
 #include "sh_prelink.h"
+#include "sh_sem.h"
 #endif
 
@@ -120,4 +122,5 @@
 volatile  int      sig_termfast;           /* SIGTERM */
 volatile  int      sig_force_check;        /* SIGTTOU */
+volatile  int      sh_load_delta_flag;
 long int           eintr__result;
 char               sh_sig_msg[SH_MINIBUF];
@@ -313,4 +316,7 @@
   ErrFlag[0] |= (1 << 11);
 #endif
+
+  sh.delayload = 0;
+
 #ifdef MKA_13
   ErrFlag[0] |= (1 << 12);
@@ -337,4 +343,5 @@
   sig_termfast           = 0;           /* SIGTERM */
   sig_force_check        = 0;           /* SIGTTOU */
+  sh_load_delta_flag     = 0;
   strcpy ( sh_sig_msg, _("None"));
 
@@ -373,4 +380,6 @@
 
   sh.pid = (UINT64) getpid();
+
+  sh.outpath = NULL;
 
   /* The flags.
@@ -647,5 +656,5 @@
     {
 
-      skey->mlock_failed = SL_FALSE;
+      skey->mlock_failed = S_FALSE;
       skey->rngI         = BAD;
       /* properly initialized later 
@@ -718,6 +727,4 @@
 #endif
 
-  SL_ENTER(_("exit_handler"));
-
 #if defined(SH_WITH_SERVER)
   sh_socket_remove ();
@@ -751,5 +758,4 @@
    */
   sh_html_zero();
-  /* sh_forward_html_write(); */
 #endif
 
@@ -775,5 +781,5 @@
 #endif
 #if defined(SH_WITH_SERVER)
-  sh_forward_free_all ();
+  sh_xfer_free_all ();
 #endif
 #if defined(SH_WITH_MAIL)
@@ -796,4 +802,8 @@
   /* --- Exit Message. ---
    */
+  if (sh.flag.exit == EXIT_FAILURE && !strcmp(sh_sig_msg, _("None")))
+    sl_strlcpy(sh_sig_msg, _("exit_failure"), SH_MINIBUF);
+  if (sh.flag.exit == EXIT_SUCCESS && !strcmp(sh_sig_msg, _("None")))
+    sl_strlcpy(sh_sig_msg, _("exit_success"), SH_MINIBUF);
   sh_error_handle ((-1), FIL__, __LINE__, sh.flag.exit, MSG_EXIT_NORMAL, 
 		   sh.prg_name, sh_sig_msg);
@@ -805,9 +815,6 @@
   /* --- Restrict error logging to stderr. ---
    */
-#ifdef WITH_MESSAGE_QUEUE
   close_ipc ();
-#endif
   sh_error_only_stderr (S_TRUE);
-
 
   /* --- Remove lock, delete critical information. ---
@@ -1215,4 +1222,260 @@
 }
 
+
+void do_reconf()
+{
+  int status, modnum;
+
+  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
+  
+  sh_thread_pause_flag = S_TRUE;
+  
+#if defined(WITH_EXTERNAL)
+  /* delete list of external tasks
+   */
+  (void) sh_ext_cleanup();
+#endif
+#if defined(SH_WITH_MAIL)
+  sh_nmail_free();
+#endif
+  
+  /* delete the file list, make all database
+   * entries visible (allignore = FALSE)
+   */
+  (void) sh_files_deldirstack ();
+  (void) sh_files_delfilestack ();
+  (void) sh_files_delglobstack ();
+  (void) sh_ignore_clean ();
+  (void) hash_full_tree ();
+  sh_audit_delete_all ();
+  
+  
+#if defined(SH_WITH_CLIENT)
+  reset_count_dev_server();
+#endif
+#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
+  sh_restrict_purge ();
+  
+  
+  FileSchedOne = free_sched(FileSchedOne);
+  FileSchedTwo = free_sched(FileSchedTwo);
+  
+  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
+    {
+      /* 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
+  
+  reset_count_dev_console();
+  reset_count_dev_time();
+  
+  (void) sh_unix_maskreset();
+  
+#ifdef RELOAD_DATABASE
+  sh_hash_hashdelete();
+
+  if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
+    {
+      char hashbuf[KEYBUF_SIZE];
+      (void) sl_strlcpy(sh.data.hash,
+			sh_tiger_hash (file_path('D', 'R'), 
+				       TIGER_FILE, TIGER_NOLIM, 
+				       hashbuf, sizeof(hashbuf)), 
+			KEY_LEN+1);
+    }
+#endif
+  (void) sl_trust_purge_user();
+  (void) sh_files_hle_reg (NULL);
+  (void) sh_prelink_run (NULL, NULL, 0, 0);
+  
+  /* --------------------------
+   * --- READ CONFIGURATION ---
+   * --------------------------
+   */
+  (void) sh_readconf_read ();
+  sig_config_read_again = 0;
+  (void) sh_files_setrec();
+  (void) sh_files_test_setup();
+  sh_audit_commit ();
+  
+  if (0 != sh.flag.nice)
+    {
+#ifdef HAVE_SETPRIORITY
+      setpriority(PRIO_PROCESS, 0, sh.flag.nice);
+#else
+      nice(sh.flag.nice);
+#endif
+    }
+  
+  if (sh.flag.checkSum == SH_CHECK_INIT)
+    {
+      sh.flag.isdaemon = S_FALSE;
+      sh.flag.loop     = S_FALSE;
+    }
+  
+  
+  /* --- Initialize modules. ---
+   */
+  TPT((0, FIL__, __LINE__, _("msg=<Initialize modules.>\n")));
+  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
+    {
+      status = modList[modnum].mod_init(&(modList[modnum]));
+      
+      if (status < 0)
+	{
+	  if (status == (-1)) {
+	    sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, 
+			     status, MSG_MOD_FAIL,
+			     _(modList[modnum].name),
+			     status+SH_MOD_OFFSET);
+	  } else {
+	    sh_error_handle ((-1), FIL__, __LINE__, 
+			     status, MSG_MOD_FAIL,
+			     _(modList[modnum].name),
+			     status+SH_MOD_OFFSET);
+	  }
+	  modList[modnum].initval = SH_MOD_FAILED;
+	}
+      else
+	{
+	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MOD_OK,
+			   _(modList[modnum].name));
+	  modList[modnum].initval = status;
+	}
+    }
+  
+  /* module is properly set up now
+   */
+  sh_thread_pause_flag = S_FALSE;
+
+  return;
+}
+
+static void check_signals (volatile int *flag_check_1, 
+			   volatile int * flag_check_2)
+{
+  if (sig_raised > 0) 
+    {
+      
+      TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
+	
+	if (sig_termfast == 1)  /* SIGTERM */
+	  {
+	    TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
+	    --sig_raised; --sig_urgent;
+	    aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+	  }
+      
+      if (sig_force_check == 1) /* SIGTTOU */
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Check run triggered.>\n")));
+	  *flag_check_1 = 1; *flag_check_2 = 1;
+	  sig_force_check = 0; --sig_raised; 
+	  sh_sem_trylock();
+	}
+      
+      if (sig_config_read_again == 1 && /* SIGHUP */
+	  sh_global_suspend_flag == 0)
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")));
+	  do_reconf();
+	  --sig_raised;
+	}
+      
+      if (sig_fresh_trail == 1) /* SIGIOT */
+	{
+	  if (sh_global_suspend_flag == 0)
+	    {
+	      SH_MUTEX_LOCK(mutex_thread_nolog);
+	      
+	      /* Logfile access 
+	       */
+#ifdef SH_USE_XML
+	      (void) sh_log_file (NULL, NULL);
+#endif
+	      TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
+	      sh_error_only_stderr (S_TRUE);
+	      (void) sh_unix_rm_lock_file(sh.srvlog.name);
+	      (void) retry_msleep(3, 0);
+	      sh.flag.log_start = S_TRUE;
+	      sh_error_only_stderr (S_FALSE);
+	      sh_thread_pause_flag = S_FALSE;
+	      sig_fresh_trail       = 0;
+	      --sig_raised;
+	      SH_MUTEX_UNLOCK(mutex_thread_nolog);
+	    }
+	}
+      
+      if (sig_terminate == 1)  /* SIGQUIT */
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
+	  strncpy (sh_sig_msg, _("Quit"), 20);
+	  --sig_raised;
+	  aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+	}
+	  
+      if (sig_debug_switch == 1)  /* SIGUSR1 */
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
+	  sh_error_dbg_switch();
+	  sig_debug_switch = 0;
+	  --sig_raised;
+	}
+	  
+      if (sig_suspend_switch > 0)  /* SIGUSR2 */
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
+	  if (sh_global_suspend_flag != 1) {
+	    SH_MUTEX_LOCK_UNSAFE(mutex_thread_nolog);
+	    sh_global_suspend_flag = 1;
+	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, 
+			    sh.prg_name);
+	  } else {
+	    sh_global_suspend_flag = 0;
+	    SH_MUTEX_UNLOCK_UNSAFE(mutex_thread_nolog);
+	  }
+	  --sig_suspend_switch;
+	  --sig_raised; --sig_urgent;
+	}
+
+      if (sh_load_delta_flag > 0 &&
+	  sh_global_suspend_flag == 0)  /* DELTA Command */
+	{
+	  if (0 == sh_dbIO_load_delta())
+	    {
+	      --sh_load_delta_flag; --sig_raised;
+	    } 
+	}
+
+      sig_raised = (sig_raised < 0) ? 0 : sig_raised;
+      sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
+      TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
+    }
+  return;
+}
+
+void check_for_delta_db()
+{
+  /* Need to contact the server.
+   */
+  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_CHECK_2);
+
+  if (sig_raised > 0 && sh_load_delta_flag > 0)  /* DELTA Command */
+    {
+      /* There was a DELTA Command
+       */
+      if (0 == sh_dbIO_load_delta())
+	{
+	  --sh_load_delta_flag; --sig_raised;
+	} 
+    }
+  return;
+}
+
 #endif
 
@@ -1229,5 +1492,5 @@
 {
 #if defined(INET_SYSLOG)
-  extern int    create_syslog_socket (int flag);
+  extern int    sh_xfer_create_syslog_socket (int flag);
 #endif
 #if defined(SH_WITH_SERVER)
@@ -1272,5 +1535,5 @@
   /* --- Close all but first three file descriptors. ---
    */
-  sh_unix_closeall(3, -1, SL_FALSE); /* at program start */
+  sh_unix_closeall(3, -1, S_FALSE); /* at program start */
 
 
@@ -1535,22 +1798,7 @@
   /* --- load database; checksum of database
    */
-#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
-  TPT((0, FIL__, __LINE__, _("msg=<Get checksum of the database.>\n")))
-  if (sh.flag.checkSum == SH_CHECK_CHECK) 
-    {
-      if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
-	{
-	  char hashbuf[KEYBUF_SIZE];
-	  (void) sl_strlcpy(sh.data.hash,
-			    sh_tiger_hash (file_path('D', 'R'), 
-					   TIGER_FILE, TIGER_NOLIM, 
-					   hashbuf, sizeof(hashbuf)), 
-			    KEY_LEN+1);
-	}
-
-      /* this eventually fetches the file from server to get checksum
-       */
-      sh_hash_init ();
-    }
+#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
+  if (0 == sh.delayload)
+    sh_hash_init_and_checksum();
 #endif
 
@@ -1564,4 +1812,12 @@
     }
 
+#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
+  if (sh.delayload)
+    {
+      sleep(sh.delayload);
+      sh_hash_init_and_checksum();
+    }
+#endif
+
   /* --- drop privileges eventually ---
    */
@@ -1569,5 +1825,5 @@
   sh_create_tcp_socket ();
 #if defined(INET_SYSLOG)
-  create_syslog_socket (S_TRUE);
+  sh_xfer_create_syslog_socket (S_TRUE);
 #endif
   SL_REQUIRE(sl_policy_get_real(DEFAULT_IDENT) == SL_ENONE, 
@@ -1591,5 +1847,5 @@
    */
 #if defined(INET_SYSLOG) && defined(SH_WITH_SERVER)
-  create_syslog_socket (S_FALSE);
+  sh_xfer_create_syslog_socket (S_FALSE);
 #endif
 
@@ -1656,5 +1912,5 @@
 
  
-  if ((skey == NULL) || (skey->mlock_failed == SL_TRUE))
+  if ((skey == NULL) || (skey->mlock_failed == S_TRUE))
     sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
 
@@ -1678,10 +1934,10 @@
   if (sh.flag.isserver == S_TRUE)
     { 
-      sh_receive();
+      sh_xfer_start_server();
       TPT((0, FIL__, __LINE__, _("msg=<End server.>\n")))
       aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
     }
 #else
-  sh_receive();
+  sh_xfer_start_server();
   TPT((0, FIL__, __LINE__, _("msg=<End server.>\n")))
   aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
@@ -1745,4 +2001,8 @@
     }
 
+  /*  --------  CREATE SEMAPHORE  ---------
+   */
+  sh_sem_open();
+
   /*  --------  MAIN LOOP  ---------
    */
@@ -1763,228 +2023,9 @@
       tcurrent = time (NULL);
 
-      if (sig_raised > 0) 
-	{
-
-	  TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
-
-	  if (sig_termfast == 1)  /* SIGTERM */
-	    {
-	      TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
-	      /* strncpy (sh_sig_msg, _("SIGTERM"), 20); */
-	      --sig_raised; --sig_urgent;
-	      aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
-	    }
-
-	  if (sig_force_check == 1) /* SIGTTOU */
-	    {
-	      TPT((0, FIL__, __LINE__, _("msg=<Check run triggered.>\n")));
-	      flag_check_1 = 1;
-	      flag_check_2 = 1;
-	      sig_force_check = 0;
-	      --sig_raised; 
-	    }
-	  
-	  if (sig_config_read_again == 1 && /* SIGHUP */
-	      sh_global_suspend_flag == 0)
-	    {
-	      TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")))
-	      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
-
-	      sh_thread_pause_flag = S_TRUE;
-
-#if defined(WITH_EXTERNAL)
-	      /* delete list of external tasks
-	       */
-	      (void) sh_ext_cleanup();
-#endif
-#if defined(SH_WITH_MAIL)
-	      sh_nmail_free();
-#endif
-
-	      /* delete the file list, make all database
-	       * entries visible (allignore = FALSE)
-	       */
-	      (void) sh_files_deldirstack ();
-	      (void) sh_files_delfilestack ();
-	      (void) sh_files_delglobstack ();
-	      (void) sh_ignore_clean ();
-	      (void) hash_full_tree ();
-	      sh_audit_delete_all ();
-
-
-#if defined(SH_WITH_CLIENT)
-	      reset_count_dev_server();
-#endif
-#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
-	      sh_restrict_purge ();
-
-
-	      FileSchedOne = free_sched(FileSchedOne);
-	      FileSchedTwo = free_sched(FileSchedTwo);
-
-	      for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
-		{
-		  /* 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
-
-	      reset_count_dev_console();
-	      reset_count_dev_time();
-
-	      (void) sh_unix_maskreset();
- 
-	      /* Should this be included ??? 
-	       * (i.e. should we reload the database ?)
-	       */
-#ifdef RELOAD_DATABASE
-	      sh_hash_hashdelete();
-
-	      if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
-		{
-		  char hashbuf[KEYBUF_SIZE];
-		  (void) sl_strlcpy(sh.data.hash,
-				    sh_tiger_hash (file_path('D', 'R'), 
-						   TIGER_FILE, TIGER_NOLIM, 
-						   hashbuf, sizeof(hashbuf)), 
-				    KEY_LEN+1);
-		}
-#endif
-	      (void) sl_trust_purge_user();
-	      (void) sh_files_hle_reg (NULL);
-	      (void) sh_prelink_run (NULL, NULL, 0);
-
-	      /* --------------------------
-	       * --- READ CONFIGURATION ---
-	       * --------------------------
-	       */
-	      (void) sh_readconf_read ();
-	      sig_config_read_again = 0;
-	      (void) sh_files_setrec();
-	      (void) sh_files_test_setup();
-	      sh_audit_commit ();
-
-	      if (0 != sh.flag.nice)
-		{
-#ifdef HAVE_SETPRIORITY
-		  setpriority(PRIO_PROCESS, 0, sh.flag.nice);
-#else
-		  nice(sh.flag.nice);
-#endif
-		}
-
-	      if (sh.flag.checkSum == SH_CHECK_INIT)
-		{
-		  sh.flag.isdaemon = S_FALSE;
-		  sh.flag.loop     = S_FALSE;
-		}
-
-
-	      /* --- Initialize modules. ---
-	       */
-	      TPT((0, FIL__, __LINE__, _("msg=<Initialize modules.>\n")));
-	      for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
-		{
-		  status = modList[modnum].mod_init(&(modList[modnum]));
-
-		  if (status < 0)
-		    {
-		      if (status == (-1)) {
-			sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, 
-					 status, MSG_MOD_FAIL,
-					 _(modList[modnum].name),
-					 status+SH_MOD_OFFSET);
-		      } else {
-			sh_error_handle ((-1), FIL__, __LINE__, 
-					 status, MSG_MOD_FAIL,
-					 _(modList[modnum].name),
-					 status+SH_MOD_OFFSET);
-		      }
-		      modList[modnum].initval = SH_MOD_FAILED;
-		    }
-		  else
-		    {
-		      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MOD_OK,
-				       _(modList[modnum].name));
-		      modList[modnum].initval = status;
-		    }
-		}
-
-	      /* module is properly set up now
-	       */
-	      sh_thread_pause_flag = S_FALSE;
-	      
-	      --sig_raised;
-	    }
-	  
-	  if (sig_fresh_trail == 1) /* SIGIOT */
-	    {
-	      if (sh_global_suspend_flag == 0)
-		{
-		  SH_MUTEX_LOCK(mutex_thread_nolog);
-
-		  /* Logfile access 
-		   */
-#ifdef SH_USE_XML
-		  (void) sh_log_file (NULL, NULL);
-#endif
-		  TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
-		  sh_error_only_stderr (S_TRUE);
-		  (void) sh_unix_rm_lock_file(sh.srvlog.name);
-		  (void) retry_msleep(3, 0);
-		  sh.flag.log_start = S_TRUE;
-		  sh_error_only_stderr (S_FALSE);
-		  sh_thread_pause_flag = S_FALSE;
-		  sig_fresh_trail       = 0;
-		  --sig_raised;
-		  SH_MUTEX_UNLOCK(mutex_thread_nolog);
-		}
-	    }
-	  
-	  if (sig_terminate == 1)  /* SIGQUIT */
-	    {
-	      TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
-	      strncpy (sh_sig_msg, _("Quit"), 20);
-	      --sig_raised; --sig_urgent;
-	      aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
-	    }
-	  
-	  if (sig_debug_switch == 1)  /* SIGUSR1 */
-	    {
-	      TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
-	      sh_error_dbg_switch();
-	      sig_debug_switch = 0;
-	      --sig_raised;
-	    }
-	  
-	  if (sig_suspend_switch > 0)  /* SIGUSR2 */
-	    {
-	      TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
-	      if (sh_global_suspend_flag != 1) {
-		SH_MUTEX_LOCK_UNSAFE(mutex_thread_nolog);
-		sh_global_suspend_flag = 1;
-		sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, 
-				sh.prg_name);
-	      } else {
-		sh_global_suspend_flag = 0;
-		SH_MUTEX_UNLOCK_UNSAFE(mutex_thread_nolog);
-	      }
-	      --sig_suspend_switch;
-	      --sig_raised; --sig_urgent;
-	    }
-	  sig_raised = (sig_raised < 0) ? 0 : sig_raised;
-	  sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
-	  TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
-	}
-      
-      if (sh_global_suspend_flag == 1)
-	{
+      do {
+	check_signals(&flag_check_1, &flag_check_2);
+	if (sh_global_suspend_flag == 1)
 	  (void) retry_msleep (1, 0);
-	  continue;
-	}
+      } while (sh_global_suspend_flag == 1);
       
       /* see whether its time to check files
@@ -2026,4 +2067,11 @@
 	  (flag_check_1 == 1 || flag_check_2 == 1))
 	{
+	  sh_sem_trylock();
+
+	  /* Starting a check now, so make sure to fetch delta DB
+	   * if there is one to download.
+	   */
+	  check_for_delta_db();
+
 	  SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_INSCAN; );
 	  /* Refresh list files matching glob patterns.
@@ -2065,7 +2113,5 @@
 	    (void) sh_files_chk ();
 
-	  if (sig_urgent > 0)
-	    continue;
-
+	  if (sig_urgent > 0) { sh_sem_unlock(sh.statistics.files_report); continue; }
 	  /*
 	   * check for files not visited
@@ -2077,6 +2123,5 @@
 	    }
 
-	  if (sig_urgent > 0)
-	    continue;
+	  if (sig_urgent > 0) { sh_sem_unlock(sh.statistics.files_report); continue; }
 
 	  /* reset
@@ -2084,18 +2129,20 @@
 	  TPT((0, FIL__, __LINE__, _("msg=<Reset status.>\n")))
 	  sh_dirs_reset  ();
-	  if (sig_urgent > 0)
-	    continue;
+
+	  if (sig_urgent > 0) { sh_sem_unlock(sh.statistics.files_report); continue; }
 
 	  sh_files_reset ();
+	  check_done   = 1;
+
 	  flag_check_1 = 0;
 	  flag_check_2 = 0;
-	  check_done   = 1;
+	  sh_sem_unlock(sh.statistics.files_report);
+
 	  SH_INOTIFY_IFUSED( sh.flag.inotify &= ~SH_INOTIFY_INSCAN; );
 	  SH_INOTIFY_IFUSED( sh.flag.inotify &= ~SH_INOTIFY_DOSCAN; );
 
-	  (void) sh_prelink_run (NULL, NULL, 0);
-
-	  if (sig_urgent > 0)
-	    continue;
+	  (void) sh_prelink_run (NULL, NULL, 0, 0);
+
+	  if (sig_urgent > 0) continue;
 
 	  runtim = time(NULL) - sh.statistics.time_start;
@@ -2130,6 +2177,5 @@
 	  sh.fileCheck.alarm_last = time (NULL);
 
-	  if (sig_urgent > 0)
-	    continue;
+	  if (sig_urgent > 0) continue;
 
 	  /*
@@ -2142,6 +2188,5 @@
 	}
       
-      if (sig_urgent > 0)
-	continue;
+      if (sig_urgent > 0) continue;
       
       /* execute modules
@@ -2161,5 +2206,5 @@
        */ 
       if      (sh.flag.checkSum == SH_CHECK_INIT)
-	sh_hash_pushdata (NULL, NULL);
+	sh_dbIO_data_write (NULL, NULL);
 
       /* write out database
@@ -2168,5 +2213,5 @@
 	  sh.flag.update == S_TRUE && 
 	  check_done == 1)
-	sh_hash_writeout ();
+	sh_dbIO_writeout_update ();
 
       /* no-op unless MEM_LOG is defined in sh_mem.c
@@ -2196,8 +2241,6 @@
       /* no loop if not daemon
        */
-      if (sh.flag.isdaemon != S_TRUE && sh.flag.loop == S_FALSE)
-	break; 
-      if (sig_urgent > 0)
-	continue;
+      if (sh.flag.isdaemon != S_TRUE && sh.flag.loop == S_FALSE) break;
+      if (sig_urgent > 0) continue;
 
       /* see whether its time to send mail
@@ -2211,6 +2254,5 @@
 	}
 #endif
-      if (sig_urgent > 0)
-	continue;
+      if (sig_urgent > 0) continue;
             
       /* log the timestamp
@@ -2232,6 +2274,5 @@
       (void) taus_seed();
       
-      if (sig_urgent > 0)
-	continue;
+      if (sig_urgent > 0) continue;
       
       /* reset cache
@@ -2266,13 +2307,4 @@
 #endif
 
-#if 0
-  {
-    char command[128];
-    sprintf(command, "/bin/cat /proc/%d/status", (int) getpid());
-    system(command); /* flawfinder: ignore *//* debug code */
-    malloc_stats();
-  }
-#endif
-
   aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
   SL_RETURN(0, _("main"));
Index: trunk/src/samhain_erase.c
===================================================================
--- trunk/src/samhain_erase.c	(revision 476)
+++ 	(revision )
@@ -1,149 +1,0 @@
-/***************************************************************************
- *
- * Purpose:
- * -------
- *   Hide loaded kernel modules with names including the string MAGIC_HIDE 
-
- *
- * Configuration:
- * -------------
- *   If not building within the samhain system, you may remove the 
- *   line '#include "config.h"' and in the line
- *   '#define MAGIC_HIDE SH_MAGIC_HIDE', replace SH_MAGIC_HIDE with
- *   "someString" (in quotes !).
- */
-
-
-#include "config.h" 
-
-#define MAGIC_HIDE SH_MAGIC_HIDE
-
-/*  #define MAGIC_HIDE "someString"              */
-
-/* define this if you have a modversioned kernel */
-/*  #define MODVERSIONS                           */
-
-/*
- * Install:
- * -------
- *   gcc -Wall -O2 -c samhain_erase.c
- *   mv samhain_hide.o  /lib/modules/KERNEL_VERSION/misc/
- *   
- *   (Replace KERNEL_VERSION with your kernel's version.)
- *
- * Usage:
- * -----
- *   To load the module:
- *    insmod samhain_hide (for improved safety: 'sync && insmod samhain_hide')
- *
- *   To unload the module 
- *    rmmod samhain_hide  (for improved safety: 'sync && rmmod samhain_hide')
- * 
- * 
- * Tested on:
- * ---------
- *   Linux 2.2
- *
- * Copyright:
- * ---------
- *   Copyright (C) 2001 Rainer Wichmann (http://la-samhna.de)
- *
- * License: 
- * -------
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License, version 2, as
- *   published by the Free Software Foundation.
- *                                                                         
- *   This program is distributed in the hope that it will be useful,        
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of         
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
- *   GNU General Public License for more details.                           
- *                                                                         
- *   You should have received a copy of the GNU General Public License      
- *   along with this program; if not, write to the Free Software            
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              
- *
- ***************************************************************************/
-
-#define __KERNEL__
-#define MODULE
-
-/* The configure options (#defines) for the Kernel
- */
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-
-#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,33)
-#include <generated/autoconf.h>
-#else
-#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,19)
-#include <linux/autoconf.h>
-#else
-#include <linux/config.h>
-#ifdef CONFIG_MODVERSIONS
-#include <linux/modversions.h>
-#endif
-#endif
-#endif
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-
-#define N_(string) string
-#include "config.h"
-
-#ifdef MODULE_LICENSE
-MODULE_LICENSE("GPL");  
-#endif
-
-#undef  NULL
-#define NULL ((void *)0)
-
-
-int init_module()
-{
-  struct module * ptr;
-  struct module * prev;
-  int             found  = 0;
-
-  ptr  = &(__this_module);
-  prev = &(__this_module);
-
-  /* skip this module to allow 'rmmod'
-   */
-  ptr  = ptr->next;
-
-  while (ptr)
-    {
-      found = 0;
-
-      if (ptr->name && ptr->name[0] != '\0')
-	{
-	  /* printk("%s <%s>\n", ptr->name, SH_MAGIC_HIDE); */
-	  if (NULL != strstr(ptr->name, SH_MAGIC_HIDE))
-	    {
-	      prev->next = ptr->next;
-	      /* printk("-->HIDE\n"); */
-	      found = 1;
-	    }
-	} 
-
-      if (ptr->next)
-	{
-	  if (found == 0)
-	    prev = ptr;
-	  ptr = ptr->next;
-	}
-      else
-	break;
-    }
-
-  return 0;
-}
-
-void cleanup_module()
-{
-	return;
-}
-
-
Index: trunk/src/samhain_hide.c
===================================================================
--- trunk/src/samhain_hide.c	(revision 476)
+++ 	(revision )
@@ -1,1044 +1,0 @@
-/***************************************************************************
- *
- * Purpose:
- * -------
- *   (1) Hide files with the string MAGIC_HIDE in filename,
- *       where MAGIC_HIDE is defined below. 
- *       By default,  MAGIC_HIDE is defined as "samhain".
- *
- *   (2) Hide all processes, if the executable has the string MAGIC_HIDE 
- *       in its name.
- *
- *
- * Configuration:
- * -------------
- *   If not building within the samhain system, you may remove the 
- *   line '#include "config.h"' and in the line
- *   '#define MAGIC_HIDE SH_MAGIC_HIDE', replace SH_MAGIC_HIDE with
- *   "someString" (in quotes !).
- */
-
-/* #define _(string) string */
-#include "config.h" 
-
-#undef _
-#define _(string) string
-
-/* define if this is a 2.6 kernel                 */
-/* #define LINUX26                                */
-
-#define MAGIC_HIDE SH_MAGIC_HIDE
-
-/*  #define MAGIC_HIDE "someString"               */
-
-/* define this if you have a modversioned kernel  */
-/*  #define MODVERSIONS                           */
-
-/* the address of the sys_call_table (not exported in 2.5 kernels) */
-#define MAGIC_ADDRESS SH_SYSCALLTABLE
-
-/*
- * Install:
- * -------
- *   gcc -Wall -O2 -c samhain_hide.c
- *   mv samhain_hide.o  /lib/modules/KERNEL_VERSION/misc/
- *   
- *   (Replace KERNEL_VERSION with your kernel's version.)
- *
- * Usage:
- * -----
- *   To load the module:
- *    insmod samhain_hide (for improved safety: 'sync && insmod samhain_hide')
- *
- *   Self-hiding can be switched off by passing the option
- *   'removeme=0' to the module: 
- *    insmod ./samhain_hide.ko removeme=0
- *
- *   To unload the module (only possible if not hidden):
- *    rmmod samhain_hide  (for improved safety: 'sync && rmmod samhain_hide')
- * 
- *
- * Details:
- * -------
- *   The following kernel syscalls are replaced:
- *     sys_getdents     [hide files/directories/processes (/proc/PID)]
- * 
- * Tested on:
- * ---------
- *   Linux 2.2, 2.4, 2.6
- *
- * Copyright:
- * ---------
- *   Copyright (C) 2001, 2002 Rainer Wichmann (http://la-samhna.de)
- *
- * License: 
- * -------
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License, version 2, as
- *   published by the Free Software Foundation.
- *                                                                         
- *   This program is distributed in the hope that it will be useful,        
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of         
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
- *   GNU General Public License for more details.                           
- *                                                                         
- *   You should have received a copy of the GNU General Public License      
- *   along with this program; if not, write to the Free Software            
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              
- *
- ***************************************************************************/
-
-
-
-/*****************************************************
- *
- *  The defines:
- *
- *****************************************************/
-
-/* This is a Linux Loadable Kernel Module.
- */
-
-#ifndef LINUX26
-#ifndef __KERNEL__
-#define __KERNEL__
-#endif
-#ifndef MODULE
-#define MODULE
-#endif
-#endif
-#define LINUX
-
-/* Define for debugging.   
- */
-/* #define HIDE_DEBUG  */   /* query_module */
-/* #define FILE_DEBUG  */   /* getdents     */
-/* #define READ_DEBUG  */   /* read         */
-/* #define PROC_DEBUG  */   /* procfs       */
-/* #define INIT_DEBUG  */   /* module init  */
-
-/*****************************************************
- *
- *  The include files:
- *
- *****************************************************/
-
-
-/* The configure options (#defines) for the Kernel
- */
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-/* 2.6.19 (((2) << 16) + ((6) << 8) + (19)) */
-#define SH_KERNEL_MIN 132627 
-
-#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,33)
-#include <generated/autoconf.h>
-#else
-#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,19)
-#include <linux/autoconf.h>
-#else
-#include <linux/config.h>
-#endif
-#endif
-
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,0)
-#ifdef CONFIG_MODVERSIONS
-#include <linux/modversions.h>
-#endif
-#else
-#ifndef LINUX26
-#define LINUX26
-#endif
-#endif
-
-#ifdef LINUX26
-#include <linux/init.h>
-#endif
-
-#include <linux/module.h>
-
-/* File tables structures. If directory caching is used,
- * <linux/dcache.h> will be included here, and __LINUX_DCACHE_H
- * will thus be defined.
- */
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-
-/* Include the SYS_syscall defines.
- */
-#ifndef LINUX26
-#include <sys/syscall.h>
-#else
-#define SYS_getdents 141
-#define SYS_getdents64 220
-#endif
-
-
-/* Includes for 'getdents' per the manpage.
- */
-#include <linux/types.h>
-#include <linux/dirent.h>
-#include <linux/unistd.h>
-
-/* To access userspace memory.
- */
-#include <asm/uaccess.h>
-
-/* Include for lock_kernel().
- */
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(3,0,0)
-#include <linux/smp_lock.h>
-#else
-static inline void lock_kernel(void) { }
-static inline void unlock_kernel(void) { }
-#endif
-
-#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
-#include <linux/mutex.h>
-#endif
-
-/* Include for fget().
- */
-#include <linux/file.h>
-#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,26)
-#include <linux/fdtable.h>
-#endif
-
-/*****************************************************
- *
- *  The global variables:
- *
- *****************************************************/
-
-/* The kernel syscall table. Not exported anymore in 2.5 ff., and also
- * not in the RedHat 2.4 kernel.
- */
-
-#if 0
-extern void * sys_call_table[];
-#define sh_sys_call_table sys_call_table
-#endif
-
-unsigned long * sh_sys_call_table = (unsigned long *) MAGIC_ADDRESS;
-
-/* The old address of the sys_getdents syscall.
- */
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
-int (*old_getdents)(unsigned int, struct dirent *, unsigned int);
-#else
-
-struct linux_dirent {
-  unsigned long   d_ino;
-  unsigned long   d_off;
-  unsigned short  d_reclen;
-  char            d_name[1];
-};
-
-int (*old_getdents)(unsigned int, struct linux_dirent *, unsigned int);
-#endif
-
-#ifdef __NR_getdents64
-#if SH_KERNEL_NUMERIC >= 132628
-/*
- * 'asmlinkage' is __required__ to get this to work.
- */
-asmlinkage long (*old_getdents64)(unsigned int, struct linux_dirent64 __user *, unsigned int);
-#else
-long (*old_getdents64)(unsigned int, struct dirent64 *, unsigned int);
-#endif
-#endif
-
-char hidden[] = MAGIC_HIDE;
- 
-
-/*****************************************************
- *
- *  The functions:
- *
- *****************************************************/
-
-
-MODULE_AUTHOR("Rainer Wichmann");
-MODULE_DESCRIPTION("Hide files/processes/modules with MAGIC_HIDE in name.");
-#if defined(MODULE_LICENSE) || defined(LINUX26)
-MODULE_LICENSE("GPL");  
-#endif
-
-#ifdef LINUX26
-/* Default is to hide ourselves.
- */
-static int removeme = 1;
-
-#ifdef MODULE_PARM 
-MODULE_PARM (removeme, "i");
-#else
-module_param(removeme, int, 0444);
-#endif
-
-#ifdef MODULE_PARM_DESC
-MODULE_PARM_DESC(removeme, "Choose zero for not hiding.");
-#endif
-
-/* LINUX26 */
-#endif
-
-
-/* 
- *  struct task_struct is defined in linux/sched.h
- *
- *  as of 2.4.20, the vanilla kernel holds (among others):
- *        struct task_struct *next_task, *prev_task;
- *
- *  Redhat kernel seems to have a different scheduler.
- *  use:
- *        struct task_struct * find_task_by_pid (int pid);
- */
-
-#if defined(SH_VANILLA_KERNEL) && !defined(LINUX26)
-/*
- * Fetch the task struct for a given PID.
- */
-struct task_struct * fetch_task_struct (int pid)
-{
-  struct task_struct * task_ptr;
-
-#ifdef PROC_DEBUG
-  printk("FETCH TASK %d\n", pid);
-#endif
-
-  task_ptr = current;
-
-  do 
-    {
-      if (task_ptr->pid == (pid_t) pid )
-	return (task_ptr);
-      task_ptr = task_ptr->next_task;
-    } 
-  while (task_ptr != current);
-
-#ifdef PROC_DEBUG
-  printk("FETCH TASK: NOT FOUND !!!\n");
-#endif
-
-  return (NULL);
-}
-
-#else
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,25)
-struct task_struct * fetch_task_struct (int pid)
-{
-  struct task_struct * task_ptr = NULL;
-  task_ptr = find_task_by_pid (pid);
-  return (task_ptr);
-}
-#else
-struct task_struct * fetch_task_struct (int pid)
-{
-  struct task_struct * task_ptr = NULL;
-  struct pid * task_pid = find_vpid(pid);
-  if (task_pid)
-    {
-      task_ptr = pid_task (task_pid, PIDTYPE_PID);
-    }
-  return (task_ptr);
-}
-#endif
-#endif
-
-/* Convert a string to an int. 
- * Does not recognize integers with a sign (+/-) in front.
- */
-int my_atoi(char * in_str)
-{
-  int i      = 0;
-  int retval = 0;
-  int conv   = 0;
-
-  if (in_str == NULL)
-    return (-1);
-
-  while(in_str[i] != '\0')
-    {
-      /* Break if not numeric.
-       */
-      if (in_str[i] < '0' || in_str[i] > '9')
-	break;
-
-      ++conv;
-      
-      /* Leading zeroes (should not happen in /proc)
-       */
-      if (retval == 0 && in_str[i] == '0')
-	retval = retval;
-      else
-	retval = retval * 10;
-
-      retval = retval + (in_str[i] - '0');
-
-      i++;
-    }
-      
-  if (conv == 0)
-    return (-1);
-  else
-    return (retval); 
-}
-
-/* Purpose:
- * 
- *   Hide all files/dirs that include the string MAGIC_HIDE in their
- *   name. 
- */
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
-int new_getdents (unsigned int fd, struct dirent *dirp, unsigned int count)
-#else
-int new_getdents (unsigned int fd, struct linux_dirent *dirp, unsigned int count)
-#endif
-{
-  int                  status = 0;    /* Return value from original getdents */
-  struct inode       * dir_inode;
-  struct file        * fd_file;
-  int                  dir_is_proc = 0;
-
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
-  struct dirent      * dirp_prev;
-  struct dirent      * dirp_new;
-  struct dirent      * dirp_current;
-#else
-  struct linux_dirent      * dirp_prev;
-  struct linux_dirent      * dirp_new;
-  struct linux_dirent      * dirp_current;
-#endif
-
-  int                  dir_table_bytes;
-  int                  forward_bytes;
-  struct task_struct * task_ptr;
-  int                  hide_it = 0;
-  long                 dirp_offset;
-
-  unsigned long        dummy;
-
-  lock_kernel();
-
-  status = (*old_getdents)(fd, dirp, count);
-
-#ifdef FILE_DEBUG
-  printk("STATUS %d\n", status);
-#endif
-  
-  /*  0: end of directory.
-   * -1: some error
-   */
-  if (status <= 0)
-    {
-      unlock_kernel();
-      return (status);
-    }
-  
-  /* Handle directory caching. dir_inode is the inode of the directory.
-   */
-#if defined(files_fdtable)
-  {
-    struct fdtable *fdt = files_fdtable(current->files);
-    fd_file = rcu_dereference(fdt->fd[fd]);
-  }
-#else
-  {
-    fd_file = current->files->fd[fd];
-  }
-#endif
-  
-#if defined(__LINUX_DCACHE_H)
-  dir_inode  = fd_file->f_dentry->d_inode;
-#else
-  dir_inode  = fd_file->f_inode;
-#endif
-
-  /* Check for the /proc directory
-   */
-  if (dir_inode->i_ino == PROC_ROOT_INO 
-#ifndef LINUX26
-      && !MAJOR(dir_inode->i_dev) && 
-      MINOR(dir_inode->i_dev) == 1
-#endif
-      )
-    dir_is_proc = 1;
-
-  /* Allocate space for new dirent table. Can't use GFP_KERNEL 
-   * (kernel oops)
-   */
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
-  dirp_new = (struct dirent *) kmalloc (status, GFP_ATOMIC);
-#else
-  dirp_new = (struct linux_dirent *) kmalloc (status, GFP_ATOMIC);
-#endif
-
-  if (dirp_new == NULL)
-    {
-      unlock_kernel();
-      return (status);
-    }
-
-  /* Copy the dirp table to kernel space.
-   */
-  dummy = (unsigned long) copy_from_user(dirp_new, dirp, status);
-
-#ifdef FILE_DEBUG
-  printk("COPY to kernel: %ld\n", dummy);
-#endif
-
-  /* Loop over the dirp table to find entries to hide.
-   */
-  dir_table_bytes = status;
-  dirp_current    = dirp_new;
-  dirp_prev       = NULL;
-
-  while (dir_table_bytes > 0)
-    {
-      hide_it = 0;
-
-      if (dirp_current->d_reclen == 0)
-	break;
-
-      dirp_offset = dirp_current->d_off;
-      
-#ifdef FILE_DEBUG
-      printk("DIRENT %d  %d  %ld\n", 
-	     dir_table_bytes,
-	     dirp_current->d_reclen,
-	     dirp_current->d_off);
-#endif
-
-      dir_table_bytes -= dirp_current->d_reclen;
-      forward_bytes    = dirp_current->d_reclen;
-
-#ifdef FILE_DEBUG
-      printk("ENTRY %s\n", dirp_current->d_name);
-#endif
-
-      /* If /proc is scanned (e.g. by 'ps'), hide the entry for
-       * any process where the executable has MAGIC_HIDE in its name.
-       */
-      if (dir_is_proc == 1)
-	{
-	  task_ptr = fetch_task_struct(my_atoi(dirp_current->d_name));
-	  if (task_ptr != NULL)
-	    {
-	      if (strstr(task_ptr->comm, hidden) != NULL)
-		hide_it = 1;
-	    }
-	}
-      /* If it is a regular directory, hide any entry with
-       * MAGIC_HIDE in its name.
-       */
-      else
-	{
-	  if (strstr (dirp_current->d_name, hidden) != NULL)
-	    hide_it = 1;
-	}
-
-      if (hide_it == 1)
-	{
-#ifdef FILE_DEBUG
-	  printk("  -->HIDDEN %s\n", dirp_current->d_name);
-#endif
-	  if (dir_table_bytes > 0)
-	    {
-	      status -= dirp_current->d_reclen;
-	      memmove (dirp_current, 
-		       (char *) dirp_current + dirp_current->d_reclen, 
-		       dir_table_bytes);
-
-	      /* Set forward_bytes to 0, because now dirp_current is the
-	       * (previously) next entry in the dirp table.
-	       */
-	      forward_bytes    = 0;
-	      dirp_prev        = dirp_current;
-	    }
-	  else
-	    {
-	      status -= dirp_current->d_reclen;
-	      if (dirp_prev != NULL)
-		dirp_prev->d_off = dirp_offset;
-	    }
-	  
-	}
-      else
-	{
-	  dirp_prev        = dirp_current;
-	  if (dir_table_bytes == 0 && dirp_prev != NULL)
-	    dirp_prev->d_off = dirp_offset;
-	}
-
-      /* Next entry in dirp table.
-       */
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
-      if (dir_table_bytes > 0)
-	dirp_current = (struct dirent *) ( (char *) dirp_current + 
-					   forward_bytes);
-#else
-      if (dir_table_bytes > 0)
-	dirp_current = (struct linux_dirent *) ( (char *) dirp_current + 
-					   forward_bytes);
-#endif
-    }
-
-  /* Copy our modified dirp table back to user space.
-   */
-  dummy = (unsigned long) copy_to_user(dirp, dirp_new, status);
-#ifdef FILE_DEBUG
-  printk("COPY to user: %ld\n", dummy);
-#endif
-
-  kfree (dirp_new);
-#ifdef FILE_DEBUG
-  printk("KFREE\n");
-#endif
-
-  unlock_kernel();
-  return (status);
-}
-
-
-
-/* For 2.4 kernel
- */
-#ifdef __NR_getdents64
-
-#if SH_KERNEL_NUMERIC >= 132628
-/*
- * 'asmlinkage' is __required__ to get this to work.
- */
-asmlinkage long new_getdents64 (unsigned int fd, struct linux_dirent64 __user *dirp, 
-				unsigned int count)
-#else
-long new_getdents64 (unsigned int fd, struct dirent64 *dirp, unsigned int count)
-#endif
-{
-  long                 status = 0;    /* Return value from original getdents */
-  struct inode       * dir_inode;
-  struct file        * fd_file;
-  int                  dir_is_proc = 0;
-
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
-  struct dirent64    * dirp_prev;
-  struct dirent64    * dirp_new;
-  struct dirent64    * dirp_current;
-#else
-  struct linux_dirent64    * dirp_prev;
-  struct linux_dirent64    * dirp_new;
-  struct linux_dirent64    * dirp_current;
-#endif
-
-  int                  dir_table_bytes;
-  int                  forward_bytes;
-  struct task_struct * task_ptr;
-  int                  hide_it = 0;
-  __s64                dirp_offset;
-
-  unsigned long        dummy;
-
-#ifdef FILE_DEBUG
-  printk("FD64 %d\n", fd);
-#endif
-
-  lock_kernel();
-
-#ifdef FILE_DEBUG
-  if (!access_ok(VERIFY_WRITE, dirp, count))
-    printk("ACCESS64_BAD\n");
-  else
-    printk("ACCESS64_OK\n");
-#endif
-
-#if SH_KERNEL_NUMERIC >= 132628
-  status = (*old_getdents64)(fd, dirp, count);
-  /* status = my_real_getdents64(fd, dirp, count); */
-#else
-  status = (*old_getdents64)(fd, dirp, count);
-#endif
-
-#ifdef FILE_DEBUG
-  printk("STATUS64 %ld\n", status);
-#endif
-
-  /*  0: end of directory.
-   * -1: some error
-   */
-  if (status <= 0)
-    {
-      unlock_kernel();
-      return (status);
-    }
-
-  /* Handle directory caching. dir_inode is the inode of the directory.
-   */
-#if defined(files_fdtable)
-  {
-    struct fdtable *fdt = files_fdtable(current->files);
-    fd_file = rcu_dereference(fdt->fd[fd]);
-  }
-#else
-  {
-    fd_file = current->files->fd[fd];
-  }
-#endif
-
-#if defined(__LINUX_DCACHE_H)
-
-/* 2.6.20 (((2) << 16) + ((6) << 8) + (20)) */
-#if SH_KERNEL_NUMERIC >= 132628
-  dir_inode  = fd_file->f_path.dentry->d_inode;
-#else
-  dir_inode  = fd_file->f_dentry->d_inode;
-#endif
-
-#else
-  dir_inode  = fd_file->f_inode;
-#endif
-
-#ifdef FILE_DEBUG
-  printk("INODE64\n");
-#endif
-
-  /* Check for the /proc directory
-   */
-  if (dir_inode->i_ino == PROC_ROOT_INO
-#ifndef LINUX26  
-      && !MAJOR(dir_inode->i_dev) /*  && 
-      MINOR(dir_inode->i_dev) == 1 */
-      /* MINOR commented out because of problems with 2.4.17 */
-#endif
-      )
-    {
-      dir_is_proc = 1;
-
-#ifdef PROC_DEBUG
-      printk("PROC_CHECK64\n");
-#endif
-    }
-
-  /* Allocate space for new dirent table. Can't use GFP_KERNEL 
-   * (kernel oops)
-   */
-  dirp_new = kmalloc ((size_t)status, GFP_ATOMIC);
-
-#ifdef FILE_DEBUG
-  printk("KMALLOC64_0\n");
-#endif
-
-  if (dirp_new == NULL)
-    {
-      unlock_kernel();
-      return (status);
-    }
-
-#ifdef FILE_DEBUG
-  printk("KMALLOC64\n");
-#endif
-
-  /* Copy the dirp table to kernel space.
-   */
-  dummy = (unsigned long) copy_from_user(dirp_new, dirp, status);
-
-#ifdef FILE_DEBUG
-  printk("COPY64 to kernel: %ld\n", dummy);
-#endif
-
-  /* Loop over the dirp table to find entries to hide.
-   */
-  dir_table_bytes = status;
-  dirp_current    = dirp_new;
-  dirp_prev       = NULL;
-
-  while (dir_table_bytes > 0)
-    {
-      hide_it = 0;
-
-      if (dirp_current->d_reclen == 0)
-	break;
-
-      dirp_offset = dirp_current->d_off;
-      
-#ifdef FILE_DEBUG
-      printk("DIRENT %d  %d  %lld\n", 
-	     dir_table_bytes,
-	     dirp_current->d_reclen,
-	     dirp_current->d_off);
-#endif
-
-      dir_table_bytes -= dirp_current->d_reclen;
-      forward_bytes    = dirp_current->d_reclen;
-
-#ifdef FILE_DEBUG
-      printk("ENTRY %s\n", dirp_current->d_name);
-#endif
-
-      /* If /proc is scanned (e.g. by 'ps'), hide the entry for
-       * any process where the executable has MAGIC_HIDE in its name.
-       */
-      if (dir_is_proc == 1)
-	{
-#ifdef PROC_DEBUG
-	  printk("PROC %s\n", dirp_current->d_name);
-#endif
-	  task_ptr = fetch_task_struct(my_atoi(dirp_current->d_name));
-	  if (task_ptr != NULL)
-	    {
-#ifdef PROC_DEBUG
-	      printk("PROC %s <> %s\n", task_ptr->comm, hidden);
-#endif
-	      if (strstr(task_ptr->comm, hidden) != NULL)
-		hide_it = 1;
-	    }
-	}
-      /* If it is a regular directory, hide any entry with
-       * MAGIC_HIDE in its name.
-       */
-      else
-	{
-	  if (strstr (dirp_current->d_name, hidden) != NULL)
-	    hide_it = 1;
-	}
-
-      if (hide_it == 1)
-	{
-#ifdef FILE_DEBUG
-	  printk("  -->HIDDEN %s\n", dirp_current->d_name);
-#endif
-	  if (dir_table_bytes > 0)
-	    {
-	      status -= dirp_current->d_reclen;
-	      memmove (dirp_current, 
-		       (char *) dirp_current + dirp_current->d_reclen, 
-		       dir_table_bytes);
-
-	      /* Set forward_bytes to 0, because now dirp_current is the
-	       * (previously) next entry in the dirp table.
-	       */
-	      forward_bytes    = 0;
-	      dirp_prev        = dirp_current;
-	    }
-	  else
-	    {
-	      status -= dirp_current->d_reclen;
-	      if (dirp_prev != NULL)
-		dirp_prev->d_off = dirp_offset;
-	    }
-	  
-	}
-      else
-	{
-	  dirp_prev        = dirp_current;
-	  if (dir_table_bytes == 0 && dirp_prev != NULL)
-	    dirp_prev->d_off = dirp_offset;
-	}
-
-      /* Next entry in dirp table.
-       */
-#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
-      if (dir_table_bytes > 0)
-	dirp_current = (struct dirent64 *) ( (char *) dirp_current + 
-					     forward_bytes);
-#else
-      if (dir_table_bytes > 0)
-	dirp_current = (struct linux_dirent64 *) ( (char *) dirp_current + 
-					     forward_bytes);
-#endif
-    }
-
-  /* Copy our modified dirp table back to user space.
-   */
-#ifdef FILE_DEBUG
-  printk("STATUS64 AT END %ld\n", status);
-#endif
-  dummy = (unsigned long) copy_to_user(dirp, dirp_new, status);
-#ifdef FILE_DEBUG
-  printk("COPY64 to user: %ld\n", dummy);
-#endif
-
-  kfree (dirp_new);
-  unlock_kernel();
-  return (status);
-}
-#endif
-
-#ifdef LINUX26
-static struct module *sh_find_module(const char *name)
-{
-        struct module *mod;
-	struct list_head * modules = (struct list_head *) SH_LIST_MODULES;
-
-        list_for_each_entry(mod, modules, list) {
-                if (strcmp(mod->name, name) == 0)
-                        return mod;
-        }
-        return NULL;
-}
-#endif
-
-/* The initialisation function. Automatically called when module is inserted
- * via the 'insmod' command.
- */
-#ifdef LINUX26
-static int __init samhain_hide_init(void)
-#else
-int init_module(void)
-#endif
-{
-
-#ifdef INIT_DEBUG
-  printk("INIT 0\n");
-#endif
-
-  lock_kernel();
-
-#ifdef INIT_DEBUG
-  printk("INIT 1\n");
-#endif
-
-  /* Unfortunately this does not fully prevent the module from appearing
-   * in /proc/ksyms. 
-   */
-#ifndef LINUX26
-  EXPORT_NO_SYMBOLS;
-#endif
-
-#ifdef INIT_DEBUG
-  printk("INIT 1a (%d)\n", SYS_getdents);
-#endif
-
-  /* Replace the 'sys_getdents' syscall with the new version.
-   */
-  old_getdents                        = (void*) sh_sys_call_table[SYS_getdents];
-#ifdef INIT_DEBUG
-  printk("INIT 1b\n");
-#endif
-  sh_sys_call_table[SYS_getdents]     = (unsigned long) new_getdents;
-  
-#ifdef INIT_DEBUG
-  printk("INIT 2\n");
-#endif
-
-#ifdef __NR_getdents64
-  old_getdents64                      = (void*) sh_sys_call_table[SYS_getdents64];
-  sh_sys_call_table[SYS_getdents64]   = (unsigned long) new_getdents64;
-#endif
-
-#ifdef INIT_DEBUG
-  printk("INIT 3\n");
-#endif
-
-#ifdef LINUX26
-  {
-#if defined(SH_MODLIST_LOCK)
-    spinlock_t * modlist_lock = (spinlock_t * ) SH_MODLIST_LOCK;
-#endif
-#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,30)
-    struct mutex * sh_module_mutex = &module_mutex;
-#else
-#if (SH_KERNEL_NUMERIC >= SH_KERNEL_MIN)
-    struct mutex * sh_module_mutex = (struct mutex *) SH_MODLIST_MUTEX;
-#endif
-#endif
-
-    struct module *mod;
-
-#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
-#ifdef INIT_DEBUG
-    printk("INIT 4 0\n");
-#endif
-    mutex_lock(sh_module_mutex);
-#endif
-
-#ifdef INIT_DEBUG
-    printk("INIT 4 1\n");
-#endif
-
-    mod = sh_find_module(SH_INSTALL_NAME"_hide");
-
-#ifdef INIT_DEBUG
-    printk("INIT 4 2 (%d)\n", mod == 0 ? 0 : 1);
-#endif
-
-    if (mod) {
-      /* Delete from various lists */
-#if defined(SH_MODLIST_LOCK)
-#ifdef INIT_DEBUG
-      printk("INIT 4 3a\n");
-#endif
-      spin_lock_irq(modlist_lock);
-#ifdef INIT_DEBUG
-      printk("INIT 4 3b\n");
-#endif
-#endif
-      if (removeme == 1)
-	{
-#ifdef INIT_DEBUG
-	  printk("INIT 4 4a\n");
-#endif
-	  list_del(&mod->list);
-#ifdef INIT_DEBUG
-	  printk("INIT 4 4b\n");
-#endif
-	}
-#if defined(SH_MODLIST_LOCK)
-#ifdef INIT_DEBUG
-	  printk("INIT 4 5a\n");
-#endif
-      spin_unlock_irq(modlist_lock);
-#ifdef INIT_DEBUG
-	  printk("INIT 4 5b\n");
-#endif
-#endif
-    }
-
-#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
-#ifdef INIT_DEBUG
-    printk("INIT 4 6a\n");
-#endif
-    mutex_unlock(sh_module_mutex);
-#ifdef INIT_DEBUG
-    printk("INIT 4 6b\n");
-#endif
-#endif
-  }
-#endif
-
-#ifdef INIT_DEBUG
-  printk("INIT 4 7a\n");
-#endif
-  unlock_kernel();
-#ifdef INIT_DEBUG
-  printk("INIT 4 7b\n");
-#endif
-  return (0);
-}
-
-/* The cleanup function. Automatically called when module is removed
- * via the 'rmmod' command.
- */
-#ifdef LINUX26
-static void __exit samhain_hide_cleanup(void)
-#else
-void cleanup_module(void)
-#endif
-{
-  lock_kernel();
-
-  /* Restore the new syscalls to the original version.
-   */
-  sh_sys_call_table[SYS_getdents]     = (unsigned long) old_getdents;
-
-#ifdef __NR_getdents64
-  sh_sys_call_table[SYS_getdents64]   = (unsigned long) old_getdents64;
-#endif
-
-  unlock_kernel();
-}
-
-#ifdef LINUX26
-module_init(samhain_hide_init);
-module_exit(samhain_hide_cleanup);
-#endif
-
-
Index: trunk/src/samhain_kmem.c
===================================================================
--- trunk/src/samhain_kmem.c	(revision 476)
+++ 	(revision )
@@ -1,613 +1,0 @@
-/* Most of this code is ripped from the Linux kernel:
- *
- *  linux/drivers/char/mem.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  Added devfs support. 
- *    Jan-11-1998, C. Scott Ananian <cananian@alumni.princeton.edu>
- *  Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar <kanoj@sgi.com>
- */
-
-#include "config.h" 
-
-#undef _
-#define _(string) string
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/proc_fs.h>
-#include <linux/string.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/mman.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/raw.h>
-#include <linux/tty.h>
-#include <linux/capability.h>
-#include <linux/ptrace.h>
-#include <linux/device.h>
-#include <linux/highmem.h>
-#include <linux/crash_dump.h>
-#include <linux/backing-dev.h>
-#include <linux/bootmem.h>
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
-#include <linux/splice.h>
-#endif
-#include <linux/pfn.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-
-#ifdef CONFIG_IA64
-# include <linux/efi.h>
-#endif
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("samhain_kmem Kernel Module");
-MODULE_AUTHOR("Rainer Wichmann");
-
-static int debug = 0;
-#ifdef MODULE_PARM 
-MODULE_PARM (debug, "i");
-#else
-module_param(debug, int, 0444);
-#endif
-
-#ifdef MODULE_PARM_DESC
-MODULE_PARM_DESC(debug, "Set to a non-zero value for debugging.");
-#endif
-
-/* struct task_struct
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
-#define TASK_EUID euid
-#else
-#define TASK_EUID cred->euid
-#endif
-
-static struct proc_dir_entry *proc_entry;
-
-/*
- * Architectures vary in how they handle caching for addresses
- * outside of main memory.
- *
- */
-static inline int uncached_access(struct file *file, unsigned long addr)
-{
-#if defined(__i386__) && !defined(__arch_um__)
-  /*
-   * On the PPro and successors, the MTRRs are used to set
-   * memory types for physical addresses outside main memory,
-   * so blindly setting PCD or PWT on those pages is wrong.
-   * For Pentiums and earlier, the surround logic should disable
-   * caching for the high addresses through the KEN pin, but
-   * we maintain the tradition of paranoia in this code.
-   */
-  if (file->f_flags & O_SYNC)
-    return 1;
-  return !( test_bit(X86_FEATURE_MTRR, (const void *) boot_cpu_data.x86_capability) ||
-	    test_bit(X86_FEATURE_K6_MTRR, (const void *) boot_cpu_data.x86_capability) ||
-	    test_bit(X86_FEATURE_CYRIX_ARR, (const void *) boot_cpu_data.x86_capability) ||
-	    test_bit(X86_FEATURE_CENTAUR_MCR, (const void *) boot_cpu_data.x86_capability) )
-    && addr >= __pa(high_memory);
-#elif defined(__x86_64__) && !defined(__arch_um__)
-  /* 
-   * This is broken because it can generate memory type aliases,
-   * which can cause cache corruptions
-   * But it is only available for root and we have to be bug-to-bug
-   * compatible with i386.
-   */
-  if (file->f_flags & O_SYNC)
-    return 1;
-  /* same behaviour as i386. PAT always set to cached and MTRRs control the
-     caching behaviour. 
-     Hopefully a full PAT implementation will fix that soon. */      
-  return 0;
-#elif defined(CONFIG_IA64)
-  /*
-   * On ia64, we ignore O_SYNC because we cannot tolerate 
-   * memory attribute aliases.
-   */
-  return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
-#elif defined(CONFIG_MIPS)
-  {
-    extern int __uncached_access(struct file *file,
-				 unsigned long addr);
-    
-    return __uncached_access(file, addr);
-  }
-#else
-  /*
-   * Accessing memory above the top the kernel knows about 
-   * or through a file pointer
-   * that was marked O_SYNC will be done non-cached.
-   */
-  if (file->f_flags & O_SYNC)
-    return 1;
-  return addr >= __pa(high_memory);
-#endif
-}
-
-#ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
-static inline int valid_phys_addr_range(unsigned long addr, size_t count)
-{
-  if (addr + count > __pa(high_memory))
-    return 0;
-  
-  return 1;
-}
-
-static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
-{
-  return 1;
-}
-#endif
-
-
-/* #ifndef __HAVE_PHYS_MEM_ACCESS_PROT */
-static pgprot_t my_phys_mem_access_prot(struct file *file, unsigned long pfn,
-                                     unsigned long size, pgprot_t vma_prot)
-{
-#ifdef pgprot_noncached
-  unsigned long offset = pfn << PAGE_SHIFT;
-  
-  if (uncached_access(file, offset))
-    return pgprot_noncached(vma_prot);
-#else
-#error pgtable
-#endif
-  return vma_prot;
-}
-/* #endif */
-
-
-#ifndef CONFIG_MMU
-static unsigned long get_unmapped_area_mem(struct file *file,
-                                           unsigned long addr,
-                                           unsigned long len,
-                                           unsigned long pgoff,
-                                           unsigned long flags)
-{
-  if (!valid_mmap_phys_addr_range(pgoff, len))
-    return (unsigned long) -EINVAL;
-  return pgoff << PAGE_SHIFT;
-}
-
-/* can't do an in-place private mapping if there's no MMU */
-static inline int private_mapping_ok(struct vm_area_struct *vma)
-{
-  return vma->vm_flags & VM_MAYSHARE;
-}
-#else
-#define get_unmapped_area_mem   NULL
-
-static inline int private_mapping_ok(struct vm_area_struct *vma)
-{
-  return 1;
-}
-#endif
-
-static int mmap_mem(struct file * file, struct vm_area_struct * vma)
-{
-  size_t size = vma->vm_end - vma->vm_start;
-  
-  if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
-    return -EINVAL;
-  
-  if (!private_mapping_ok(vma))
-    return -ENOSYS;
-  
-  vma->vm_page_prot = my_phys_mem_access_prot(file, vma->vm_pgoff,
-					      size,
-					      vma->vm_page_prot);
-  
-  /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
-  if (remap_pfn_range(vma,
-		      vma->vm_start,
-		      vma->vm_pgoff,
-		      size,
-		      vma->vm_page_prot))
-    return -EAGAIN;
-  return 0;
-}
-
-static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
-{
-  unsigned long pfn;
-  
-  /* Turn a kernel-virtual address into a physical page frame */
-  pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
-  
-  /*
-   * RED-PEN: on some architectures there is more mapped memory
-   * than available in mem_map which pfn_valid checks
-   * for. Perhaps should add a new macro here.
-   *
-   * RED-PEN: vmalloc is not supported right now.
-   */
-  if (!pfn_valid(pfn))
-    return -EIO;
-  
-  vma->vm_pgoff = pfn;
-  return mmap_mem(file, vma);
-}
-
-static int my_permission(struct inode *inode, int op)
-{
-  /* 
-   * only root (uid 0) may read from it 
-   */
-  if (debug)
-    {
-      printk(KERN_INFO "samhain_kmem: permission op = %d, current->euid = %d\n", 
-	     op, (int)current->TASK_EUID );
-    }
-
-  if ((op & 4) != 0 && (op & 2) == 0 && current->TASK_EUID == 0)
-    {
-      if (debug)
-	{
-	  printk(KERN_INFO "samhain_kmem: access granted\n" );
-	}
-      return 0;
-    }
-  
-  /* 
-   * If it's anything else, access is denied 
-   */
-  if ((op & 2) != 0)
-    {
-      printk(KERN_INFO "/proc/kmem: access denied, "
-	     "permission op = %d, current->euid = %d\n", 
-	     op, (int)current->TASK_EUID );
-    }
-  else if (debug)
-    {
-      printk(KERN_INFO "samhain_kmem: access denied\n" );
-    }
-  return -EACCES;
-}
-
-static struct inode_operations Inode_Ops_Kmem = {
-  .permission = my_permission,	/* check for permissions */
-};
-
-static int open_kmem(struct inode * inode, struct file * filp)
-{
-  int ret = capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
-
-  if (debug)
-    {
-      printk(KERN_INFO "samhain_kmem: open_kmem retval = %d\n", ret);
-    }
-
-  if (ret == 0)
-    try_module_get(THIS_MODULE);
-
-  if (debug)
-    {
-      printk(KERN_INFO "samhain_kmem: open_kmem return\n");
-    }
-
-  return ret;
-}
-
-static int close_kmem(struct inode *inode, struct file *file)
-{
-  if (debug)
-    {
-      printk(KERN_INFO "samhain_kmem: close_kmem enter\n");
-    }
-
-  module_put(THIS_MODULE);
-
-  if (debug)
-    {
-      printk(KERN_INFO "samhain_kmem: close_kmem return\n");
-    }
-
-  return 0;		/* success */
-}
-
-/*********************************************************************
- *
- *   >>>  Required info from System.map: vmlist_lock, vmlist  <<<
- */
-static rwlock_t * sh_vmlist_lock_ptr = (rwlock_t *) SH_VMLIST_LOCK;
-
-static struct vm_struct * sh_vmlist   = (struct vm_struct *) SH_VMLIST;
-/*
- *
- *********************************************************************/
-
-static long my_vread(char *buf, char *addr, unsigned long count)
-{
-        struct vm_struct *tmp;
-        char *vaddr, *buf_start = buf;
-        unsigned long n;
-
-        /* Don't allow overflow */
-        if ((unsigned long) addr + count < count)
-                count = -(unsigned long) addr;
-
-        read_lock(sh_vmlist_lock_ptr);
-        for (tmp = sh_vmlist; tmp; tmp = tmp->next) {
-                vaddr = (char *) tmp->addr;
-                if (addr >= vaddr + tmp->size - PAGE_SIZE)
-                        continue;
-                while (addr < vaddr) {
-                        if (count == 0)
-                                goto finished;
-                        *buf = '\0';
-                        buf++;
-                        addr++;
-                        count--;
-                }
-                n = vaddr + tmp->size - PAGE_SIZE - addr;
-                do {
-                        if (count == 0)
-                                goto finished;
-                        *buf = *addr;
-                        buf++;
-                        addr++;
-                        count--;
-                } while (--n > 0);
-        }
-finished:
-        read_unlock(sh_vmlist_lock_ptr);
-	if (debug)
-	  {
-	    printk(KERN_INFO "samhain_kmem:  start %lu\n", (unsigned long) buf_start);
-	    printk(KERN_INFO "samhain_kmem:  end   %lu\n", (unsigned long) buf);
-	    printk(KERN_INFO "samhain_kmem:  size  %lu\n", (unsigned long) (buf - buf_start));
-	  }
-        return buf - buf_start;
-}
-
-static ssize_t read_kmem(struct file *file, char __user *buf, 
-                         size_t count, loff_t *ppos)
-{
-  unsigned long p = *ppos;
-  ssize_t low_count, read, sz;
-  char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
-  
-  if (debug) {
-    printk(KERN_INFO "samhain_kmem: read_kmem entry\n");
-    printk(KERN_INFO "samhain_kmem:  p    %lu\n", (unsigned long) p);
-    printk(KERN_INFO "samhain_kmem:  high %lu\n", (unsigned long) high_memory);
-  }
- 
-  read = 0;
-  if (p < (unsigned long) high_memory) {
-    low_count = count;
-
-    if (debug) {
-      printk(KERN_INFO "samhain_kmem:  low_count(1)  %ld\n", (long) low_count);
-    }
-
-    if (count > (unsigned long) high_memory - p)
-      low_count = (unsigned long) high_memory - p;
-    
-    if (debug) {
-      printk(KERN_INFO "samhain_kmem:  low_count(2)  %ld\n", (long) low_count);
-    }
-
-#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
-    /* we don't have page 0 mapped on sparc and m68k.. */
-    if (p < PAGE_SIZE && low_count > 0) {
-      size_t tmp = PAGE_SIZE - p;
-      if (tmp > low_count) tmp = low_count;
-      if (clear_user(buf, tmp))
-	{
-	  if (debug) {
-	    printk(KERN_INFO "samhain_kmem: Bad address, line %d\n", __LINE__);
-	  }
-	  return -EFAULT;
-	}
-      buf += tmp;
-      p += tmp;
-      read += tmp;
-      low_count -= tmp;
-      count -= tmp;
-    }
-#endif
-
-    if (debug) {
-      printk(KERN_INFO "samhain_kmem:  low_count(3)  %ld\n", (long) low_count);
-    }
-
-    while (low_count > 0) {
-      /*
-       * Handle first page in case it's not aligned
-       */
-      if (-p & (PAGE_SIZE - 1))
-	sz = -p & (PAGE_SIZE - 1);
-      else
-	sz = PAGE_SIZE;
-      
-      sz = min_t(unsigned long, sz, low_count);
-      
-      /*
-       * On ia64 if a page has been mapped somewhere as
-       * uncached, then it must also be accessed uncached
-       * by the kernel or data corruption may occur
-       */
-      kbuf = xlate_dev_kmem_ptr((char *)p);
-      
-      if (copy_to_user(buf, kbuf, sz))
-	{
-	  if (debug) {
-	    printk(KERN_INFO "samhain_kmem: Bad address, line %d\n", __LINE__);
-	    printk(KERN_INFO "samhain_kmem:  size %ld\n", (long) sz);
-	    printk(KERN_INFO "samhain_kmem:  kbuf %p\n", kbuf);
-	    printk(KERN_INFO "samhain_kmem:  buf  %p\n", buf);
-	    printk(KERN_INFO "samhain_kmem:  high %lu\n", (unsigned long) high_memory);
-	  }
-	  return -EFAULT;
-	}
-      buf += sz;
-      p += sz;
-      read += sz;
-      low_count -= sz;
-      count -= sz;
-      if (debug) {
-	printk(KERN_INFO "samhain_kmem:  low_count(4)  %ld\n", (long) low_count);
-      }
-    }
-  }
-
-  if (debug) {
-    printk(KERN_INFO "samhain_kmem: read_kmem mid\n");
-    printk(KERN_INFO "samhain_kmem:  count  %lu\n", (unsigned long) count);
-  }
-
-  if (count > 0) {
-    kbuf = (char *)__get_free_page(GFP_KERNEL);
-    if (!kbuf)
-      {
-	if (debug) {
-	  printk(KERN_INFO "samhain_kmem: out of memory\n");
-	}
-	return -ENOMEM;
-      }
-    while (count > 0) {
-      int len = count;
-      
-      if (len > PAGE_SIZE)
-	len = PAGE_SIZE;
-      len = my_vread(kbuf, (char *)p, len);
-      if (!len)
-	break;
-      if (copy_to_user(buf, kbuf, len)) {
-	if (debug) {
-	  printk(KERN_INFO "samhain_kmem: Bad address, line %d\n", __LINE__);
-	  printk(KERN_INFO "samhain_kmem:  size %ld\n", (long) len);
-	  printk(KERN_INFO "samhain_kmem:  kbuf %p\n", kbuf);
-	  printk(KERN_INFO "samhain_kmem:  buf  %p\n", buf);
-	  printk(KERN_INFO "samhain_kmem:  high %lu\n", (unsigned long) high_memory);
-	}
-	free_page((unsigned long)kbuf);
-	return -EFAULT;
-      }
-      count -= len;
-      buf += len;
-      read += len;
-      p += len;
-    }
-    free_page((unsigned long)kbuf);
-  }
-  *ppos = p;
-  if (debug) {
-    printk(KERN_INFO "samhain_kmem: read_kmem end\n");
-    printk(KERN_INFO "samhain_kmem:  read  %ld\n", (long) read);
-  }
-  return read;
-}
-
-
-static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
-{
-  loff_t ret;
- 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) 
-  mutex_lock(&file->f_dentry->d_inode->i_mutex);
-#else
-  mutex_lock(&file->f_path.dentry->d_inode->i_mutex);
-#endif
-
-  switch (orig) {
-  case 0:
-    file->f_pos = offset;
-    ret = file->f_pos;
-    force_successful_syscall_return();
-    break;
-  case 1:
-    file->f_pos += offset;
-    ret = file->f_pos;
-    force_successful_syscall_return();
-    break;
-  default:
-    if (debug) {
-      printk(KERN_INFO "samhain_kmem: invalid input %d\n", orig);
-    }
-    ret = -EINVAL;
-  }
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) 
-  mutex_unlock(&file->f_dentry->d_inode->i_mutex);
-#else
-  mutex_unlock(&file->f_path.dentry->d_inode->i_mutex);
-#endif
-  return ret;
-}
-
-static const struct file_operations File_Ops_Kmem = {
-  .llseek            = memory_lseek,
-  .read              = read_kmem,
-  .mmap              = mmap_kmem,
-  .open              = open_kmem,
-  .release           = close_kmem,
-  .get_unmapped_area = get_unmapped_area_mem,
-};
-
-
-/* Init function called on module entry 
- */
-static int my_module_init( void )
-{
-  int ret = 0;
-
-  proc_entry = create_proc_entry( "kmem", 0400, NULL ); 
-
-  if (proc_entry == NULL) {
-    
-    ret = -ENOMEM;
-    
-    printk(KERN_INFO "samhain_kmem: Couldn't create proc entry\n");
-    
-  } else {
-    
-/* 2.6.30 */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
-    proc_entry->owner     = THIS_MODULE;
-#endif
-    proc_entry->proc_iops = &Inode_Ops_Kmem;
-    proc_entry->proc_fops = &File_Ops_Kmem;
-    
-    proc_entry->uid       = 0;
-    proc_entry->gid       = 0;
-    proc_entry->mode      = S_IFREG | S_IRUSR;
-    
-    if (debug) {
-      printk(KERN_INFO "samhain_kmem: module is now loaded.\n");
-    }
-  }
-
-  return ret;
-}
-
-/* Cleanup function called on module exit */
-
-static void my_module_cleanup( void )
-{
-  remove_proc_entry("kmem", NULL);
-
-  if (debug) {
-    printk(KERN_INFO "samhain_kmem: module is now unloaded.\n");
-  }
-  return;
-}
-
-
-
-/* Declare entry and exit functions */
-
-module_init( my_module_init );
-
-module_exit( my_module_cleanup );
Index: trunk/src/sh_calls.c
===================================================================
--- trunk/src/sh_calls.c	(revision 476)
+++ trunk/src/sh_calls.c	(revision 481)
@@ -262,5 +262,5 @@
   errno = error;
 
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       char ipbuf[SH_IP_BUF];
@@ -291,5 +291,5 @@
   sh_ipvx_save(serv_addr, ss.ss_family, (struct sockaddr *) &ss);
 
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       char ipbuf[SH_IP_BUF];
@@ -490,6 +490,4 @@
 #endif
 
-  SL_ENTER(_("retry_msleep"));
-
   errno  = 0;
   if (millisec > 999) millisec = 999;
@@ -511,23 +509,16 @@
 #else
   if (sec > 0)
-    {
-      sleep (sec); /* nanosleep not available */
-    }
-  else
-    {
+    sleep (sec); /* nanosleep not available */
+  else {
 #ifdef HAVE_USLEEP
-      if (millisec > 0)
-	{
-	  usleep(1000 * millisec);
-	}
+    if (millisec > 0)
+      usleep(1000 * millisec);
 #else
-      if (millisec > 0)
-	{
-	  sleep (1);
-	}
-#endif
-    }
-#endif
-  SL_RETURN(result, _("retry_msleep"));
+    if (millisec > 0)
+      sleep (1);
+#endif
+  }
+#endif
+  return result;
 }
 
@@ -835,27 +826,27 @@
   
 /*@noreturn@*/
-void aud_exit (const char * file, int line, int fd)
+void aud_exit (const char * file, int line, int exitval)
 {
   if (sh.flag.audit != 0 && (sh.flag.aud_mask & AUD_EXIT) != 0)
     sh_error_handle ((-1), file, line, 0, MSG_AUD_EXIT,
-		      (long) fd);
+		      (long) exitval);
 
   SL_ENTER(_("aud_exit"));
 
-  sh.flag.exit = fd;
-  exit(fd);
+  sh.flag.exit = exitval;
+  exit(exitval);
 }
 
 /*@noreturn@*/
-void aud__exit (const char * file, int line, int fd)
+void aud__exit (const char * file, int line, int exitval)
 {
   if (sh.flag.audit != 0 && (sh.flag.aud_mask & AUD_EXIT) != 0)
     sh_error_handle ((-1), file, line, 0, MSG_AUD_EXIT,
-		      (long) fd);
+		      (long) exitval);
 
   SL_ENTER(_("aud__exit"));
 
-  sh.flag.exit = fd;
-  _exit(fd);
+  sh.flag.exit = exitval;
+  _exit(exitval);
 }
 
Index: trunk/src/sh_cat.c
===================================================================
--- trunk/src/sh_cat.c	(revision 476)
+++ trunk/src/sh_cat.c	(revision 481)
@@ -70,4 +70,5 @@
   { MSG_CHECK_0,     SH_ERR_WARN,    RUN,   N_("msg=\"No files or directories defined for checking\"")},
   { MSG_CHECK_1,     SH_ERR_STAMP,   STAMP, N_("msg=\"File check completed.\" time=\"%ld\" kBps=\"%f\"")},
+  { MSG_CHECK_2,     SH_ERR_STAMP,   STAMP, N_("msg=\"File check starting.\"")},
   { MSG_STAMP,       SH_ERR_STAMP,   STAMP, N_("msg=\"---- TIMESTAMP ----\"")},
 
@@ -75,4 +76,6 @@
   { MSG_D_DSTART,    SH_ERR_INFO,    RUN,   N_("msg=\"Downloading database file\"")},
   { MSG_D_FAIL,      SH_ERR_INFO,    RUN,   N_("msg=\"No file from server, trying local file\"")},
+  { MSG_D_DELTAOK,   SH_ERR_SEVERE,  RUN,   N_("msg=\"Delta database downloaded\", path=\"%s\"")},
+  { MSG_D_DELTAFAIL, SH_ERR_SEVERE,  RUN,   N_("msg=\"Delta database download failed\", path=\"%s\"")},
 
 
@@ -93,17 +96,4 @@
   { MSG_SUID_QREPORT,SH_ERR_SEVERE,  EVENT, N_("msg=\"Quarantine report: %s\" path=\"%s\"") },
   { MSG_SUID_ERROR,  SH_ERR_SEVERE,  EVENT, N_("msg=\"Quarantine error: %s\"") },
-#endif
-
-#ifdef SH_USE_KERN
-  /* FreeBSD */
-  { MSG_KERN_POLICY, SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Kernel] BSD syscall table: new: %#lx old: %#lx\" syscall=\"%03d %s\"") },
-  { MSG_KERN_POL_CO, SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Kernel] BSD syscall code: new: %#x,%#x old: %#x,%#x\" syscall=\"%03d %s\"") },
-
-  /* Linux */
-  { MSG_KERN_SYSCALL,SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Kernel] SYSCALL modified syscall\" syscall=\"%03d %s\" %s") },
-  { MSG_KERN_PROC,   SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Kernel] PROC modified proc filesystem: %s\"") },
-  { MSG_KERN_IDT,    SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Kernel] IDT modified interrupt %03d: new: 0x%-8.8lx %-9s %3d %c old: 0x%-8.8lx %-9s %3d %c\" %s") },
-  { MSG_KERN_GATE,   SH_ERR_SEVERE,  EVENT, N_("msg=\"POLICY [Kernel] SYS_GATE modified system_call: new: %#x,%#x old: %#x,%#x\" syscall=\"%03d %s\" %s") },
-
 #endif
 
@@ -411,4 +401,5 @@
   { MSG_CHECK_0,     SH_ERR_WARN,    RUN,   N_("msg=<No files or directories defined for checking>")},
   { MSG_CHECK_1,     SH_ERR_STAMP,   STAMP, N_("msg=<File check completed.>, time=<%ld>, kBps=<%f>")},
+  { MSG_CHECK_2,     SH_ERR_STAMP,   STAMP, N_("msg=<File check starting.>")},
   { MSG_STAMP,       SH_ERR_STAMP,   STAMP, N_("msg=<---- TIMESTAMP ---->")},
 
@@ -416,4 +407,6 @@
   { MSG_D_DSTART,    SH_ERR_INFO,    RUN,   N_("msg=<Downloading database file>")},
   { MSG_D_FAIL,      SH_ERR_INFO,    RUN,   N_("msg=<No file from server, trying local file>")},
+  { MSG_D_DELTAOK,   SH_ERR_SEVERE,  RUN,   N_("msg=<Delta database downloaded>, path=<%s>")},
+  { MSG_D_DELTAFAIL, SH_ERR_SEVERE,  RUN,   N_("msg=<Delta database download failed>, path=<%s>")},
 
 
Index: trunk/src/sh_database.c
===================================================================
--- trunk/src/sh_database.c	(revision 476)
+++ trunk/src/sh_database.c	(revision 481)
@@ -180,5 +180,6 @@
   { NULL, N_("link_old"),    0,  49, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, link_old)},
   { NULL, N_("link_new"),    0,  50, MAX_PATH_STORE+1, 0, offsetof(struct dbins_, link_new)},
-               				    
+
+  /* These go into  dbins.ulong_data[n - START_SEC_LONGS] */             				    
   { NULL, N_("size_old"),     0,  51,    0, 0, 0  },
   { NULL, N_("size_new"),     0,  52,    0, 0, 0  },
@@ -201,19 +202,28 @@
   { NULL, N_("port"),         0,  67,    0, 0, 0  },
   { NULL, N_("return_code"),  0,  68,    0, 0, 0  },
-  /* { NULL, N_("userid"),        0,  69,    0, 0  }, old 'userid', 1.8.1 */
-
-  { NULL, N_("host"),         0,  70,   64, 0, offsetof(struct dbins_, fromhost)},
-  { NULL, N_("attr_old"),     0,  71,   16, 0, offsetof(struct dbins_, attr_old)},
-  { NULL, N_("attr_new"),     0,  72,   16, 0, offsetof(struct dbins_, attr_new)},
-  { NULL, N_("acl_old"),      0,  73, 1024, 0, offsetof(struct dbins_, acl_old)},
-  { NULL, N_("acl_new"),      0,  74, 1024, 0, offsetof(struct dbins_, acl_new)},
+
+  { NULL, N_("checkflags_old"), 0,  69,    0, 0, 0  },
+  { NULL, N_("checkflags_new"), 0,  70,    0, 0, 0  },
+
+  /* END_SEC_LONGS                                         */
+
+  { NULL, N_("host"),         0,  71,   64, 0, offsetof(struct dbins_, fromhost)},
+  { NULL, N_("attr_old"),     0,  72,   16, 0, offsetof(struct dbins_, attr_old)},
+  { NULL, N_("attr_new"),     0,  73,   16, 0, offsetof(struct dbins_, attr_new)},
+  { NULL, N_("acl_old"),      0,  74, 1024, 0, offsetof(struct dbins_, acl_old)},
+  { NULL, N_("acl_new"),      0,  75, 1024, 0, offsetof(struct dbins_, acl_new)},
 
   { NULL, NULL,      0,  0, 0, 0, 0 }
 };
 
-#define SH_SLOT_HOST    70
+#define SH_SLOT_CHECKFLAGS 69
+
+/* need special attention b/o reserved SQL words    */
+#define SH_SLOT_HOST    71
 #define SH_SLOT_GROUP    7
+
+/* these go into dbins.ulong_data[n-START_SEC_LONGS */
 #define START_SEC_LONGS 51
-#define END_SEC_LONGS   68
+#define END_SEC_LONGS   70
 
 #if defined(HAVE_INT_32)
@@ -1163,5 +1173,5 @@
     }
 
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       p = mysql_info (db_conn);
@@ -1360,4 +1370,10 @@
   while (attr_tab[i].attr != NULL)
     {
+      if (SH_SLOT_CHECKFLAGS == attr_tab[i].val) {
+	if (db_entry->ulong_data[attr_tab[i].val-START_SEC_LONGS] == 0 &&
+	    db_entry->ulong_data[attr_tab[i+1].val-START_SEC_LONGS] == 0)
+	  { i+= 2; continue; } 
+      }
+
       if (attr_tab[i].size != 0)
 	{
@@ -1728,9 +1744,8 @@
 				       (size_t) res->size);
 		  }
-		else if (res->val >= START_SEC_LONGS)
+		else if (res->val >= START_SEC_LONGS && res->val <= END_SEC_LONGS)
 		  {
 		    db_entry->ulong_data[res->val-START_SEC_LONGS]
-		      = strtoul(&p[j+2], (char **) NULL, 10); 
-		    /* atol(&p[j+2]); */
+		      = strtoul(&p[j+2], (char **) NULL, 0);
 		  }
 
Index: trunk/src/sh_dbCheck.c
===================================================================
--- trunk/src/sh_dbCheck.c	(revision 481)
+++ trunk/src/sh_dbCheck.c	(revision 481)
@@ -0,0 +1,122 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 2015 Rainer Wichmann                                      */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+
+#include <string.h>
+
+#include "samhain.h"
+#include "sh_unix.h"
+#include "sh_utils.h"
+#include "sh_hash.h"
+#include "sh_files.h"
+#include "sh_tiger.h"
+
+#include "sh_dbIO.h"
+#include "sh_dbIO_int.h"
+#include "sh_pthread.h"
+
+#undef  FIL__
+#define FIL__  _("sh_dbCheck.c")
+
+#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) 
+
+static void file_verify(sh_file_t * p)
+{
+  int reported = 0;
+  unsigned long check_flags;
+  char * dir_name;
+  char * file_name;
+
+  if (p->next != NULL)
+    file_verify(p->next);
+  if (p->fullpath == NULL || p->fullpath[0] != '/')
+    return;
+
+  check_flags = p->theFile.checkflags;
+
+  if (!MODI_INITIALIZED(check_flags)) {
+    MODI_SET(check_flags, MODI_INIT|MASK_READONLY_);
+    sh_tiger_get_mask_hashtype(&check_flags);
+  }
+
+  dir_name   = sh_util_dirname(p->fullpath);
+  file_name  = sh_util_basename(p->fullpath);
+
+  if (SH_FILE_UNKNOWN == sh_files_filecheck (SH_LEVEL_READONLY, check_flags,
+					     dir_name, file_name,
+					     &reported, 0))
+    ++sh.statistics.files_report;
+
+  SH_FREE(dir_name);
+  SH_FREE(file_name);
+  return;
+}
+
+static void dbCheck_setup()
+{
+  sh_hash_set_initialized();
+  sh.flag.isdaemon = S_FALSE; 
+  sh.flag.loop     = S_FALSE;
+  sh.flag.update   = S_FALSE;
+  sh.flag.checkSum = SH_CHECK_CHECK;
+  
+  sh.statistics.files_report  = 0;
+  ShDFLevel[SH_ERR_T_FILE]    = SH_ERR_SEVERE;
+  ShDFLevel[SH_ERR_T_RO]      = SH_ERR_SEVERE;
+  ShDFLevel[SH_ERR_T_NAME]    = SH_ERR_SEVERE;
+
+  return;
+}
+#include <stddef.h>
+int sh_dbCheck_verify (const char * db_file)
+{
+  unsigned int i;
+  sh_file_t ** mtab = get_default_data_table();
+  
+  sh_error_only_stderr (S_TRUE);
+  sh_error_setprint(_("none"));
+
+  /* for sh.effective.home in open_tmp() */
+  sh_unix_getUser (); 
+
+  if (sh_dbIO_load_db_file(mtab, db_file) < 0)
+    aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+
+  dbCheck_setup();
+
+  /* Don't lock because:
+   * (a) we are single-treaded, thus it's not required
+   * (b) it will lead to deadlocking
+   */
+  for (i = 0; i < TABSIZE; ++i)
+    {
+      if (mtab[i] != NULL) 
+	file_verify(mtab[i]);
+    }
+  
+  sh_hash_unvisited (SH_ERR_INFO);
+  
+  if (0 != sh.statistics.files_report)
+    aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+  aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+  return 0;
+}
+
+#endif
Index: trunk/src/sh_dbCreate.c
===================================================================
--- trunk/src/sh_dbCreate.c	(revision 481)
+++ trunk/src/sh_dbCreate.c	(revision 481)
@@ -0,0 +1,227 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 2015 Rainer Wichmann                                      */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "samhain.h"
+#include "sh_utils.h"
+#include "sh_hash.h"
+#include "sh_files.h"
+
+#include "sh_dbIO.h"
+#include "sh_dbIO_int.h"
+#include "sh_pthread.h"
+#include "sh_guid.h"
+
+#undef  FIL__
+#define FIL__  _("sh_dbCreate.c")
+
+#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) 
+
+static int dbCreate_writeout()
+{
+  char   uuid[SH_UUID_BUF];
+  char * path;
+  int    retval;
+
+  if (sh.outpath == NULL || sh.outpath[0] == '\0')
+    {
+      sh_uuid_generate_random(uuid, sizeof(uuid));
+      path = sh_util_strconcat(_("file."), sh.host.name, ".", uuid, NULL);
+    }
+  else
+    path = sh_util_strdup(sh.outpath);
+
+  retval = sh_dbIO_writeout_to_path(path);
+  SH_FREE(path);
+  return retval;
+}
+
+static void  dbCreate_run_filecheck(unsigned long add_mask, char * str)
+{
+  int status;
+
+  int reported = 0;
+  unsigned long check_flags = (MASK_READONLY_ | MODI_INIT | add_mask);
+  char * dir_name   = sh_util_dirname(str);
+  char * file_name  = sh_util_basename(str);
+
+  status = sh_files_filecheck (SH_LEVEL_READONLY, check_flags,
+			       dir_name, file_name, &reported, 0);
+
+  if (status == SH_FILE_UNKNOWN)
+    {
+      sh_hash_insert_null(str);
+    }
+
+  return;
+}
+
+static int dbCreate_filecheck(char * str)
+{
+  unsigned long add_mask = 0;
+
+  if (*str == '+')
+    {
+      add_mask = MODI_TXT;
+      ++str; while (isspace((int)*str)) ++str;
+    }
+  if (*str != '/')
+    {
+      char * tmp  = sh_util_safe_name (str);
+      sh_error_handle((-1), FIL__, __LINE__, EINVAL, MSG_E_SUBGPATH,
+		      _("Not an absolute path"), 
+		      _("dbCreate_filecheck"), tmp);
+      SH_FREE(tmp);
+      return -1;
+    }
+  dbCreate_run_filecheck(add_mask, str);
+  return 0;
+}
+
+char * rtrim(char * str)
+{
+  size_t len;
+
+  if (!str)
+    return str;
+
+  len = strlen(str);
+  while (len > 0)
+    {
+      --len;
+      if (str[len] == '\n' || str[len] == '\r')
+        str[len] = '\0';
+      else
+        break;
+    }
+    
+  return str;
+}
+
+static int dbCreate_loop(FILE * fd)
+{
+  int  status, retval = 0;
+  size_t linesize = MAX_PATH_STORE+2;
+  char * line = SH_ALLOC(linesize);
+
+  do {
+    status = sh_dbIO_getline(fd, line, linesize);
+
+    if (status > 0)
+      {
+	char * str = rtrim(line);   
+	while (isspace((int)*str)) ++str;
+	if (*str != '#')
+	  {
+	    int    fstatus = -1;
+	    size_t len     = 0;
+	    char * p       = sh_files_parse_input(str, &len);
+
+	    if (p)
+	      {
+		fstatus = dbCreate_filecheck(p);
+		SH_FREE(p);
+	      }
+	    if (fstatus != 0)
+	      retval = -1;
+	  }
+      }
+  } while (status != -1);
+
+  SH_FREE(line);
+  return retval;
+}
+
+static FILE * dbCreate_open (const char * path)
+{
+  FILE * fd = fopen(path, "r");
+  if (!fd)
+    {
+      int error = errno;
+      char * tmp  = sh_util_safe_name (path);
+      sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_SUBGPATH,
+		      _("Cannot open file for read"), 
+		      _("dbCreate_open"), tmp);
+      SH_FREE(tmp);
+      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+    }
+  return fd;
+}
+
+static void dbCreate_setup()
+{
+  sh_hash_set_initialized();
+  sh.flag.isdaemon = S_FALSE; 
+  sh.flag.loop     = S_FALSE;
+  sh.flag.update   = S_FALSE;
+  sh.flag.checkSum = SH_CHECK_CHECK;
+  
+  sh.statistics.files_report  = 0;
+  ShDFLevel[SH_ERR_T_FILE]    = SH_ERR_SEVERE;
+  ShDFLevel[SH_ERR_T_RO]      = SH_ERR_SEVERE;
+  ShDFLevel[SH_ERR_T_NAME]    = SH_ERR_SEVERE;
+
+  sh_error_only_stderr (S_TRUE);
+  sh_error_setprint(_("none"));
+
+  return;
+}
+
+
+int sh_dbCreate (const char * path)
+{
+  FILE * fd;
+
+  /* Initialize application status
+   */
+  dbCreate_setup();
+
+  /* Open file list
+   */
+  fd = dbCreate_open(path);
+
+  /* Load the database
+   */
+  sh_hash_init_and_checksum();
+
+  /* Loop over file list to check files.
+   */
+  dbCreate_loop(fd);
+
+  /* Close file list
+   */
+  fclose(fd);
+
+  /* Write out database
+   */
+  if (0 != dbCreate_writeout())
+    aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+
+  /* Exit on success.
+   */
+  aud_exit(FIL__, __LINE__, EXIT_SUCCESS);
+  return 0;
+}
+    
+#endif
Index: trunk/src/sh_dbIO.c
===================================================================
--- trunk/src/sh_dbIO.c	(revision 481)
+++ trunk/src/sh_dbIO.c	(revision 481)
@@ -0,0 +1,1762 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 2015 Rainer Wichmann                                      */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "samhain.h"
+#include "sh_utils.h"
+#include "sh_dbIO_int.h"
+#include "sh_hash.h"
+#include "sh_dbIO.h"
+#include "sh_gpg.h"
+#include "sh_tiger.h"
+#include "sh_xfer.h"
+#include "sh_pthread.h"
+#include "sh_socket.h"
+#include "sh_files.h"
+
+#undef  FIL__
+#define FIL__  _("sh_dbIO.c")
+
+#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) 
+
+/* external prototypes                                                     */
+
+extern int get_the_fd (SL_TICKET ticket);
+
+SH_MUTEX_EXTERN(mutex_hash);
+
+/******************************************************************
+ *
+ * Get a single line
+ *
+ ******************************************************************/
+static FILE * sh_fin_fd = NULL;
+
+int sh_dbIO_getline (FILE * fd, char * line, const size_t sizeofline)
+{
+  size_t  n = 0;
+
+  SL_REQUIRE(sizeofline >= SH_MINIBUF, _("sizeofline >= SH_MINIBUF"));
+
+  if (NULL != fgets(line, sizeofline, fd))
+    {
+      n = strlen(line);
+      if (n > 0 && line[n-1] == '\n') {
+	n--; line[n] = '\0';
+      }
+    } 
+  else {
+    line[0] = '\0';
+    return -1;
+  }
+
+  return n;
+}
+
+/******************************************************************
+ *
+ * Fast forward to start of data
+ *
+ ******************************************************************/
+
+static void reopen_fin_fd(SL_TICKET fd)
+{
+  if (sh_fin_fd != NULL)
+    {
+      sl_fclose (FIL__, __LINE__, sh_fin_fd);
+      sh_fin_fd = NULL;
+    }
+
+  sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb");
+  return;
+}
+
+
+static int seek_sof(FILE * fd, char * line, int size, const char * file)
+{
+  long i;
+
+  while (1) 
+    {
+      i =  sh_dbIO_getline (fd, line, size);
+      if (i < 0 ) 
+	{
+	  SH_FREE(line);
+	  dlog(1, FIL__, __LINE__, 
+	       _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
+	       (NULL == file) ? _("(null)") : file);
+	       
+	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
+			   ( (NULL == file) ? _("(null)") : file)
+			   );
+	  return -1;
+	}
+
+#if defined(SH_STEALTH)
+      if (0 == sl_strncmp (line, N_("[SOF]"), 5)) 
+#else
+      if (0 == sl_strncmp (line, _("[SOF]"),  5)) 
+#endif
+	break;
+    }
+  fflush(fd);
+  return 0;
+}
+
+static int sh_dbIO_setdataent (SL_TICKET fd, char * line, int size, 
+			       const char * file)
+{
+  int retval;
+
+  SL_ENTER(_("sh_dbIO_setdataent"));
+
+  sl_rewind (fd);
+  reopen_fin_fd(fd);
+
+  if (!sh_fin_fd)
+    {
+      dlog(1, FIL__, __LINE__, 
+	   _("The file signature database: %s is not readable.\n"),
+	   (NULL == file) ? _("(null)") : file);
+      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
+		       ( (NULL == file) ? _("(null)") : file)
+		       );
+      SL_RETURN( -1, _("sh_dbIO_setdataent"));
+    }
+
+  retval = seek_sof(sh_fin_fd, line, size, file);
+  SL_RETURN( retval, _("sh_dbIO_setdataent"));
+}
+
+static int sh_dbIO_setdataent_old (SL_TICKET fd, char * line, int size, 
+				   const char * file)
+{
+  FILE * fdp;
+
+  SL_ENTER(_("sh_dbIO_setdataent_old"));
+
+  sl_rewind (fd);
+  fdp = sl_stream(fd, "r+");
+  if (0 != seek_sof(fdp, line, size, file))
+    SL_RETURN( SL_EREAD, _("sh_dbIO_setdataent_old"));
+  if (0 != ftruncate(fileno(fdp), ftello(fdp)))
+    {
+      char ebuf[SH_ERRBUF_SIZE];
+      int errnum = errno;
+      sh_error_message(errnum, ebuf, sizeof(ebuf));
+      sh_error_handle ((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN,
+		       ebuf, _("sh_dbIO_setdataent_old") );
+      SL_RETURN( SL_EWRITE, _("sh_dbIO_setdataent_old"));
+    }
+  SL_RETURN( 0, _("sh_dbIO_setdataent_old"));
+}
+
+/******************************************************************
+ *
+ * IO helper functions
+ *
+ ******************************************************************/
+
+
+static UINT32 * swap_32 (UINT32 * iptr)
+{
+#ifdef WORDS_BIGENDIAN
+  unsigned char swap;
+  unsigned char * ii = (unsigned char *) iptr;
+  swap = ii[0]; ii[0] = ii[3]; ii[3] = swap;
+  swap = ii[1]; ii[1] = ii[2]; ii[2] = swap;
+  return iptr;
+#else
+  return iptr;
+#endif
+}
+
+static UINT64 *  swap_64 (UINT64 * iptr)
+{
+#ifdef WORDS_BIGENDIAN
+#ifdef UINT64_IS_32
+  swap_32 ((UINT32*) iptr);
+#else
+  unsigned char swap;
+  unsigned char * ii = (unsigned char *) iptr;
+  swap = ii[0]; ii[0] = ii[7]; ii[7] = swap;
+  swap = ii[1]; ii[1] = ii[6]; ii[6] = swap;
+  swap = ii[2]; ii[2] = ii[5]; ii[5] = swap;
+  swap = ii[3]; ii[3] = ii[4]; ii[4] = swap;
+#endif
+  return iptr;
+#else
+  return iptr;
+#endif
+}
+
+static unsigned short *  swap_short (unsigned short * iptr)
+{
+#ifdef WORDS_BIGENDIAN
+  if (sizeof(short) == 4)
+    swap_32 ((UINT32*) iptr);
+  else
+    {
+      /* alignment problem */
+      unsigned char swap;
+      static unsigned short ooop;
+      unsigned char * ii;
+      ooop = *iptr;
+      ii = (unsigned char *) &ooop;
+      swap = ii[0]; ii[0] = ii[1]; ii[1] = swap;
+      return &ooop;
+    }
+  return iptr;
+#else
+  return iptr;
+#endif
+}
+
+static void swap_data(sh_filestore_t * ft)
+{
+  swap_32(&(ft->mode));
+  swap_32(&(ft->linkmode));
+  swap_64(&(ft->dev));
+  swap_64(&(ft->rdev));
+  swap_32(&(ft->hardlinks));
+  swap_32(&(ft->ino));
+  swap_64(&(ft->size));
+  swap_64(&(ft->atime));
+  swap_64(&(ft->mtime));
+  swap_64(&(ft->ctime));
+  swap_32(&(ft->owner));
+  swap_32(&(ft->group));
+  swap_32(&(ft->checkflags));
+#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
+  swap_32(&(ft->attributes));
+#endif
+  ft->mark = *(swap_short(&(ft->mark)));
+  return;
+}
+
+#define QUOTE_CHAR '='
+
+char * unquote_string (const char * str, size_t len)
+{
+  int    i = 0, t1, t2;
+  char * tmp = NULL;
+  size_t l2, j, k = 0;
+
+  SL_ENTER(_("unquote_string"));
+
+  if (str != NULL)
+    {
+      l2  = len - 2;
+      tmp = SH_ALLOC(len + 1);
+
+      for (j = 0; j <= len; ++j)
+	{
+	  if (str[j] != QUOTE_CHAR)
+	    {
+	      tmp[k] = str[j];
+	    }
+	  else if (str[j] == QUOTE_CHAR && j < l2)
+	    {
+	      t1 = sh_util_hexchar(str[j+1]);
+	      t2 = sh_util_hexchar(str[j+2]);
+	      if ((t1|t2) >= 0)
+		{
+		  i = 16 * t1 + t2;
+		  tmp[k] = i; 
+		  j += 2;
+		}
+	      else
+		{
+		  tmp[k] = str[j];
+		}
+	    }
+	  else
+	    tmp[k] = str[j];
+	  ++k;
+	}
+    }
+  SL_RETURN(tmp, _("unquote_string"));
+}
+
+static char * int2hex (unsigned char i, char * i2h)
+{
+  static char hexchars[] = "0123456789ABCDEF";
+
+  i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */
+  i2h[1] = hexchars[((i) & 0x0F)];        /* low  */
+
+  return i2h;
+}
+
+char * quote_string (const char * str, size_t len)
+{
+  char * tmp;
+  char * tmp2;
+  size_t l2, j, i = 0, k = 0;
+  char   i2h[2];
+
+  SL_ENTER(_("quote_string"));
+
+  if (str == NULL)
+    {
+      SL_RETURN(NULL, _("quote_string"));
+    }
+
+  for (j = 0; j < len; ++j)
+    if (str[j] == '\n' || str[j] == QUOTE_CHAR) ++i;
+
+  l2 = len + 1;
+  if (sl_ok_muls(3, i) && sl_ok_adds(l2, (3*i)))
+    {
+      tmp = SH_ALLOC(len + 1 + 3*i);
+    }
+  else
+    {
+      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+		      _("integer overflow"), 
+		      _("quote_string"));
+      SL_RETURN(NULL, _("quote_string"));
+    }
+
+  for (j = 0; j <= len; ++j)
+    {
+      if (str[j] == '\n')
+	{
+	  tmp2 = int2hex((unsigned char) '\n', i2h);
+	  tmp[k] = QUOTE_CHAR; ++k;
+	  tmp[k] = tmp2[0];    ++k;
+	  tmp[k] = tmp2[1];
+	}
+      else if (str[j] == QUOTE_CHAR)
+	{
+	  tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h);
+	  tmp[k] = QUOTE_CHAR; ++k;
+	  tmp[k] = tmp2[0];    ++k;
+	  tmp[k] = tmp2[1];
+	}
+      else
+	{
+	  tmp[k] = str[j];
+	}
+      ++k;
+    }
+  SL_RETURN(tmp, _("quote_string"));
+}
+
+static char * unquote_path(char * line, long i)
+{
+  char * tmp  = unquote_string (line, i);
+  size_t len  = sl_strlen(tmp)+1;
+  char * path = SH_ALLOC(len);
+
+  (void) sl_strlcpy (path, tmp, len);
+  if (tmp)
+    SH_FREE(tmp);
+  if (len > 1) {
+    if (path[len-2] == '\n')
+      path[len-2] = '\0';
+  }
+  return path;
+}
+
+/******************************************************************
+ *
+ * Read next record and return it
+ *
+ ******************************************************************/
+
+static void corrupt_record(char * file, int line, const char * filepath)
+{
+  dlog(1, file, line, 
+       _("There is a corrupt record in the file signature database: %s\n"),
+       (NULL == filepath)? _("(null)") : filepath);
+  sh_error_handle ((-1), file, line, 0, MSG_E_SUBGPATH,
+		   _("Corrupt record in file signature database"), 
+		   _("sh_dbIO_getdataent"),
+		   ( (NULL == filepath) ? _("(null)") : filepath) );
+  return;
+}
+
+static void wrong_version(char * file, int line, const char * filepath)
+{
+  dlog(1, file, line, 
+       _("There is a record with a bad version number in the file signature database: %s\n"),
+       (NULL == filepath) ? _("(null)") : filepath);
+  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
+		  _("Record with bad version number in file signature database"), 
+		  _("sh_dbIO_getdataent"),
+		  (NULL == filepath) ? _("(null)") : filepath);
+  return;
+}
+
+static size_t dbIO_fread_struct (sh_filestore_t * ptr, FILE *stream, 
+				 const char * path, int * errflag)
+{
+  sh_filestore_old_t old_struct;
+  fpos_t position;
+  static int oldflag = -1;
+
+ start:
+  if (oldflag != -1) /* 'initialized' case first */
+    {
+      if (oldflag == 0)
+	return fread (ptr, sizeof(sh_filestore_t), 1, stream);
+
+      else
+	{
+	  unsigned short mark;
+	  if (1 != fread (&old_struct, sizeof(old_struct), 1, stream))
+	    return 0;
+
+	  /* set mark to current version */
+	  mark = old_struct.mark;
+	  mark = *(swap_short(&(mark)));
+	  if ((mark & ~REC_FLAGS_MASK) != OLD_REC_MAGIC)
+	    {
+	      sh_filestore_old_t try_struct;
+	      char try[5];
+
+	      memset(&try_struct, '\0', sizeof(try_struct));
+	      if (!memcmp(&old_struct, &try_struct, sizeof(try_struct)))
+		return 0; /* NULL read */
+	      if (1 != fread (try, sizeof(try), 1, stream))
+		return 0;
+	      if (feof(stream))
+		return 0;
+
+	      wrong_version(FIL__, __LINE__, path);
+	      *errflag = -1;
+	      return 0;
+	    }
+	  if ((mark & REC_FLAGS_ATTR) != 0)
+	    mark = REC_MAGIC|REC_FLAGS_ATTR;
+	  else
+	    mark = REC_MAGIC;
+	  mark = *(swap_short(&(mark)));
+	  old_struct.mark = mark;
+
+	  /* copy into current struct version */
+	  memcpy(ptr, &old_struct, sizeof(old_struct));
+	  ptr->checkflags = 0;
+	  return 1;
+	}
+    }
+  else /* not initialized yet, test DB version */
+    {
+      if (0 == fgetpos(stream, &position))
+	{
+	  unsigned short mark;
+
+	  if (1 != fread (&old_struct, sizeof(old_struct), 1, stream))
+	    return 0;
+
+	  mark = old_struct.mark;
+	  mark = *(swap_short(&(mark)));
+	  if ((mark & ~REC_FLAGS_MASK) == REC_MAGIC)
+	    oldflag = 0;
+	  else if ((mark & ~REC_FLAGS_MASK) == OLD_REC_MAGIC)
+	    oldflag = 1;
+	  else
+	    {
+	      wrong_version(FIL__, __LINE__, path);
+	      *errflag = -1;
+	      return 0;
+	    }
+
+	  /* return to previous position and read data */
+	  if (0 != fsetpos(stream, &position))
+	    return 0;
+	  goto start;
+	}
+      return 0;
+    }
+}
+
+int sig_end_detected (void * ft)
+{
+  char * str = (char *) ft;
+  char cmp[SH_MINIBUF];
+
+  sl_strlcpy(cmp, _("-----BEGIN PGP SIGNATURE-----"), sizeof(cmp));
+
+  if ( 0 == memcmp(str, cmp, strlen(cmp)) ) 
+    return S_TRUE;
+  return S_FALSE;
+}
+
+static sh_file_t *  sh_dbIO_getdataent (char * line, int size, 
+					const char * filepath, int * errflag)
+{
+  sh_file_t * p;
+  sh_filestore_t ft;
+  long i;
+  char * fullpath;
+  char * linkpath;
+  char * attr_string = NULL;
+
+  SL_ENTER(_("sh_dbIO_getdataent"));
+
+  *errflag = 0;
+
+  p = SH_ALLOC(sizeof(sh_file_t));
+
+  /* Read next record -- Part One 
+   */
+  if (1 != dbIO_fread_struct (&ft, sh_fin_fd, filepath, errflag))
+    {
+      SH_FREE(p);
+      SL_RETURN( NULL, _("sh_dbIO_getdataent"));
+    }
+
+  ft.mark = *(swap_short(&(ft.mark)));
+
+  if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
+    {
+      if (sig_end_detected(&ft))
+	{
+	  SH_FREE(p);
+	  SL_RETURN( NULL, _("sh_dbIO_getdataent"));
+	}
+      SH_FREE(p);
+      wrong_version(FIL__, __LINE__, filepath);
+      *errflag = -1;
+      SL_RETURN( NULL, _("sh_dbIO_getdataent"));
+    }
+
+  ft.mark = *(swap_short(&(ft.mark)));
+  swap_data(&ft);
+
+  /* Read next record -- Part Two -- Fullpath
+   */
+  i = sh_dbIO_getline (sh_fin_fd, line, size);
+
+  if (i <= 0 ) 
+    {
+      SH_FREE(p);
+      corrupt_record(FIL__, __LINE__, filepath);
+      *errflag = -1;
+      SL_RETURN( NULL, _("sh_dbIO_getdataent"));
+    }
+
+  fullpath = unquote_path(line, i);
+
+  /* Read next record -- Part Three -- Linkpath
+   */
+  i =  sh_dbIO_getline (sh_fin_fd, line, size);
+
+  if (i <= 0 ) 
+    {
+      SH_FREE(fullpath); SH_FREE(p);
+      corrupt_record(FIL__, __LINE__, filepath);
+      *errflag = -1;
+      SL_RETURN( NULL, _("sh_dbIO_getdataent"));
+    }
+
+  linkpath = unquote_path(line, i);
+
+  /* Read next record -- Part Four -- attr_string
+   */
+  if ((ft.mark & REC_FLAGS_ATTR) != 0)
+    {
+      i =  sh_dbIO_getline (sh_fin_fd, line, size);
+      if (i <= 0 ) 
+	{
+	  SH_FREE(fullpath); SH_FREE(linkpath); SH_FREE(p);
+	  corrupt_record(FIL__, __LINE__, filepath);
+	  *errflag = -1;
+	  SL_RETURN( NULL, _("sh_dbIO_getdataent"));
+	}
+
+      attr_string = unquote_path(line, i);
+    }
+
+  /* Read next record -- Part Four -- Decode
+   */
+#if defined(SH_STEALTH)
+  sh_do_decode(fullpath,    sl_strlen(fullpath));
+#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
+  sh_do_decode(ft.c_attributes,   sl_strlen(ft.c_attributes));
+#endif
+  sh_do_decode(ft.c_mode,   sl_strlen(ft.c_mode));
+  sh_do_decode(ft.c_owner,  sl_strlen(ft.c_owner));
+  sh_do_decode(ft.c_group,  sl_strlen(ft.c_group));
+  sh_do_decode(ft.checksum, sl_strlen(ft.checksum));  
+  /* 
+   * TXT entries are c_mode[0] != 'l' and do not get decoded 
+   */
+  if (ft.c_mode[0] == 'l' && linkpath[0] != '-')
+    {  
+      sh_do_decode(linkpath, sl_strlen(linkpath));
+    }
+  if ((ft.mark & REC_FLAGS_ATTR) != 0)
+    {  
+      sh_do_decode(attr_string, sl_strlen(attr_string));
+    }
+#endif
+
+  memcpy( &(*p).theFile, &ft, sizeof(sh_filestore_t) );
+
+  /* init fflags, such that suid files in 
+   * database are recognized as such 
+   */
+  {
+    mode_t mode = (mode_t) ft.mode;
+
+    if (S_ISREG(mode) &&
+	(0 !=(S_ISUID & mode) ||
+#if defined(HOST_IS_LINUX)
+	 (0 !=(S_ISGID & mode) && 
+	  0 !=(S_IXGRP & mode)) 
+#else  
+	 0 !=(S_ISGID & mode)
+#endif
+	 )
+	)
+      p->fflags = SH_FFLAG_SUIDCHK;
+
+    else
+      p->fflags = 0;
+  }
+
+  p->modi_mask   = ft.checkflags;
+  if (MODI_ISSET(ft.checkflags, MODI_ALLIGNORE))
+    SET_SH_FFLAG_ALLIGNORE(p->fflags);
+  p->fullpath    = fullpath;
+  p->linkpath    = linkpath;
+  p->attr_string = attr_string;
+
+  /* set to an invalid value 
+   */
+  ft.mark = (REC_MAGIC + 5);
+
+  SL_REQUIRE((*errflag == 0), _("errflag not set correctly"));
+  SL_RETURN( p, _("sh_dbIO_getdataent"));
+}
+
+/******************************************************************
+ *
+ * Data loading routines
+ *
+ ******************************************************************/
+static SL_TICKET load_data_from_server(const char * uuid)
+{
+  SL_TICKET fd = -1;
+
+#if defined(SH_WITH_CLIENT)
+  char hashbuf[KEYBUF_SIZE];
+
+  /* Data file from Server
+   */
+  if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
+    return -1;
+
+  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_DSTART);
+  fd = sh_xfer_request_file((!uuid) ? _("DATA") : uuid);
+
+  if (SL_ISERROR(fd))
+    {
+      if (!uuid)
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD);
+	  dlog(1, FIL__, __LINE__, 
+	       _("Could not retrieve the file signature database from the server(errnum = %ld).\nPossible reasons include:\n - the server is not running,\n - session key negotiation failed (see the manual for proper setup), or\n - the server cannot access the file.\n"), fd);  
+	}
+      else
+	sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_TCP_FBAD);
+      return fd;
+    }
+  sl_rewind (fd);
+
+  if (!uuid)
+    {
+      sl_strlcpy (sh.data.hash, 
+		  sh_tiger_hash (file_path('D', 'R'),  
+				 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
+		  KEY_LEN+1);
+      sl_rewind (fd);
+    }
+#else
+  (void) uuid;
+#endif
+  return fd;
+}
+
+static SL_TICKET load_data_from_disk(const char * filepath)
+{
+  char hashbuf[KEYBUF_SIZE];
+  SL_TICKET fd = -1;
+
+  /* Local data file
+   */
+  if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, filepath, SL_YESPRIV)) )
+    {
+      TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"), filepath));
+      dlog(1, FIL__, __LINE__, 
+    _("Could not open the local file signature database for reading because\nof the following error: %s (errnum = %ld)\nIf this is a permission problem, you need to change file permissions\nto make the file readable for the effective UID: %d\n"), 
+	   sl_get_errmsg(), fd, (int) sl_ret_euid());
+      sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1, 
+		       sh.prg_name);
+      return -1;
+    }
+  
+  TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"), 
+	filepath));
+
+  if (sh.data.hash[0] == '\0')
+    {
+      char hashbuf[KEYBUF_SIZE];
+      sl_strlcpy(sh.data.hash, 
+		 sh_tiger_hash (filepath, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), 
+		 KEY_LEN+1);
+    }
+  else
+    {
+      if (0 != sl_strncmp(sh.data.hash, 
+			  sh_tiger_hash (filepath, fd, TIGER_NOLIM, 
+					 hashbuf, sizeof(hashbuf)),
+			  KEY_LEN)
+	  && sh.flag.checkSum != SH_CHECK_INIT) 
+	{
+	  dlog(1, FIL__, __LINE__, 
+	       _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
+	       sh.data.hash, sh_tiger_hash (filepath, fd, TIGER_NOLIM, 
+					    hashbuf, sizeof(hashbuf)));
+	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
+			   ( (NULL == filepath) ? _("(null)") :
+			     filepath )
+			   );
+	}
+    }
+  sl_rewind (fd);
+  return fd;
+}
+
+static SL_TICKET verify_data (SL_TICKET fd)
+{
+#if defined(WITH_GPG) || defined(WITH_PGP)
+  SL_TICKET fdTmp;
+
+  /* extract the data and copy to temporary file
+   */
+  fdTmp = sh_gpg_extract_signed(fd);
+
+  if (sig_termfast == 1)  /* SIGTERM */
+    {
+      TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
+      --sig_raised; --sig_urgent;
+      return -1;
+    }
+
+  sl_close(fd);
+  fd = fdTmp;
+
+  /* Validate signature of open file.
+   */
+  if (0 != sh_gpg_check_sign (fd, SIG_DATA))
+    {
+      sl_close(fd);
+      return -1;
+    }
+  sl_rewind (fd);
+#endif
+
+  return fd;
+}
+
+static int read_data(SL_TICKET fd, sh_file_t * tab[TABSIZE], 
+		     const char * filepath)
+{
+  sh_file_t * p;
+  int count = 0;
+  int errflag = 0;
+  char * line = SH_ALLOC(MAX_PATH_STORE+2);
+
+  /* fast forward to start of data
+   */
+  if (0 != sh_dbIO_setdataent(fd, line, MAX_PATH_STORE+1, filepath))
+    return -1;
+
+  while (1) 
+    {
+      if (sig_termfast == 1)  /* SIGTERM */
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
+	  --sig_raised; --sig_urgent;
+	  SH_FREE(line);
+	  return -1;
+	}
+
+      p = sh_dbIO_getdataent (line, MAX_PATH_STORE+1, filepath, &errflag);
+      if (p != NULL)
+	{
+	  if (!sh_hash_is_null_record(&(p->theFile)))
+	    hashinsert (tab, p);
+	  else
+	    sh_hash_remove_unconditional (p->fullpath);
+	  ++count;
+	}
+      else
+	break;
+    }
+
+  if (line != NULL)
+    SH_FREE(line);
+
+  /* Always keep db in memory, so we have no open file
+   */
+  sl_close (fd);
+
+  sl_fclose (FIL__, __LINE__, sh_fin_fd);
+  sh_fin_fd = NULL;
+
+  return errflag;
+}
+
+
+static int sh_dbIO_load_db_int(sh_file_t * tab[TABSIZE], 
+			       const char * filepath, const char * uuid)
+{
+#define FGETS_BUF 16384
+
+  SL_TICKET fd = -1;
+
+  if (uuid)
+    {
+      fd = load_data_from_server(uuid);
+      if (SL_ISERROR(fd))
+	return -1;
+    }
+  else if (!filepath)
+    {
+      char * dbpath = file_path('D', 'R');
+
+      fd = load_data_from_server(NULL);
+
+      if (SL_ISERROR(fd))
+	{
+	  if (*dbpath == '/')
+	    fd = load_data_from_disk(dbpath);
+	}
+    }
+  else
+    {
+      fd = load_data_from_disk(filepath);
+    }
+
+  if (SL_ISERROR(fd))
+    return -1;
+
+  if (sig_termfast == 1)  /* SIGTERM */
+    {
+      TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
+      --sig_raised; --sig_urgent;
+      aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+    }
+
+  fd = verify_data(fd);
+  if (SL_ISERROR(fd))
+    return -1;
+
+  if (!uuid) { int i; for (i = 0; i < TABSIZE; ++i) tab[i] = NULL; }
+
+  return read_data (fd, tab, filepath);
+}
+
+
+int sh_dbIO_load_db(sh_file_t * tab[TABSIZE])
+{
+  return sh_dbIO_load_db_int(tab, NULL, NULL);
+}
+int sh_dbIO_load_db_file(sh_file_t * tab[TABSIZE], const char * filepath)
+{
+  return sh_dbIO_load_db_int(tab, filepath, NULL);
+}
+
+int sh_dbIO_load_delta()
+{
+  int    status = 0;
+#if defined(SH_WITH_CLIENT)
+  sh_file_t ** mtab = get_default_data_table();
+  int errflag = 0;
+  unsigned int count;
+  time_t last;
+
+  if ( sh.flag.checkSum != SH_CHECK_INIT )
+    {
+      if (sh_hash_get_initialized() != 0)
+	{
+	  char * uuid = sh_socket_get_uuid(&errflag, &count, &last);
+
+	  if (!uuid) 
+	    return errflag;
+
+	  if (count > 0)
+	    sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, count, MSG_E_SUBGEN,
+			  _("Retrying download of delta DB"), 
+			  _("sh_dbIO_load_delta"));
+
+	  status = sh_dbIO_load_db_int(mtab, NULL, uuid);
+	  if (status < 0)
+	    {
+	      /* Return status < 0 indicates that max_try is exceeded
+	       */
+	      if (sh_socket_return_uuid(uuid, count, last) < 0)
+		sh_error_handle((-1), FIL__, __LINE__, -1, MSG_D_DELTAFAIL, uuid);
+	    }
+	  else
+	    {
+	      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_D_DELTAOK, uuid);
+	    }
+	  SH_FREE(uuid);
+	}
+      else
+	{
+	  /* not initialized yet */
+	  sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			  _("Download of delta DB skipped, not initialized yet"), 
+			  _("sh_dbIO_load_delta"));
+	  return -1;
+	}
+    }
+#endif
+  return status;
+}
+
+/******************************************************************
+ *
+ * Writing out a file to the database.
+ *
+ ******************************************************************/ 
+static int       pushdata_isfirst =  1;
+static SL_TICKET pushdata_fd      = -1;
+
+static int       pushdata_stdout  =  S_FALSE;
+
+static char * sh_db_version_string = NULL;
+
+int sh_dbIO_writeout_stdout (const char * str)
+{
+  if (!str)
+    { pushdata_stdout  =  S_TRUE; return 0; }
+  return -1;
+}
+
+int sh_dbIO_version_string(const char * str)
+{
+  if (str)
+    {
+      if (sh_db_version_string != NULL) {
+	SH_FREE(sh_db_version_string);
+      }
+      if (0 == sl_strncmp(str, _("NULL"), 4))
+	{
+	  sh_db_version_string = NULL;
+	  return 0;
+	}
+      sh_db_version_string = sh_util_strdup(str);
+      return 0;
+    }
+  return -1;
+}
+
+void do_writeout_checks(const char * outpath)
+{
+  if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
+    {
+      dlog(1, FIL__, __LINE__, 
+	   _("You cannot write the database to stdout when you use update rather than init.\n"));
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
+		      _("Writing database to stdout with update"), 
+		      sh.prg_name, 
+		      _("sh_dbIO_data_write_int"));
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+
+  if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
+    {
+      dlog(1, FIL__, __LINE__, 
+	   _("You cannot write the database to stdout when running with suid privileges.\n"));
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
+		      _("Writing database to stdout when suid"), 
+		      sh.prg_name, 
+		      _("sh_dbIO_data_write_int"));
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+
+
+  if ( (pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) && 
+       ( (NULL == outpath) || (0 == sl_strcmp(outpath, _("REQ_FROM_SERVER"))) ) )
+    {
+      dlog(1, FIL__, __LINE__, 
+	   _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
+		      _("No local path for database specified"), 
+		      sh.prg_name, 
+		      _("sh_dbIO_data_write_int"));
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+
+  if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))  
+    {
+      /* Warn that file already exists; file_path != NULL here because
+       * checked above
+       */
+      struct stat sbuf;
+
+      if (0 == retry_lstat(FIL__, __LINE__, outpath, &sbuf))
+	{
+	  if (sh.flag.update == S_FALSE)
+	    {
+	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
+			      file_path('D', 'W'));
+	    }
+	}
+    }
+
+  return;
+}
+
+static SL_TICKET open_writeout_data_truncate(const char * path)
+{
+  int status;
+  SL_TICKET fd;
+
+  if ( SL_ISERROR(fd = sl_open_rdwr_trunc(FIL__, __LINE__, path, SL_YESPRIV))) 
+    {
+      sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS,
+		      geteuid(), path);
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+
+  if (SL_ISERROR(status = sl_lock (fd)))
+    {
+      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
+		      _("Failed to lock baseline database"), _("sh_dbIO_data_write_int"),
+		      path);
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+  return fd;
+}
+
+static SL_TICKET open_writeout_data(const char * path)
+{
+  int status;
+  SL_TICKET fd;
+
+  if ( SL_ISERROR(fd = sl_open_rdwr(FIL__, __LINE__, path, SL_YESPRIV))) 
+    {
+      sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_ACCESS,
+		      geteuid(), path);
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+
+  if (SL_ISERROR(status = sl_lock (fd)))
+    {
+      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
+		      _("Failed to lock baseline database"), _("sh_dbIO_data_write_int"),
+		      path);
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+  return fd;
+}
+
+static void seek_writeout_data(SL_TICKET fd, const char * path)
+{
+  int status;
+
+  if ( SL_ISERROR(status = sl_forward(fd))) 
+    {
+      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
+		      _("Failed to seek to end of baseline database"),
+		      _("seek_writeout_data"),
+		      path);
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+  return;
+}
+
+static int seek_writeout_data_old(SL_TICKET fd, const char * path)
+{
+  char * line = SH_ALLOC(MAX_PATH_STORE+1);
+
+  if (SL_ISERROR(sh_dbIO_setdataent_old (fd, line, MAX_PATH_STORE, path)))
+    {
+      SH_FREE(line);
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
+		      _("Failed to seek to end of baseline database"),
+		      _("seek_writeout_data_old"),
+		      path);
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+  SH_FREE(line);
+  return 0;
+}
+
+char * prep_path(char * path, int flag)
+{
+  size_t old_len = sl_strlen(path);
+  char * tmp;
+  size_t tmp_len;
+  size_t path_len;
+  char * outpath = NULL;
+#if !defined(SH_STEALTH)
+  (void) flag;
+#endif
+
+#if defined(SH_STEALTH)
+  if (flag == S_TRUE)
+    sh_do_encode(path, old_len);
+#endif
+  tmp = quote_string(path, old_len);
+  tmp_len = sl_strlen(tmp);
+#if defined(SH_STEALTH)
+  if (flag == S_TRUE)
+    sh_do_decode(path, old_len);
+#endif
+
+  if (tmp && tmp_len <= MAX_PATH_STORE) 
+    {
+      outpath = sh_util_strdup(path);
+    } 
+  else 
+    {
+      char hashbuf[KEYBUF_SIZE];
+      
+      outpath = sh_util_strdup(sh_tiger_hash (path,
+					      TIGER_DATA, old_len, 
+					      hashbuf, sizeof(hashbuf)));
+    }
+  if (tmp) 
+    SH_FREE(tmp);
+
+  path_len = sl_strlen(outpath);
+#if defined(SH_STEALTH)
+  if (flag == S_TRUE)
+    sh_do_encode(outpath, path_len);
+#endif
+  
+  tmp = quote_string(outpath, path_len);
+  if (tmp) {
+    SH_FREE(outpath);
+    outpath = tmp;
+  }
+  return outpath;
+}
+
+static char * prep_attr(char * attr_str)
+{
+  char * tmp;
+  char * outstr = NULL;
+  size_t old_len = sl_strlen(attr_str);
+
+#if defined(SH_STEALTH)
+  sh_do_encode(attr_str, old_len);
+#endif
+
+  tmp = quote_string(attr_str, old_len);
+  if (tmp)
+    {
+      outstr = tmp;
+    }
+
+#if defined(SH_STEALTH)
+  sh_do_decode(attr_str, old_len);
+#endif
+  return outstr;
+}
+
+static void prep_encode(sh_filestore_t * p)
+{
+#if defined(SH_STEALTH)
+  sh_do_encode(p->c_mode,   sl_strlen(p->c_mode));
+  sh_do_encode(p->c_owner,  sl_strlen(p->c_owner));
+  sh_do_encode(p->c_group,  sl_strlen(p->c_group));
+  sh_do_encode(p->checksum, sl_strlen(p->checksum));
+  sh_do_encode(p->c_attributes,   sl_strlen(p->c_attributes));
+#else
+  (void) p;
+#endif
+  return;
+}
+
+static void prep_struct(sh_filestore_t * p, file_type * buf, char * fileHash)
+{
+#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
+  int    i;
+#endif
+  p->mark = REC_MAGIC;
+  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);
+  if (fileHash) {
+    sl_strlcpy(p->checksum, fileHash,      KEY_LEN+1);
+  }
+#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
+  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
+ 
+  prep_encode(p);
+  
+#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
+  p->attributes  = (UINT32) buf->attributes;
+#else
+  p->attributes  = 0;
+#endif
+  p->linkmode    = (UINT32) buf->linkmode;
+  p->hardlinks   = (UINT32) buf->hardlinks;
+  p->dev   = (UINT64) buf->dev;
+  p->rdev  = (UINT64) buf->rdev;
+  p->mode  = (UINT32) buf->mode;
+  p->ino   = (UINT32) buf->ino;
+  p->size  = (UINT64) buf->size;
+  p->mtime = (UINT64) buf->mtime;
+  p->atime = (UINT64) buf->atime;
+  p->ctime = (UINT64) buf->ctime;
+  p->owner = (UINT32) buf->owner;
+  p->group = (UINT32) buf->group;
+
+  p->checkflags = (UINT32) buf->check_flags; 
+  
+  return;
+}
+
+
+static void write_start_header(SL_TICKET fd)
+{
+  char   timestring[81];
+
+  if (pushdata_stdout == S_FALSE)
+    {
+      sl_write (fd, _("\n#Host "), 7);
+      sl_write (fd, sh.host.name, 
+		sl_strlen(sh.host.name));
+      sl_write (fd, _(" Version "), 9);
+      sl_write (fd, sh_db_version_string, 
+		sl_strlen(sh_db_version_string));
+      sl_write (fd, _(" Date "), 6);
+      (void) sh_unix_time(0, timestring, sizeof(timestring));
+      sl_write (fd, timestring, strlen(timestring));
+      sl_write (fd,        "\n", 1);
+    } 
+  else 
+    {
+      printf ("%s",_("\n#Host "));
+      printf ("%s", sh.host.name);
+      printf ("%s",_(" Version "));
+      printf ("%s", sh_db_version_string);
+      printf ("%s",_(" Date "));
+      (void) sh_unix_time(0, timestring, sizeof(timestring));
+      printf ("%s\n", timestring);
+    }
+}
+
+static void write_start_marker(SL_TICKET fd)
+{
+  if (sh_db_version_string != NULL)
+    {
+      write_start_header(fd);
+    }
+  
+  if (pushdata_stdout == S_FALSE)
+    {
+#if defined(SH_STEALTH)
+      sl_write      (fd,        "\n", 1);
+      sl_write_line (fd, N_("[SOF]"), 5);
+#else
+      sl_write_line (fd, _("\n[SOF]"),  6);
+#endif
+    }
+  else 
+    {
+#if defined(SH_STEALTH)
+      puts (N_("[SOF]"));
+#else
+      puts (_("\n[SOF]"));
+#endif
+    }
+}
+
+static void   write_record(SL_TICKET fd, sh_filestore_t * p, 
+			   char * fullpath, char * linkpath, char * attr_string)
+{
+  static char ll[2] = { '-', '\0' };
+  char * lpath;
+
+  if (!linkpath || 0 == sl_strlen(linkpath))
+    lpath = ll;
+  else
+    lpath = linkpath;
+
+  if (pushdata_stdout == S_FALSE)
+    {
+      sl_write           (fd,        p, sizeof(sh_filestore_t));
+      sl_write_line_fast (fd, fullpath, sl_strlen(fullpath));
+      sl_write_line_fast (fd,    lpath, sl_strlen(lpath));
+      if (attr_string)
+	sl_write_line_fast (fd, attr_string, sl_strlen(attr_string));
+    } 
+  else 
+    {
+      if (fwrite (p, sizeof(sh_filestore_t), 1, stdout))
+	{
+	  puts (fullpath);
+	  puts (lpath);
+	  if (attr_string)
+	    puts (attr_string);
+	}
+      else
+	{
+	  perror(_("Error writing database"));
+	  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+	}
+    }
+
+  SH_FREE(fullpath);
+  if (linkpath)
+    SH_FREE(linkpath);
+  if (attr_string)
+    SH_FREE(attr_string);
+
+  return;
+}
+
+static void sh_dbIO_data_write_int (file_type * buf, char * fileHash, 
+				    const char * outpath, int truncate)
+{
+  static long p_count = 0;
+  sh_filestore_t p;
+  char *  fullpath = NULL;
+  char *  linkpath = NULL;
+  char *  attr_string = NULL;
+
+  SL_ENTER(_("sh_dbIO_data_write_int"));
+
+  do_writeout_checks(outpath);
+
+  if (sh.flag.update == S_FALSE)
+    {
+      if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
+	{
+	  if (truncate == S_TRUE)
+	    pushdata_fd = open_writeout_data_truncate(outpath);
+	  else
+	    {
+	      pushdata_fd = open_writeout_data(outpath);
+	      seek_writeout_data(pushdata_fd, outpath);
+	    }
+	}
+    }
+  else /* update == TRUE */
+    {
+      if (pushdata_isfirst == 1)
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")));
+	  pushdata_fd = open_writeout_data(outpath);
+	  seek_writeout_data_old(pushdata_fd, outpath);
+ 	}
+    }
+	 
+  if (!buf) {
+    memset(&p, '\0', sizeof(sh_filestore_t));
+  }
+
+  if (buf != NULL) 
+    {
+      fullpath = prep_path(buf->fullpath, S_TRUE);
+    }
+
+  /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded 
+   */
+  if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL) 
+    {  
+      if (buf->c_mode[0] == 'l')
+	linkpath = prep_path(buf->link_path, S_TRUE);
+      else
+	linkpath = prep_path(buf->link_path, S_FALSE);
+    }
+
+  if (buf != NULL && buf->attr_string != NULL) 
+    {
+      attr_string = prep_attr(buf->attr_string);
+    }
+
+  if (buf != NULL) 
+    {
+      prep_struct(&p, buf, fileHash);
+      if (attr_string)
+	p.mark |= REC_FLAGS_ATTR;
+      swap_data(&p);
+    }
+
+  /* write the start marker 
+   */
+  if (pushdata_isfirst == 1) 
+    {
+      if (sh.flag.update == S_FALSE)
+	write_start_marker(pushdata_fd);
+      pushdata_isfirst = 0;
+    }
+
+  if (buf && fullpath)
+    {
+      write_record(pushdata_fd, &p, fullpath, linkpath, attr_string);
+      ++p_count;
+    }
+
+  if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
+    {
+      if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
+	{
+	  sl_close (pushdata_fd);
+	  pushdata_fd = -1;
+	}
+    }
+
+  SL_RET0(_("sh_dbIO_data_write_int"));
+}
+
+SH_MUTEX_STATIC(mutex_writeout,PTHREAD_MUTEX_INITIALIZER);
+
+void sh_dbIO_data_write (file_type * buf, char * fileHash)
+{
+  SH_MUTEX_LOCK(mutex_writeout); 
+  sh_dbIO_data_write_int (buf, fileHash, file_path('D', 'W'), S_FALSE);
+  SH_MUTEX_UNLOCK(mutex_writeout); 
+  return;
+}
+
+
+static int dbIO_writeout(sh_file_t * mtab[TABSIZE], const char * outpath, int truncate)
+{
+  sh_file_t * p;
+  int         i;
+  file_type * f;
+  char   fileHash[KEY_LEN + 1];
+
+  SL_ENTER(_("dbIO_writeout"));
+
+  SH_MUTEX_LOCK(mutex_writeout); 
+  if (!SL_ISERROR(pushdata_fd))
+    {
+      sl_close(pushdata_fd);
+      pushdata_fd = -1;
+    }
+  pushdata_isfirst =  1;
+
+
+  SH_MUTEX_LOCK(mutex_hash);
+  for (i = 0; i < TABSIZE; ++i)
+    {
+      for (p = mtab[i]; p; p = p->next)
+	{
+	  f = sh_hash_create_ft (p, fileHash);
+	  sh_dbIO_data_write_int (f, fileHash, outpath, (i == 0) ? truncate : S_FALSE);
+	  if (f->attr_string) SH_FREE(f->attr_string);
+	  if (f->link_path)   SH_FREE(f->link_path);
+	  SH_FREE(f);
+	}
+    }
+  SH_MUTEX_UNLOCK(mutex_hash);
+
+  if (!SL_ISERROR(pushdata_fd))
+    {
+      sl_close(pushdata_fd);
+      pushdata_fd = -1;
+    }
+  pushdata_isfirst =  1;
+  SH_MUTEX_UNLOCK(mutex_writeout); 
+
+  SL_RETURN (0, _("dbIO_writeout"));
+}
+
+int sh_dbIO_writeout_update()
+{
+  sh_file_t ** mtab = get_default_data_table();
+
+  if (S_TRUE == file_is_remote())
+    {
+      sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN, 
+		      _("Baseline database is remote"), _("sh_dbIO_writeout"));
+      SL_RETURN (1, _("sh_dbIO_writeout_update"));
+    }
+
+  return dbIO_writeout(mtab, file_path('D', 'W'), S_FALSE);
+}
+
+int sh_dbIO_writeout_to_path(const char * path)
+{
+  sh_file_t ** mtab = get_default_data_table();
+  return dbIO_writeout(mtab, path, S_TRUE);
+}
+
+static void dbIO_write_record(sh_file_t * record, SL_TICKET fd)
+{
+  sh_filestore_t * p = &(record->theFile);
+  char * fullpath    = NULL;
+  char * linkpath    = NULL;
+  char * attr_string = NULL;
+
+  fullpath = prep_path(record->fullpath, S_TRUE);
+
+  /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded 
+   */
+  if (record->linkpath != NULL && 0 != strcmp("-", record->linkpath)) 
+    {  
+      if (p->c_mode[0] == 'l')
+	linkpath = prep_path(record->linkpath, S_TRUE);
+      else
+	linkpath = prep_path(record->linkpath, S_FALSE);
+    }
+
+  if (record->attr_string != NULL) 
+    attr_string = prep_attr(record->attr_string);
+
+  prep_encode(p);
+  swap_data(p);
+
+  write_record(fd, p, fullpath, linkpath, attr_string);
+  return;
+}
+
+static void dbIO_write_entry(sh_file_t * p)
+{
+  static int is_first = 1;
+
+  if (is_first)
+    {
+      pushdata_isfirst =  1;
+      if (!sh.outpath || sh.outpath[0] == '\0') 
+	pushdata_stdout  =  S_TRUE;
+      else
+	pushdata_fd = open_writeout_data_truncate(sh.outpath);
+      write_start_marker(pushdata_fd);
+      pushdata_isfirst = 0;
+      is_first = 0;
+    }
+
+  dbIO_write_record(p, pushdata_fd);
+
+}
+
+
+/******************************************************************
+ *
+ * Listing the database.
+ *
+ ******************************************************************/ 
+
+static int ListBinary = S_FALSE;
+static char * ListFilter = NULL;
+
+int sh_dbIO_list_binary (const char * c)
+{
+  (void) c;
+  ListBinary = S_TRUE;
+  return 0;
+}
+int sh_dbIO_list_filter (const char * c)
+{
+  ListFilter = sh_util_strdup(c);
+  return 0;
+}
+
+#include "zAVLTree.h"
+
+static zAVLTree * filter_list = NULL;
+extern char * rtrim (char * str);
+
+#include <ctype.h>
+static void read_filter()
+{
+  int    i, n = 0;
+  size_t len;
+  char * key;
+  char * str;
+  char * line = SH_ALLOC(SH_MAXBUF);
+  FILE * fd   = fopen(ListFilter, "r");
+  
+  if (!fd)
+    {
+      perror(_("read_filter: fopen:"));
+      _exit(EXIT_FAILURE);
+    }
+  do {
+    i = sh_dbIO_getline (fd, line, SH_MAXBUF);
+    str = rtrim(line);
+    while (isspace((int)*str)) ++str;
+
+    key = sh_files_parse_input(str, &len);
+
+    if (key && *key == '/')
+      {
+	zAVL_string_set(&filter_list, key);
+	++n;
+      }
+  } while (i >= 0);
+
+  fclose(fd);
+  SH_FREE(line);
+
+  if (n == 0)
+    {
+      fprintf(stderr, _("read_filter: empty file <%s>\n"), ListFilter);
+      _exit (EXIT_FAILURE);
+    }
+  return;
+}
+
+static int check_filter(char * path)
+{
+  if (NULL == zAVL_string_get(filter_list, path))
+    return S_FALSE;
+  return S_TRUE;
+}
+
+int sh_dbIO_list_db (const char * db_file)
+{
+  sh_file_t * p;
+  SL_TICKET fd;
+  char * line;
+  int  errflag = 0;
+  int  flag = 0;
+  char * ListFile = get_list_file();
+
+  if (!db_file)
+    {
+      fputs(_("ERROR: no database file given\n"), stderr);
+      _exit(EXIT_FAILURE);
+      return -1; 
+    }
+  if (sl_is_suid())
+    {
+      fputs(_("ERROR: insufficient privilege\n"), stderr);
+      _exit (EXIT_FAILURE);
+      return -1; /* for Mac OSX compiler */
+    }
+  if (0 == strcmp(db_file, _("default")))
+    db_file = file_path('D', 'W');
+  if (!db_file)
+    {
+      fputs(_("ERROR: no filename\n"), stderr);
+      _exit(EXIT_FAILURE);
+      return -1; 
+    }
+
+  if (ListFilter) 
+    read_filter();
+
+  line = SH_ALLOC(MAX_PATH_STORE+2);
+
+  if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV))) 
+    {
+      fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"), 
+	      db_file, fd);
+      _exit(EXIT_FAILURE);
+      return -1; 
+    }
+
+  /* fast forward to start of data
+   */
+  if (0 != sh_dbIO_setdataent(fd, line, MAX_PATH_STORE+1, db_file))
+    {
+      fprintf(stderr, _("ERROR: can't find start marker in %s\n"), 
+	      db_file);
+      _exit(EXIT_FAILURE);
+      return -1; 
+    }
+
+  while (1) 
+    {
+      p = sh_dbIO_getdataent (line, MAX_PATH_STORE+1, db_file, &errflag);
+      if ((p != NULL) && (p->fullpath[0] == '/'))
+	{
+	  if (!ListFile)
+	    {
+	      flag = 1;
+	      if (ListFilter && S_FALSE == check_filter(p->fullpath))
+		continue;
+	      if (ListBinary)
+		dbIO_write_entry (p);
+	      else
+		sh_hash_list_db_entry (p); 
+	    }
+	  else
+	    {
+	      if (0 != sl_strcmp(ListFile, p->fullpath))
+		{
+		  continue;
+		}
+	      flag = 1;
+	      if ('l' != p->theFile.c_mode[0])
+		{
+		  if (sh_hash_printcontent(p->linkpath) < 0)
+		    {
+		      fputs(_("Error listing file content\n"), stderr);
+		      _exit(EXIT_FAILURE);
+		      return -1;
+		    }
+		}
+	      else
+		{
+		  fputs(_("File is a link\n"), stderr);
+		  _exit(EXIT_FAILURE);
+		  return -1;
+		}
+	      break;
+	    }
+	}
+      else if (p == NULL)
+	{
+	  break;
+	}
+    }
+
+  if (line != NULL)
+    SH_FREE(line);
+  sl_close (fd);
+
+  fflush(NULL);
+
+  if (flag == 0)
+    {
+      fputs(_("File not found.\n"), stderr);
+      _exit(EXIT_FAILURE);
+    }
+  else if (errflag < 0)
+    {
+      fputs(_("Error while reading file.\n"), stderr);
+      _exit(EXIT_FAILURE);
+    }
+      
+  _exit(EXIT_SUCCESS);
+  return 0; 
+}
+
+/* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
+#endif
Index: trunk/src/sh_entropy.c
===================================================================
--- trunk/src/sh_entropy.c	(revision 476)
+++ trunk/src/sh_entropy.c	(revision 481)
@@ -300,5 +300,5 @@
 	{
 	  m_count = sl_read_timeout_fd(fd2, nbuf, nbytes, 
-				       timeout_val, SL_FALSE);
+				       timeout_val, S_FALSE);
 	  if (m_count < 0)
 	    m_count = 0;
@@ -337,7 +337,7 @@
 
 #ifdef NAME_OF_DEV_URANDOM
-  m_count = read_mbytes (  1, NAME_OF_DEV_RANDOM, nbuf, nbytes);
+  m_count = read_mbytes ( 10, NAME_OF_DEV_URANDOM, nbuf, nbytes);
 #else
-  m_count = read_mbytes (300, NAME_OF_DEV_RANDOM, nbuf, nbytes);
+  m_count = read_mbytes (300, NAME_OF_DEV_RANDOM,  nbuf, nbytes);
 #endif
 
@@ -346,5 +346,5 @@
 #ifdef NAME_OF_DEV_URANDOM
       sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, EIO, MSG_NODEV, 
-		       (long) sh.real.uid, NAME_OF_DEV_RANDOM);
+		       (long) sh.real.uid, NAME_OF_DEV_URANDOM);
 #else
       sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_NODEV, 
@@ -353,11 +353,11 @@
     }
 
-#ifdef NAME_OF_DEV_URANDOM
+#ifdef NAME_OF_DEV_RANDOM
   if (m_count < nbytes)
     {
-      i = read_mbytes(30, NAME_OF_DEV_URANDOM, &nbuf[m_count], nbytes-m_count);
+      i = read_mbytes(300, NAME_OF_DEV_RANDOM, &nbuf[m_count], nbytes-m_count);
       if (i == 0)
 	sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_NODEV, 
-			 (long) sh.real.uid, NAME_OF_DEV_URANDOM);
+			 (long) sh.real.uid, NAME_OF_DEV_RANDOM);
       else
 	m_count += i;
@@ -601,5 +601,5 @@
       /* don't leak file descriptors
        */
-      sh_unix_closeall (3, -1, SL_TRUE); /* in child process */
+      sh_unix_closeall (3, -1, S_TRUE); /* in child process */
 
       /* zero priv info
@@ -942,4 +942,28 @@
     }
 
+#ifdef HAVE_GETTIMEOFDAY
+  {
+    unsigned short tseed[3];
+
+    gettimeofday(&tv, 0);
+    tseed[0] = tv.tv_sec & 0xFFFF;
+    tseed[1] = tv.tv_usec & 0xFFFF;
+    tseed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
+    keybuf = (char *) sh_tiger_hash_uint32 ((char *) tseed, 
+					    TIGER_DATA, sizeof(tseed),
+					    kbuf, KEY_BYT/sizeof(UINT32));
+    memset(addbuf, '\0', sizeof(addbuf));
+    for (i = 0; i < KEY_BYT; ++i)
+      {
+	addbuf[i]         = keybuf[i];
+	addbuf[i+KEY_BYT] = skey->poolv[i];
+      }
+    SH_MUTEX_LOCK_UNSAFE(mutex_skey);
+    for (i = 0; i < KEY_BYT; ++i)
+      skey->poolv[i] ^= keybuf[i];
+    SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
+  }
+#endif
+
   if (bufcount > 0) 
     {
@@ -1002,16 +1026,22 @@
   char                 bufy[9 * sizeof(UINT32) + 1];
   int                  status;
-
-  memset(skey->poolv, '\0', KEY_BYT);
-
-  status = sh_entropy (24, bufx);
-  CuAssertTrue(tc, 0 == status);
-
-  memset(skey->poolv, '\0', KEY_BYT);
-
-  status = sh_entropy (24, bufy);
-  CuAssertTrue(tc, 0 == status);
-
-  CuAssertTrue(tc, 0 != memcmp(bufx, bufy, 24));
+  int                  count;
+
+  for (count = 0; count < 20; ++count)
+    {
+      memset(skey->poolv, '\0', KEY_BYT);
+      skey->poolc = 0;
+
+      status = sh_entropy (24, bufx);
+      CuAssertTrue(tc, 0 == status);
+      
+      memset(skey->poolv, '\0', KEY_BYT);
+      skey->poolc = 0;
+
+      status = sh_entropy (24, bufy);
+      CuAssertTrue(tc, 0 == status);
+      
+      CuAssertTrue(tc, 0 != memcmp(bufx, bufy, 24));
+    }
 }
 #endif
Index: trunk/src/sh_err_console.c
===================================================================
--- trunk/src/sh_err_console.c	(revision 476)
+++ trunk/src/sh_err_console.c	(revision 481)
@@ -25,4 +25,5 @@
 #include "sh_error.h"
 #include "sh_utils.h"
+#include "sh_sem.h"
 
 #undef  FIL__
@@ -36,5 +37,4 @@
 
 extern int  OnlyStderr;
-
  
 #if !defined(O_NONBLOCK)
@@ -53,4 +53,8 @@
 #include <sys/msg.h>
 
+#if !defined(EIDRM)
+#define EIDRM (EINVAL)
+#endif
+
 struct sh_msgbuf {
   long mtype;
@@ -66,25 +70,22 @@
 /* Open the SysV message queue, creating it when neccesary
  */
-static int open_ipc(void)
+static int open_queue(void)
 {
   key_t            key;
 #if defined(WITH_TPT) 
-  int              error = 0;
   char errbuf[SH_ERRBUF_SIZE];
 #endif
 
-  SL_ENTER(_("open_ipc"));
+  SL_ENTER(_("open_queue"));
 
   /* get key
    */
-  key = ftok ("/tmp", '#');
+  key = ftok (DEFAULT_DATAROOT, '#');
+
   if (key == (key_t) -1)
     {
-#if defined(WITH_TPT) 
-      error = errno;
-#endif
       TPT(( 0, FIL__, __LINE__, _("msg=<ftok: %s> errno=<%d>\n"), 
-	    sh_error_message(error, errbuf, sizeof(errbuf)), error));
-      SL_RETURN(-1, _("open_ipc"));
+	    sh_error_message(errno, errbuf, sizeof(errbuf)), errno));
+      SL_RETURN(-1, _("open_queue"));
     }
 
@@ -95,24 +96,20 @@
   if (msgid < 0)
     {
-#if defined(WITH_TPT) 
-      error = errno;
-#endif
       TPT(( 0, FIL__, __LINE__, _("msg=<msgget: %s> errno=<%d>\n"), 
-	    sh_error_message(error, errbuf, sizeof(errbuf)), error));
-      SL_RETURN(-1, _("open_ipc"));
-    }
-
-  SL_RETURN(0, _("open_ipc"));
-}
-
-/* Close the SysV message queue
+	    sh_error_message(errno, errbuf, sizeof(errbuf)), errno));
+      SL_RETURN(-1, _("open_queue"));
+    }
+
+  SL_RETURN(0, _("open_queue"));
+}
+
+/* Close the SysV message queue and/or semaphore
  */
 void close_ipc (void)
 {
-  SL_ENTER(_("close_ipc"));
-
   if (msgid != (-1))
     (void) msgctl (msgid, IPC_RMID, NULL);
-  SL_RET0(_("close_ipc"));
+  sh_sem_close();
+  return;
 }
 
@@ -128,6 +125,23 @@
 }
 
-/* #define MY_MAX_MSG    254 */
 #define MY_MAX_MSG    1022
+
+static void remove_message()
+{
+  int rc;
+  struct {
+    long    mtype;       /* Message type. */
+    char    mtext[128];  /* Message text. */
+  } recv_msg;
+
+  recv_msg.mtype = 1;
+  do {
+    rc = msgrcv(msgid, &recv_msg, sizeof(recv_msg.mtext), 1, 
+		MSG_NOERROR|IPC_NOWAIT);
+  } while (rc < 0 && errno == EINTR);
+
+  memset(&recv_msg, '\0', sizeof(recv_msg));
+  return;
+}
 
 static int push_message_queue (const char * msg)
@@ -138,5 +152,4 @@
   int              count    = 0;
 #if defined(WITH_TPT) 
-  int              error = 0;
   char errbuf[SH_ERRBUF_SIZE];
 #endif
@@ -153,10 +166,10 @@
     {
       TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n"))); 
-      status = open_ipc();
+      status = open_queue();
     }
 
   if (status < 0)
     {
-      TPT(( 0, FIL__, __LINE__, _("msg=<open_ipc() failed>\n"))); 
+      TPT(( 0, FIL__, __LINE__, _("msg=<open_queue() failed>\n"))); 
       SL_RETURN(-1, _("push_message_queue"));
     }
@@ -165,6 +178,6 @@
    *   long mtype;
    *   char mtext[1];  <-- sizeof(mtext) will be  1+MY_MAX_MSG
-   * }
-   */
+   * } */
+
   recv_msg = (struct sh_msgbuf*) SH_ALLOC(sizeof(struct sh_msgbuf)+MY_MAX_MSG);
   recv_msg->mtype = 1;
@@ -177,47 +190,37 @@
   if (count > 1)
     {
+      memset(recv_msg, '\0', MY_MAX_MSG+1);
       SH_FREE(recv_msg);
       SL_RETURN(-1, _("push_message_queue"));
     }
 
-  /* send the message
-   */ 
-  do {
-    errno = 0;
+  do { errno = 0;
     rc = msgsnd(msgid, recv_msg, strlen(recv_msg->mtext)+1, IPC_NOWAIT);
-  }
-  while (rc < 0 && errno == EINTR);
+
+    if (rc == -1 && errno == EAGAIN)
+      remove_message();
+  } while (rc < 0 && (errno == EINTR && errno == EAGAIN));
   
   if (rc == -1 && errno != EAGAIN) 
     {
-      /* EIDRM is not in OpenBSD
-       */
-      if (errno == EINVAL
-#if defined(EIDRM)
-	  || errno == EIDRM
-#endif
-	  )
-	{
-	  TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n"))); 
-	  status = open_ipc();
-	  if (status == 0)
-	    {
-	      ++count;
-	      goto send_it;
-	    }
-	}
-      else
-	{
-#if defined(WITH_TPT) 
-	  error = errno;
-#endif
-	  TPT(( 0, FIL__, __LINE__, _("msg=<msgsnd: %s> errno=<%d>\n"), 
-		sh_error_message(error, errbuf, sizeof(errbuf)), error));
-	  SH_FREE(recv_msg);
-	  SL_RETURN(-1, _("push_message_queue"));
-	}
-    }
-
+      /* EIDRM is not in OpenBSD */
+      if (errno == EINVAL || errno == EIDRM) {
+	TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n"))); 
+	status = open_queue();
+	if (status == 0) {
+	  ++count;
+	  goto send_it; }
+      } else {
+	TPT(( 0, FIL__, __LINE__, _("msg=<msgsnd: %s> errno=<%d>\n"), 
+	      sh_error_message(errno, errbuf, sizeof(errbuf)), errno));
+	memset(recv_msg, '\0', MY_MAX_MSG+1);
+	SH_FREE(recv_msg);
+	SL_RETURN(-1, _("push_message_queue"));
+      }
+    }
+
+  memset(recv_msg, '\0', MY_MAX_MSG+1);
   SH_FREE(recv_msg);
+
   SL_RETURN(0, _("push_message_queue"));
 }
@@ -234,4 +237,8 @@
 #endif
 
+#else /* no message queue */
+
+void close_ipc() { sh_sem_close(); return; }
+
 #endif
 
@@ -283,5 +290,4 @@
   static int service_failure[2] = { 0, 0};
   int    fd[2] = { -1, -1};
-  int    sflags;
   int    cc;
   size_t len;
@@ -331,25 +337,9 @@
     {
       fd[0] = open ( sh.srvcons.name, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
-      if (fd[0] >= 0) {
-	sflags = (int) retry_fcntl(FIL__, __LINE__, fd[0], F_GETFL, 0);
-	if (sflags >= 0)
-	  {
-	    (void) retry_fcntl(FIL__, __LINE__, fd[0], 
-			       F_SETFL, sflags & ~O_NONBLOCK);
-	  }
-      }
 
       if (sh.srvcons.alt[0] != '\0')
 	{
 	  fd[1] = open (sh.srvcons.alt, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
-	  if (fd[1] >= 0) {
-	    sflags = (int) retry_fcntl(FIL__, __LINE__, fd[1], F_GETFL, 0);
-	    if (sflags >= 0)
-	      {
-		(void) retry_fcntl(FIL__, __LINE__, fd[1], 
-				   F_SETFL, sflags & ~O_NONBLOCK);
-	      }
-	    ccMax = 2;
-	  }
+	  ccMax = 2;
 	}
 
Index: trunk/src/sh_err_log.c
===================================================================
--- trunk/src/sh_err_log.c	(revision 476)
+++ trunk/src/sh_err_log.c	(revision 481)
@@ -770,10 +770,10 @@
 
 #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
-  if (skey->mlock_failed == SL_FALSE) 
+  if (skey->mlock_failed == S_FALSE) 
     {
       if ( (-1) == sh_unix_mlock( FIL__, __LINE__, log_msg.msg, 
 				  (size_t)(2*KEY_LEN + status + 32) ) ) 
 	{
-	  skey->mlock_failed = SL_TRUE;
+	  skey->mlock_failed = S_TRUE;
 #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
 	  sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK); 
@@ -782,7 +782,7 @@
     }
 #else
-  if (skey->mlock_failed == SL_FALSE) 
-    {
-      skey->mlock_failed = SL_TRUE;
+  if (skey->mlock_failed == S_FALSE) 
+    {
+      skey->mlock_failed = S_TRUE;
 #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
       sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
@@ -1207,15 +1207,15 @@
   int i;
 
-  if (SL_TRUE == sl_ok_adds (gSave[0], sh.statistics.bytes_hashed))
+  if (S_TRUE == sl_ok_adds (gSave[0], sh.statistics.bytes_hashed))
     gSave[0] += sh.statistics.bytes_hashed;
-  if (SL_TRUE == sl_ok_adds (gSave[1], sh.statistics.dirs_checked))
+  if (S_TRUE == sl_ok_adds (gSave[1], sh.statistics.dirs_checked))
     gSave[1] += sh.statistics.dirs_checked;
-  if (SL_TRUE == sl_ok_adds (gSave[2], sh.statistics.files_checked))
+  if (S_TRUE == sl_ok_adds (gSave[2], sh.statistics.files_checked))
     gSave[2] += sh.statistics.files_checked;
-  if (SL_TRUE == sl_ok_adds (gSave[3], sh.statistics.files_report))
+  if (S_TRUE == sl_ok_adds (gSave[3], sh.statistics.files_report))
     gSave[3] += sh.statistics.files_report;
-  if (SL_TRUE == sl_ok_adds (gSave[4], sh.statistics.files_error))
+  if (S_TRUE == sl_ok_adds (gSave[4], sh.statistics.files_error))
     gSave[4] += sh.statistics.files_error;
-  if (SL_TRUE == sl_ok_adds (gSave[5], sh.statistics.files_nodir))
+  if (S_TRUE == sl_ok_adds (gSave[5], sh.statistics.files_nodir))
     gSave[5] += sh.statistics.files_nodir;
 
Index: trunk/src/sh_error.c
===================================================================
--- trunk/src/sh_error.c	(revision 476)
+++ trunk/src/sh_error.c	(revision 481)
@@ -60,5 +60,5 @@
 #include "sh_tiger.h"
 #include "sh_nmail.h"
-#include "sh_forward.h"
+#include "sh_xfer.h"
 #include "sh_prelude.h"
 #include "sh_pthread.h"
@@ -77,6 +77,6 @@
 extern int clt_class;
 
-int flag_err_debug = SL_FALSE;
-int flag_err_info  = SL_FALSE;
+int flag_err_debug = S_FALSE;
+int flag_err_info  = S_FALSE;
 
 int  ShDFLevel[SH_ERR_T_END];
@@ -100,7 +100,7 @@
 static int  sh_error_init (void);
 
-/*@owned@*//*@null@*/inline
-static char * get_format(unsigned long msg_id, /*@out@*/int * priority, 
-			 /*@out@*/unsigned int * class);
+inline
+static const char * get_format(unsigned long msg_id, int * priority, 
+			       unsigned int * class);
 
 static int sh_error_string (struct _log_t * lmsg, va_list vl);
@@ -177,21 +177,21 @@
 {
   if ((errFlags.loglevel & SH_ERR_ALL) != 0)
-    flag_err_debug = SL_TRUE;
+    flag_err_debug = S_TRUE;
   else if ((errFlags.printlevel & SH_ERR_ALL) != 0)
-    flag_err_debug = SL_TRUE;
+    flag_err_debug = S_TRUE;
   else if ((errFlags.maillevel & SH_ERR_ALL) != 0)
-    flag_err_debug = SL_TRUE;
+    flag_err_debug = S_TRUE;
   else if ((errFlags.exportlevel & SH_ERR_ALL) != 0)
-    flag_err_debug = SL_TRUE;
+    flag_err_debug = S_TRUE;
   else if ((errFlags.sysloglevel & SH_ERR_ALL) != 0)
-    flag_err_debug = SL_TRUE;
+    flag_err_debug = S_TRUE;
   else if ((errFlags.externallevel & SH_ERR_ALL) != 0)
-    flag_err_debug = SL_TRUE;
+    flag_err_debug = S_TRUE;
   else if ((errFlags.databaselevel & SH_ERR_ALL) != 0)
-    flag_err_debug = SL_TRUE;
+    flag_err_debug = S_TRUE;
   else if ((errFlags.preludelevel & SH_ERR_ALL) != 0)
-    flag_err_debug = SL_TRUE;
+    flag_err_debug = S_TRUE;
   else
-    flag_err_debug = SL_FALSE;
+    flag_err_debug = S_FALSE;
   return;
 }
@@ -201,21 +201,21 @@
 {
   if ((errFlags.loglevel & SH_ERR_INFO) != 0)
-    flag_err_info = SL_TRUE;
+    flag_err_info = S_TRUE;
   else if ((errFlags.printlevel & SH_ERR_INFO) != 0)
-    flag_err_info = SL_TRUE;
+    flag_err_info = S_TRUE;
   else if ((errFlags.maillevel & SH_ERR_INFO) != 0)
-    flag_err_info = SL_TRUE;
+    flag_err_info = S_TRUE;
   else if ((errFlags.exportlevel & SH_ERR_INFO) != 0)
-    flag_err_info = SL_TRUE;
+    flag_err_info = S_TRUE;
   else if ((errFlags.sysloglevel & SH_ERR_INFO) != 0)
-    flag_err_info = SL_TRUE;
+    flag_err_info = S_TRUE;
   else if ((errFlags.externallevel & SH_ERR_INFO) != 0)
-    flag_err_info = SL_TRUE;
+    flag_err_info = S_TRUE;
   else if ((errFlags.databaselevel & SH_ERR_INFO) != 0)
-    flag_err_info = SL_TRUE;
+    flag_err_info = S_TRUE;
   else if ((errFlags.preludelevel & SH_ERR_INFO) != 0)
-    flag_err_info = SL_TRUE;
+    flag_err_info = S_TRUE;
   else
-    flag_err_info = SL_FALSE;
+    flag_err_info = S_FALSE;
   return;
 }
@@ -230,5 +230,5 @@
 			     SH_ERR_SEVERE | SH_ERR_FATAL);
       dbg_flag  = 1;
-      flag_err_debug = SL_TRUE;
+      flag_err_debug = S_TRUE;
     }
   else {
@@ -935,5 +935,5 @@
   int    severity;
   unsigned int class;
-  char * fmt;
+  const char * fmt;
   volatile int sev = sev1;            /* Avoids the 'clobbered by longjmp' warning. */
 
@@ -1286,5 +1286,5 @@
 	      sl_snprintf(ex_msg, ex_len, _("%d?%u?%s"),
 		      severity, class, lmsg->msg);
-              retval = sh_forward (ex_msg);
+              retval = sh_xfer_report (ex_msg);
 	      SH_FREE(ex_msg);
               export_block = 0;
@@ -1438,5 +1438,5 @@
   int    severity;
   unsigned int class;
-  char * fmt;
+  const char * fmt;
   int retval; 
 
@@ -1517,5 +1517,5 @@
  */
 /*@owned@*/ /*@null@*/inline
-static char * get_format(unsigned long msg_id, /*@out@*/ int * priority, 
+static const char * get_format(unsigned long msg_id, /*@out@*/ int * priority, 
 			 /*@out@*/unsigned int * class)
 {
@@ -1532,5 +1532,5 @@
 	  *priority = (int) msg_cat[i].priority;
 	  *class    = (unsigned int) msg_cat[i].class;
-	  SL_RETURN (((char *) _(msg_cat[i].format)), _("get_format"));
+	  SL_RETURN (((const char *) _(msg_cat[i].format)), _("get_format"));
 	}
       ++i;
@@ -1573,4 +1573,14 @@
   SL_RETURN( 0, _("sh_error_ehead"));
 }
+
+#if !defined(VA_COPY)
+#if defined(__GNUC__) && defined(__PPC__) && (defined(_CALL_SYSV) || defined(_WIN32))
+#define VA_COPY(ap1, ap2)     (*(ap1) = *(ap2))
+#elif defined(VA_COPY_AS_ARRAY)
+#define VA_COPY(ap1, ap2)     memmove ((ap1), (ap2), sizeof (va_list))
+#else /* va_list is a pointer */
+#define VA_COPY(ap1, ap2)     ((ap1) = (ap2))
+#endif
+#endif 
 
 
@@ -1707,6 +1717,6 @@
   else 
     {
-      /* use va_copy */
-      /*@i@*/va_copy(vl2, vl);
+      /* use VA_COPY */
+      /*@i@*/VA_COPY(vl2, vl);
       len      = sl_strlen(lmsg->msg);
       /*@i@*/required = sl_vsnprintf(&(lmsg->msg[len]), 
@@ -1769,5 +1779,5 @@
 			     SH_ERR_STAMP | SH_ERR_ERR    | SH_ERR_SEVERE |
 			     SH_ERR_FATAL);
-  flag_err_info           = SL_TRUE;
+  flag_err_info           = S_TRUE;
 #endif
 
Index: trunk/src/sh_extern.c
===================================================================
--- trunk/src/sh_extern.c	(revision 476)
+++ trunk/src/sh_extern.c	(revision 481)
@@ -305,5 +305,5 @@
 	   */
 #if !defined(PDGBFILE)
-	  sh_unix_closeall (3, task->com_fd, SL_TRUE); /* in child process */
+	  sh_unix_closeall (3, task->com_fd, S_TRUE); /* in child process */
 #endif
 
@@ -423,6 +423,6 @@
 		char str1[128];
 		int ival = pfd;
-		int n = 0;
-		int m = 0;
+		unsigned int n = 0;
+		unsigned int m = 0;
 
 		if (ival < 0) ival = -ival;
@@ -633,5 +633,5 @@
 	    {
 	      task->exit_status = WEXITSTATUS(task->exit_status);
-	      if ((flag_err_debug == SL_TRUE) || (task->exit_status != 0))
+	      if ((flag_err_debug == S_TRUE) || (task->exit_status != 0))
 		sl_snprintf(infomsg, sizeof(infomsg),
 			    _("Subprocess exited normally with status %d"),
@@ -687,5 +687,5 @@
       /*@+bufferoverflowhigh@*/
       status = task->exit_status;
-      if (flag_err_debug == SL_TRUE)
+      if (flag_err_debug == S_TRUE)
 	{
 	  sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, task->exit_status, 
@@ -867,5 +867,5 @@
 }
 
-int sh_ext_popen_init (sh_tas_t * task, char * command, char * argv0, ...)
+int sh_ext_popen_init (sh_tas_t * task, const char * command, char * argv0, ...)
 {
   va_list vl;
@@ -956,5 +956,5 @@
  * ifconfig | grep -1 lo | tail -n 1 | sed s/.*inet addr:\([0-9.]*\)\(.*\)/\1/
  */
-char * sh_ext_popen_str (char * command)
+char * sh_ext_popen_str (const char * command)
 {
   sh_tas_t task;
Index: trunk/src/sh_fInotify.c
===================================================================
--- trunk/src/sh_fInotify.c	(revision 476)
+++ trunk/src/sh_fInotify.c	(revision 481)
@@ -35,4 +35,5 @@
 #include "sh_unix.h"
 #include "sh_hash.h"
+#include "sh_dbIO.h"
 #include "sh_files.h"
 #include "sh_ignore.h"
@@ -111,5 +112,5 @@
 static int sh_fInotify_process(struct inotify_event * event);
 static int sh_fInotify_report(struct inotify_event * event, char * filename,
-			      int class, unsigned long check_mask, int ftype, int rdepth);
+			      int class, unsigned long check_flags, int ftype, int rdepth);
 
 int sh_fInotify_init(struct mod_type * arg)
@@ -236,5 +237,5 @@
       count2 = 0; /* Update baseline database. */
       if (sh.flag.checkSum == SH_CHECK_CHECK && sh.flag.update == S_TRUE)
-	sh_hash_writeout ();
+	sh_dbIO_writeout_update ();
     }
 
@@ -329,5 +330,5 @@
   int    type;
   int    rdepth;
-  unsigned long check_mask;
+  unsigned long check_flags;
   int    retval;
   int    errnum;
@@ -349,9 +350,9 @@
 
   while (NULL != (filename = sh_inotify_pop_dormant(&sh_file_watches, 
-						    &class, &check_mask, 
+						    &class, &check_flags, 
 						    &type, &rdepth)))
     {
       retval = sh_inotify_add_watch(filename, &sh_file_watches, &errnum,
-				    class, check_mask, type, rdepth);
+				    class, check_flags, type, rdepth);
 
       if (retval < 0)
@@ -424,6 +425,4 @@
   if (event->mask & IN_UNMOUNT) sl_strlcat(dbgbuf, "IN_UNMOUNT ", sizeof(dbgbuf));
   
-  /* fprintf(stderr, "FIXME: %s\n", dbgbuf); */
-  
   SH_MUTEX_LOCK(mutex_thread_nolog);
   sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
@@ -437,9 +436,9 @@
   int ftype;
   int rdepth;
-  unsigned long check_mask;
+  unsigned long check_flags;
   char * filename;
   extern int flag_err_debug;
 
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       sh_fInotify_logmask(event);
@@ -449,9 +448,9 @@
     {
       filename = sh_inotify_search_item(&sh_file_watches, event->wd, 
-					&class, &check_mask, &ftype, &rdepth);
+					&class, &check_flags, &ftype, &rdepth);
 
       if (filename)
 	{
-	  sh_fInotify_report(event, filename, class, check_mask, ftype, rdepth);
+	  sh_fInotify_report(event, filename, class, check_flags, ftype, rdepth);
 	  SH_FREE(filename);
 	}
@@ -488,5 +487,5 @@
 }
 
-void sh_fInotify_report_add(char * path, int class, unsigned long check_mask)
+void sh_fInotify_report_add(char * path, int class, unsigned long check_flags)
 {
   if (S_FALSE == sh_ignore_chk_new(path))
@@ -496,7 +495,7 @@
       sh_files_clear_file_reported(path);
       
-      sh_files_search_file(path, &class, &check_mask, &reported);
+      sh_files_search_file(path, &class, &check_flags, &reported);
       
-      sh_files_filecheck (class, check_mask, path, NULL,
+      sh_files_filecheck (class, check_flags, path, NULL,
 			  &reported, 0);
       if (SH_FFLAG_REPORTED_SET(reported))
@@ -521,5 +520,5 @@
 static int sh_fInotify_report_change (struct inotify_event * event, 
 				      char * path, char * filename,
-				      int class, unsigned long check_mask, int ftype)
+				      int class, unsigned long check_flags, int ftype)
 {
   int    reported;
@@ -529,5 +528,5 @@
   if (S_FALSE == sh_ignore_chk_mod(path))
     {
-      ret  = sh_files_search_file(path, &class, &check_mask, &reported);
+      ret  = sh_files_search_file(path, &class, &check_flags, &reported);
 
       if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
@@ -537,5 +536,5 @@
       else
 	{
-	  sh_files_filecheck (class, check_mask, filename,
+	  sh_files_filecheck (class, check_flags, filename,
 			      (event->len > 0) ? event->name : NULL,
 			      &reported, 0);
@@ -548,5 +547,5 @@
 static int sh_fInotify_report_missing (struct inotify_event * event, 
 				       char * path,
-				       int class, unsigned long check_mask, int ftype)
+				       int class, unsigned long check_flags, int ftype)
 {
   int    reported;
@@ -560,5 +559,5 @@
       if (0 != hashreport_missing(path, level))
 	{
-	  int ret = sh_files_search_file(path, &class, &check_mask, &reported);
+	  int ret = sh_files_search_file(path, &class, &check_flags, &reported);
 	  
 	  if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
@@ -578,9 +577,6 @@
     }
 
-#ifndef REPLACE_OLD
-  sh_hash_set_visited_true(path);
-#else
   sh_hash_set_missing(path);
-#endif
+
   if (sh.flag.reportonce == S_TRUE)
     sh_files_set_file_reported(path);
@@ -596,5 +592,5 @@
 static int sh_fInotify_report_added (struct inotify_event * event, 
 				     char * path, char * filename,
-				     int class, unsigned long check_mask, 
+				     int class, unsigned long check_flags, 
 				     int ftype, int rdepth)
 {
@@ -608,5 +604,5 @@
       sh_files_clear_file_reported(path);
 	  
-      ret = sh_files_search_file(path, &class, &check_mask, &reported);
+      ret = sh_files_search_file(path, &class, &check_flags, &reported);
       
       if ((ret == 0) && (event->len > 0) && (ftype == SH_INOTIFY_FILE))
@@ -618,9 +614,9 @@
 	  int classD = class;
 	  int reportedD = reported; 
-	  unsigned long check_maskD = check_mask;
+	  unsigned long check_flagsD = check_flags;
 	  
 	  if (event->mask & IN_ISDIR)
 	    {
-	      retD = sh_files_search_dir(path, &classD, &check_maskD, 
+	      retD = sh_files_search_dir(path, &classD, &check_flagsD, 
 					 &reportedD, &rdepthD);
 	      if (retD != 0)
@@ -629,10 +625,10 @@
 		    {
 		      class      = classD;
-		      check_mask = check_maskD;
+		      check_flags = check_flagsD;
 		    }
 		}
 	    }
 	  
-	  sh_files_filecheck (class, check_mask, filename,
+	  sh_files_filecheck (class, check_flags, filename,
 			      (event->len > 0) ? event->name : NULL,
 			      &reported, 0);
@@ -641,5 +637,5 @@
 	    {
 	      SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_INSCAN;   );
-	      sh_files_checkdir (classD, check_maskD, rdepthD, 
+	      sh_files_checkdir (classD, check_flagsD, rdepthD, 
 				 path, (event->len > 0) ? event->name : NULL);
 	      SH_INOTIFY_IFUSED( sh.flag.inotify &= ~SH_INOTIFY_INSCAN;  );
@@ -657,5 +653,5 @@
 	{
 	  sh_inotify_add_watch(path, &sh_file_watches, &ret,
-			       class, check_mask, 
+			       class, check_flags, 
 			       (event->mask & IN_ISDIR)?SH_INOTIFY_DIR:SH_INOTIFY_FILE, 
 			       rdepthD);
@@ -666,5 +662,5 @@
 
 static int sh_fInotify_report(struct inotify_event * event, char * filename,
-			      int class, unsigned long check_mask, int ftype, int rdepth)
+			      int class, unsigned long check_flags, int ftype, int rdepth)
 {
   char * fullpath = NULL;
@@ -684,15 +680,15 @@
     {
       sh_fInotify_report_change (event, path, filename,
-				 class, check_mask, ftype);
+				 class, check_flags, ftype);
     }
   else if ((event->mask & (IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF|IN_MOVED_FROM)) != 0)
     {
       sh_fInotify_report_missing (event, path,
-				  class, check_mask, ftype);
+				  class, check_flags, ftype);
    }
   else if((event->mask & (IN_CREATE|IN_MOVED_TO)) != 0)
     {
       sh_fInotify_report_added (event, path, filename,
-				class, check_mask, 
+				class, check_flags, 
 				ftype, rdepth);
     }
Index: trunk/src/sh_fifo.c
===================================================================
--- trunk/src/sh_fifo.c	(revision 476)
+++ trunk/src/sh_fifo.c	(revision 481)
@@ -180,8 +180,5 @@
 	      memset(getit->data, 0, len);
 	      if (NULL != sl_strstr (getit->data, _("LOGKEY")))
-		{
-		  MUNLOCK(getit->data, (len+1));
-		  ;
-		}
+		MUNLOCK(getit->data, (len+1));
 	      if (getit->s_xtra)
 		SH_FREE(getit->s_xtra);
@@ -197,5 +194,5 @@
 /* push an item on the head of the list
  */
-int push_list (SH_FIFO * fifo, char * indat, int in_i, const char * in_str)
+int push_list (SH_FIFO * fifo, const char * indat, int in_i, const char * in_str)
 {
   struct dlist * item;
@@ -224,8 +221,5 @@
   
   if (NULL != sl_strstr (indat, _("LOGKEY")))
-    {
-      MLOCK(item->data, (len+1));
-      ;
-    }
+    MLOCK(item->data, (len+1));
 
   sl_strlcpy (item->data, indat, len+1);
@@ -260,5 +254,5 @@
 /* push an item on the tail of the list
  */
-int push_tail_list (SH_FIFO * fifo, char * indat, int in_i, const char * in_str)
+int push_tail_list (SH_FIFO * fifo, const char * indat, int in_i, const char * in_str)
 {
   struct dlist * item;
@@ -287,8 +281,5 @@
 
   if (NULL != sl_strstr (indat, _("LOGKEY")))
-    {
-      MLOCK(item->data, (len+1));
-      ;
-    }
+    MLOCK(item->data, (len+1));
 
   sl_strlcpy (item->data, indat, len+1);
@@ -318,5 +309,5 @@
   ++(fifo->fifo_cts);
 
-  SL_RETURN((0), _("push_tail_list"));
+  SL_RETURN((fifo->fifo_cts), _("push_tail_list"));
 }
 
@@ -356,8 +347,5 @@
 
   if (NULL != sl_strstr (retval, _("LOGKEY")))
-    {
-      MUNLOCK(getit->data, (len+1));
-      ;
-    }
+    MUNLOCK(getit->data, (len+1));
 
   if (getit->s_xtra)
@@ -372,4 +360,82 @@
 
 
-
-
+#ifdef SH_CUTEST
+#include "CuTest.h"
+
+void Test_fifo (CuTest *tc) {
+
+  SH_FIFO ff;
+  int ret;
+  char * p;
+
+  fifo_init(&ff);
+
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrEquals(tc, NULL, p);
+
+  /* first sequence */
+  ret = sh_fifo_push(&ff, "one");
+  CuAssertIntEquals(tc,1,ret);
+  ret = sh_fifo_push(&ff, "two");
+  CuAssertIntEquals(tc,2,ret);
+  ret = sh_fifo_push(&ff, "three");
+  CuAssertIntEquals(tc,3,ret);
+
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"one", p);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"two", p);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"three", p);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrEquals(tc, NULL, p);
+
+  /* second sequence */
+  ret = sh_fifo_push(&ff, "one");
+  CuAssertIntEquals(tc,1,ret);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"one", p);
+  ret = sh_fifo_push_tail(&ff, "one");
+  CuAssertIntEquals(tc,1,ret);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"one", p);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrEquals(tc, NULL, p);
+
+  /* third sequence */
+  ret = sh_fifo_push(&ff, "one");
+  CuAssertIntEquals(tc,1,ret);
+  ret = sh_fifo_push(&ff, "two");
+  CuAssertIntEquals(tc,2,ret);
+  ret = sh_fifo_push(&ff, "three");
+  CuAssertIntEquals(tc,3,ret);
+
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"one", p);
+  ret = sh_fifo_push_tail(&ff, p);
+  CuAssertIntEquals(tc,3,ret);
+
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"one", p);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"two", p);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc,"three", p);
+  p = sh_fifo_pop(&ff);
+  CuAssertPtrEquals(tc, NULL, p);
+}
+
+#endif
+
+
+
+
Index: trunk/src/sh_files.c
===================================================================
--- trunk/src/sh_files.c	(revision 476)
+++ trunk/src/sh_files.c	(revision 481)
@@ -88,4 +88,5 @@
 #include "sh_inotify.h"
 #include "zAVLTree.h"
+#include "sh_dbIO.h"
 
 #undef  FIL__
@@ -211,4 +212,34 @@
 }
 
+char * sh_files_parse_input(const char * str_s, size_t * len)
+{
+  char  * p;
+
+  if (!str_s || *str_s == '\0')
+    return NULL;
+
+  *len = sl_strlen(str_s);
+
+  if ( (str_s[0] == '"'  && str_s[*len-1] == '"' ) ||
+       (str_s[0] == '\'' && str_s[*len-1] == '\'') )
+    {
+      if (*len < 3)
+	return NULL;
+      --(*len);
+      p = sh_util_strdup_l(&str_s[1], *len);
+      p[*len-1] = '\0';
+      --(*len);
+    }
+  else
+    {
+      p = sh_util_strdup_l(str_s, *len);
+    }
+
+  p = sh_files_C_dequote(p, len);
+
+  return p;
+}
+
+
 extern int flag_err_debug;
 extern int flag_err_info;
@@ -251,5 +282,5 @@
   char                  * name;
   int                     class;
-  unsigned long           check_mask;
+  unsigned long           check_flags;
   int                     rdepth;
   short                   checked;
@@ -322,5 +353,5 @@
     SL_RETURN((-1), _("sh_files_setrecursion"));
 
-  if (sh.flag.opts == 1)  
+  if (sh.flag.opts == S_TRUE)  
     reject = 1;
 
@@ -380,15 +411,8 @@
 			   tmp);
 	}
-#ifndef REPLACE_OLD
-      /* this will tell that we have seen the file, and thus prevent
-       * deletion from the database, resulting in an incomplete
-       * message when the file reappears
-       */
-      if (sh.flag.checkSum != SH_CHECK_INIT) 
-	sh_hash_set_visited_true(ptr->name);
-#else
+
       if (sh.flag.checkSum != SH_CHECK_INIT) 
 	sh_hash_set_missing(ptr->name);
-#endif
+
       if (sh.flag.reportonce == S_TRUE)
 	SET_SH_FFLAG_REPORTED(ptr->is_reported);
@@ -431,13 +455,9 @@
 		  }
 		}
-#ifndef REPLACE_OLD
-	      if (sh.flag.checkSum != SH_CHECK_INIT) 
-		sh_hash_set_visited_true(ptr->name);
-#else
+
 	      /* delete from database
 	       */
 	      if (sh.flag.checkSum != SH_CHECK_INIT) 
 		sh_hash_set_missing(ptr->name);
-#endif
 	    }
 	  else
@@ -494,5 +514,5 @@
 
 	  
-	  if (flag_err_info == SL_TRUE)
+	  if (flag_err_info == S_TRUE)
 	    {
 	      char pstr[32];
@@ -508,5 +528,5 @@
 	    {
 	      sh_inotify_add_watch_later(ptr->name, &sh_file_watches, NULL,
-					 ptr->class, ptr->check_mask, 
+					 ptr->class, ptr->check_flags, 
 					 SH_INOTIFY_FILE, 0);
 	    }
@@ -514,5 +534,5 @@
 	  BREAKEXIT(sh_files_filecheck);
 	  tmp_reported = ptr->is_reported; /* fix aliasing warning */ 
-	  status = sh_files_filecheck (ptr->class, ptr->check_mask, dir, file, 
+	  status = sh_files_filecheck (ptr->class, ptr->check_flags, dir, file, 
 				       &tmp_reported, 0);
 	  ptr->is_reported = tmp_reported;
@@ -590,5 +610,5 @@
 }
 
-static void * sh_dummy_candidate;
+void * sh_dummy_621_candidate;
 
 static char * intern_find_morespecific_dir(zAVLTree * tree, 
@@ -605,5 +625,5 @@
     return NULL;
 
-  sh_dummy_candidate = (void *) &candidate;
+  sh_dummy_621_candidate = (void *) &candidate;
 
   SH_MUTEX_LOCK(mutex_zfiles);
@@ -1069,5 +1089,5 @@
 
 int sh_files_push_file_int (int class, const char * str_s, size_t len, 
-			    unsigned long check_mask)
+			    unsigned long check_flags)
 {
   dirstack_t * new_item_ptr;
@@ -1085,5 +1105,5 @@
   new_item_ptr->name           = fileName;
   new_item_ptr->class          = class;
-  new_item_ptr->check_mask     = check_mask;
+  new_item_ptr->check_flags     = check_flags;
   new_item_ptr->rdepth         = 0;
   new_item_ptr->checked        = S_FALSE;
@@ -1122,18 +1142,18 @@
     {
       int           reported;
-      unsigned long check_mask = sh_files_maskof(class);
+      unsigned long check_flags = sh_files_maskof(class);
 
       if ((sh.flag.inotify & SH_INOTIFY_INSCAN) != 0)
 	{
-	  sh_files_filecheck (class, check_mask, str_s, NULL,
+	  sh_files_filecheck (class, check_flags, str_s, NULL,
 			      &reported, 0);
 	  if (SH_FFLAG_REPORTED_SET(reported))
 	    sh_files_set_file_reported(str_s);
 	  sh_inotify_add_watch_later(str_s, &sh_file_watches, NULL,
-				     class, check_mask, 
+				     class, check_flags, 
 				     SH_INOTIFY_FILE, 0);
 	}
 
-      if (MODI_AUDIT_ENABLED(check_mask))
+      if (MODI_AUDIT_ENABLED(check_flags))
 	{
 	  sh_audit_mark(str_s);
@@ -1144,5 +1164,5 @@
 }
 
-int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_mask);
+int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags);
 
 #ifdef HAVE_GLOB_H
@@ -1151,5 +1171,5 @@
   char                  * name;
   int                     class;
-  unsigned long           check_mask;
+  unsigned long           check_flags;
   int                     rdepth;
   short                   type;
@@ -1160,5 +1180,5 @@
 
 static int sh_files_pushglob (int class, int type, const char * p, int rdepth,
-			       unsigned long check_mask_in, int flag)
+			       unsigned long check_flags_in, int flag)
 {
   int     globstatus = -1;
@@ -1167,5 +1187,5 @@
 
   volatile int     count = 0;
-  volatile unsigned long check_mask = (flag == 0) ? sh_files_maskof(class) : check_mask_in;
+  volatile unsigned long check_flags = (flag == 0) ? sh_files_maskof(class) : check_flags_in;
   
   SL_ENTER(_("sh_files_pushglob"));
@@ -1190,5 +1210,5 @@
 	  new_item_ptr->name           = fileName;
 	  new_item_ptr->class          = class;
-	  new_item_ptr->check_mask     = check_mask;
+	  new_item_ptr->check_flags     = check_flags;
 	  new_item_ptr->rdepth         = rdepth;
 	  new_item_ptr->type           = type;
@@ -1219,5 +1239,5 @@
 	    {
 	      count += sh_files_push_file_int (class, pglob.gl_pathv[gloop], 
-					       sl_strlen(pglob.gl_pathv[gloop]), check_mask);
+					       sl_strlen(pglob.gl_pathv[gloop]), check_flags);
 	    }
 	  else
@@ -1226,5 +1246,5 @@
 
 	      count += sh_files_push_dir_int  (class, pglob.gl_pathv[gloop], 
-					       sl_strlen(pglob.gl_pathv[gloop]), rdepth, check_mask);
+					       sl_strlen(pglob.gl_pathv[gloop]), rdepth, check_flags);
 	    }
 	}
@@ -1285,5 +1305,5 @@
 	  sh_files_pushglob(testPattern->class, testPattern->type, 
 			    testPattern->name, testPattern->rdepth,
-			    testPattern->check_mask, 1);
+			    testPattern->check_flags, 1);
 	}
     }
@@ -1306,5 +1326,5 @@
       sh_files_pushglob(testPattern->class, testPattern->type, 
 			testPattern->name, testPattern->rdepth,
-			testPattern->check_mask, 1);
+			testPattern->check_flags, 1);
     }
   SH_MUTEX_UNLOCK(mutex_zglob);
@@ -1370,5 +1390,5 @@
    * is the only one -- and will stay the only one
    */
-  if (sh.flag.opts == 1) 
+  if (sh.flag.opts == S_TRUE) 
     {
       sh_files_delfilestack ();
@@ -1378,25 +1398,5 @@
     }
 
-  if (str_s == NULL || str_s[0] == '\0') 
-    SL_RETURN((-1),_("sh_files_pushfile"));
-
-  len = sl_strlen(str_s);
-
-  if ( (str_s[0] == '"'  && str_s[len-1] == '"' ) ||
-       (str_s[0] == '\'' && str_s[len-1] == '\'') )
-    {
-      if (len < 3)
-	SL_RETURN((-1),_("sh_files_pushfile"));
-      --len;
-      p = sh_util_strdup_l(&str_s[1], len);
-      p[len-1] = '\0';
-      --len;
-    }
-  else
-    {
-      p = sh_util_strdup_l(str_s, len);
-    }
-
-  p = sh_files_C_dequote(p, &len);
+  p = sh_files_parse_input(str_s, &len);
   if (!p || len == 0)
     SL_RETURN((-1), _("sh_files_pushfile"));
@@ -1491,5 +1491,5 @@
 }
 
-static void * sh_dummy_ptr;
+void * sh_dummy_1493_ptr;
 
 unsigned long sh_dirs_chk (int which)
@@ -1507,5 +1507,5 @@
   SL_ENTER(_("sh_dirs_chk"));
 
-  sh_dummy_ptr = (void *) &ptr;
+  sh_dummy_1493_ptr = (void *) &ptr;
   
   SH_MUTEX_RECURSIVE_INIT(mutex_zdirs);
@@ -1536,5 +1536,5 @@
 		  BREAKEXIT(sh_files_filecheck);
 		  tmp_reported = dst_ptr->is_reported;
-		  filetype = sh_files_filecheck (dst_ptr->class, dst_ptr->check_mask, 
+		  filetype = sh_files_filecheck (dst_ptr->class, dst_ptr->check_flags, 
 						 ptr->name,  
 						 NULL,  &tmp_reported, 0);
@@ -1555,5 +1555,5 @@
 	    {
 	      tmp_reported = ptr->is_reported;
-	      filetype = sh_files_filecheck (ptr->class,  ptr->check_mask, 
+	      filetype = sh_files_filecheck (ptr->class,  ptr->check_flags, 
 					     ptr->name,  NULL,  &tmp_reported, 0);
 	      ptr->is_reported = tmp_reported;
@@ -1562,5 +1562,5 @@
 
 	  BREAKEXIT(sh_files_checkdir);
-	  status = sh_files_checkdir (ptr->class, ptr->check_mask, 
+	  status = sh_files_checkdir (ptr->class, ptr->check_flags, 
 				      ptr->rdepth, ptr->name, 
 				      ptr->name);
@@ -1710,5 +1710,5 @@
 }
 
-int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_mask)
+int sh_files_push_dir_int (int class, char * tail, size_t len, int rdepth, unsigned long check_flags)
 {
   zAVLTree   * tree;
@@ -1726,5 +1726,5 @@
   new_item_ptr->name           = dirName;
   new_item_ptr->class          = class;
-  new_item_ptr->check_mask     = check_mask;
+  new_item_ptr->check_flags     = check_flags;
   new_item_ptr->rdepth         = rdepth;
   new_item_ptr->checked        = S_FALSE;
@@ -1776,5 +1776,5 @@
   else
     {
-      if (MODI_AUDIT_ENABLED(check_mask))
+      if (MODI_AUDIT_ENABLED(check_flags))
 	{
 	  sh_audit_mark(tail);
@@ -1794,5 +1794,5 @@
   SL_ENTER(_("sh_files_pushdir"));
 
-  if (sh.flag.opts == 1) {
+  if (sh.flag.opts == S_TRUE) {
     sh_files_delfilestack ();
     sh_files_deldirstack ();
@@ -1800,27 +1800,7 @@
   }
 
-  if (str_s == NULL || str_s[0] == '\0') 
+  p = sh_files_parse_input(str_s, &len);
+  if (!p || len == 0)
     SL_RETURN((-1),_("sh_files_pushdir"));
-
-  len = sl_strlen(str_s);
-
-  if ( (str_s[0] == '"'  && str_s[len-1] == '"' ) ||
-       (str_s[0] == '\'' && str_s[len-1] == '\'') )
-    {
-      if (len < 3)
-	SL_RETURN((-1),_("sh_files_pushdir"));
-      --len;
-      p = sh_util_strdup_l(&str_s[1], len);
-      p[len-1] = '\0';
-      --len;
-    }
-  else
-    {
-      p = sh_util_strdup_l(str_s, len);
-    }
-
-  p = sh_files_C_dequote(p, &len);
-  if (!p || len == 0)
-    SL_RETURN((-1), _("sh_files_pushdir"));
 
   if (p[0] != '/')
@@ -2048,5 +2028,5 @@
  *    check the directory inode itself.
  */
-int sh_files_checkdir (int iclass, unsigned long check_mask, 
+int sh_files_checkdir (int iclass, unsigned long check_flags, 
 		       int idepth, char * iname, 
 		       char * relativeName)
@@ -2073,6 +2053,6 @@
   volatile int    class_next;
   volatile int    file_class_next;
-  volatile unsigned long   check_mask_next;
-  volatile unsigned long   file_check_mask_next;
+  volatile unsigned long   check_flags_next;
+  volatile unsigned long   file_check_flags_next;
 
   volatile int    checked_flag  = S_FALSE;
@@ -2114,5 +2094,5 @@
     }
 
-  if (flag_err_info == SL_TRUE)
+  if (flag_err_info == S_TRUE)
     {
       char pstr[32];
@@ -2149,5 +2129,5 @@
   theFile->attr_string = NULL;
   theFile->link_path   = NULL;
-  theFile->check_mask  = check_mask;
+  theFile->check_flags  = check_flags;
 
   (void) relativeName;
@@ -2190,5 +2170,5 @@
     {
       sh_inotify_add_watch_later(iname, &sh_file_watches, &status,
-				 iclass, check_mask, SH_INOTIFY_DIR, idepth);
+				 iclass, check_flags, SH_INOTIFY_DIR, idepth);
     }
    
@@ -2301,7 +2281,7 @@
     rdepth_next     = rdepth - 1;
     class_next      = class;
-    check_mask_next = check_mask;
+    check_flags_next = check_flags;
     file_class_next = class;
-    file_check_mask_next = check_mask;
+    file_check_flags_next = check_flags;
     checked_flag    = -1;
     cchecked_flag   = -1;
@@ -2322,5 +2302,5 @@
 	 */
 	file_class_next    = dst_ptr->class;
-	file_check_mask_next = dst_ptr->check_mask;
+	file_check_flags_next = dst_ptr->check_flags;
 	checked_flag       = dst_ptr->checked;
 	cchecked_flag      = dst_ptr->childs_checked;
@@ -2338,5 +2318,5 @@
 	     */
 	    file_class_next    = dst_ptr->class;
-	    file_check_mask_next = dst_ptr->check_mask;
+	    file_check_flags_next = dst_ptr->check_flags;
 	    checked_flag       = dst_ptr->checked;
 	    cchecked_flag      = dst_ptr->childs_checked;
@@ -2355,5 +2335,5 @@
 	 */
 	file_class_next    = dst_ptr->class;
-	file_check_mask_next = dst_ptr->check_mask;
+	file_check_flags_next = dst_ptr->check_flags;
 	checked_flag       = dst_ptr->checked;
 	/* not set, hence always FALSE                   */
@@ -2403,5 +2383,5 @@
 	 */
 
-	checkit = sh_files_filecheck (file_class_next, file_check_mask_next, 
+	checkit = sh_files_filecheck (file_class_next, file_check_flags_next, 
 				      iname, 
 				      dirlist->sh_d_name,
@@ -2453,5 +2433,5 @@
 		rdepth_next   = tmp_ptr->rdepth;
 		class_next    = tmp_ptr->class;
-		check_mask_next = tmp_ptr->check_mask;
+		check_flags_next = tmp_ptr->check_flags;
 		/* 28. Aug 2001 reversed
 		 */
@@ -2471,5 +2451,5 @@
 		    rdepth_next   = tmp_ptr->rdepth;
 		    class_next    = tmp_ptr->class;
-		    check_mask_next = tmp_ptr->check_mask;
+		    check_flags_next = tmp_ptr->check_flags;
 		    /* 28. Aug 2001 reversed
 		     */
@@ -2491,5 +2471,5 @@
 	    if (cchecked_flag == S_FALSE)
 	      {
-		sh_files_checkdir (class_next, check_mask_next, rdepth_next, 
+		sh_files_checkdir (class_next, check_flags_next, rdepth_next, 
 				   tmpcat, dirlist->sh_d_name);
 		/*
@@ -2499,5 +2479,5 @@
 	      }
 	    else if (checked_flag == -1)
-	      sh_files_checkdir (class_next, check_mask_next, rdepth_next, 
+	      sh_files_checkdir (class_next, check_flags_next, rdepth_next, 
 				 tmpcat, dirlist->sh_d_name);
 	    
@@ -2532,5 +2512,5 @@
   } while (dirlist != NULL);
 
-  if (flag_err_info == SL_TRUE)
+  if (flag_err_info == S_TRUE)
     {
       sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DSUM,
@@ -2576,4 +2556,12 @@
 }
 
+void sh_files_fixup_mask (int class, unsigned long * check_flags)
+{
+  if (class == SH_LEVEL_ALLIGNORE)
+    MODI_SET((*check_flags), MODI_ALLIGNORE);
+  sh_tiger_get_mask_hashtype(check_flags);
+  return;
+}
+
 int get_the_fd (SL_TICKET ticket);
 
@@ -2589,5 +2577,5 @@
 static void * sh_dummy_tmpdir;
 
-ShFileType sh_files_filecheck (int class, unsigned long check_mask,
+ShFileType sh_files_filecheck (int class, unsigned long check_flags,
 			       const char * dirName, 
 			       const char * infileName,
@@ -2701,5 +2689,5 @@
    */
   sl_strlcpy (theFile->fullpath, fullpath, PATH_MAX);
-  theFile->check_mask    = check_mask /* sh_files_maskof(class) */;
+  theFile->check_flags    = check_flags /* sh_files_maskof(class) */;
   theFile->file_reported = (*reported);
   theFile->attr_string   = NULL;
@@ -2712,5 +2700,5 @@
 			     fileName,
 			     theFile, fileHash, class);
-  
+
   if (status != 0)
     {
@@ -2732,5 +2720,5 @@
   /* report
    */
-  if ((flag_err_debug == SL_TRUE) && (theFile->c_mode[0] == '-'))
+  if ((flag_err_debug == S_TRUE) && (theFile->c_mode[0] == '-'))
     {
       tmpname = sh_util_safe_name (fullpath); /* fixed in 1.5.4 */
@@ -2743,7 +2731,12 @@
   ++sh.statistics.files_checked;
       
-  if ( sh.flag.checkSum == SH_CHECK_INIT /* && sh.flag.update == S_FALSE */) 
-    {
-      sh_hash_pushdata (theFile, fileHash);
+  if ( sh.flag.checkSum == SH_CHECK_INIT) 
+    {
+      if (class == SH_LEVEL_ALLIGNORE)
+	MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
+      if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
+	MODI_SET(theFile->check_flags, MODI_NOCHECK);
+      sh_tiger_get_mask_hashtype(&(theFile->check_flags));
+      sh_dbIO_data_write (theFile, fileHash);
     }
   else if (sh.flag.checkSum == SH_CHECK_CHECK 
@@ -2752,4 +2745,12 @@
 	   ) 
     {
+      if (sh.flag.update == S_TRUE)
+	{
+	  if (class == SH_LEVEL_ALLIGNORE)
+	    MODI_SET(theFile->check_flags, MODI_ALLIGNORE);
+	  if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
+	    MODI_SET(theFile->check_flags, MODI_NOCHECK);
+	  sh_tiger_get_mask_hashtype(&(theFile->check_flags));
+	}
       sh_hash_compdata (class, theFile, fileHash, NULL, -1);
     }
@@ -2760,5 +2761,5 @@
    */
 #if !defined(O_NOATIME)
-  if (class == SH_LEVEL_NOIGNORE && (theFile->check_mask & MODI_ATM) != 0)
+  if (class == SH_LEVEL_NOIGNORE && (theFile->check_flags & MODI_ATM) != 0)
     {
       utime_buf.actime   = (time_t) theFile->atime;
@@ -2792,5 +2793,5 @@
 	  if (S_TRUE == sh_unix_file_exists (testpath))
 	    {
-	      sh_files_filecheck (class, check_mask, fullpath, rsrc, &dummy, 1);
+	      sh_files_filecheck (class, check_flags, fullpath, rsrc, &dummy, 1);
 	    }
 	}
@@ -2860,5 +2861,5 @@
  */
 int sh_files_search_dir(char * name, int * class, 
-			unsigned long *check_mask, int *reported,
+			unsigned long *check_flags, int *reported,
 			int * rdepth)
 {
@@ -2877,5 +2878,5 @@
   if (item)
     {
-      *check_mask = item->check_mask;
+      *check_flags = item->check_flags;
       *class      = item->class;
       *reported   = item->is_reported;
@@ -2892,5 +2893,5 @@
   if (item)
     {
-      *check_mask = item->check_mask;
+      *check_flags = item->check_flags;
       *class      = item->class;
       *reported   = item->is_reported;
@@ -2914,5 +2915,5 @@
 	  if (0 == fnmatch(testPattern->name, name, FNM_PATHNAME|FNM_PERIOD))
 	    {
-	      *check_mask = testPattern->check_mask;
+	      *check_flags = testPattern->check_flags;
 	      *class      = testPattern->class;
 	      *rdepth     = testPattern->rdepth;
@@ -2932,5 +2933,5 @@
 
 int sh_files_search_file(char * name, int * class, 
-			 unsigned long *check_mask, int *reported)
+			 unsigned long *check_flags, int *reported)
 {
   volatile int retval = 0;
@@ -2946,5 +2947,5 @@
   if (item)
     {
-      *check_mask = item->check_mask;
+      *check_flags = item->check_flags;
       *class      = item->class;
       *reported   = item->is_reported;
@@ -2966,5 +2967,5 @@
 			       FNM_PATHNAME|FNM_PERIOD))
 		{
-		  *check_mask = testPattern->check_mask;
+		  *check_flags = testPattern->check_flags;
 		  *class      = testPattern->class;
 		  retval = 1;
@@ -3035,7 +3036,7 @@
     {
       if (0 == strcmp(name, pfilL->name) &&
-	  (pfilL->check_mask & MODI_ATM) == 0 &&
-	  (pfilL->check_mask & MODI_CTM) == 0 &&
-	  (pfilL->check_mask & MODI_MTM) == 0)
+	  (pfilL->check_flags & MODI_ATM) == 0 &&
+	  (pfilL->check_flags & MODI_CTM) == 0 &&
+	  (pfilL->check_flags & MODI_MTM) == 0)
 	{
 	  retval = 0;
@@ -3087,7 +3088,7 @@
 		  (0 == strncmp(pfilL->name, pdirL->name, dlen)))
 		{
-		  if ((pdirL->check_mask & MODI_ATM) != 0  ||
-		      (pdirL->check_mask & MODI_MTM) != 0  ||
-		      (pdirL->check_mask & MODI_CTM) != 0)
+		  if ((pdirL->check_flags & MODI_ATM) != 0  ||
+		      (pdirL->check_flags & MODI_MTM) != 0  ||
+		      (pdirL->check_flags & MODI_CTM) != 0)
 		    {
 		      if (check_file (pdirL->name) != 0)
Index: trunk/src/sh_filetype.c
===================================================================
--- trunk/src/sh_filetype.c	(revision 476)
+++ trunk/src/sh_filetype.c	(revision 481)
@@ -406,17 +406,4 @@
     }
 
-  /* fprintf(stderr, "FIXME: %d %d %s ", dtype, length, type); */
-  /**
-  if (dtype == 0)
-    fprintf(stderr, "%s\n", pattern);
-  else
-    {
-      int k;
-      for (k = 0; k < length; ++k)
-	fprintf(stderr, "0x%X", (unsigned int) (pattern[k]));
-      fprintf(stderr, "\n");
-    }
-  **/
-
   for (i = 0; i < n; ++i)
     {
@@ -523,19 +510,4 @@
 	  p = &buffer[sh_ftype_arr[i]->offset];
 
-#if 0
-	  {
-	    int dd;
-	    /* fprintf(stderr, "FIXME: %03d comp %d:%d  ", i, 
-	       sh_ftype_arr[i]->offset, sh_ftype_arr[i]->length); */
-	    for (dd = 0; dd < sh_ftype_arr[i]->length; ++dd) {
-	      fprintf(stderr, "0x%X ", sh_ftype_arr[i]->pattern[dd]);
-	    }
-	    for (dd = 0; dd < sh_ftype_arr[i]->length; ++dd) {
-	      fprintf(stderr, "0x%X ", p[dd]);
-	    }
-	    fprintf(stderr, "\n");
-	  }
-#endif
-
 	  if (0 == memcmp(p, sh_ftype_arr[i]->pattern, sh_ftype_arr[i]->length))
 	    {
@@ -582,5 +554,5 @@
   long len;
 
-  len = sl_read_timeout (ft, buffer, sizeof(buffer), 12, SL_TRUE);
+  len = sl_read_timeout (ft, buffer, sizeof(buffer), 12, S_TRUE);
 
   sl_rewind(ft);
Index: trunk/src/sh_forward.c
===================================================================
--- trunk/src/sh_forward.c	(revision 476)
+++ 	(revision )
@@ -1,6043 +1,0 @@
-/* SAMHAIN file system integrity testing                                   */
-/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
-/*                                                                         */
-/*  This program is free software; you can redistribute it                 */
-/*  and/or modify                                                          */
-/*  it under the terms of the GNU General Public License as                */
-/*  published by                                                           */
-/*  the Free Software Foundation; either version 2 of the License, or      */
-/*  (at your option) any later version.                                    */
-/*                                                                         */
-/*  This program is distributed in the hope that it will be useful,        */
-/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
-/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
-/*  GNU General Public License for more details.                           */
-/*                                                                         */
-/*  You should have received a copy of the GNU General Public License      */
-/*  along with this program; if not, write to the Free Software            */
-/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
-
-#include "config_xor.h"
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-/* Must be early on FreeBSD
- */
-#include <sys/types.h>
-
-/* must be .le. than (1020 * 64)
- * (see sh_tools.c -- put_header)
- *
- * also: must be  (N * 16), otherwise
- * binary files cannot be transferred encrypted
- *
- * 65280 = (1020*64)
- * #define TRANS_BYTES 8000  V0.8
- */
-#ifdef  SH_ENCRYPT_2
-#define TRANS_BYTES 65120
-#else
-#define TRANS_BYTES 65280
-#endif
-
-/* timeout for session key
- */
-#define TIMEOUT_KEY 7200
-
-/* max time between connection attempts
- */
-#define TIMEOUT_CON 2048 
-
-/* #undef  SRP_DEBUG */
-/* #define SRP_DEBUG */
-
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-/*
-#ifdef TM_IN_SYS_TIME
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-*/
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#ifdef  HAVE_UNISTD_H
-#include <errno.h>
-#include <signal.h>
-#include <setjmp.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/stat.h>
-#include <sys/resource.h>
-#include <fcntl.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#endif
-
-#ifndef FD_SET
-#define NFDBITS         32
-#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
-#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
-#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
-#endif /* !FD_SET */
-#ifndef FD_SETSIZE
-#define FD_SETSIZE      32
-#endif
-#ifndef FD_ZERO
-#define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p)))
-#endif
-
-#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
-#include <sys/mman.h>
-#endif
-
-
-#include <netdb.h> 
-#include <sys/types.h> 
-#include <netinet/in.h> 
-#include <sys/socket.h> 
-#ifndef S_SPLINT_S
-#include <arpa/inet.h>
-#endif
-
-#include "sh_ipvx.h"
-#include "samhain.h"
-#include "sh_tiger.h"
-#include "sh_utils.h"
-#include "sh_unix.h"
-#include "sh_forward.h"
-#include "sh_srp.h"
-#include "sh_fifo.h"
-#include "sh_tools.h"
-#include "sh_entropy.h"
-#include "sh_html.h"
-#include "sh_nmail.h"
-#include "sh_socket.h"
-#define SH_NEED_GETHOSTBYXXX
-#include "sh_static.h"
-
-#ifdef SH_ENCRYPT
-#include "rijndael-api-fst.h"
-char * sh_tools_makePack (unsigned char * header, 
-			  char * payload, unsigned long payload_size,
-			  keyInstance * keyInstE);
-char * sh_tools_revertPack (unsigned char * header, char * message,
-			    keyInstance * keyInstE, 
-			    unsigned long message_size);
-#endif
-
-/* define this if you want to debug the client/server communication */
-/* #define SH_DBG_PROT 1 */
-
-#ifdef  SH_DBG_PROT
-#define SH_SHOWPROT(c,d) sh_tools_show_header((c), (d))
-#else
-#define SH_SHOWPROT(c,d) 
-#endif
-
-/* the port client will be connecting to 
- */
-#ifndef SH_DEFAULT_PORT
-#define SH_DEFAULT_PORT 49777    
-#endif
-
-#ifndef SH_SELECT_REPEAT
-#define SH_SELECT_REPEAT 60
-#endif
-
-#ifndef SH_HEADER_SIZE
-#define SH_HEADER_SIZE 7
-#endif
-
-#ifndef SH_CHALLENGE_SIZE
-#define SH_CHALLENGE_SIZE 9
-#endif
-
-#undef  FIL__
-#define FIL__  _("sh_forward.c")
-
-int     clt_class = (-1);
-
-extern int flag_err_debug;
-extern int flag_err_info;
-
-#ifndef SH_STANDALONE
-
-#if defined(WITH_TRACE) || defined(WITH_TPT) 
-char * hu_trans(const char * ihu)
-{
-  static char ohu[17];
-  sprintf(ohu, _("%c%03o"), '\\',                   /* known to fit  */
-	  (unsigned char) ihu[0]);
-  sprintf(&(ohu[4]), _("%c%03o"), '\\',             /* known to fit  */
-	  (unsigned char) ihu[1]);
-  sprintf(&(ohu[8]), _("%c%03o"), '\\',             /* known to fit  */
-	  (unsigned char) ihu[2]);
-  sprintf(&(ohu[12]), _("%c%03o"), '\\',            /* known to fit  */
-	  (unsigned char) ihu[3]);
-  ohu[16] = '\0';
-  return ohu;
-}
-#endif
-
-static int StripDomain = S_TRUE;
-
-int sh_forward_set_strip (const char * str)
-{
-  static int fromcl = 0;
-  char dummy[2] = "F";
-
-  if (fromcl == 1)
-    return 0;
-
-  if (str == NULL)
-    {
-      fromcl = 1;
-      return (sh_util_flagval(dummy, &StripDomain));
-    }
-  else
-    return (sh_util_flagval(str, &StripDomain));
-}
-
-#include <ctype.h>
-
-const char * sh_strip_domain (char *name)
-{
-  char *          first;
-  static char     name_2[SH_MINIBUF+1];
-  register int    i = 0;
-
-  SL_ENTER(_("sh_strip_domain"));
-
-  if (StripDomain == S_FALSE || (first  = strchr(name, '.')) == NULL) 
-    {
-      SL_RETURN( name, _("sh_strip_domain"));
-    }
-  else
-    {
-
-      /* check whether it is in dotted number format
-       * --> last part must be kept
-       */
-      if (0 != sh_ipvx_is_numeric(name))
-	{
-	  SL_RETURN( name, _("sh_strip_domain"));
-	  /*
-	  i = sl_strlen(name) - 1;
-	  while (name[i] != '.' && i >= 0)
-	    --i;
-	  if (name[i] == '.') ++i;
-	  sl_strlcpy( name_2, &name[i], SH_MINIBUF +1 );
-	  */
-	}
-      else
-	{
-	  first = name;
-	  while (i < SH_MINIBUF && *first != '.' && *first != '\0')
-	    {
-	      name_2[i] = *first;
-	      ++first; ++i;
-	    }
-	  name_2[i] = '\0';
-	}
-    }
-
-  SL_RETURN( name_2, _("sh_strip_domain"));
-}
-
-/* #ifndef SH_STANDALONE */
-#endif
-
-#ifndef USE_SRP_PROTOCOL
-static
-void sh_passwd (char * salt, char * password, char * nounce, char *hash)
-{
-
-  char           *combi;
-  size_t          len;
-  register int i;
-  unsigned char * dez = NULL;
-  char hashbuf[KEYBUF_SIZE];
-
-  if (password == NULL)
-    dez = (unsigned char *) &(skey->pw[0]);
-  else if (sl_strlen(password) < PW_LEN)
-    {
-      fprintf(stderr, _("Password has less than %d chars !\n"),
-		   PW_LEN);
-      _exit(EXIT_FAILURE);
-    }
-
-  if (password == NULL)
-    {
-      /* --- copy password ---
-       */
-      for (i = 0; i < PW_LEN; ++i)
-	{ 
-	  skey->vernam[i] = (char)(*dez); 
-	  ++dez; 
-	}
-      (void) sl_strlcpy (skey->vernam,
-			 sh_tiger_hash(skey->vernam, TIGER_DATA, PW_LEN,
-				       hashbuf, sizeof(hashbuf)), 
-			 KEY_LEN+1);
-    }
-  else
-    {
-      (void) sl_strlcpy (skey->vernam, password, KEY_LEN+1);
-    }
-
-  len = sl_strlen(salt) + 1;
-  if (sl_ok_adds(len, sl_strlen(skey->vernam)))
-    len += sl_strlen(skey->vernam);
-  if (nounce != NULL && sl_ok_adds(len, sl_strlen(nounce))) 
-    len += sl_strlen(nounce);
-  
-  /* H(s,P)
-   */
-  combi = SH_ALLOC(len);
-  (void) sl_strlcpy (combi, salt, len);
-  (void) sl_strlcat (combi, skey->vernam, len);
-  if (nounce != NULL)
-    (void) sl_strlcat (combi, nounce, len);
-  (void) sl_strlcpy (hash, 
-		     sh_tiger_hash(combi, TIGER_DATA, 
-				   (unsigned long) sl_strlen(combi),
-				   hashbuf, sizeof(hashbuf)),
-		     KEY_LEN+1);
-
-  /*
-    fprintf(stderr, "DD: A: <%s>\n", salt);
-    fprintf(stderr, "DD: P: <%s>\n", skey->pw); 
-    fprintf(stderr, "DD: V: <%s>\n", skey->vernam); 
-    fprintf(stderr, "DD: C: <%s>\n", combi);
-    fprintf(stderr, "DD: H: <%s>\n", hash); 
-  */
-
-  SH_FREE (combi);
-  hash[KEY_LEN] = '\0';
-  return;
-}
-#endif
-
-#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
-
-static int count_dev_server = 0;
-
-void reset_count_dev_server(void)
-{
-  count_dev_server = 0;
-  return;
-}
-
-int sh_forward_setlogserver (const char * address)
-{
-  SL_ENTER(_("sh_forward_setlogserver"));
-
-  if (address != NULL && count_dev_server < 2 
-      && sl_strlen(address) < SH_PATHBUF && sl_strlen(address) > 0) 
-    {
-      if (count_dev_server == 0)
-	(void) sl_strlcpy (sh.srvexport.name, address, SH_PATHBUF);
-      else
-	(void) sl_strlcpy (sh.srvexport.alt,  address, SH_PATHBUF);
-
-      ++count_dev_server;
-      SL_RETURN (0, _("sh_forward_setlogserver"));
-    }
-  SL_RETURN (-1, _("sh_forward_setlogserver"));
-}
-
-static
-int sh_forward_send_intern (int mysocket, char protocol, char * micro, 
-			    char * msgbuf, unsigned long length, int docrypt)
-{
-  unsigned long           numbytes, countbytes;
-  int                     flag_err = 0;
-  unsigned char           head[SH_HEADER_SIZE];
-  char                  * outbuf;
-
-#ifdef SH_ENCRYPT
-
-  unsigned long           blkfac;
-  int                     rem;
-  unsigned long           length2;
-  char                  * msg2buf = NULL;
-  char                  * p, * q;
-  RIJ_BYTE                    inBlock[B_SIZ]; 
-  RIJ_BYTE                    outBlock[B_SIZ];
-  unsigned long           j;
-  cipherInstance          cipherInst;
-  int                     err_num;
-  char expbuf[SH_ERRBUF_SIZE];
-#else
-  docrypt = SL_FALSE; /* dummy to fix compiler warning */
-#endif
-
-  SL_ENTER(_("sh_forward_send_intern"));
-
-#ifdef SH_ENCRYPT
-  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_EN2) != (char)0))
-    {
-      put_header (head, (int)protocol, &length, micro);
-      msg2buf  = sh_tools_makePack (head, msgbuf, length, 
-				    &(skey->keyInstE));
-      /*@-usedef@*/
-      length   = (unsigned long) (256 * (unsigned int)head[1] + 
-				  (unsigned int)head[2]);
-      /*@+usedef@*/
-      outbuf   = msg2buf;
-    }
-  else if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != (char)0))
-    {
-      blkfac  = length/B_SIZ;
-      rem     = (int) (length - (B_SIZ * blkfac));
-      length2 = (B_SIZ * blkfac);
-      if ((rem > 0) && (length2+B_SIZ) > length2) 
-	length2 += B_SIZ;
-      else
-	rem = 0;
-
-      msg2buf = SH_ALLOC((size_t)length2);
-      p       = msgbuf;
-      q       = msg2buf;
-      
-      err_num = cipherInit (&cipherInst, (RIJ_BYTE)MODE_CBC, NULL);
-
-      if (err_num < 0)
-	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			_("sh_forward_send_intern: cipherInit"));
-
-
-      for (j = 0; j < blkfac; ++j)
-	{
-	  memcpy(inBlock, p, B_SIZ);
-	  err_num = blockEncrypt(&cipherInst, &(skey->keyInstE), 
-				 inBlock, 128 * BNUM, outBlock);
-	  if (err_num < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			    _("sh_forward_send_intern: blockEncrypt"));
-	  memcpy(q, outBlock, B_SIZ);
-	  p += B_SIZ;
-	  q += B_SIZ;
-	}
-      if (rem > 0)
-	{
-	  memset(inBlock, 0, B_SIZ);
-	  memcpy(inBlock, p, (size_t)rem);
-	  err_num = blockEncrypt(&cipherInst, &(skey->keyInstE), 
-				 inBlock, 128 * BNUM, outBlock);
-	  if (err_num < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			    _("sh_forward_send_intern: blockEncrypt"));
-	  memcpy(q, outBlock, B_SIZ);
-	  /* q += B_SIZ; *//* never read */
-	}
-
-      outbuf = msg2buf;
-      length = length2;
-      put_header (head, (int)protocol, &length, micro);
-    }
-  else
-    {
-      outbuf = msgbuf;
-      put_header (head, (int)protocol, &length, micro);
-    }
-#else
-  outbuf = msgbuf;
-  put_header (head, (int)protocol, &length, micro);
-#endif
-
-  SH_SHOWPROT(head,'>');
-  
-  numbytes     = SH_HEADER_SIZE;
-  countbytes   = write_port (mysocket, 
-			     (char *) head, numbytes,
-			     &flag_err, 300);
-
-  if (countbytes == numbytes && outbuf != NULL)
-    {
-      numbytes     = (length);
-      countbytes   = write_port (mysocket, 
-				 outbuf, numbytes,
-				 &flag_err, 300);
-    }
-
-#ifdef SH_ENCRYPT
-  /*@-usedef@*/
-  if (msg2buf != NULL)
-    SH_FREE(msg2buf);
-  /*@+usedef@*/
-#endif
-
-  if (countbytes == numbytes)
-    {
-      SL_RETURN( 0, _("sh_forward_send_intern"));
-    }
-  else
-    {
-      SL_RETURN( flag_err, _("sh_forward_send_intern"));
-    }
-}
-static
-int sh_forward_send (int mysocket, char protocol, char * micro, 
-		     char * msgbuf, unsigned long length)
-{
-  int i;
-  SL_ENTER(_("sh_forward_send"));
-  TPT(( 0, FIL__, __LINE__, _("msg=<Send.>\n")));
-  i =  sh_forward_send_intern (mysocket, protocol, micro, 
-			       msgbuf, length, S_FALSE);
-  SL_RETURN(i, _("sh_forward_send"));
-}
-static
-int sh_forward_send_crypt (int mysocket, char protocol, char * micro, 
-			   char * msgbuf, unsigned long length)
-{
-  int i;
-  SL_ENTER(_("sh_forward_send_crypt"));
-#ifdef SH_ENCRYPT
-  TPT(( 0, FIL__, __LINE__, _("msg=<Send encrypted.>\n")));
-#else
-  TPT(( 0, FIL__, __LINE__, _("msg=<Send.>\n")));
-#endif
-  i = sh_forward_send_intern (mysocket, protocol, micro, 
-			      msgbuf, length, S_TRUE);
-  SL_RETURN(i, _("sh_forward_send_crypt"));
-}
-
-
-/* receive answer, add a trailing NULL to terminate string
- * rev 0.8
- */
-static
-long sh_forward_receive_intern (int mysocket, char protocol, char * micro,     
-				char *  msgbuf, unsigned long length, 
-				int docrypt)
-{
-  unsigned long numbytes, countbytes;
-  int           flag_err = -1;
-  unsigned char head[SH_HEADER_SIZE];
-
-#ifdef SH_ENCRYPT
-
-  unsigned long           head_length;
-  unsigned long           blkfac;
-  /* unsigned long           length2; */
-  char                  * p, * q, * tmp;
-  RIJ_BYTE                    inBlock[B_SIZ]; 
-  RIJ_BYTE                    outBlock[B_SIZ];
-  unsigned long           j;
-  cipherInstance          cipherInst;
-  int                     err_num;
-  char expbuf[SH_ERRBUF_SIZE];
-#else
-  docrypt = SL_FALSE; /* dummy to fix compiler warning */
-#endif
-
-  SL_ENTER(_("sh_forward_receive_intern"));
-
-#ifdef SH_ENCRYPT
-  /* make sure length is not multiple of B_SIZ, see below 
-   */
-  ASSERT_RET((length % B_SIZ != 0), _("length % 16 != 0"), flag_err);
-#endif
-
-  if (micro != NULL)
-    micro[4]     = '\0';
-
-  if (msgbuf != NULL)
-    msgbuf[0]     = '\0';
-
-  numbytes     = SH_HEADER_SIZE;
-  countbytes   = read_port (mysocket, 
-			    (char *) head, numbytes,
-			    &flag_err, 300);
-
-  if (countbytes != numbytes)
-    {
-      TPT(( 0, FIL__, __LINE__, _("msg=<countbytes != numbytes>\n")));
-      SL_RETURN(flag_err, _("sh_forward_receive_intern"));
-    }
-  /*@-usedef +ignoresigns@*/
-  else if (msgbuf == NULL)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		      _("msgbuf is NULL"), _("sh_forward_receive_intern"));
-      SL_RETURN((-1), _("sh_forward_receive_intern"));
-    }
-  else if (head[0] != protocol &&  
-	   (head[0] & SH_PROTO_SRP) == (char)0 /* not set */)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISMATCH);
-      SL_RETURN((-1), _("sh_forward_receive_intern"));
-    }
-  /*@+usedef -ignoresigns@*/
-  else
-    {
-      get_header (head, &numbytes, micro);
-      SH_SHOWPROT(head, '<');
-
-      if (numbytes > 0)
-	{
-	  numbytes = (numbytes > length ? length : numbytes);
-
-	  countbytes   = read_port (mysocket, 
-				    msgbuf, numbytes,
-				    &flag_err, 300);
-
-	  if (countbytes < length)
-	    msgbuf[countbytes] = '\0';
-	  else
-	    msgbuf[length-1] = '\0';
-
-	  if (flag_err != 0)
-	    {
-	      TPT(( 0, FIL__, __LINE__, _("msg=<read error>\n")));
-	      SL_RETURN((-1), _("sh_forward_receive_intern"));
-	    }
-	}
-    }
-
-#ifdef SH_ENCRYPT
-  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_EN2) != (char)0))
-    {
-      tmp = SH_ALLOC((size_t)length);
-      memcpy(tmp, msgbuf, (size_t)length);
-      tmp = sh_tools_revertPack (head, tmp, &(skey->keyInstD), countbytes);
-
-      head_length = (unsigned long) (256 * (unsigned int)head[1] + 
-				     (unsigned int)head[2]);
-
-      /* 
-       * revertPack returns header with length <= (original_length-16), so
-       * the following msgbuf[length] = '\0' is always safe.
-       * Nevertheless, check for proper length.
-       */
-      if (head_length <= (length-1))
-	length      = head_length;
-      else
-	--length;
-
-      memcpy(msgbuf, tmp, (size_t)length);
-      msgbuf[length] = '\0';
-      SH_FREE(tmp);
-      if (countbytes == numbytes) 
-	{
-	  countbytes = length; /* to avoid error on return, see below */
-	}
-      numbytes = length;
-    }
-  else if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != (char)0))
-    {
-      /* Decrypt only complete blocks. If there is an incomplete block,
-       * something is wrong anyway.
-       * Decrypt in place.
-       */
-      blkfac  = countbytes/B_SIZ;
-
-      p       = msgbuf;
-      q       = msgbuf;
-      
-      err_num = cipherInit (&cipherInst, (RIJ_BYTE)MODE_CBC, NULL);
-
-      if (err_num < 0)
-	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			_("sh_forward_receive_intern: cipherInit"));
-
-      /* here we want to have (length % B_SIZ != 0), such that the
-       * terminating '\0' cannot be overwritten
-       */
-      for (j = 0; j < blkfac; ++j)
-	{
-	  memcpy(inBlock, p, B_SIZ);
-	  err_num = blockDecrypt(&cipherInst, &(skey->keyInstD), 
-				 inBlock, 128 * BNUM, outBlock);
-	  if (err_num < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			    _("sh_forward_receive_intern: blockDecrypt"));
-	  memcpy(q, outBlock, B_SIZ);
-	  p += B_SIZ;
-	  q += B_SIZ;
-	}
-    }
-#endif
-
-  if (countbytes == numbytes)
-    {
-      SL_RETURN(((long)numbytes), _("sh_forward_receive_intern"));
-    }
-  else
-    {
-      TPT(( 0, FIL__, __LINE__, _("msg=<short read>\n")));
-      SL_RETURN(flag_err, _("sh_forward_receive_intern"));
-    }
-}
-
-static
-long sh_forward_receive (int mysocket, char protocol, char * micro,     
-			 char * msgbuf, unsigned long length)
-{
-  long i;
-  SL_ENTER(_("sh_forward_receive"));
-  TPT(( 0, FIL__, __LINE__, _("msg=<Receive.>\n")));
-  i = sh_forward_receive_intern (mysocket, protocol, micro, 
-				 msgbuf, length, S_FALSE);
-  SL_RETURN(i, _("sh_forward_receive"));
-}
-
-static
-long sh_forward_receive_crypt (int mysocket, char protocol, char * micro,     
-			       char * msgbuf, unsigned long length)
-{
-  long i;
-  SL_ENTER(_("sh_forward_receive_crypt"));
-#ifdef SH_ENCRYPT
-  TPT(( 0, FIL__, __LINE__, _("msg=<Receive encrypted.>\n")));
-#else
-  TPT(( 0, FIL__, __LINE__, _("msg=<Receive.>\n")));
-#endif
-  i = sh_forward_receive_intern (mysocket, protocol, micro, 
-				 msgbuf, length, S_TRUE);
-  SL_RETURN(i, _("sh_forward_receive"));
-}
-
-/**************************************************
- *
- *
- *  C L I E N T  
- *
- *
- ***************************************************/
-
-
-#include <time.h>
-
-static SH_FIFO * fifo = NULL;
-
-static long sh_forward_try (char * errmsg);
-
-static unsigned int ServerPort = SH_DEFAULT_PORT;
-
-int sh_forward_server_port (const char * str)
-{
-  unsigned long l;
-  char * endptr;
-
-  SL_ENTER(_("sh_forward_server_port"));
-
-  l = strtoul (str, &endptr, 0);
-  if (l > 65535 || endptr == str)
-    {
-      SL_RETURN (-1, _("sh_forward_server_port"));
-    }
-  ServerPort = (unsigned int) l;
-  SL_RETURN (0, _("sh_forward_server_port"));
-}
-
-long sh_forward (char * errmsg)
-{
-  static int           have_server = GOOD;
-  long   status;
-  char * popmsg;
-  static int failed = GOOD;
-
-  SL_ENTER(_("sh_forward"));
-
-  /* --- No log server available. ---
-   */
-  if (have_server == GOOD && sh.srvexport.name[0] == '\0')
-    {
-      have_server = BAD;
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NONAME);
-      SL_RETURN (-1, _("sh_forward"));
-    }
-  else if (have_server == BAD)
-    {
-      SL_RETURN (-1, _("sh_forward"));
-    }
-
-  /* --- Allocate fifo. ---
-   */
-  if (fifo == NULL)
-    {
-      fifo = SH_ALLOC(sizeof(SH_FIFO));
-      fifo_init(fifo);
-    }
-
-  /* --- Check for messages on the queue, and send them first. ---
-   */
-  while (NULL != (popmsg = pop_list(fifo)) )
-    {
-      status = sh_forward_try (popmsg);
-      if (status != 0)
-	{
-	  (void) push_tail_list (fifo, popmsg, 0, NULL); 
-	  SH_FREE(popmsg);
-	  if (SH_FIFO_MAX == push_list (fifo, errmsg, 0,NULL))
-	    {
-	      SL_RETURN (-2, _("sh_forward"));
-	    }
-	  SL_RETURN (-1, _("sh_forward"));
-	}
-      SH_FREE(popmsg);
-    }
-
-  /* --- Now send the error message. ---
-   */ 
-  status = sh_forward_try (errmsg);
-  if (status != 0)
-    {
-      if (failed == GOOD)
-	sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL,
-			 _("log server"), 
-			 sh.srvexport.name);
-      failed = BAD;
-      if (SH_FIFO_MAX == push_list (fifo, errmsg, 0, NULL))/* push on stack */
-	{
-	  SL_RETURN (-2, _("sh_forward"));
-	}
-      SL_RETURN (-1, _("sh_forward"));
-    }
-
-  failed = GOOD;
-  SL_RETURN (0, _("sh_forward"));  
-}
-
-static long sh_forward_try_impl (char * errmsg, char what);
-
-static long sh_forward_try (char * errmsg)
-{
-  long i;
-  SL_ENTER(_("sh_forward_try"));
-  i = sh_forward_try_impl (errmsg, (char)SH_PROTO_MSG);
-  SL_RETURN(i, _("sh_forward_try")); 
-}
-
-long sh_forward_req_file (char * file)
-{
-  long i;
-  char tmp_file[8];
-  SL_ENTER(_("sh_forward_req_file"));
-  (void) sl_strlcpy(tmp_file, file, 8);
-  i = sh_forward_try_impl (tmp_file, (char)SH_PROTO_BIG);
-  SL_RETURN(i, _("sh_forward_req_file")); 
-}
-
-static unsigned long sh_throttle_delay = 0;
-
-int sh_forward_set_throttle_delay (const char * c)
-{
-  long val;
-
-  SL_ENTER(_("sh_forward_set_throttle_delay"));
-
-  val = strtol (c, (char **)NULL, 10);
-  if (val < 0)
-    SL_RETURN( (-1), _("sh_forward_set_throttle_delay"));
-
-  val = (val > 1000) ? 1000 : val;
-
-  sh_throttle_delay = (unsigned long) val;
-  SL_RETURN( (0), _("sh_forward_set_throttle_delay"));
-}
-
-
-static  long sh_forward_try_impl (char * errmsg, char what)
-{
-  static int           initialized = BAD;
-  static int           conn_state  = GOOD;
-  int                  sockfd;
-  int                  flag_err;
-  char               * answer;
-
-  unsigned char        theProto;
-
-  char                 hash[KEY_LEN+1];
-  size_t               len;
-  char               * buffer;
-#ifdef SH_ENCRYPT_2
-  size_t               pos;  /* for the server command */
-#endif
-  char   head_u[5];
-
-  char   nsrv[KEY_LEN+1];
-  char   nclt[KEY_LEN+1];
-  SL_TICKET sfd = -1;
-  int    transfercount;
-
-  char   foo_M1[KEY_LEN+1];
-  UINT32 ticks;
-
-  char         error_msg[256];
-  char         error_call[SH_MINIBUF];
-  int          error_num = 0;
-
-#ifdef USE_SRP_PROTOCOL
-  char   u_real[SH_CHALLENGE_SIZE];
-  char * foo_A;
-  char * foo_Sc;
-  char * M;
-#else
-  char   nounce[KEY_LEN+1];
-  char   temp[2*KEY_LEN+1];
-  char   nonce_u[KEY_LEN+1];
-#endif
-  
-#ifdef SH_ENCRYPT
-  int err_num;
-  char expbuf[SH_ERRBUF_SIZE];
-#endif
-
-  static time_t time_now  = 1200;
-  static time_t time_last =    0;
-
-  static time_t timeout_val =  1;
-  char hashbuf[KEYBUF_SIZE];
-  char sigbuf[KEYBUF_SIZE];
-
-  SL_ENTER(_("sh_forward_try_impl"));
-
-  /* --- No message to transmit. ---
-   */
-  if (errmsg == NULL && initialized == GOOD)
-    SL_RETURN( 0, _("sh_forward_try_impl"));
-  
-  /* --- Connection in bad state. ---
-   */
-  if (initialized == BAD || conn_state == BAD)
-    {
-      timeout_val = 
-	(time_t)((timeout_val > TIMEOUT_CON) ? TIMEOUT_CON : timeout_val);
-
-      /* --- Retry bad attempt only after some time. ---
-       */
-      time_now  = time (NULL);
-      if ((time_now - time_last) < timeout_val) 
-	{
-	  TPT(( 0, FIL__, __LINE__, _("msg=<Within deadtime, no retry.>\n")));
-	  SL_RETURN( (-1), _("sh_forward_try_impl"));
-	}
-      TPT(( 0, FIL__, __LINE__, _("msg=<Retry.>\n")));
-    }
-  time_last  = time (NULL);
-
-
-  /* --- Try to connect to log server. ---
-   */
-  error_call[0] = '\0';
-
-  sockfd = connect_port_2 (sh.srvexport.name, sh.srvexport.alt, 
-			   ServerPort, 
-			   error_call, &error_num, error_msg, 256);
-
-  if (sockfd < 0)
-    {
-      conn_state = BAD;
-      timeout_val *= 2;
-      sh_error_handle ((-1), FIL__, __LINE__, error_num, 
-		       MSG_E_NET, error_msg, error_call,
-		       _("export"), sh.srvexport.name);
-      SL_RETURN( (-1), _("sh_forward_try_impl"));
-    }
-
-  conn_state = GOOD;
-
-  /*************************
-   *
-   *  initialization
-   * 
-   */
-
-  flag_err = 0;
-  answer   = SH_ALLOC(512);
-  MLOCK(answer, 512);
-
-
-#ifndef USE_SRP_PROTOCOL
-
-  /**************************************************
-   *
-   * --- challenge/response authentication ---
-   *
-   **************************************************/
-
-  if (initialized == BAD)
-    {
-      theProto = (unsigned char) SH_PROTO_SRP;
-
-      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: entry>\n")));
-
-      (void) sl_strlcpy (answer, sh.host.name, 512);
-
-      flag_err = sh_forward_send (sockfd, (char) theProto, _("SALT"), 
-				  answer,  (unsigned long)sl_strlen(answer));
-
-      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: sent SALT, flag_err = %d>\n"), 
-	    flag_err));
-
-      /* get nonce from server
-       */
-      if (flag_err == 0)
-	{
-	  flag_err = (int) sh_forward_receive (sockfd, (char)theProto, head_u, 
-					       answer,  511);
-	  flag_err = (flag_err < 0) ? flag_err : 0;
-	  TPT(( 0, FIL__, __LINE__, 
-		_("msg=<c/r: rcvt nonce, flag_err = %d>\n"), 
-		flag_err));
-	}
-
-      /* entry point for jump from message forward if session key must
-       * be re-initialized
-       */	 
- initBlock:
-
-      if (0 == check_request (head_u, _("INIT")) && 
-	  flag_err == 0                         &&
-	  sl_strlen(answer) >  KEY_LEN )
-	(void) sl_strlcpy(nounce, &answer[KEY_LEN], KEY_LEN+1);
-      else
-	flag_err = (-1);
-
-      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: rcvt INIT, flag_err = %d>\n"), 
-	    flag_err));
-
-      /* verify random nonce v from server H(v, P)v
-       */
-      sh_passwd (nounce, NULL, NULL, temp);
-      if ( 0 != sl_strncmp(temp, answer, KEY_LEN))
-	flag_err = (-1);
-
-      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: vrfy nonce, flag_err = %d>\n"), 
-	    flag_err));
-
-
-      /* --- Create own nonce. ---
-       */
-      ticks = (UINT32) taus_get ();
-
-      (void) sl_strlcpy(nonce_u, 
-			sh_tiger_hash((char *) &ticks, 
-				      TIGER_DATA, 
-				      (unsigned long)sizeof(UINT32), 
-				      hashbuf, sizeof(hashbuf)),
-			KEY_LEN+1);
-
-      /* --- Form the message H(H(u,v),P)u ---
-       */
-      (void) sl_strlcpy(temp, nonce_u, 2*KEY_LEN+1); 
-      (void) sl_strlcat(temp,  nounce, 2*KEY_LEN+1); 
-      (void) sl_strlcpy(temp, 
-			sh_tiger_hash(temp, 
-				      TIGER_DATA, 
-				      (unsigned long)sl_strlen(temp), 
-				      hashbuf, sizeof(hashbuf)),
-			KEY_LEN+1);
-      sh_passwd (temp, NULL, NULL, foo_M1);
-      (void) sl_strlcpy(temp, foo_M1, 2*KEY_LEN+1);
-      (void) sl_strlcat(temp, nonce_u, 2*KEY_LEN+1);
-
-      /* --- Send it to server. ---
-       */
-      if (flag_err == 0)
-	{
-	  flag_err = (int) sh_forward_send (sockfd, 
-					    (char)(theProto|SH_PROTO_SRP), 
-					    _("PASS"), temp, 
-					    (unsigned long)sl_strlen(temp));
-	  TPT(( 0, FIL__, __LINE__, _("msg=<c/r: sent PASS, flag_err = %d>\n"),
-		flag_err));
-	}
-
-      if (flag_err == 0)
-	{
-	  flag_err = (int)sh_forward_receive (sockfd,
-					      (char)(theProto|SH_PROTO_SRP), 
-					      head_u, answer,  511);  
-	  sh_passwd (nounce, NULL, nonce_u, foo_M1);
-	  (void) sl_strlcpy (skey->session, foo_M1, KEY_LEN+1);
-#ifdef SH_ENCRYPT
-	  err_num = makeKey(&(skey->keyInstE), 
-			    (RIJ_BYTE)DIR_ENCRYPT, 192, skey->session);
-	  if (err_num < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			    _("sh_forward_try_impl: makeKey"));
-
-	  err_num = makeKey(&(skey->keyInstD), 
-			    (RIJ_BYTE)DIR_DECRYPT, 192, skey->session);
-	  if (err_num < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			    _("sh_forward_try_impl: make_key"));
-#endif
-	  initialized = GOOD;
-	}
-
-      if (initialized == BAD)
-	{
-	  timeout_val *= 2;
-	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH);
-	  memset(answer, 0, 512);
-	  MUNLOCK(answer, 512);
-	  SH_FREE(answer);
-	  SL_RETURN( (-1), _("sh_forward_try_impl"));
-	}
-      else
-	{
-	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AUTH);
-	}
-    }    
-
-#else
-
-
-  /* This is the SRP authenticated key exchange protocol.
-   * Produces a session key skey->session.
-   */
-  if (initialized == BAD)
-    {
-      TPT(( 0, FIL__, __LINE__, _("msg=<srp: entry>\n")));
-
-      theProto = SH_PROTO_SRP;
-
-      sl_strlcpy (answer, sh.host.name, 512);
-      flag_err = sh_forward_send    (sockfd, theProto, _("SALT "), 
-				     answer,  sl_strlen(answer)); 
-
-      TPT(( 0, FIL__, __LINE__, _("msg=<srp: sent SALT, flag_err = %d>\n"), 
-	    flag_err));
-
-      if (flag_err == 0)
-	{
-	  flag_err = sh_forward_receive (sockfd, theProto, head_u, 
-					 answer,  511);
-	  flag_err = (flag_err < 0) ? flag_err : 0;
-	  TPT(( 0, FIL__, __LINE__, 
-		_("msg=<srp: rcvt nonce, flag_err = %d>\n"), 
-		flag_err));
-	}
-
-      /* Entry point for jump from message forward if session key must
-       * be re-initialized.
-       */	 
-    initBlock:
-      TPT(( 0, FIL__, __LINE__, _("msg=<srp: INIT>\n")));
-
-      if (flag_err == 0 &&
-	  (0 == check_request (head_u, _("INIT"))))
-	{
-	  if (0 != sh_srp_init())
-	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_EBGN);
-	  else /* if (0 == sh_srp_init()) */
-	    {
-	      TPT(( 0, FIL__, __LINE__, _("msg=<srp: bignum initialized>\n")));
-
-	      sh_srp_x (answer, NULL);  /* x        password      */
-	      sh_srp_make_a ();         /* a        random number */
-	      foo_A = sh_srp_A();       /* g^a                    */
-
-	      TPT(( 0, FIL__, __LINE__, _("msg=<srp: A = %s>\n"), foo_A));
-
-	      if (foo_A == NULL)
-		flag_err = (-1);
-
-	      if (flag_err == 0)
-		flag_err = sh_forward_send    (sockfd, 
-					       (theProto|SH_PROTO_SRP), 
-					       _("PC01"),
-					       foo_A, sl_strlen(foo_A)+1); 
-	      if (flag_err == 0)
-		{
-		  flag_err = sh_forward_receive (sockfd, 
-						 (theProto|SH_PROTO_SRP),
-						 head_u,
-						 answer, 511);
-		  flag_err = (flag_err < 0) ? flag_err : 0;
-		  TPT(( 0, FIL__, __LINE__, _("msg=<srp: B = %s>\n"), answer));
-		  TPT(( 0, FIL__, __LINE__, _("msg=<srp: u = %03o-%03o-%03o-%03o>\n"), head_u[0], head_u[1], head_u[2], head_u[3]));
-		}
-
-	      /*                     u        nounce        */
-	      /*                     B        answer        */
-	      /*                     S = (B-g^x)^(a+ux)     */
-	      
-	      if (flag_err == 0)
-		{ 
-		  if (0 != sh_srp_check_zero (answer))
-		    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_EZERO);
-		  else /* if (0 != sh_srp_check_zero (answer)) */
-		    {
-		      sl_strlcpy(u_real, sh_tiger_hash(head_u, TIGER_DATA, 4, 
-						       hashbuf, sizeof(hashbuf)), 
-				 SH_CHALLENGE_SIZE);
-		      foo_Sc = sh_srp_S_c (u_real, answer);
-
-		      TPT(( 0, FIL__, __LINE__, _("msg=<srp: U = %s>\n"), 
-			    u_real));
-		      TPT(( 0, FIL__, __LINE__, _("msg=<srp:Sc = %s>\n"), 
-			    foo_Sc));
-
-		      /* --- Now send H(A,B,H(Sc)) and check. --- 
-		       */
-		      if (foo_Sc != NULL && 0 == sh_srp_check_zero (foo_Sc))
-			{
-			  sh_srp_M(foo_A, 
-				   answer, 
-				   sh_tiger_hash(foo_Sc, 
-						 TIGER_DATA, 
-						 sl_strlen(foo_Sc), 
-						 hashbuf, sizeof(hashbuf)),
-				   foo_M1, KEY_LEN+1);
-
-
-			  TPT(( 0, FIL__, __LINE__, _("msg=<srp:M1 = %s>\n"), 
-				foo_M1));
-
-			  flag_err = sh_forward_send(sockfd, 
-						     (theProto|SH_PROTO_SRP), 
-						     _("PC02"),
-						     foo_M1, KEY_LEN+1);
-			}
-		      else
-			{
-			  flag_err = (-1);
-			}
-
-		      if (flag_err == 0)
-			{
-			  flag_err =sh_forward_receive(sockfd, 
-						       (theProto|SH_PROTO_SRP),
-						       head_u, 
-						       answer, 511);
-			  flag_err = (flag_err < 0) ? flag_err : 0;
-			  TPT(( 0, FIL__, __LINE__, _("msg=<srp: M = %s>\n"), 
-				answer));
-			}
-
-		      if (flag_err == 0   &&
-			  (0 == check_request (head_u, _("PARP"))))
-			{
-			  /* ------  verify M2 = H(A, M1, K) --------
-			   */
-			  char M_buf[KEY_LEN+1];
-			  M = sh_srp_M (foo_A, foo_M1,
-					sh_tiger_hash(foo_Sc,
-						      TIGER_DATA,
-						      sl_strlen(foo_Sc), 
-						      hashbuf, sizeof(hashbuf)),
-					M_buf, sizeof(M_buf)
-					);
-			  if (M != NULL && 
-			      0 == sl_strncmp (answer, M, KEY_LEN+1))
-			    {
-			      sl_strlcpy (skey->session, 
-					  sh_tiger_hash(foo_Sc, 
-							TIGER_DATA,
-							sl_strlen(foo_Sc), 
-							hashbuf, sizeof(hashbuf)),
-					  KEY_LEN+1);
-			      TPT(( 0, FIL__, __LINE__, 
-				    _("msg=<srp: Key = %s>\n"), 
-				    skey->session));
-
-#ifdef SH_ENCRYPT
-			      err_num = makeKey(&(skey->keyInstE), 
-						DIR_ENCRYPT, 
-						192, skey->session);
-			      if (err_num < 0)
-				sh_error_handle((-1), FIL__, __LINE__, -1, 
-						MSG_E_SUBGEN,
-						errorExplain(err_num, expbuf, sizeof(expbuf)), 
-						_("sh_forward_try_impl: makeKey"));
-			      err_num = makeKey(&(skey->keyInstD), 
-						DIR_DECRYPT, 
-						192, skey->session);
-			      if (err_num < 0)
-				sh_error_handle((-1), FIL__, __LINE__, -1, 
-						MSG_E_SUBGEN,
-						errorExplain(err_num, expbuf, sizeof(expbuf)), 
-						_("sh_forward_try_impl: makeKey"));
-#endif
-			      initialized = GOOD;
-			    }
-			}
-		      if (foo_Sc != NULL)
-			SH_FREE(foo_Sc);
-		    }
-		}
-	      if (foo_A != NULL)
-		SH_FREE(foo_A);
-	      sh_srp_exit();
-	    }
-	}
-
-      if (initialized == BAD)
-	{
-	  timeout_val *= 2;
-	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH);
-	  memset(answer, '\0', 512);
-	  MUNLOCK(answer, 512);
-	  SH_FREE(answer);
-	  SL_RETURN( (-1), _("sh_forward_try_impl"));
-	}
-      else
-	{
-	  if (flag_err_info == SL_TRUE)
-	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AUTH);
-	}
-    }
-
-#endif
-
-  /* no message, just session key negotiated
-   */
-  if (errmsg == NULL)
-    {
-      timeout_val = 1;
-      memset(answer, 0, 512);
-      MUNLOCK(answer, 512);
-      SH_FREE(answer);
-      TPT(( 0, FIL__, __LINE__, _("msg=<No message.>\n")));
-      SL_RETURN( (0), _("sh_forward_try_impl"));
-    }
-  else if (what == (char)SH_PROTO_BIG)
-    {
-      MUNLOCK(answer, 512);
-      SH_FREE (answer);
-      answer   = SH_ALLOC(TRANS_BYTES + 256);
-      MLOCK(answer, TRANS_BYTES + 256);
-      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer.>\n")));
-    }
-
-
-  (void) sl_strlcpy (answer, sh_util_siggen(skey->session,
-					    sh.host.name,
-					    sl_strlen(sh.host.name),
-					    sigbuf, sizeof(sigbuf)), 
-	      KEY_LEN+1);
-  TPT((0, FIL__, __LINE__, _("msg=<host %s>\n"), sh.host.name));
-  TPT((0, FIL__, __LINE__, _("msg=<ckey %s>\n"), skey->session));
-  TPT((0, FIL__, __LINE__, _("msg=<sign %s>\n"), answer));
-
-    
-  (void) sl_strlcat (answer, sh.host.name, 512);
-
-  TPT((0, FIL__, __LINE__, _("msg=<mesg %s>\n"), answer));
-
-  /***********************************************
-   *
-   * send the message
-   *
-   */
-
-  if (what == (char) SH_PROTO_MSG)
-    {
-      theProto = (unsigned char)SH_PROTO_MSG;
-
-      /* say HELO       
-       */
-
-      flag_err = sh_forward_send    (sockfd, 
-				     (char)theProto, _("HELO"),
-				     answer, 
-				     (unsigned long)sl_strlen(answer)); 
-      TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s, status %d.>\n"), 
-	    answer, flag_err));
-      if (flag_err == 0)
-	{ 
-	  /* --- Get challenge. ---  
-	   */
-	  flag_err = (int) sh_forward_receive (sockfd, 
-					       (char)SH_PROTO_MSG, head_u, 
-					       answer, 255);   
-	  TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s, u %s, status %d.>\n"), 
-	    answer, hu_trans(head_u), flag_err));
-	  flag_err = (flag_err < 0) ? flag_err : 0;
-	  
-	  if (flag_err == 0)
-	    {
-	      
-	      /* --- Re-negotiate key. ---
-	       */
-	      if (0 == check_request_nerr(head_u, _("INIT")))
-		{
-		  flag_err    = 0;
-		  initialized = BAD;
-		  goto initBlock;
-		}
-	      
-	      else if (0 == check_request(head_u, _("TALK")))
-		{
-
-		  /* --- Save the challenge. ---  
-		   */
-		  (void) sl_strlcpy(nsrv, answer, KEY_LEN + 1);
-		  
-		  /* --- Hash(msg,challenge,sessionkey). ---  
-		   */
-		  len    = sl_strlen(errmsg) + sl_strlen(answer) 
-		    + KEY_LEN + 1;
-		  len = (size_t)((len < 256) ? 256 : len);
-		  buffer = SH_ALLOC(len);
-		  MLOCK(buffer, len);
-		  (void) sl_strlcpy(buffer, errmsg, len);
-		  (void) sl_strlcat(buffer, answer, len);
-		  (void) sl_strlcpy(hash, 
-				    sh_util_siggen (skey->session, 
-						    buffer, 
-						    sl_strlen(buffer),
-						    sigbuf, sizeof(sigbuf)), 
-				    KEY_LEN+1);
-		  TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
-		       sh_util_siggen(skey->session, buffer, 
-				      sl_strlen(buffer), sigbuf, sizeof(sigbuf))));  		      
-
-		  (void) sl_strlcpy(buffer, errmsg, len);
-		  (void) sl_strlcat(buffer, hash,   len);
-
-		  flag_err = 
-		    sh_forward_send_crypt (sockfd, 
-#ifdef SH_ENCRYPT
-#ifdef SH_ENCRYPT_2
-					   (char)(SH_PROTO_MSG|SH_PROTO_ENC|SH_PROTO_EN2),
-#else
-					   (char)(SH_PROTO_MSG|SH_PROTO_ENC),
-#endif
-#else
-					   (char)(SH_PROTO_MSG),
-#endif
-					   _("MESG"),
-					   buffer, 
-					   (unsigned long)(sl_strlen(buffer)+1));
-		  TPT(( 0, FIL__, __LINE__, 
-			_("msg=<Sent %s, status %d.>\n"), 
-			answer, flag_err));
-
-		  /* --- Get confirmation. ---
-		   */
-		  if (flag_err == 0)
-		    {
-		      flag_err = (int)
-			sh_forward_receive_crypt (sockfd, 
-#ifdef SH_ENCRYPT
-#ifdef SH_ENCRYPT_2
-						  (char)(SH_PROTO_MSG|SH_PROTO_ENC|SH_PROTO_EN2|SH_PROTO_END),
-#else
-						  (char)(SH_PROTO_MSG|SH_PROTO_ENC|SH_PROTO_END),
-#endif
-#else
-						  (char)(SH_PROTO_MSG|SH_PROTO_END),
-#endif
-						  head_u, 
-						  answer, 255);   
-		      TPT(( 0, FIL__, __LINE__, 
-			    _("msg=<Rcvt %s, u %s, status %d.>\n"), 
-			    answer, hu_trans(head_u), flag_err));
-		      flag_err = (flag_err < 0) ? flag_err : 0;
-		    }
-
-
-		  /* --- Check confirmation. ---
-		   */
-		  if (flag_err == 0)
-		    {
-		      /*   CLIENT CONF RECV
-		       * 
-		       *   first KEY_LEN bytes must be
-		       *   sig(skey->session (errmsg nsrv))
-		       *
-		       */
-		      (void) sl_strlcpy(buffer, errmsg, len);
-		      (void) sl_strlcat(buffer, nsrv,   len);
-		      flag_err = sl_strncmp(answer,
-					    sh_util_siggen(skey->session, 
-							   buffer,
-							   sl_strlen(buffer),
-							   sigbuf, sizeof(sigbuf)),
-					    KEY_LEN);
-		      TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
-			   sh_util_siggen(skey->session, buffer, 
-					  sl_strlen(buffer), sigbuf, sizeof(sigbuf))));
-
-		      if (flag_err != 0)
-			{
-#ifdef ENOMSG
-			  flag_err = ENOMSG;
-#else
-			  flag_err = EIO;
-#endif
-			  sh_error_handle((-1), FIL__, __LINE__, flag_err,
-					  MSG_TCP_NOCONF);
-			}
-		      else
-			{
-#ifdef SH_ENCRYPT_2
-			  /* --- SERVER CMD --- */
-			  if (answer[KEY_LEN] != '\0' && 
-			      sl_strlen(answer) > (2*KEY_LEN))
-			    {
-			      pos = sl_strlen(answer) - (2*KEY_LEN);
-			      /*
-			       * buffer is  >= 256
-			       * answer has <= 255 bytes
-			       */
-			      (void) sl_strlcpy(buffer, &answer[KEY_LEN], 
-						pos+1);
-			      flag_err = 
-				sl_strncmp(&answer[KEY_LEN+pos],
-					   sh_util_siggen(skey->session, 
-							  buffer,
-							  pos,
-							  sigbuf, sizeof(sigbuf)),
-					   KEY_LEN);
-			      
-			      TPT((0, FIL__, __LINE__, 
-				   _("CONF RECV <%d> <%s>\n"),
-				   flag_err, &answer[KEY_LEN]));
-			      
-			      if (flag_err != 0) {
-				sh_error_handle((-1), FIL__, __LINE__, 
-						flag_err,
-						MSG_TCP_NOCONF);
-			      } 
-#ifdef SH_WITH_CLIENT
-			      else {
-				sh_socket_server_cmd(buffer);
-			      }
-#endif
-			      flag_err = 0;
-
-			    } else {
-			      
-			      TPT((0, FIL__, __LINE__, 
-				   _("CONF RECV <0> <[null]>\n")));
-			      
-			    }
-			  /* --- SERVER CMD END --- */
-#endif
-			  if (flag_err_debug == SL_TRUE)
-			    sh_error_handle((-1), FIL__, __LINE__, 0,
-					    MSG_TCP_CONF);
-			}
-		    }
-
-		  memset(buffer, 0, len);
-		  MUNLOCK(buffer, len);
-		  SH_FREE(buffer);
-		}
-	      else
-		{
-		  /* --- Unexpected reply from server. ---
-		   */
-		  sh_error_handle((-1), FIL__, __LINE__, 0,
-				  MSG_TCP_UNEXP);
-		  flag_err = (-1);
-		}
-	    }
-	}
-    }
-
-
-  else if (what == (char)SH_PROTO_BIG)
-    {
-      theProto = (unsigned char) SH_PROTO_BIG;
-
-      /* --- Say HELO  ---       
-       */
-      flag_err = sh_forward_send    (sockfd, (char) theProto, _("HELO"),
-				     answer, (unsigned long)sl_strlen(answer));
-      TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s, status %d.>\n"), 
-	    answer, flag_err));
-
-      if (flag_err == 0)
-	{ 
-	  /* --- Get NSRV. ---  
-	   */
-	  flag_err = (int) sh_forward_receive (sockfd, 
-					       (char)SH_PROTO_BIG, head_u, 
-					       answer, 255);
-	  TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s, u %s, status %d.>\n"), 
-	    answer, hu_trans(head_u), flag_err));
-	  flag_err = (flag_err < 0) ? flag_err : 0;
-	}   
-
-      if (flag_err == 0)
-	{
-	  
-	  /* --- Re-negotiate key. ---
-	   */
-	  if (0 == check_request_nerr(head_u, _("INIT")))
-	    {
-	      flag_err    = 0;
-	      initialized = BAD;
-	      goto initBlock;
-	    }
-	  
- 
-	  else if (0 == check_request(head_u, _("NSRV")))
-	    {
-#ifdef SH_ENCRYPT
-	      /* --- Set encryption flag. ---
-	       */
-#ifdef SH_ENCRYPT_2
-	      theProto = 
-		(unsigned char)(SH_PROTO_BIG | SH_PROTO_ENC | SH_PROTO_EN2);
-#else
-	      theProto = (unsigned char)(SH_PROTO_BIG | SH_PROTO_ENC);
-#endif
-#endif
-
-	      (void) sl_strlcpy(nsrv, answer, KEY_LEN+1);
-	      
-	      /* --- Generate a nonce. ---
-	       */
-	      ticks = (UINT32) taus_get ();
-              
-	      (void) sl_strlcpy(nclt, 
-				sh_tiger_hash((char *) &ticks, 
-					      TIGER_DATA, 
-					      (unsigned long)sizeof(UINT32), 
-					      hashbuf, sizeof(hashbuf)),
-				KEY_LEN+1);
-
-	      /* --- Compute H(nsrv, nclt, skey). ---
-	       */
-	      buffer = sh_util_strconcat (nsrv, nclt, 
-					  skey->session, NULL);
-	      (void)sl_strlcpy(foo_M1, 
-			       sh_tiger_hash(buffer, TIGER_DATA,
-					     (unsigned long)sl_strlen(buffer), 
-					     hashbuf, sizeof(hashbuf)),
-			       KEY_LEN+1);
-	      memset (buffer, 0, sl_strlen(buffer));
-
-	      /* --- Send (nclt, msg) ---
-	       */
-	      (void) sl_strlcpy(buffer, nclt, KEY_LEN+1);
-	      (void) sl_strlcat(buffer, errmsg, KEY_LEN+5);
-
-#ifndef SH_ENCRYPT
-	      buffer[KEY_LEN+4] = theProto;
-	      buffer[KEY_LEN+5] = '\0';
-	      sh_tools_hash_add(foo_M1, buffer, KEY_LEN+5);
-#endif
-
-	      flag_err = 
-		sh_forward_send_crypt (sockfd, (char) theProto, _("NCLT"),
-				       buffer, 
-				       (unsigned long) sl_strlen(buffer));
- 
-	      TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s, status %d.>\n"), 
-		    buffer, flag_err));
-	      SH_FREE (buffer);
-	    }   
-	}
-
-      if (flag_err == 0)
-	{
-	  /* --- Receive the file. ---
-	   */
-
-          /* --- Open a temporary file. ---
-           */
-	  
-          if ( (sfd = open_tmp ()) < 0)
-	    {
-	      flag_err = (-1);
-	      sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_EFIL);
-	    }
-	  else
-	    {
-	      /* --- Read from socket into tmp file. ---
-	       */
-	      transfercount = 0;
-	      /* flag_err      = 0; *//* never read */
-
-	      do {
-		flag_err = (int)
-		  sh_forward_receive_crypt (sockfd, 
-#ifdef SH_ENCRYPT
-#ifdef SH_ENCRYPT_2
-					    (char)(SH_PROTO_BIG|SH_PROTO_EN2|SH_PROTO_ENC),
-#else
-					    (char)(SH_PROTO_BIG|SH_PROTO_ENC),
-#endif
-#else
-					    (char)(SH_PROTO_BIG),
-#endif
-					    head_u, 
-					    answer, 
-					    TRANS_BYTES + 255);
-
-		TPT(( 0, FIL__, __LINE__, 
-		      _("msg=<Received: %d bytes, marked %s.>\n"),
-		      flag_err, hu_trans(head_u)));
-
-		if (flag_err > 0 && 0 == check_request_nerr(head_u, _("FILE")))
-		  {
-		    if (0 == hash_check (foo_M1, answer, flag_err))
-		      {
-			(void) sl_write(sfd, &answer[KEY_LEN], 
-					flag_err-KEY_LEN);
-			++transfercount;
-			/***
-			 ***  --- Delay for throughput throttling ---
-			 ***/
-			if (sh_throttle_delay > 0)
-			  retry_msleep(sh_throttle_delay/1000, sh_throttle_delay % 1000);
-			/***
-			 ***  --- End delay                       ---
-			 ***/
-			flag_err = 
-			  sh_forward_send_crypt (sockfd, (char) theProto, 
-						 _("RECV"),
-						 nclt, 
-						 (unsigned long)sl_strlen(nclt));
-
-		      }
-		    else
-		      {
-			TPT(( 0, FIL__, __LINE__, 
-			      _("msg=<File transfer: Hash check failed.>\n")));
-			break;
-		      }
-		  }
-		else
-		  {
-		    TPT(( 0, FIL__, __LINE__, 
-			  _("msg=<File transfer: No more data.>\n")));
-		    break;
-		  }
-	      } while (transfercount < 32000); /* 64 Mbyte */
-		    
-	      if (0 == check_request_nerr(head_u, _("EEOT")) &&
-		  0 <  flag_err                             &&
-		  0 == hash_check (foo_M1, answer, (int)sl_strlen(answer)))
-		{
-		  flag_err = 
-		    sh_forward_send_crypt (sockfd, (char) theProto, 
-					   _("EOTE"),
-					   nclt, 
-					   (unsigned int) sl_strlen(nclt));
-
-		  (void) rewind_tmp (sfd);
-		  (void) sl_sync(sfd);
-		  if (flag_err_info == SL_TRUE)
-		    sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_FOK);
-		}
-	      else
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD);
-		  (void) sl_close (sfd);
-		  sfd = (-1);
-		}
-
-	      (void) sl_close_fd (FIL__, __LINE__, sockfd);
-	      memset(answer, 0, TRANS_BYTES + 256);
-	      MUNLOCK(answer, TRANS_BYTES + 256);
-	      SH_FREE(answer);
-	      timeout_val = 1;
-
-	      SL_RETURN( (sfd), _("sh_forward_try_impl"));
-	    }
-	}
-
-      (void) sl_close_fd (FIL__, __LINE__, sockfd);
-      memset(answer, 0, TRANS_BYTES + 256);
-      MUNLOCK(answer, TRANS_BYTES + 256);
-      SH_FREE(answer);
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD);
-      timeout_val *= 2;
-
-      SL_RETURN( (-1), _("sh_forward_try_impl"));
-    }
-		  
-      
- 
-  (void) sl_close_fd (FIL__, __LINE__, sockfd);
-  memset(answer, 0, 512);
-  MUNLOCK(answer, 512);
-  SH_FREE(answer);
-
-#ifndef EIO
-#define EIO 5
-#endif
-  
-
-#ifdef SH_ERROR_H  
-  if (flag_err != 0)
-    {
-      char errbuf[SH_ERRBUF_SIZE];
-      conn_state = BAD;
-      timeout_val *= 2;
-      if (flag_err < 0 || NULL == sh_error_message(flag_err, errbuf, sizeof(errbuf)))
-	flag_err = EIO;
-      sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_ECONN,
-		      sh_error_message(flag_err, errbuf, sizeof(errbuf)));
-      SL_RETURN( (-1), _("sh_forward_try_impl"));
-    }
-#endif
-  timeout_val = 1;
-
-  SL_RETURN( (0), _("sh_forward_try_impl"));
-}
-
-/* #ifdef SH_WITH_CLIENT */
-#endif
-
-
-#if defined (SH_WITH_SERVER)
-
-#ifndef USE_SRP_PROTOCOL
-
-int sh_forward_make_client (const char * str)
-{
-  /* char *          safer; */
-  char            key[KEY_LEN+1];
-  unsigned char   in[PW_LEN+1];
-  int    i = 0, j, k, l = 0;
-  char hashbuf[KEYBUF_SIZE];
-  
-  if (sl_strlen(str) != (PW_LEN * 2)) 
-    {
-      fprintf(stderr, 
-	      _("Input must be a %d digit hexadecimal number"\
-		" (only 0-9, a-f, A-F allowed in input)\n"),
-	      (PW_LEN * 2));
-      _exit(EXIT_FAILURE);
-    }
-  
-  while (i < (PW_LEN * 2))
-    {
-      k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); 
-      if (k != -1 && j != -1) 
-        {
-          in[l] = (k * 16 + j);
-          ++l; i+= 2;
-        }
-      else
-        {
-          fprintf(stderr, _("Invalid char %c\n"), str[i]);
-          _exit(EXIT_FAILURE);
-        }
-    }
-  in[PW_LEN] = '\0';
-
-  sl_strlcpy ((char *)key, 
-	      sh_tiger_hash ((char*)in, TIGER_DATA, PW_LEN, 
-			     hashbuf, sizeof(hashbuf)), 
-	      KEY_LEN+1);
-  key[KEY_LEN] = '\0';
-  
-  fprintf(stdout, _("Client entry: Client=HOSTNAME@00000000@%s\n"), 
-	  key);
-  fflush(stdout);
-
-  _exit(EXIT_SUCCESS);
-  return 0;
-}
-
-#else
-
-int sh_forward_make_client (const char * str)
-{
-  char * foo_v;
-
-  char   salt[17];
-  char   key[KEY_LEN+1];
-  char   in[PW_LEN];
-  int    i = 0, j, k, l = 0;
-  char hashbuf[KEYBUF_SIZE];
-  
-  if (sl_strlen(str) != (PW_LEN*2)) 
-    {
-      fprintf(stderr, 
-	      _("Input must be a %d digit hexadecimal number"\
-		" (only 0-9, a-f, A-F allowed in input)\n"),
-	      (PW_LEN*2));
-      _exit(EXIT_FAILURE);
-    }
-
-    while (i < (PW_LEN*2))
-      {
-        k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); 
-        if (k != -1 && j != -1) 
-          {
-            in[l] = (k * 16 + j);
-            ++l; i+= 2;
-          }
-        else
-          {
-            fprintf(stderr, _("Invalid char %c\n"), str[i]);
-            _exit(EXIT_FAILURE);
-          }
-      }
-    
-  
-    if (0 == sh_srp_init())
-      {
-	sh_util_keyinit(key, KEY_LEN);
-	sl_strlcpy(salt, sh_tiger_hash(key, TIGER_DATA, KEY_LEN, 
-				       hashbuf, sizeof(hashbuf)), 
-		   17); 
-	sh_srp_x (salt, in);
-	foo_v  = sh_srp_verifier ();
-	fprintf(stdout, _("Client=HOSTNAME@%s@%s\n"), 
-		salt, foo_v);
-	fflush(stdout);
-	SH_FREE(foo_v);
-	sh_srp_exit();
-	_exit(EXIT_SUCCESS);
-      }
-    fprintf(stdout, "%s",_("ERROR initializing BigNum library.\n"));
-    fflush (stdout);
-    _exit(EXIT_FAILURE);
-    return -1;
-}
-#endif
-
-
-int sh_forward_create_password (const char * dummy)
-{
-  UINT32   val[2]; 
-  char     output[KEY_LEN+1];
-  char hashbuf[KEYBUF_SIZE];
-
-  val[0] = taus_get ();
-  val[1] = taus_get ();
-
-  sl_strlcpy (output, 
-	      sh_tiger_hash((char *)(&val[0]), TIGER_DATA, 2*sizeof(UINT32),
-			    hashbuf, sizeof(hashbuf)),
-	      KEY_LEN);
-
-  output[16] = '\0';
-
-  fprintf(stdout, _("%s\n"), output);
-  fflush (stdout);
-
-  if (dummy)
-    _exit(EXIT_SUCCESS);
-  else
-    _exit(EXIT_SUCCESS);  
-  return (0);  /* avoid compiler warning */
-}
-
-/* #if defined (SH_WITH_SERVER) */
-#endif
-
-/**************************************************
- *
- *
- *  S E R V E R   
- *
- *
- ***************************************************/
-
-#ifdef SH_WITH_SERVER
-
-#include "sh_readconf.h"
-
-
-#define CONN_FREE    0
-#define CONN_READING 1
-#define CONN_SENDING 2
-#define CONN_PAUSE   3
-#define CONN_BUSY    4
-
-char * clt_stat[] = {
-  N_("Inactive"),
-  N_("Started"),
-  N_("ILLEGAL"),
-  N_("FAILED"),
-  N_("Exited"),
-  N_("PANIC"),
-  N_("POLICY"),
-  N_("File_transfer"),
-  N_("Message"),
-  N_("TIMEOUT_EXCEEDED"),
-  N_("Suspended"),
-  N_("Filecheck"),
-};
-
-#include <time.h>
-
-/* in sh_html.h:
- *  typedef struct client_entry {
- *  } client_t;
- */
-
-#include "zAVLTree.h"
-
-static char * sh_tolower (char * s)
-{
-  char * ret = s;
-  if (s)
-    {
-      for (; *s; ++s)
-	{ 
-	  *s = tolower((unsigned char) *s);
-	}
-    }
-  return ret;
-}
-
-/* Function to return the key for indexing
- * the argument 
- */
-zAVLKey sh_avl_key (void const * arg)
-{
-  const client_t * sa = (const client_t *) arg;
-  return (zAVLKey) sa->hostname;
-}
-
-zAVLTree * all_clients = NULL;
-
-void sh_forward_html_write()
-{
-  SL_ENTER(_("sh_forward_html_write"));
-  sh_html_write(all_clients);
-  SL_RET0(_("sh_forward_html_write"));
-}
-
-
-int sh_forward_use_clt_class (const char * c)
-{
-  int i;
-  SL_ENTER(_("sh_forward_use_clt_class"));
-  i = sh_util_flagval(c, &(sh.flag.client_class));
-  SL_RETURN(i, _("sh_forward_use_clt_class"));
-}
-
-int sh_forward_use_clt_sev (const char * c)
-{
-  int i;
-  SL_ENTER(_("sh_forward_use_clt_sev"));
-  i = sh_util_flagval(c, &(sh.flag.client_severity));
-  SL_RETURN(i, _("sh_forward_use_clt_sev"));  
-}
-
-
-/* the destructor
- */
-void free_client(void * inptr)
-{
-  client_t * here;
-
-  SL_ENTER(_("free_client"));
-  if (inptr == NULL)
-    SL_RET0(_("free_client"));
-  else
-    here = (client_t *) inptr;
-
-  if (here->hostname != NULL)
-    SH_FREE(here->hostname);
-  if (here->salt != NULL)
-    SH_FREE(here->salt);
-  if (here->verifier != NULL)
-    SH_FREE(here->verifier);
-  SH_FREE(here);
-  SL_RET0(_("free_client"));
-}
-
-
-int sh_forward_register_client (const char * str)
-{
-  client_t   * newclt;
-  client_t   * testclt;
-
-  const char * ptr;
-  int          sepnum = 0;
-  int          sep[2];
-  register int i = 0;
-  int          siz_str = 0;
-
-  SL_ENTER(_("sh_forward_register_client"));
-
-  ptr = str; 
-  while (*ptr) {
-    if (*ptr == '@' && sepnum < 2 ) 
-      { 
-	sep[sepnum] = i;
-	++sepnum;
-      } 
-    ++ptr; ++i; 
-  }
-
-  if (all_clients == NULL)
-    {
-      all_clients = zAVLAllocTree (sh_avl_key, zAVL_KEY_STRING);
-      if (all_clients == NULL) 
-	{
-	  (void) safe_logger (0, 0, NULL);
-	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-	}
-    }
-  
-  if ((sepnum == 2) && (sep[0] > 0) && (sep[1] > sep[0]))
-    {
-      newclt = SH_ALLOC (sizeof(client_t));
-      newclt->hostname = SH_ALLOC (sep[0]+1);
-      newclt->salt     = SH_ALLOC (sep[1]-sep[0]);
-      newclt->verifier = SH_ALLOC (sl_strlen(str)-sep[1]+1);
-      newclt->exit_flag         = 0;
-      newclt->dead_flag         = 0;
-#ifdef SH_ENCRYPT
-#ifdef SH_ENCRYPT_2
-      newclt->encf_flag         = SH_PROTO_ENC|SH_PROTO_EN2;
-      newclt->ency_flag         = SH_PROTO_ENC|SH_PROTO_EN2;
-#else
-      newclt->encf_flag         = SH_PROTO_ENC;
-      newclt->ency_flag         = SH_PROTO_ENC;
-#endif
-#else
-      newclt->encf_flag         = 0;
-      newclt->ency_flag         = 0;
-#endif
-      newclt->session_key[0]    = '\0';
-      newclt->last_connect      = (time_t) 0;
-      newclt->session_key_timer = (time_t) 0;
-      newclt->status_now        = CLT_INACTIVE;
-      for (i = 0; i < CLT_MAX; ++i) 
-	newclt->status_arr[i] = CLT_INACTIVE;
-      (void) sh_unix_time(0, newclt->timestamp[CLT_INACTIVE], TIM_MAX);
-
-      /* truncate */
-      sl_strlcpy(newclt->hostname,  &str[0],        sep[0]+1);
-      sh_tolower(newclt->hostname);
-
-      /* truncate */
-      sl_strlcpy(newclt->salt,      &str[sep[0]+1], sep[1]-sep[0]);
-      sl_strlcpy(newclt->verifier,  &str[sep[1]+1], sl_strlen(str)-sep[1]+1);
-
-      testclt = (client_t *) zAVLSearch (all_clients, newclt->hostname);
-
-      if (testclt != NULL)
-	{
-	  SH_FREE(testclt->verifier);
-	  siz_str = strlen (newclt->verifier) + 1;
-	  testclt->verifier = SH_ALLOC (siz_str);
-	  sl_strlcpy(testclt->verifier, newclt->verifier, siz_str);
-
-	  SH_FREE(testclt->salt);
-	  siz_str = strlen (newclt->salt) + 1;
-	  testclt->salt = SH_ALLOC (siz_str);
-	  sl_strlcpy(testclt->salt, newclt->salt, siz_str);
-
-	  testclt->dead_flag = 0;
-	      
-	  free_client(newclt);
-	  SL_RETURN( 0, _("sh_forward_register_client"));
-	}
-      else
-	{
-	  if (0 == zAVLInsert (all_clients, newclt))
-	    {
-	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CREG,
-			      newclt->hostname, 
-			      newclt->salt, newclt->verifier);
-	      SL_RETURN( 0, _("sh_forward_register_client"));
-	    }
-	}
-    }
-  SL_RETURN (-1, _("sh_forward_register_client"));
-}
-
-typedef struct {
-  int             state;
-  int             fd;
-  char          * buf;
-  unsigned char   head[SH_HEADER_SIZE];
-  char            challenge[SH_CHALLENGE_SIZE];
-  char            peer[SH_MINIBUF+1];
-  client_t      * client_entry;
-  char          * K;
-  char          * M1;
-  char          * A;
-  int             headcount;
-  unsigned long   bytecount;
-  unsigned long   bytes_to_send;
-  unsigned long   bytes_to_get;
-  int             pass;
-  unsigned long   timer;
-
-  char          * FileName;
-  unsigned long   FileLength;
-  unsigned long   FileSent;
-  char            FileType[5];
-
-  struct sh_sockaddr addr_peer;
-} sh_conn_t;
-
-
-static char zap_challenge[SH_CHALLENGE_SIZE] = { 0 };
- 
-void sh_forward_do_free (sh_conn_t * conn)
-{
-  SL_ENTER(_("sh_forward_do_free"));
-
-  if (conn->K != NULL) 
-    {
-      SH_FREE(conn->K);
-      conn->K           = NULL;
-    }
-  if (conn->A != NULL) 
-    {
-      SH_FREE(conn->A);
-      conn->A           = NULL;
-    }
-  if (conn->M1 != NULL) 
-    {
-      SH_FREE(conn->M1);
-      conn->M1           = NULL;
-    }
-  if (conn->buf != NULL) 
-    {
-      SH_FREE(conn->buf);
-      conn->buf          = NULL;
-    }
-  if (conn->fd != (-1))
-    {
-      sl_close_fd (FIL__, __LINE__, conn->fd);
-      conn->fd            = -1;
-    }
-  memcpy(conn->challenge, zap_challenge, SH_CHALLENGE_SIZE);
-  conn->state         = CONN_FREE;
-  conn->headcount     = 0;
-  conn->bytecount     = 0;
-  conn->bytes_to_send = 0;
-  conn->bytes_to_get  = 0;
-  conn->pass          = 0;
-  conn->timer         = 0;
-  conn->client_entry  = NULL;
-
-  if (conn->FileName != NULL) 
-    {
-      SH_FREE(conn->FileName);
-      conn->FileName     = NULL;
-    }
-  conn->FileLength     = 0;
-  conn->FileSent       = 0;
-  conn->FileType[0] = '\0';
-  conn->FileType[1] = '\0';
-  conn->FileType[2] = '\0';
-  conn->FileType[3] = '\0';
-  conn->FileType[4] = '\0';
-
-  --server_status.conn_open;
-  
-  SL_RET0(_("sh_forward_do_free"));
-}
-
-/****************************************
- *
- *   -- Reconfiguration. --
- *
- *   (1) Mark all clients as 'dead'.
- *   (2) Reload configuration - clients
- *       in config are non-dead now.
- *   (3) Remove all clients still
- *       marked as 'dead'.
- */
-
-/* -- Mark all clients as dead.
- */
-void sh_forward_mark_dead (void)
-{
-  zAVLCursor avlcursor;
-  client_t * item;
-
-  SL_ENTER(_("sh_forward_mark_dead"));
-
-  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
-       item = (client_t *) zAVLNext(&avlcursor))
-    {
-      item->dead_flag = 1;
-    }
-  SL_RET0(_("sh_forward_mark_dead"));
-}
-
-
-/* -- Clean tree from dead clients.
- */
-void sh_forward_clean_tree (void)
-{
-  zAVLCursor avlcursor;
-  client_t * item;
-
-  SL_ENTER(_("sh_forward_clean_tree"));
-
- repeat_search:
-
-  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
-       item = (client_t *) zAVLNext(&avlcursor))
-    {
-      if (item->dead_flag == 1)
-	{
-	  zAVLDelete (all_clients, item->hostname);
-	  free_client (item);
-	  goto repeat_search;
-	}
-    }
-  SL_RET0(_("sh_forward_clean_tree"));
-}
-
-/*
- *
- **********************************************/
-
-
-
-/* -- SERVER SEND FUNKTION. --
- */
-void sh_forward_prep_send_int (sh_conn_t * conn, 
-			       char * msg, unsigned long length,
-			       char * u, char protocol,
-			       int docrypt)
-{
-  /* register unsigned long i; */
-  unsigned long           length2;
-
-#ifdef SH_ENCRYPT
-  unsigned long           blkfac = 0;
-  int                     rem = 0;
-  char                  * p, * q;
-  RIJ_BYTE                    inBlock[B_SIZ]; 
-  RIJ_BYTE                    outBlock[B_SIZ];
-  unsigned int            j;
-  cipherInstance          cipherInst;
-  int                     err_num;
-  char expbuf[SH_ERRBUF_SIZE];
-#else
-  (void) docrypt;
-#endif
-
-  SL_ENTER(_("sh_forward_prep_send_int"));
-
-  TPT((0, FIL__, __LINE__, _("msg=<%s>, docrypt=<%d>\n"), msg, docrypt ));
-
-#ifdef SH_ENCRYPT
-  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_EN2) != 0) )
-    {
-      length2 = length;
-    }
-  else if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0) )
-    {
-      blkfac  = length/B_SIZ;
-      rem     = length - (B_SIZ * blkfac);
-      length2 = (B_SIZ * blkfac);
-      if (rem > 0 && (length2 + B_SIZ) > length2) 
-	length2 += B_SIZ;
-      else
-	rem = 0;
-    }
-  else
-    {
-      length2 = length;
-    }
-#else
-  length2 = length;
-#endif
-
-  conn->headcount     = 0;
-  conn->bytecount     = 0;
-  conn->bytes_to_send = 0;
-  conn->bytes_to_get  = 0;
-
-  if (conn->buf != NULL) 
-    {
-      SH_FREE(conn->buf);
-      conn->buf           = NULL;
-    }
-
-
-  put_header (conn->head, protocol, &length2, u);
-  SH_SHOWPROT(conn->head,'>');
-
-  TPT((0, FIL__, __LINE__, _("msg=<put_header done>\n") ));
-
-  if (msg == NULL) 
-    length2 = 0;
-  
-#ifdef SH_ENCRYPT
-  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_EN2) != 0))
-    {
-      TPT((0, FIL__, __LINE__, _("encrypting (version 2)\n")));
-      
-      conn->buf = sh_tools_makePack (conn->head, msg, length2,
-				     &(conn->client_entry->keyInstE));
-    }
-  else if (msg == NULL)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-		      _("msg is NULL"), 
-		      _("sh_forward_prep_send_int: cipherInit"));
-    }
-  else if ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0) &&
-	   ((length2 + 1) > length2))
-    {
-      conn->buf       = SH_ALLOC(length2 + 1);
-
-      p       = msg;
-      q       = conn->buf;
-
-      TPT((0, FIL__, __LINE__, _("encrypting (version 1)\n")));
-
-      err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
-      if (err_num < 0)
-	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			_("sh_forward_prep_send_int: cipherInit"));
-
-      for (j = 0; j < blkfac; ++j)
-	{
-	  memcpy(inBlock, p, B_SIZ);
-	  err_num = blockEncrypt(&cipherInst, &(conn->client_entry->keyInstE), 
-		       inBlock, 128 * BNUM, outBlock);
-	  if (err_num < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			    _("sh_forward_prep_send_int: blockEncrypt"));
-	  memcpy(q, outBlock, B_SIZ);
-	  p += B_SIZ;
-	  q += B_SIZ;
-	}
-      if (rem > 0)
-	{
-	  /* incomplete block at end
-	   */
-	  memset(inBlock, '\0', B_SIZ);
-	  memcpy(inBlock, p, rem);
-	  err_num = blockEncrypt(&cipherInst, &(conn->client_entry->keyInstE), 
-		       inBlock, 128 * BNUM, outBlock);
-	  if (err_num < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			    _("sh_forward_prep_send_int: blockEncrypt"));
-	  memcpy(q, outBlock, B_SIZ);
-	  /* q += B_SIZ; *//* never read */
-	}
-
-      TPT((0, FIL__, __LINE__, _("msg=<encryption done>\n") ));
-    }
-  else
-    {
-      if ((length2 + 1) < length2) --length2;
-      conn->buf       = SH_ALLOC(length2 + 1);
-
-      memcpy(conn->buf, msg, length2);
-      /*
-      for (i = 0; i < length2; ++i) 
-	conn->buf[i] = msg[i];
-      */
-      conn->buf[length2] = '\0';
-      TPT((0, FIL__, __LINE__, _("msg=<no encryption done>\n") ));
-    }
-#else
-  if ((length2 + 1) < length2) --length2;
-  conn->buf       = SH_ALLOC(length2 + 1);
-
-  memcpy(conn->buf, msg, length2);
-  /*
-  for (i = 0; i < length; ++i) 
-    conn->buf[i] = msg[i];
-  */
-  conn->buf[length2] = '\0';
-  TPT((0, FIL__, __LINE__, _("msg=<no encryption done>\n") ));
-#endif
-
-  conn->state     = CONN_SENDING;
-  SL_RET0(_("sh_forward_prep_send_int"));
-}
-
-/* -- Send/Receive. --
- */
-void sh_forward_prep_send (sh_conn_t * conn, 
-			   char * msg, unsigned long length,
-			   char * u, char protocol)
-{
-  SL_ENTER(_("sh_forward_prep_send"));
-  sh_forward_prep_send_int (conn,  msg, length, u, protocol, S_FALSE);
-  SL_RET0(_("sh_forward_prep_send"));
-}  
-
-void sh_forward_prep_send_crypt (sh_conn_t * conn, 
-				 char * msg, unsigned long length,
-				 char * u, char protocol)
-{
-  SL_ENTER(_("sh_forward_prep_send_crypt"));
-  sh_forward_prep_send_int (conn,  msg, length, u, protocol, S_TRUE);
-  SL_RET0(_("sh_forward_prep_send_crypt"));
-}  
-
-/* #include <sys/times.h> */
-
-#if defined(WITH_EXTERNAL)
-#include "sh_extern.h"
-#endif
-
-/* -- Update the client status. --
- *
- * Update the status array for the client,
- * and eventually call external program.
- */
-static void status_update (client_t * conn, int status)
-{ 
-#if defined(WITH_EXTERNAL)
-  char msg[2 * SH_MINIBUF + TIM_MAX + 3];
-#endif
-
-  SL_ENTER(_("status_update"));
-
-  if (conn == NULL || 
-      status < 0   || status >= CLT_MAX)
-    SL_RET0(_("status_update"));
-
-  conn->status_now = status;
-  conn->status_arr[status] = status;
-  (void) sh_unix_time(0, conn->timestamp[status], TIM_MAX);
-
-#if defined(WITH_EXTERNAL)
-  sl_snprintf(msg, sizeof(msg), _("%s %s %s"),
-	      conn->hostname, conn->timestamp[status], _(clt_stat[status]));
-  sh_ext_execute('s', 'r', 'v', msg, 0);
-#endif
-
-  SL_RET0(_("status_update"));
-}
-
-static time_t time_client_limit = 86400;
-
-int sh_forward_set_time_limit (const char * c)
-{
-  long val;
-
-  SL_ENTER(_("sh_forward_set_time_limit"));
-
-  val = strtol (c, (char **)NULL, 10);
-  if (val <= 0)
-    SL_RETURN( (-1), _("sh_forward_set_time_limit"));
-
-  time_client_limit = (time_t) val;
-  SL_RETURN( (0), _("sh_forward_set_time_limit"));
-}
-
-
-/* -- Check for time limit exceeded. --
- */
-static int client_time_check(void)
-{
-  zAVLCursor avlcursor;
-  client_t * item;
-
-  SL_ENTER(_("client_time_check"));
-
-  if (time_client_limit == (time_t) 0)
-    SL_RETURN( 0, _("client_time_check"));
-
-  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
-       item = (client_t *) zAVLNext(&avlcursor))
-    {
-      if (item->exit_flag == 0 && item->last_connect != (time_t) 0)
-	{
-	  if ( (time(NULL) - item->last_connect) > time_client_limit)
-	    {
-	      if (item->status_now != CLT_TOOLONG)
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMEXC,
-				  item->hostname);
-		  status_update (item, CLT_TOOLONG);
-		}
-	    }
-	}
-    }
-  SL_RETURN( 0, _("client_time_check"));
-}
-
-static int lookup_err = SH_ERR_SEVERE;
-
-int sh_forward_lookup_level (const char * c)
-{
-  int ci =  sh_error_convert_level (c);
-
-  SL_ENTER(_("sh_forward_lookup_level"));
-
-  if (ci >= 0)
-    {
-      lookup_err = ci;
-      SL_RETURN( 0, _("sh_forward_lookup_level"));
-    }
-  else
-    SL_RETURN( (-1), _("sh_forward_lookup_level"));
-}
-
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN  127
-#endif
-
-int check_addr (const char * claim, struct sh_sockaddr * addr_peer)
-{
-  char               h_name[MAXHOSTNAMELEN + 1];
-  char               h_peer[MAXHOSTNAMELEN + 1];
-  char               h_peer_IP[SH_IP_BUF];
-  char               tmp_peer_IP[SH_IP_BUF];
-  char             * canonical;
-  char               numeric[SH_IP_BUF];
-
-  SL_ENTER(_("check_addr"));
-
-  if (claim == NULL)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		      _("NULL input"), _("check_addr"));
-      SL_RETURN ((-1), _("check_addr"));
-    }
-
-  /* Make sure we have the canonical name for the client
-   */
-  canonical = sh_ipvx_canonical(claim, numeric, sizeof(numeric));
-
-  /* copy canonical name into h_name
-   */
-  if (canonical != NULL)
-    {
-      sl_strlcpy(h_name, canonical, MAXHOSTNAMELEN + 1);
-      SH_FREE(canonical);
-    }
-  else
-    {
-      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESCLT,
-		      claim);
-      SL_RETURN ((0), _("check_addr"));
-    }
-
-
-  /* get canonical name of socket peer
-   */
-  canonical = sh_ipvx_addrtoname(addr_peer);
-
-  if (canonical)
-    {
-      if (0 == sl_strcmp(canonical, _("localhost")))
-	sl_strlcpy(h_peer, sh.host.name, MAXHOSTNAMELEN + 1);
-      else
-	sl_strlcpy(h_peer, canonical, MAXHOSTNAMELEN + 1);
-      SH_FREE(canonical);
-    }
-  else
-    {
-      sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer);
-      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESPEER,
-		      claim, tmp_peer_IP);
-      SL_RETURN ((0), _("check_addr"));
-    }
-
-  sh_ipvx_ntoa (h_peer_IP, sizeof(h_peer_IP), addr_peer);
-
-#if 0
-  if (S_FALSE == DoReverseLookup)
-    {
-      SL_RETURN ((0), _("check_addr"));
-    }
-#endif
-
-  /* reverse lookup
-   */
-  if (0 == sh_ipvx_reverse_check_ok (h_peer, ServerPort, addr_peer))
-    {
-      sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer);
-
-      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKERS,
-		      claim, h_peer, tmp_peer_IP);
-      SL_RETURN ((0), _("check_addr"));
-    }
-
-  /* Check whether claim and peer are identical
-   */
-
-  sh_tolower(h_peer); /* Canonical name of what the peer is     */
-  sh_tolower(h_name); /* Canonical name of what the peer claims */
-
-  if ((0 == sl_strcmp(h_peer, h_name)) || (0 == sl_strcmp(h_peer_IP, h_name)))
-    {
-      SL_RETURN ((0), _("check_addr"));
-    }
-#if !defined(USE_IPVX)
-  else
-    {
-      struct hostent   * he = sh_gethostbyname(h_peer);
-      int                i = 0;
-      int                flag = 0;
-
-      while (he->h_aliases[i] != NULL)
-	{
-	  if (0 == sl_strcmp(sh_tolower(he->h_aliases[i]), h_name))
-	    {
-	      flag = 1;
-	      break;
-	    }
-	  ++i;
-	}
-      if (flag == 0) 
-	sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKUP,
-			claim, h_peer);
-    }
-#endif
-
-  SL_RETURN ((0), _("check_addr"));
-}
-
-static int UseSocketPeer = S_FALSE;
-
-int set_socket_peer (const char * c)
-{
-  return sh_util_flagval(c, &UseSocketPeer);
-}
-
-
-/* -- Search register. --
- */
-client_t * search_register(sh_conn_t * conn, int pos)
-{
-  client_t * this_client;
-  char       peer_ip[SH_IP_BUF];
-  char       numerical[SH_IP_BUF];
-  char       peer_name[MAXHOSTNAMELEN+1];
-  char     * search_string;
-
-  struct sh_sockaddr peer_addr;
-  char             * canonical;
-
-  SL_ENTER(_("search_register"));
-
-  if (UseSocketPeer == S_TRUE)
-    {
-      memcpy(&peer_addr, &(conn->addr_peer), sizeof(struct sh_sockaddr));
-      sh_ipvx_ntoa (peer_ip, sizeof(peer_ip), &peer_addr);
-
-      /* get canonical name of socket peer
-       */
-      canonical = sh_ipvx_canonical(peer_ip, numerical, sizeof(numerical));
-
-      if (canonical != NULL)
-	{
-	  if (0 == sl_strcmp(canonical, _("localhost")))
-	    sl_strlcpy(peer_name, sh.host.name, MAXHOSTNAMELEN + 1);
-	  else
-	    sl_strlcpy(peer_name, canonical,    MAXHOSTNAMELEN + 1);
-	  SH_FREE(canonical);
-	}
-
-      if (0 == sh_ipvx_reverse_check_ok (peer_name, ServerPort, &peer_addr))
-	{
-	  sl_strlcpy(peer_name, peer_ip, MAXHOSTNAMELEN + 1);
-	}
-
-      search_string = peer_name;
-    }
-  else
-    {
-      search_string = &(conn->buf[pos]);
-
-      if (0 != check_addr (search_string, &(conn->addr_peer)))
-	{
-	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-			  _("Reverse lookup failed"), search_string);
-	  sh_forward_do_free (conn);
-	  SL_RETURN( NULL, _("search_register"));
-	} 
-    }
-
-  sh_tolower(search_string);
-
-  /* ----  search the register  -----
-   */
-  this_client = zAVLSearch(all_clients, search_string);
-
-  if (this_client == NULL)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-		      _("Not in client list"), search_string);
-      sh_forward_do_free (conn);
-      SL_RETURN( NULL, _("search_register"));
-    } 
-  if (this_client->exit_flag == 1)
-    {
-      TPT((0, FIL__, __LINE__, _("msg=<this_client->exit_flag == 1>\n")));
-      this_client->session_key_timer = (time_t) 0;
-      this_client->session_key[0]    = '\0';
-      this_client->exit_flag         = 0;    
-    }
-  TPT((0, FIL__, __LINE__, _("msg=<search_register: client %s>\n"), 
-       this_client->hostname));
-  TPT((0, FIL__, __LINE__, _("msg=<search_register: key %s>\n"), 
-       this_client->session_key));
-  SL_RETURN( this_client, _("search_register"));
-}  
-
-
-/************************************************************************
- *
- * Here we check the message received, and decide on the answer to send
- * (if any). The connection is in CONN_PAUSED state, thus we must:
- * (i)   define the proper reaction
- * (ii)  reset to CONN_READING or CONN_WRITING or CONN_FREE
- * (iii) eventually reset the connection entry
- *
- *************************************************************************/
-static
-void check_protocol(sh_conn_t * conn, int state)
-{
-  client_t * this_client; 
-
-  char     * cmd;
-
-  char       hash[SH_MAXMSGLEN + KEY_LEN + KEY_LEN + 1];
-  char     * buffer;
-
-  int        clt_sev;
-  char     * ptok;
-
-  UINT32     ticks;
-  size_t     len;
-  int        i;
-  char     * test;
-  char       u[5] = "OOOO";
-
-  SL_TICKET  sfd = -1;
-  char     * read_buf = 0;
-  char     * send_buf;
-  int        bytes;
-
-#ifdef SH_ENCRYPT
-  int        blkfac;
-  int        rem;
-  int        send_bytes;
-  int        err_num;
-  char expbuf[SH_ERRBUF_SIZE];
-#endif
-
-
-#ifdef USE_SRP_PROTOCOL
-  char     * foo_B;
-  char     * foo_Ss;
-#endif
-  char hashbuf[KEYBUF_SIZE];
-  char sigbuf[KEYBUF_SIZE];
-
-  SL_ENTER(_("check_protocol"));
-
-  /* seed / re-seed the PRNG if required
-   */
-  (void) taus_seed();
-
-
-  /* protocols: 
-   * -- (iii)    file transfer
-   * -- (ii)     authenticated message transfer
-   * -- (i)      SRP key exchange
-   */
-
-  /* --------- FILE TRANSFER  -----------
-   */
-  if ( (conn->head[0] & SH_PROTO_SRP) == 0  &&
-       (conn->head[0] & SH_PROTO_BIG) != 0  /* is set */ )
-    {
-
-      if (state == SH_DO_READ)        /* finished reading */
-	{
-	  TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - entry.>\n")));
-
-	  /* -- Client requests challenge. --
-	   */
-	  if (0 == check_request_nerr ((char *) &(conn->head[3]), _("HELO")))
-	    {
-
-	      TPT(( 0, FIL__, __LINE__, 
-		    _("msg=<File transfer - HELO (1).>\n")));
-
-	      if (conn->buf == NULL || sl_strlen(conn->buf) <= KEY_LEN)
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-
-	      /* ----  search the register  -----
-	       */
-	      
-	      this_client = search_register (conn, KEY_LEN);
-	      if (this_client == NULL)
-		SL_RET0(_("check_protocol"));
-
-	      /* ---- force authentication -----
-	       */
-
-	      if (this_client->session_key[0] == '\0' ||
-		  (time(NULL) - this_client->session_key_timer) 
-		  > (time_t) TIMEOUT_KEY )
-		{
-		  /* fake an auth request and jump there
-		   */
-		  conn->head[0]  = (conn->head[0] | SH_PROTO_SRP);
-		  conn->head[3]  = 'S';
-		  conn->head[4]  = 'A';
-		  conn->head[5]  = 'L';
-		  conn->head[6]  = 'T';
-		  if (flag_err_info == SL_TRUE)
-		    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FAUTH,
-				    &(conn->buf[KEY_LEN]));
-		  len = sl_strlen(&(conn->buf[KEY_LEN])) + 1;
-		  /* &(conn->buf[KEY_LEN]) is hostname         */
-		  /* may overlap, thus only memmove is correct */
-		  memmove(conn->buf, &(conn->buf[KEY_LEN]), len); 
-		  this_client->session_key[0]    = '\0';
-		  this_client->session_key_timer = (time_t) 1;
-		  goto servInit;
-		}
-
-	      /* --- check whether hostname is properly signed ---
-	       */ 
-	      if (conn->K != NULL) 
-		{
-		  SH_FREE(conn->K);
-		  conn->K = NULL;
-		}
-
-	      /* FIXME
-	      len = sl_strlen(&(conn->buf[KEY_LEN])) + 1;
-	      if (sl_ok_adds(len, KEY_LEN))
-		len += KEY_LEN;
-	      len = (len < (KEY_LEN+1)) ? (KEY_LEN+1) : len;
-	      */
-	      conn->K = SH_ALLOC(KEY_LEN+1);
-
-	      sl_strlcpy (conn->K, 
-			  sh_util_siggen(this_client->session_key,
-					 &(conn->buf[KEY_LEN]),
-					 sl_strlen(&(conn->buf[KEY_LEN])),
-					 sigbuf, sizeof(sigbuf)),
-			  KEY_LEN+1);
-	      TPT((0, FIL__, __LINE__, _("msg=<host %s>\n"),
-		   &(conn->buf[KEY_LEN])));
-	      TPT((0, FIL__, __LINE__, _("msg=<ckey %s>\n"),
-		   this_client->session_key));
-	      TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
-		   sh_util_siggen(this_client->session_key, 
-				  &(conn->buf[KEY_LEN]), 
-				  sl_strlen(&(conn->buf[KEY_LEN])),
-				  sigbuf, sizeof(sigbuf))));
-
-	      if (0 != sl_strncmp(conn->K, conn->buf, KEY_LEN))
-		{
-		  TPT((0, FIL__, __LINE__, _("msg=<clt %s>\n"), conn->buf));
-		  TPT((0, FIL__, __LINE__, _("msg=<srv %s>\n"), conn->K));
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("Signature mismatch"), 
-				  &(conn->buf[KEY_LEN]));
-
-		  this_client->session_key_timer =
-		    time(NULL) - (2*TIMEOUT_KEY);
-
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		}
-	      SH_FREE(conn->K); 
-	      conn->K = NULL;
-
-	      /* --- create and send a nonce ---
-	       */
-	      
-	      conn->client_entry = this_client;
-	      sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1);
-
-	      ticks = (UINT32) taus_get ();
-
-	      if (conn->K != NULL) 
-		{
-		  SH_FREE(conn->K);
-		  conn->K = NULL;
-		}
-	      conn->K = SH_ALLOC(KEY_LEN+1);
-	      sl_strlcpy (conn->K, 
-			  sh_tiger_hash ((char *) &ticks, 
-					 TIGER_DATA, sizeof(UINT32), 
-					 hashbuf, sizeof(hashbuf)), 
-			  KEY_LEN+1);
-
-	      TPT((0, FIL__, __LINE__, _("msg=<send nonce>\n")));
-	      sh_forward_prep_send (conn, conn->K, KEY_LEN+1, _("NSRV"), 
-				    SH_PROTO_BIG);
-	    }
-
-	  /* --- Client has send a message. Check state and message. ---
-	   */
-	  else if (0 == check_request_nerr((char *)&(conn->head[3]), _("NCLT")) &&
-		   conn->client_entry != NULL                           &&
-		   sl_strlen(conn->buf) > KEY_LEN                       &&
-		   conn->K != NULL)
-	    {
-
-	      TPT(( 0, FIL__, __LINE__, 
-		    _("msg=<File transfer - NCLT (3).>\n")));
-
-	      /* --- get client nonce and compute hash ---
-	       */
-	      if (conn->A != NULL)
-		{
-		  SH_FREE(conn->A);
-		  conn->A = NULL;
-		}
-	      conn->A = SH_ALLOC(3*KEY_LEN+1);
-	      sl_strlcpy (conn->A, conn->K, KEY_LEN+1); 
-	      sl_strlcat(conn->A, conn->buf, /* truncate */
-			 2*KEY_LEN+1);
-	      sl_strlcat(conn->A, conn->client_entry->session_key, 
-			 3*KEY_LEN+1);
-	      sl_strlcpy (conn->K, sh_tiger_hash(conn->A,TIGER_DATA,3*KEY_LEN,
-						 hashbuf, sizeof(hashbuf)),
-			  KEY_LEN+1);
-	      SH_FREE(conn->A); 
-	      conn->A = NULL;
-
-
-#ifdef SH_ENCRYPT
-	      if ((conn->client_entry->encf_flag != 0) &&
-		  ((conn->head[0] & SH_PROTO_ENC) == 0)) 
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
-				  _("file download"),
-#ifdef SH_ENCRYPT_2
-				  _("version2"),
-#else
-				  _("version1"),
-#endif
-				  _("none"));
-		  if (sl_strlen(conn->buf) > (KEY_LEN + 5)) {
-		    if (sh_tools_hash_vfy(conn->K, conn->buf, KEY_LEN+5)) {
-		      if (conn->buf[KEY_LEN+4] == conn->head[0]) {
-			/* conn->client_entry->encf_flag = 0 */ ; /* FIXME */
-		      }
-		    }
-		  }
-		}
-	      else if ((conn->client_entry->encf_flag != 0) &&
-		       ((conn->head[0] & SH_MASK_ENC) != 
-			conn->client_entry->encf_flag))
-		{
-		  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, 
-				  MSG_TCP_MISENC,
-				  _("file download"),
-#ifdef SH_ENCRYPT_2
-				  _("version2"),
-#else
-				  _("version1"),
-#endif
-				  ((conn->head[0] & SH_PROTO_EN2) == SH_PROTO_EN2) ? _("version2") : _("version1")
-				  );
-		  conn->client_entry->encf_flag = 
-		    (conn->head[0] & SH_MASK_ENC);
-		}
-#else
-	      if ((conn->head[0] & SH_PROTO_ENC) != 0) 
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, 
-				  MSG_TCP_MISENC,
-				  _("file download"),
-				  _("none"), 
-				  ((conn->head[0] & SH_PROTO_EN2) == SH_PROTO_EN2) ? _("version2") : _("version1"));
-		}
-#endif
-
-
-	      /* ---- K = H(NSRV, NCLT, session_key) -------
-	       */ 
-
-	      if (conn->FileName != NULL)
-		{
-		  SH_FREE(conn->FileName);
-		  conn->FileName = NULL;
-		}
-
-	      if (0 == sl_strncmp (_("CONF"), &(conn->buf[KEY_LEN]), 4))
-		{
-		  strcpy(conn->FileType, _("CONF"));     /* known to fit  */
-		  conn->FileName = get_client_conf_file(conn->peer, 
-							&(conn->FileLength));
-		  conn->FileSent = 0;
-		}
-	      else  if (0 == sl_strncmp (_("DATA"), &(conn->buf[KEY_LEN]), 4))
-		{
-		  strcpy(conn->FileType, _("DATA"));     /* known to fit  */
-		  conn->FileName = get_client_data_file(conn->peer, 
-							&(conn->FileLength));
-		  conn->FileSent = 0;
-		}
-	      else
-		{
-		  ptok = sh_util_safe_name(&(conn->buf[KEY_LEN]));
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FFILE,
-				  conn->peer, 
-				  ptok);
-		  SH_FREE(ptok);
-		  status_update (conn->client_entry, CLT_FAILED);
-		  sh_forward_do_free (conn);
-		}
-
-	      bytes = -1;
-
-	      if (conn != NULL && conn->FileName != NULL)
-		{
-		  sfd = sl_open_read(FIL__, __LINE__, 
-				     conn->FileName, SL_YESPRIV);
-		  if (!SL_ISERROR(sfd))
-		    {
-		      read_buf = SH_ALLOC(TRANS_BYTES);
-		      bytes = sl_read (sfd, read_buf, TRANS_BYTES);
-		      sl_close(sfd);
-		    }
-
-		  else
-		    {
-		      sh_error_handle((-1), FIL__, __LINE__, sfd, 
-				      MSG_E_ACCESS,
-				      (long) geteuid(),
-				      conn->FileName);
-		    }
-		  if (bytes >= 0)
-		    {
-#ifdef SH_ENCRYPT
-		      /* need to send N * B_SIZ bytes
-		       */ 
-		      blkfac = bytes / B_SIZ;
-		      rem    = bytes - (blkfac * B_SIZ);
-		      if (rem != 0)
-			{
-			  memset(&read_buf[bytes], '\n', (B_SIZ-rem));
-			  ++blkfac;
-			  send_bytes = blkfac * B_SIZ;
-			}
-		      else
-			send_bytes = bytes;
-
-		      send_buf = hash_me(conn->K, read_buf, 
-					 send_bytes);
-
-		      sh_forward_prep_send_crypt (conn, send_buf, 
-						  send_bytes+KEY_LEN, 
-						  _("FILE"),  
-						  SH_PROTO_BIG|conn->client_entry->encf_flag);
-#else
-		      send_buf = hash_me(conn->K, read_buf, bytes);
-		      sh_forward_prep_send_crypt (conn, send_buf, 
-						  bytes+KEY_LEN, 
-						  _("FILE"),  SH_PROTO_BIG);
-#endif
-		      conn->FileSent += bytes;
-		      if (send_buf != NULL) 
-			{
-			  SH_FREE(send_buf);
-			}
-		      SH_FREE(read_buf);
-		    }
-		}
-
-	      if (conn == NULL    || conn->FileName == NULL || 
-		  SL_ISERROR(sfd) || bytes < 0)
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, sfd, MSG_TCP_NFILE,
-				  conn->peer, 
-				  (conn->FileName == NULL) ? 
-				  _("(NULL)") : conn->FileName);
-		  status_update (conn->client_entry, CLT_FAILED);
-		  sh_forward_do_free (conn);
-		}
-
-	    }
-	  
-	 else if (0 == check_request_nerr((char *)&(conn->head[3]), 
-					  _("RECV"))                    &&
-		   conn->client_entry != NULL                           &&
-		   conn->K != NULL                                      &&
-		   conn->FileName != NULL)
-	    {
-
-	      TPT(( 0, FIL__, __LINE__, 
-		    _("msg=<File transfer - RCVT (5+).>\n")));
-
-	      if (conn->FileSent == conn->FileLength)
-		{
-		  send_buf = hash_me(conn->K, conn->peer, 
-				     sl_strlen(conn->peer));
-#ifdef SH_ENCRYPT
-		  sh_forward_prep_send_crypt (conn, send_buf, 
-					      sl_strlen(conn->peer)+KEY_LEN, 
-					      _("EEOT"),  
-					      SH_PROTO_BIG|conn->client_entry->encf_flag);
-#else
-		  sh_forward_prep_send_crypt (conn, send_buf, 
-					      sl_strlen(conn->peer)+KEY_LEN, 
-					      _("EEOT"),  
-					      SH_PROTO_BIG);
-#endif
-		  SH_FREE(send_buf);
-		}
-	      else
-		{
-		  bytes = -1;
-		  sfd = sl_open_read(FIL__, __LINE__, 
-				     conn->FileName, SL_YESPRIV);
-		  if (!SL_ISERROR(sfd))
-		    {
-		      read_buf = SH_ALLOC(TRANS_BYTES);
-		      sl_seek (sfd, (off_t) conn->FileSent);
-		      bytes = sl_read (sfd, read_buf, TRANS_BYTES);
-		      sl_close(sfd);
-		    }
-		  else
-		    {
-		      sh_error_handle((-1), FIL__, __LINE__, sfd, 
-				      MSG_E_ACCESS,
-				      (long) geteuid(),
-				      conn->FileName);
-		    }
-		  if (bytes >= 0)
-		    {
-#ifdef SH_ENCRYPT
-		      /* need to send N * B_SIZ bytes
-		       */ 
-		      blkfac = bytes / B_SIZ;
-		      rem    = bytes - (blkfac * B_SIZ);
-		      if (rem != 0)
-			{
-			  memset(&read_buf[bytes], '\n', (B_SIZ-rem));
-			  ++blkfac;
-			  send_bytes = blkfac * B_SIZ;
-			}
-		      else
-			send_bytes = bytes;
-
-		      send_buf = hash_me(conn->K, read_buf, 
-					 send_bytes);
-
-		      sh_forward_prep_send_crypt (conn, send_buf, 
-						  send_bytes+KEY_LEN, 
-						  _("FILE"),  
-						  SH_PROTO_BIG|conn->client_entry->encf_flag);
-#else
-
-		      send_buf = hash_me(conn->K, read_buf, bytes);
-		      sh_forward_prep_send_crypt (conn, send_buf, 
-						  bytes+KEY_LEN, 
-						  _("FILE"),  
-						  SH_PROTO_BIG);
-#endif
-
-		      conn->FileSent += bytes;
-		      SH_FREE(send_buf);
-		      SH_FREE(read_buf);
-		    }
-		  else
-		    {
-		      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NFILE,
-				      conn->peer,
-				      (conn->FileName == NULL) ? 
-				      _("(NULL)") : conn->FileName);
-		      status_update (conn->client_entry, CLT_FAILED);
-		      sh_forward_do_free (conn);
-		    }
-		}
-	    }
-
-
-	  else if (0 == check_request_nerr((char *)&(conn->head[3]), 
-					   _("EOTE")) &&
-		   conn->client_entry != NULL)
-	    {
-
-	      TPT(( 0, FIL__, __LINE__, 
-		    _("msg=<File transfer - EOTE (7).>\n")));
-
-	      if (flag_err_info == SL_TRUE)
-		sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKFILE,
-				conn->peer);
-
-	      if ((conn->client_entry->status_now != CLT_SUSPEND) &&
-		  (conn->client_entry->status_now != CLT_TOOLONG))
-		{ status_update (conn->client_entry, CLT_FILE); }
-	      else
-		{ conn->client_entry->session_key[0]    = '\0'; }
-	      conn->client_entry->last_connect = time (NULL);
-	      sh_forward_do_free (conn);
-	    }
-	    
-
-	  /* client does something unexpected
-	   */
-	  else  /* ---- ??? ----- */
-	    {
-	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
-			      1, conn->pass, conn->peer,  
-			      '\\', conn->head[3], '\\',conn->head[4],
-			      '\\', conn->head[5], '\\',conn->head[6]);
-	      status_update (conn->client_entry, CLT_FAILED);
-	      sh_forward_do_free (conn);
-	    }
-	}
-
-      else if (state == SH_DO_WRITE)  /* finished writing */
-	{
-	  TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - (wait).>\n")));
-
-	  /* challenge is sent, now wait for message from client
-	   */
-	  conn->headcount     = 0;
-	  conn->bytecount     = 0;
-	  conn->bytes_to_send = 0;
-	  conn->bytes_to_get  = 0;
-	  if (conn->buf != NULL) 
-	    {
-	      SH_FREE(conn->buf);
-	      conn->buf           = NULL;
-	    }
-	  conn->state     = CONN_READING;
-	}
-      SL_RET0(_("check_protocol"));
-    }
-
-  /* ---------  message exchange  -----------
-   */
-  if ((conn->head[0] & SH_PROTO_SRP) == 0  && 
-      (conn->head[0] & SH_PROTO_MSG) != 0  /* is set */ )
-    {
-
-      if (state == SH_DO_READ)        /* finished reading */
-	{
-
-	  TPT(( 0, FIL__, __LINE__, _("msg=<Message transfer - entry.>\n")));
-
-	  /* client requests challenge
-	   */
-	 if (0 == check_request_nerr ((char *)&(conn->head[3]), _("HELO")))
-	    {
-
-	      TPT(( 0, FIL__, __LINE__, 
-		    _("msg=<Message transfer - HELO (1).>\n")));
-
-	      if (conn->buf == NULL || sl_strlen(conn->buf) <= KEY_LEN )
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-
-	      TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s.>\n"), conn->buf));
-
-	      /* ----  search the register  -----
-	       */
-	      this_client = search_register (conn, KEY_LEN);
-	      if (NULL == this_client)
-		SL_RET0(_("check_protocol"));
-
-	      /* ---- force authentication -----
-	       */
-	      if ( (this_client->session_key[0] == '\0') || 
-		   ((time(NULL)-this_client->session_key_timer) 
-		    > (time_t) TIMEOUT_KEY)
-		   )
-		{
-
-		  /* fake an auth request and jump there
-		   */
-		  conn->head[0]  = (conn->head[0] | SH_PROTO_SRP);
-		  conn->head[3]  = 'S';
-		  conn->head[4]  = 'A';
-		  conn->head[5]  = 'L';
-		  conn->head[6]  = 'T';
-		  if (flag_err_info == SL_TRUE)
-		    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FAUTH,
-				    &(conn->buf[KEY_LEN]));
-		  len = sl_strlen(&(conn->buf[KEY_LEN])) + 1;
-		  /* &(conn->buf[KEY_LEN]) is hostname         */
-		  /* may overlap, thus only memmove is correct */
-		  memmove(conn->buf, &(conn->buf[KEY_LEN]), len); 
-		  this_client->session_key[0]    = '\0';
-		  this_client->session_key_timer = (time_t) 1;
-
-		  goto servInit;
-		}
-	      
-	      /* check whether hostname is properly signed
-	       */ 
-	      if (conn->K != NULL)
-		{ 
-		  SH_FREE(conn->K);
-		  conn->K = NULL;
-		}
-	      /* FIXME len = sl_strlen(&(conn->buf[KEY_LEN])) + KEY_LEN + 1; */
-	      conn->K = SH_ALLOC(KEY_LEN + 1);
-
-	      sl_strlcpy (conn->K, 
-			  sh_util_siggen(this_client->session_key,
-					 &(conn->buf[KEY_LEN]),
-					 sl_strlen(&(conn->buf[KEY_LEN])),
-					 sigbuf, sizeof(sigbuf)),
-			  KEY_LEN+1);
-	      TPT((0, FIL__, __LINE__, _("msg=<host %s>\n"), 
-		   &(conn->buf[KEY_LEN])));
-	      TPT((0, FIL__, __LINE__, _("msg=<ckey %s>\n"), 
-		   this_client->session_key));
-	      TPT((0, FIL__, __LINE__, _("msg=<sign %s>\n"), conn->K));
-
-	      if (0 != sl_strncmp(conn->K, conn->buf, KEY_LEN))
-		{
-		  TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s>\n"), conn->buf));
-		  TPT(( 0, FIL__, __LINE__, _("msg=<Want %s>\n"), conn->K));
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("Signature mismatch"), 
-				  &(conn->buf[KEY_LEN]));
-
-		  this_client->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		}
-	      SH_FREE(conn->K); 
-	      conn->K = NULL;
-
-	      /* -- create a nonce and send it --
-	       */
-
-	      conn->client_entry = this_client;
-	      sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1);
-
-	      ticks = (UINT32) taus_get ();
-
-	      test = (char *) &ticks;
-	      sh_util_cpylong (conn->challenge, test, 4);
-	      conn->challenge[4] = '\0';
-	      for (i = 0; i < 4; ++i)
-		if (conn->challenge[i] == '\0')
-		  conn->challenge[i] = 0x01;
-
-	      sh_forward_prep_send (conn, conn->challenge, 5, _("TALK"), 
-				    SH_PROTO_MSG);
-	      TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s.>\n"), 
-		    hu_trans(conn->challenge)));
-	    }
-
-	  /* Client has send a message. Check whether we are in proper
-	   * state, and verify message.
-	   */
-	  else if (0 == 
-		   check_request_nerr((char *)&(conn->head[3]), _("MESG")) &&
-		   conn->client_entry != NULL                           &&
-		   conn->client_entry->session_key[0] != '\0'           &&
-		   (len = sl_strlen(conn->buf) - KEY_LEN) > 0           &&
-		   sl_strlen(conn->challenge) == 4)
-	    {
-	      TPT(( 0, FIL__, __LINE__, 
-		    _("msg=<Message transfer - MESG (3).>\n")));
-
-#ifdef SH_ENCRYPT
-	      if (conn->client_entry->encf_flag == 0) {
-		conn->client_entry->ency_flag = 0;
-	      }
-	      if ((conn->client_entry->ency_flag != 0) && 
-		  ((conn->head[0] & SH_PROTO_ENC) == 0)) 
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
-				  _("message transfer"), 
-#ifdef SH_ENCRYPT_2
-				  _("version2"),
-#else
-				  _("version1"),
-#endif 
-				  _("none"));
-		  /* conn->client_entry->ency_flag = 0; */
-		}
-	      else if ((conn->client_entry->ency_flag != 0) &&
-		       ((conn->head[0] & SH_MASK_ENC) != 
-			conn->client_entry->ency_flag))
-		{
-		  sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, 
-				  MSG_TCP_MISENC,
-				  _("message transfer"), 
-#ifdef SH_ENCRYPT_2
-				  _("version2"),
-#else
-				  _("version1"),
-#endif 
-				  ((conn->head[0] & SH_PROTO_EN2) == SH_PROTO_EN2) ? _("version2") : _("version1"));
-		  conn->client_entry->ency_flag = 
-		    (conn->head[0] & SH_MASK_ENC); 
-		}
-#else
-	      if ((conn->head[0] & SH_PROTO_ENC) != 0) 
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, 
-				  MSG_TCP_MISENC,
-				  _("message transfer"), 
-				  _("none"), 
-				  ((conn->head[0] & SH_PROTO_EN2) == SH_PROTO_EN2) ? _("version2") : _("version1"));
-		}
-#endif
-
-	      TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s.>\n"), conn->buf));
-	      /* get hash from message end, truncate message
-	       */
-	      sl_strlcpy(hash, &(conn->buf[len]), KEY_LEN+1);
-	      conn->buf[len] = '\0';
-	      
-	      /* verify hash
-	       */
-	      buffer = sh_util_strconcat(conn->buf, conn->challenge, NULL);
-	      i =  sl_strncmp(hash, 
-			      sh_util_siggen(conn->client_entry->session_key,
-					     buffer,
-					     sl_strlen(buffer),
-					     sigbuf, sizeof(sigbuf)),
-			      KEY_LEN);
-	      TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
-		   sh_util_siggen(conn->client_entry->session_key,
-				  buffer,
-				  sl_strlen(buffer),
-				  sigbuf, sizeof(sigbuf))));
-
-
-	      if (0 != i)
-		{
-		  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
-		  status_update (conn->client_entry, CLT_FAILED);
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("Msg signature mismatch"), conn->peer);
-		  conn->client_entry->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		}
-	      else
-		{
-		  conn->client_entry->last_connect = time (NULL);
-
-		  if (NULL != sl_strstr(conn->buf,      _("EXIT")))
-		    {
-		      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
-		      conn->client_entry->exit_flag = 1;
-		      status_update (conn->client_entry, CLT_EXITED);
-		    }
-		  else if (NULL != sl_strstr(conn->buf, _("PANIC")))
-		    {
-		      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
-		      status_update (conn->client_entry, CLT_PANIC);
-		    }
-		  else if (NULL != sl_strstr(conn->buf, _("SUSPEND")))
-		    {
-		      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
-		      status_update (conn->client_entry, CLT_SUSPEND);
-		    }
-		  else if (NULL != sl_strstr(conn->buf, _("POLICY")))
-		    {
-		      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
-		      status_update (conn->client_entry, CLT_POLICY);
-		    }
-		  else if (NULL != sl_strstr(conn->buf, 
-					     _("File check completed")))
-		    {
-		      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
-		      status_update (conn->client_entry, CLT_CHECK);
-		    }
-		  else if (NULL != sl_strstr(conn->buf, _("START")))
-		    {
-		      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
-		      sh_socket_add2reload (conn->client_entry->hostname);
-		      if (conn->client_entry->status_now == CLT_SUSPEND) {
-			status_update (conn->client_entry, CLT_ILLEGAL);
-			sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL,
-					conn->peer);
-		      }
-		      else
-			status_update (conn->client_entry, CLT_STARTED);
-		    }
-		  else
-		    {
-		      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
-		      if (NULL != sl_strstr(conn->buf, 
-					    _("Runtime configuration reloaded")))
-			{
-			  sh_socket_add2reload (conn->client_entry->hostname);
-			}
-		      status_update (conn->client_entry, CLT_MSG);
-		    }
-
-		  TPT((0, FIL__, __LINE__, _("msg=<status updated>\n")));
-		  clt_sev   = atoi(conn->buf);
-		  clt_class = (-1);
-		  ptok    = strchr(conn->buf, '?');
-		  if (ptok != NULL)
-		    {
-		      ++ptok;
-		      if (ptok != NULL && sh.flag.client_class == S_TRUE) 
-			clt_class = atoi(ptok);  /* is a global */
-		      ptok = strchr(ptok, '?');
-		      if (ptok != NULL) 
-			++ptok;
-		    }
-		  if (sh.flag.client_severity == S_FALSE)
-		    clt_sev = (-1);
-
-		  /* here we expect an xml formatted message, thus we don't
-		     escape xml special chars (flag == 0) */
-		  ptok = 
-		    sh_tools_safe_name ((ptok!=NULL) ? ptok : conn->buf, 0);
-
-		  /* push client name to error routine
-                   */
-#if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE)
-		  {
-		    char peer_ip[SH_IP_BUF];
-		    sh_ipvx_ntoa(peer_ip, sizeof(peer_ip), &(conn->addr_peer)); 
-		    sh_error_set_peer_ip( peer_ip );
-		  }                        
-#endif
-                  sh_error_set_peer(sh_strip_domain (conn->peer));
-		  sh_error_handle(clt_sev, FIL__, __LINE__, 0, MSG_TCP_MSG,
-				  sh_strip_domain (conn->peer), 
-				  ptok);
-                  sh_error_set_peer(NULL);
-#if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE)
-                  sh_error_set_peer_ip(NULL);
-#endif
-                  
-		  TPT((0, FIL__, __LINE__, _("msg=<%s>\n"), ptok));
-		  SH_FREE(ptok);
-		  clt_class = (-1);
-		}
-	      memset(buffer, '\0', sl_strlen(buffer));
-	      SH_FREE(buffer);
-
-	      /* SERVER CONF SEND
-	       */
-	      buffer = sh_util_strconcat(conn->buf,
-					 conn->challenge,
-					 NULL);
-	      sl_strlcpy(hash, 
-			 sh_util_siggen ( conn->client_entry->session_key,
-					  buffer,
-					  sl_strlen(buffer),
-					  sigbuf, sizeof(sigbuf)),
-			 KEY_LEN+1);
-	      
-	      /* --- SERVER CMD --- */
-	      cmd = sh_socket_check (conn->peer);
-
-	      if (cmd != NULL)
-		{
-		  /* max cmd size is SH_MAXMSGLEN bytes
-		   */
-		  sl_strlcpy(&hash[KEY_LEN], cmd, SH_MAXMSGLEN);
-		  sl_strlcat(&hash[KEY_LEN],
-			     sh_util_siggen ( conn->client_entry->session_key,
-					      &hash[KEY_LEN],
-					      sl_strlen(&hash[KEY_LEN]),
-					      sigbuf, sizeof(sigbuf)),
-			     SH_MAXMSGLEN+KEY_LEN+1);
-		  
-		  TPT((0, FIL__, __LINE__, _("CONF SEND <0> <%s>\n"), 
-			  &hash[KEY_LEN]));
-		  
-		} else {
-		  
-		  TPT((0, FIL__, __LINE__, _("CONF SEND <0> <[NULL]>\n")));
-		  
-		}
-	      /* --- SERVER CMD END --- */
-
-	      TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
-		   sh_util_siggen(conn->client_entry->session_key,
-				  buffer,
-				  sl_strlen(buffer),
-				  sigbuf, sizeof(sigbuf))));
-	  
-#ifdef SH_ENCRYPT
-	      sh_forward_prep_send_crypt (conn, hash, 
-					  sl_strlen(hash) /* KEY_LEN */, 
-					  _("CONF"), 
-					  SH_PROTO_MSG|SH_PROTO_END|conn->client_entry->ency_flag);
-#else
-	      sh_forward_prep_send_crypt (conn, hash, 
-					  sl_strlen(hash) /* KEY_LEN */, 
-					  _("CONF"), 
-					  SH_PROTO_MSG|SH_PROTO_END);
-#endif
-
-	      memset(buffer, '\0', sl_strlen(buffer));
-	      SH_FREE(buffer);
-	      
-	      /* sh_forward_do_free (conn); */
-	    }
-	  
-	  /* client does something unexpected
-	   */
-	  else  /* ---- ??? ----- */
-	    {
-	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
-			      2, conn->pass, conn->peer,  
-			      '\\', conn->head[3], '\\',conn->head[4],
-			      '\\', conn->head[5], '\\',conn->head[6]);
-	      status_update (conn->client_entry, CLT_FAILED);
-	      conn->client_entry->session_key_timer = 
-		time(NULL) - (2*TIMEOUT_KEY);
-	      sh_forward_do_free (conn);
-	    }
-	}
-      else if (state == SH_DO_WRITE)  /* finished writing */
-	{
-	  if (0 != (conn->head[0] & SH_PROTO_END))
-	    {
-	      if (flag_err_debug == SL_TRUE)
-		sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKMSG,
-				sh_strip_domain (conn->peer));
-	      sh_forward_do_free (conn);
-	      SL_RET0(_("check_protocol"));
-	    }
-
-	  TPT(( 0, FIL__, __LINE__, _("msg=<Msg transfer - (wait).>\n")));
-
-	  /* challenge is sent, now wait for message from client
-	   */
-	  conn->headcount     = 0;
-	  conn->bytecount     = 0;
-	  conn->bytes_to_send = 0;
-	  conn->bytes_to_get  = 0;
-	  if (conn->buf != NULL) 
-	    {
-	      SH_FREE(conn->buf);
-	      conn->buf           = NULL;
-	    }
-	  conn->state     = CONN_READING;
-	}
-      TPT((0, FIL__, __LINE__, _("msg=<return>\n") ));
-      SL_RET0(_("check_protocol"));
-    }
-
-  /* ---------  authentication  -----------
-   */
-
-  /* entry point for jump from message forward if session key must
-   * be re-initialized
-   */	 
- servInit:
-
-  if ( (conn->head[0] & SH_PROTO_SRP) != 0   /* is set */ )
-    {
-
-#ifndef USE_SRP_PROTOCOL
-
-      if (state == SH_DO_READ)        /* finished reading */
-	{
-	  TPT((0, FIL__, __LINE__, _("msg=<Authentication - entry.>\n")));
-
-	  /* first pass -- client request salt  
-	   */
-	  if (conn->pass    == 1) 
-	    {
-
-	      TPT((0, FIL__, __LINE__, 
-		   _("msg=<Authentication - SALT (1).>\n")));
-
-	      if (conn->buf == NULL || sl_strlen(conn->buf) == 0)
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-		  
-
-	      /* search the register
-	       */
-
-	      this_client = search_register (conn, 0);
-	      if (NULL == this_client)
-		SL_RET0(_("check_protocol"));
-
-
-	      conn->client_entry = this_client;
-	      sl_strlcpy (conn->peer, conn->buf, SH_MINIBUF+1);
-
-	      if (0 != check_request_s((char *)&(conn->head[3]), 
-				       _("SALT"),conn->peer))
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("No salt requested"), conn->peer);
-		  status_update (conn->client_entry, CLT_FAILED);
-		  conn->client_entry->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-
-	       
-	      /* -- create server nounce v --
-	       */
-	      ticks = (UINT32) taus_get ();
-	      
-	      if (conn->A != NULL)
-		{
-		  SH_FREE(conn->A);
-		  conn->A = NULL;
-		}
-	      conn->A = SH_ALLOC(KEY_LEN+1);
-
-	      sl_strlcpy(conn->A, 
-			 sh_tiger_hash((char *) &ticks, 
-				       TIGER_DATA, sizeof(UINT32), 
-				       hashbuf, sizeof(hashbuf)),
-			 KEY_LEN+1);
-	      u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0';
-
-	      if (conn->M1 != NULL)
-		{
-		  SH_FREE(conn->M1);
-		  conn->M1 = NULL;
-		}
-	      conn->M1 = SH_ALLOC(2*KEY_LEN+1);
-
-	      /* compute hash key H(v(server), P)v(server)
-	       */
-	      sh_passwd (conn->A, conn->client_entry->verifier, 
-			 NULL, conn->M1);
-
-	      sl_strlcat(conn->M1, conn->A, 2*KEY_LEN+1);
-
-
-	      /* --- send H(v(server), P)v(server) ----
-	       */
-      	      sh_forward_prep_send (conn, 
-				    conn->M1, 
-				    sl_strlen(conn->M1), 
-				    u, 
-				    (conn->head[0]|SH_PROTO_SRP));
-
-	      SH_FREE(conn->M1); 
-	      conn->M1 = NULL;
-	    }
-
-	  /* client -- third pass
-	   * Message is H(H(u,v),P)u
-	   *
-	   * A := v, verifier := H(password), 
-	   */
-	  else if (conn->pass    == 3                   && 
-		   conn->client_entry != NULL)
-	    {
-
-	      TPT((0, FIL__, __LINE__, 
-		   _("msg=<Authentication - PASS (3).>\n")));
-				  
-	      if (0 != check_request_s((char *) &(conn->head[3]), _("PASS"), 
-				       conn->peer)                    ||
-		  sl_strlen(conn->buf) <= KEY_LEN                        ||
-		  conn->A == NULL)
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("Invalid client request"), conn->peer);
-		  status_update (conn->client_entry, CLT_FAILED);
-		  conn->client_entry->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-
-	      /* store random nonce u from client
-	       */
-	      if (conn->K != NULL)
-		{
-		  SH_FREE(conn->K);
-		  conn->K = NULL;
-		}
-	      conn->K = SH_ALLOC(KEY_LEN+1);
-	      sl_strlcpy(conn->K, &(conn->buf[KEY_LEN]), KEY_LEN+1);
-
-	      /* verify random nonce u from client
-	       */
-	      if (conn->M1 != NULL)
-		{
-		  SH_FREE(conn->M1);
-		  conn->M1 = NULL;
-		}
-	      conn->M1 = sh_util_strconcat(conn->K, conn->A, NULL);
-
-	      TPT((0, FIL__, __LINE__, _("msg=<c/r: K = %s>\n"), conn->K));
-	      TPT((0, FIL__, __LINE__, _("msg=<c/r: A = %s>\n"), conn->A));
-	      TPT((0, FIL__, __LINE__, _("msg=<c/r: M = %s>\n"), conn->M1));
-
-	      sl_strlcpy(hash, sh_tiger_hash (conn->M1, 
-					      TIGER_DATA, 
-					      sl_strlen(conn->M1),
-					      hashbuf, sizeof(hashbuf)), 
-			 KEY_LEN+1); 
-	      sh_passwd (hash, conn->client_entry->verifier, NULL, conn->M1);
-
-	      TPT((0, FIL__, __LINE__, _("msg=<c/r: H = %s>\n"), hash));
-	      TPT((0, FIL__, __LINE__, _("msg=<c/r: P = %s>\n"), conn->M1));
-
-	      if ( 0 != sl_strncmp(conn->M1, conn->buf, KEY_LEN))
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("Session key mismatch"), conn->peer);
-		  status_update (conn->client_entry, CLT_FAILED);
-		  conn->client_entry->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-		  
-
-	      /* ---- compute hash key H(v, P, u) ----
-	       */
-	      
-	      sh_passwd (conn->A, conn->client_entry->verifier, conn->K,
-			 conn->M1);
-
-	      sl_strlcpy(conn->client_entry->session_key, 
-			 conn->M1, KEY_LEN+1);
-	      TPT((0, FIL__, __LINE__, _("msg=<c/r: Key = %s>\n"), 
-		   conn->client_entry->session_key));
-
-#ifdef SH_ENCRYPT
-	       err_num = makeKey(&(conn->client_entry->keyInstE), 
-				 DIR_ENCRYPT, 192, 
-				 conn->client_entry->session_key);
-	       if (err_num < 0)
-		 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-				 errorExplain(err_num, expbuf, sizeof(expbuf)), 
-				 _("check_protocol: makeKey"));
-	       err_num = makeKey(&(conn->client_entry->keyInstD), 
-				 DIR_DECRYPT, 192, 
-				 conn->client_entry->session_key);
-	       if (err_num < 0)
-		 sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-				 errorExplain(err_num, expbuf, sizeof(expbuf)), 
-				 _("check_protocol: makeKey"));
-#endif
-
-	      if (conn->K  != NULL) SH_FREE (conn->K);
-	      conn->K  = NULL;
-	      if (conn->A  != NULL) SH_FREE (conn->A);
-	      conn->A  = NULL;
-	      if (conn->M1 != NULL) SH_FREE (conn->M1);
-	      conn->M1 = NULL;
-
-	      /* if (conn->client_entry->status_now == CLT_STARTED */
-	      if (((conn->client_entry->status_now != CLT_INACTIVE) &&
-		   (conn->client_entry->status_now != CLT_EXITED)   &&
-		   (conn->client_entry->status_now != CLT_SUSPEND))
-		  && conn->client_entry->session_key_timer > (time_t) 1)
-		{
-		  status_update (conn->client_entry, CLT_ILLEGAL);
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL,
-				  conn->peer);
-		}
-	      else if (conn->client_entry->session_key_timer == (time_t) 0)
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NEW,
-				  conn->peer);
-		  if (conn->client_entry->status_now != CLT_SUSPEND)
-		    status_update (conn->client_entry, CLT_STARTED);
-		}
-
-	      conn->client_entry->session_key_timer = time (NULL);
-	      conn->client_entry->last_connect = time (NULL);
-
-	      /* put in read state
-	       */
-	      sh_forward_prep_send (conn, 
-				    _("AUTH"),
-				    5, 
-				    _("AUTH"), 
-				    (conn->head[0]|SH_PROTO_SRP));
-
-	    }
-	  else
-	    {
-	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
-			      3, conn->pass, conn->peer, 
-			      '\\', conn->head[3], '\\', conn->head[4],
-			      '\\', conn->head[5], '\\', conn->head[6]);
-	      sh_forward_do_free (conn);
-	    }
-	}
-
-#else
-      /* use SRP                    */
-
-
-      if (state == SH_DO_READ)        /* finished reading */
-	{
-
-	  TPT((0, FIL__, __LINE__, _("msg=<Authentication - entry.>\n")));
-
-	  /* first pass -- client request salt  
-	   */
-	  if (conn->pass    == 1)
-	    {
-	      TPT((0, FIL__, __LINE__, 
-		   _("msg=<Authentication - SALT (1).>\n")));
-
-	      if (conn->buf == NULL)
-		{
-		  sh_error_handle( (-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-
-	      /* search the register
-	       */
-	      this_client = search_register(conn, 0);
-	      if (NULL == this_client)
-		SL_RET0(_("check_protocol"));
-
-	      conn->client_entry = this_client;
-	      sl_strlcpy (conn->peer, conn->buf, SH_MINIBUF+1);
-
-	      if (0 != check_request_s((char *)&(conn->head[3]), _("SALT"),
-				       conn->peer))
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("No salt requested"), conn->peer);
-		  status_update (conn->client_entry, CLT_FAILED);
-		  conn->client_entry->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-		  
-
-	      u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0';
-	      
-	      sh_forward_prep_send (conn, 
-				    conn->client_entry->salt, 
-				    sl_strlen(conn->client_entry->salt), 
-				    u, 
-				    (conn->head[0]|SH_PROTO_SRP));
-	    }
-
-	  /* client has sent A -- third pass
-	   */
-	  else if (conn->pass == 3                    && 
-		   conn->client_entry != NULL)
-	    {
-
-	      TPT((0, FIL__, __LINE__, 
-		   _("msg=<Authentication - PC01 (3).>\n")));
-
-	      if (0 != check_request_s((char *)&(conn->head[3]),_("PC01"),conn->peer)||
-		  conn->buf == NULL
-		  )
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("Invalid client request"), conn->peer);
-		  status_update (conn->client_entry, CLT_FAILED);
-		  conn->client_entry->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-
-	      if (0 != sh_srp_init())
-		{
-		  status_update (conn->client_entry, CLT_FAILED);
-		  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
-				  MSG_TCP_EBGN);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		}
-		  
-
-	      /* check A, only send B if correct 
-	       */
-	      if ( sl_strlen(conn->buf) < SH_BUFSIZE && 
-		   0 == sh_srp_check_zero (conn->buf) )
-		{
-		  len = sl_strlen(conn->buf)+1;
-
-		  if (conn->A != NULL)
-		    {
-		      SH_FREE(conn->A);
-		      conn->A = NULL;
-		    }
-		  conn->A = SH_ALLOC(len);
-		  sl_strlcpy (conn->A, conn->buf, len);
-		  
-		  /* 
-		   * compute B 
-		   */
-		  if (0 != sh_srp_make_a ())     /* b        random number */
-		    {
-		      status_update (conn->client_entry, CLT_FAILED);
-		      
-		      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
-				      MSG_TCP_EBGN);
-		      sh_srp_exit();
-		      sh_forward_do_free (conn);
-		      SL_RET0(_("check_protocol"));
-		    }
-             
-		  foo_B = sh_srp_B               /* B = v + g^b            */
-		    (conn->client_entry->verifier);
-
-		  if (foo_B == NULL)
-		    {
-		      status_update (conn->client_entry, CLT_FAILED);
-		      
-		      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
-				      MSG_TCP_EBGN);
-		      sh_srp_exit();
-		      sh_forward_do_free (conn);
-		      SL_RET0(_("check_protocol"));
-		    }
-
-		  TPT((0, FIL__, __LINE__, _("msg=<srp: A = %s>\n"), conn->A));
-		  TPT((0, FIL__, __LINE__, _("msg=<srp: B = %s>\n"), foo_B));
-
-		  /* 
-		   * create nonce u 
-		   */
-		  ticks = (UINT32) taus_get ();
-
-		  test = (char *) &ticks;
-		  sh_util_cpylong (u, test, 4);  /* u        nounce        */
-		  u[4] = '\0';
-		  sl_strlcpy(conn->challenge, 
-			     sh_tiger_hash(u, TIGER_DATA, 4, hashbuf, sizeof(hashbuf)),
-			     SH_CHALLENGE_SIZE);
-
-		  TPT((0, FIL__, __LINE__, _("msg=<srp: u = %03o-%03o-%03o-%03o>\n"), u[0], u[1], u[2], u[3]));
-		  TPT((0, FIL__, __LINE__, _("msg=<srp: U = %s>\n"), 
-		       conn->challenge));
-
-		  /* 
-		   * compute the session key K and M1 = Hash(A,B,K)
-		   */
-		  foo_Ss = sh_srp_S_s (conn->challenge, 
-				       conn->A, 
-				       conn->client_entry->verifier);
-
-		  if (foo_Ss == NULL || 0 != sh_srp_check_zero (foo_Ss))
-		    {
-		      status_update (conn->client_entry, CLT_FAILED);
-		      
-		      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
-				      MSG_TCP_EBGN);
-		      sh_srp_exit();
-		      sh_forward_do_free (conn);
-		      SL_RET0(_("check_protocol"));
-		    }
-
-		  if (conn->K != NULL)
-		    {
-		      SH_FREE(conn->K);
-		      conn->K = NULL;
-		    }
-		  conn->K = SH_ALLOC(KEY_LEN+1);
-		  sl_strlcpy(conn->K, 
-			     sh_tiger_hash(foo_Ss, TIGER_DATA, 
-					   sl_strlen(foo_Ss), 
-					   hashbuf, sizeof(hashbuf)),
-			     KEY_LEN+1);
-
-		  if (conn->M1 != NULL)
-		    {
-		      SH_FREE(conn->M1);
-		      conn->M1 = NULL;
-		    }
-		  conn->M1 = SH_ALLOC(KEY_LEN+1);
-		  sh_srp_M (conn->A, foo_B, conn->K, conn->M1, KEY_LEN+1);
-
-		  TPT((0, FIL__, __LINE__, _("msg=<srp:Ss = %s>\n"), foo_Ss));
-		  TPT((0, FIL__, __LINE__, _("msg=<srp: K = %s>\n"), conn->K));
-		  TPT((0, FIL__, __LINE__, _("msg=<srp:M1 = %s>\n"),conn->M1));
-
-		  /*
-		   * send B
-		   */
-		  sh_forward_prep_send (conn, 
-					foo_B,
-					sl_strlen(foo_B)+1,
-					u,
-					(conn->head[0]|SH_PROTO_SRP));
-		  if (foo_Ss != NULL)
-		    {
-		      SH_FREE(foo_Ss);
-		      foo_Ss = NULL;
-		    }
-		  if (foo_B  != NULL)
-		    {
-		      SH_FREE(foo_B);
-		      foo_B = NULL;
-		    }
-		}
-	      else
-		{
-		  status_update (conn->client_entry, CLT_FAILED);
-
-		  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
-				  MSG_TCP_EZERO);
-		  sh_forward_do_free (conn);
-		}
-
-	      sh_srp_exit();
-	    }
-		  
-	  /* client has sent M1 -- fifth pass
-	   */
-	  else if (conn->pass    == 5           && 
-		   conn->client_entry != NULL) 
-	    {
-	      TPT((0, FIL__, __LINE__, 
-		   _("msg=<Authentication - PC02 (5).>\n")));
-
-	      /* check that the state is valid
-	       */
-	      if (0 != check_request_s((char *)&(conn->head[3]), _("PC02"),
-				       conn->peer)                   ||
-		  conn->A == NULL || conn->K == NULL || conn->M1 == NULL)
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("Invalid client request"), conn->peer);
-		  status_update (conn->client_entry, CLT_FAILED);
-		  conn->client_entry->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-		  sh_forward_do_free (conn);
-		  SL_RET0(_("check_protocol"));
-		} 
-
-	      /* ------ verify M1 = H(A,  B, K) -------
-	       * -----    send M2 = H(A, M1, K) -------
-	       */
-	      if (conn->buf != NULL && 
-		  sl_strncmp(conn->buf, conn->M1, KEY_LEN) == 0)
-		{
-		  /*
-		   * send M2
-		   */
-		  char M_buf[KEY_LEN+1];
-		  sh_forward_prep_send (conn, 
-					sh_srp_M (conn->A, conn->M1, conn->K,
-						  M_buf, sizeof(M_buf)),
-					KEY_LEN+1,
-					_("PARP"),
-					(conn->head[0]|SH_PROTO_SRP));
-
-		  if (conn->A  != NULL) SH_FREE(conn->A);  conn->A  = NULL;
-		  if (conn->M1 != NULL) SH_FREE(conn->M1); conn->M1 = NULL;
-		  sl_strlcpy(conn->client_entry->session_key, 
-			     conn->K, KEY_LEN+1);
-		  TPT((0, FIL__, __LINE__, _("msg=<key %s>\n"), 
-		       conn->client_entry->session_key));
-
-#ifdef SH_ENCRYPT
-		  err_num = makeKey(&(conn->client_entry->keyInstE), 
-				    DIR_ENCRYPT, 192, 
-				    conn->client_entry->session_key);
-		  if (err_num < 0)
-		    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-				    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-				    _("sh_forward_prep_send_int: makeKey"));
-		  err_num = makeKey(&(conn->client_entry->keyInstD), 
-				    DIR_DECRYPT, 192, 
-				    conn->client_entry->session_key);
-		  if (err_num < 0)
-		    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-				    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-				    _("sh_forward_prep_send_int: makeKey"));
-#endif
-
-		  if (conn->K  != NULL) SH_FREE(conn->K);  conn->K  = NULL;
-
-		  conn->client_entry->last_connect = time (NULL);
-		  
-		  if (((conn->client_entry->status_now != CLT_INACTIVE) &&
-		       (conn->client_entry->status_now != CLT_EXITED)   &&
-		       (conn->client_entry->status_now != CLT_SUSPEND))
-		      && conn->client_entry->session_key_timer > (time_t) 1)
-		    {
-		      status_update (conn->client_entry, CLT_ILLEGAL);
-
-		      sh_error_handle((-1), FIL__, __LINE__, 0, 
-				      MSG_TCP_ILL,
-				      conn->peer);
-		    }
-		  else if (conn->client_entry->session_key_timer == (time_t) 0)
-		    {
-		      sh_error_handle((-1), FIL__, __LINE__, 0, 
-				      MSG_TCP_NEW,
-				      conn->peer);
-		      if (conn->client_entry->status_now != CLT_SUSPEND)
-			status_update (conn->client_entry, CLT_STARTED);
-		    }
-		  conn->client_entry->session_key_timer = time (NULL);
-
-		}
-	      else
-		{
-		  status_update (conn->client_entry, CLT_FAILED);
-		  conn->client_entry->session_key_timer = 
-		    time(NULL) - (2*TIMEOUT_KEY);
-
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
-				  _("Session key mismatch"), conn->peer);
-		  sh_forward_do_free (conn);
-		} 
-	    }
-
-	  else
-	    {
-	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
-			      4, conn->pass, conn->peer, 
-			      '\\', conn->head[3], '\\', conn->head[4],
-			      '\\', conn->head[5], '\\', conn->head[6]);
-	      sh_forward_do_free (conn);
-	    }
-	}
-
-#endif
-
-      else if (state == SH_DO_WRITE)  /* finished writing */
-	{
-	  TPT((0, FIL__, __LINE__, _("msg=<Authentication -- (wait).>\n")));
-
-	  conn->headcount     = 0;
-	  conn->bytecount     = 0;
-	  conn->bytes_to_send = 0;
-	  conn->bytes_to_get  = 0;
-	  if (conn->buf != NULL) 
-	    {
-	      SH_FREE(conn->buf);
-	      conn->buf           = NULL;
-	    }
-	  conn->state     = CONN_READING;
-	}
-    }
-  SL_RET0(_("check_protocol"));
-}
-
-
-/***********************************************************
- *
- *    SERVER RECEIVE FUNCTION
- *
- ***********************************************************
- */
-int sh_forward_do_read (sh_conn_t * conn)
-{
-  unsigned long   byteread;     /* bytes read         */
-
-#ifdef SH_ENCRYPT
-
-  unsigned long           blkfac = 0;
-  /* unsigned long           length2; */
-  char                  * p = NULL, * q = NULL;
-  RIJ_BYTE                    inBlock[B_SIZ]; 
-  RIJ_BYTE                    outBlock[B_SIZ];
-  unsigned int            j;
-  cipherInstance          cipherInst;
-  int                     err_num;
-  char expbuf[SH_ERRBUF_SIZE];
-#endif
-
-  SL_ENTER(_("sh_forward_do_read"));
-
-  if (conn->state == CONN_SENDING)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_SYNC,
-		      conn->peer);
-      SL_RETURN( (-1), _("sh_forward_do_read"));
-    }
-
-  if (conn->headcount < SH_HEADER_SIZE) 
-    {
-      conn->bytes_to_get = SH_HEADER_SIZE - conn->headcount;
-      byteread           = read (conn->fd, &(conn->head[conn->headcount]),
-				    conn->bytes_to_get);
-      if (byteread > 0 || errno == EINTR) 
-	{
-	  if (byteread > 0) 
-	    conn->headcount += byteread;
-	  if (conn->headcount == SH_HEADER_SIZE)
-	    {
-		conn->bytes_to_get = 
-		  (256 * (unsigned int)conn->head[1] + 
-		   (unsigned int)conn->head[2]);
-		SH_SHOWPROT(conn->head, '<');
-		conn->bytecount = 0;
-	    }
-	}
-      else
-	{
-	  goto conn_reset;
-	}
-      SL_RETURN( (0), _("sh_forward_do_read"));
-    }
-
-
-  /* limit message size
-   */
-  /*
-  conn->bytes_to_get = 
-    (conn->bytes_to_get > (16*SH_BUFSIZE - 1)) ? 
-    (16*SH_BUFSIZE - 1) : conn->bytes_to_get;
-  */
-  conn->bytes_to_get = (conn->bytes_to_get > TRANS_BYTES) ? 
-    TRANS_BYTES : conn->bytes_to_get;
-
-  if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get > 0)
-    {
-      if ((conn->bytecount > 0) && (conn->bytes_to_get > conn->bytecount))
-	{
-	  /* do nothing */;
-	}
-      else
-	{
-	  if (conn->buf != NULL)
-	    SH_FREE (conn->buf);
-	  conn->buf = SH_ALLOC(conn->bytes_to_get + 1); /* <= TRANS_BYTES+1 */
-	  conn->bytecount = 0;
-	}
-
-      byteread           = read (conn->fd, &(conn->buf[conn->bytecount]),
-				 conn->bytes_to_get - conn->bytecount);
-      if (byteread > 0 || errno == EINTR) 
-	{
-	  if (byteread > 0) 
-	    conn->bytecount    += byteread;
-	  if (conn->bytecount == conn->bytes_to_get) 
-	    {
-	      ++conn->pass;
-	      /* always terminate with NULL - we might use sl_strcmp()
-	       */
-	      conn->buf[conn->bytecount] = '\0';
-	      conn->state                = CONN_PAUSE;
-
-#ifdef SH_ENCRYPT
-	      if      ((conn->head[0] & SH_PROTO_EN2) != 0) /* if encrypted */
-		{
-		  conn->buf = 
-		    sh_tools_revertPack (conn->head, conn->buf,
-					 &(conn->client_entry->keyInstD),
-					 conn->bytecount);
-		}
-	      else if ((conn->head[0] & SH_PROTO_ENC) != 0) /* if encrypted */
-		{
-		  /* Decrypt only complete blocks. 
-		   * If there is an incomplete block,
-		   * something is wrong anyway.
-		   * Decrypt in place.
-		   */
-		  blkfac  = conn->bytecount / B_SIZ;
-		  /* length2 = (B_SIZ * blkfac); */
-		  p       = conn->buf;
-		  q       = conn->buf;
-      
-		  err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
-		  if (err_num < 0)
-		    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-				    errorExplain(err_num, expbuf, sizeof(expbuf)), 
-				    _("sh_forward_do_read: cipherInit"));
-
-		  for (j = 0; j < blkfac; ++j)
-		    {
-		      memcpy(inBlock, p, B_SIZ);
-		      err_num = blockDecrypt(&cipherInst, 
-					     &(conn->client_entry->keyInstD), 
-					     inBlock, 128 * BNUM, outBlock);
-		      if (err_num < 0)
-			sh_error_handle((-1), FIL__, __LINE__, -1, 
-					MSG_E_SUBGEN,
-					errorExplain(err_num, expbuf, sizeof(expbuf)), 
-					_("sh_forward_do_read: blockDecrypt"));
-		      memcpy(q, outBlock, B_SIZ);
-		      p += 16;
-		      q += 16;
-		    }
-		}
-#endif
-
-	      /* ------  HERE CALL check_protocol(conn) -------  */
-	      check_protocol(conn, SH_DO_READ);
-	    }
-	}
-      else
-	{
-	  goto conn_reset;
-	}
-    }
-
-  else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get == 0)
-    {
-      if (conn->buf != NULL)
-	SH_FREE (conn->buf);
-      conn->buf       = NULL;
-      conn->bytecount = 0;
-      ++conn->pass;
-      conn->state     = CONN_PAUSE;
-      /* fprintf(stderr, "\n**** FIXME null read ****\n\n"); */
-      /* ------  HERE CALL check_protocol(conn) -------  */
-      check_protocol(conn, SH_DO_READ);
-    }
-      
-  SL_RETURN( (0), _("sh_forward_do_read"));
-
- conn_reset:
-  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET,
-		  conn->peer);
-  sh_forward_do_free ( conn );
-  SL_RETURN( (-1), _("sh_forward_do_read"));
-}
-
-#if !defined(O_NONBLOCK)
-#if defined(O_NDELAY)
-#define O_NONBLOCK  O_NDELAY
-#else
-#define O_NONBLOCK  0
-#endif
-#endif
-
-/* send to the client
- */
-int sh_forward_do_write (sh_conn_t * conn)
-{
-  int    flags;
-  long   arg = 0;
-  long   bytesent;     /* bytes read         */
-
-  SL_ENTER(_("sh_forward_do_write"));
-
-  /* ---- consistency check ------
-   */
-  if (conn->state == CONN_READING)
-    {
-      sh_error_handle( (-1), FIL__, __LINE__, 0, MSG_TCP_SYNC,
-		      conn->peer);
-      SL_RETURN( (-1), _("sh_forward_do_write"));
-    }
-      
-  
-  flags = retry_fcntl (FIL__, __LINE__, conn->fd, F_GETFL, arg);
-  retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags|O_NONBLOCK);
-
-  /* ---- send the header ------
-   */
-  if (conn->headcount < SH_HEADER_SIZE) 
-    {
-      conn->bytes_to_send = SH_HEADER_SIZE - conn->headcount;
-      bytesent            = write (conn->fd, 
-				   &(conn->head[conn->headcount]), 
-				   conn->bytes_to_send);
-      if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) 
-	{
-	  if (bytesent > 0) 
-	    conn->headcount += bytesent;
-	  if (conn->headcount == SH_HEADER_SIZE) 
-	    {
-	      conn->bytes_to_send = 
-		(256 * (int)conn->head[1] + (int)conn->head[2]);
-	    }
-	}
-      else 
-	{
-	  goto conn_reset_w;
-	}
-      if (conn->fd >= 0)
-	retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags);
-      SL_RETURN( (0), _("sh_forward_do_write"));
-    }
-
-
-  /* ---- send the body ------
-   */
-
-  if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send > 0 &&
-      conn->buf != NULL)
-    {
-      bytesent           = write (conn->fd, &(conn->buf[conn->bytecount]), 
-				     conn->bytes_to_send - conn->bytecount);
-      if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) 
-	{
-	  if (bytesent > 0) 
-	    conn->bytecount    += bytesent;
-	  if (conn->bytecount == conn->bytes_to_send) 
-	    {
-	      ++conn->pass;
-	      conn->state         = CONN_PAUSE;
-	      /* ------  HERE CALL check_protocol(conn) -------  */
-	      check_protocol(conn, SH_DO_WRITE);
-	    }
-	}
-      else
-	{
-	  goto conn_reset_w;
-	}
-    }
-      
-  else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send == 0)
-    {
-      ++conn->pass;
-      conn->state     = CONN_PAUSE;
-      /* fprintf(stderr, "\n**** FIXME null write ****\n\n"); */
-      /* ------  HERE CALL check_protocol(conn) -------  */
-      check_protocol(conn, SH_DO_WRITE);
-    }
-
-  if (conn->fd >= 0)
-    retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags);
-  SL_RETURN( (0), _("sh_forward_do_write"));
-
- conn_reset_w:
-  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET,
-		  conn->peer);
-  sh_forward_do_free ( conn );
-  SL_RETURN( (-1), _("sh_forward_do_write"));
-}
-
-/* accept a connection from a client
- */ 
-#include <syslog.h>
-#ifdef SH_USE_LIBWRAP
-#include <tcpd.h>
-
-#ifndef ALLOW_SEVERITY 
-#define ALLOW_SEVERITY LOG_INFO
-#define DENY_SEVERITY  LOG_WARNING
-#endif
-
-int allow_severity;
-int deny_severity;
-#endif
-
-int sh_forward_accept (int sock, sh_conn_t * newconn)
-{
-  int                errflag;
-  int                rc;
-  struct sh_sockaddr addr;
-#ifdef SH_USE_LIBWRAP
-  struct request_info request;
-  char                errbuf[128];
-  char                daemon[128];
-#endif
-  
-  /* handle AIX (size_t addrlen) in wrapper
-   */
-  int                addrlen = sizeof(addr);
-
-  SL_ENTER(_("sh_forward_accept"));
-
-  rc = retry_accept(FIL__, __LINE__, sock, &addr, &addrlen);
-
-  if (rc >= 0)
-    {
-
-      if (addrlen == 0)
-	{
-	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
-			  _("Connecting entity unknown"), _("accept"));
-	  newconn->fd    = -1;
-	  newconn->state = CONN_FREE;
-	  sl_close_fd(FIL__, __LINE__, rc);
-	  SL_RETURN( (-1), _("sh_forward_accept"));
-	}
-
-#ifdef SH_USE_LIBWRAP
-      sl_strlcpy(daemon, SH_INSTALL_NAME, sizeof(daemon));
-      request_init(&request, RQ_DAEMON, daemon, RQ_FILE, rc, 0);
-      fromhost(&request);
-      if (!hosts_access(&request)) 
-	{
-	  sl_strlcpy(errbuf, _("Refused connection from "), sizeof(errbuf));
-	  sl_strlcat(errbuf,   eval_client(&request), sizeof(errbuf));
-
-	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
-			  errbuf, _("libwrap"));
-	  newconn->fd    = -1;
-	  newconn->state = CONN_FREE;
-	  sl_close_fd(FIL__, __LINE__, rc);
-	  SL_RETURN( (-1), _("sh_forward_accept"));
-	}
-#endif
-
-      memcpy (&(newconn->addr_peer), &addr, sizeof(struct sh_sockaddr));
-
-      /* prepare for usage of connection
-       */
-      (void) retry_fcntl( FIL__, __LINE__, rc, F_SETFD, 1 );
-      newconn->fd           = rc;
-      newconn->state        = CONN_READING;
-      newconn->timer        = (unsigned long) time (NULL);
-
-      if (flag_err_info == SL_TRUE)
-	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CNEW, newconn->fd);
-
-      SL_RETURN( (0), _("sh_forward_accept"));
-    }
-  else
-    {
-      char err_buf[SH_ERRBUF_SIZE];
-      errflag = errno;
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		      sh_error_message(errflag,err_buf, sizeof(err_buf)), _("accept"));
-      newconn->fd    = -1;
-      newconn->state = CONN_FREE;
-      SL_RETURN( (-1), _("sh_forward_accept"));
-    }
-}
-
-extern char sh_sig_msg[64];  /* defined in sh_unix.c */
-
-/* ------------  port and interface -------
- */
-static unsigned int server_port = SH_DEFAULT_PORT;
-
-int sh_forward_set_port (const char * str)
-{
-  int retval = 0;
-  unsigned long   i;
-  char * endptr;
-  
-  SL_ENTER(_("sh_forward_set_port"));
-  i = strtoul (str, &endptr, 0);
-  if (endptr == str) {
-    retval = -1;
-  } else if (i > 65535) {
-    retval = -1;
-  } else {
-    server_port = i;
-  }
-  SL_RETURN( (retval), _("sh_forward_set_port"));
-}
-
-static struct sh_sockaddr server_interface;
-static int            use_server_interface = 0;
-
-int sh_forward_set_interface (const char * str)
-{
-  if (0 == strcmp(str, _("INADDR_ANY")))
-    {
-      use_server_interface = 0;
-      return 0;
-    }
-
-  if (0 == sh_ipvx_aton(str, &server_interface)) 
-    {
-      use_server_interface = 0;
-      return -1;
-    }
-
-  use_server_interface = 1;
-  return 0;
-}
-
-/* ------------  print error --------------
- */
-struct sock_err_st {
-  char msg[128];
-  int  errnum;
-  int  port;
-  int  line;
-  int  euid;
-};
-
-static struct sock_err_st sock_err[2];
-
-void sh_forward_printerr(char * str, int errnum, unsigned int port, int line)
-{
-  int slot = 0;
-
-  if (port != server_port)
-    slot = 1;
-  if (str == NULL)
-    sock_err[slot].msg[0] = '\0';
-  else
-    sl_strlcpy(sock_err[slot].msg, str, 128);
-  sock_err[slot].errnum = errnum;
-  sock_err[slot].port   = port;
-  sock_err[slot].line   = line;
-  sock_err[slot].euid   = (int) geteuid();
-}
-
-int sh_forward_printerr_final(int slot)
-{
-  char errbuf[SH_ERRBUF_SIZE];
-
-  SL_ENTER(_("sh_forward_printerr_final"));
-  if (sock_err[slot].msg[0] != '\0')
-    {
-      dlog(1, FIL__, __LINE__, 
-	   _("Could not set up the listening socket for the server because of the\nfollowing error: %s\nPossible reasons include:\n - insufficient privilege for UID %d, or\n - the port %d is already used by another program.\n"),
-	   sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)), 
-	   sock_err[slot].euid, 
-	   sock_err[slot].port);
-      sh_error_handle((-1), FIL__, sock_err[slot].line, 
-		      sock_err[slot].errnum, MSG_EXIT_ABORTS,
-		      sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)),
-		      sh.prg_name,
-		      sock_err[slot].msg);
-      SL_RETURN((-1), _("sh_forward_printerr_final"));
-    }
-  SL_RETURN(0, _("sh_forward_printerr_final"));
-}
-
-#define  TIME_OUT_DEF 900
-static   unsigned long  time_out_val = TIME_OUT_DEF;
-
-int sh_forward_set_timeout (const char * c)
-{
-  long val;
-
-  SL_ENTER(_("sh_forward_set_time_out"));
-
-  val = strtol (c, (char **)NULL, 10);
-
-  if (val == 0)
-    {
-      val = TIME_OUT_DEF;
-    }
-  else if (val < 0)
-    {
-      time_out_val = TIME_OUT_DEF;
-      SL_RETURN( (-1), _("sh_forward_set_time_out"));
-    }
-
-  time_out_val = (unsigned long) val;
-  SL_RETURN( (0), _("sh_forward_set_time_out"));
-}
-
-
-static   sh_conn_t        * conns = NULL;
-static   int  maxconn = 0;  /* maximum number of simultaneous connections */
-
-
-#ifdef INET_SYSLOG
-#define INET_SUSPEND_TIME 180		/* equal to 3 minutes */
-#define SH_MINSOCK_DEFAULT 3
-int create_syslog_socket (int flag);
-static int recv_syslog_socket   (int fd);
-static int syslog_sock[SH_SOCKMAX] = { -1 };
-static int syslog_sock_n = 0;
-#else
-#define SH_MINSOCK_DEFAULT 2
-#endif
-
-static int SH_MINSOCK = SH_MINSOCK_DEFAULT;
-extern int pf_unix_fd;
-
-/* the tcp socket, and the function to establish it
- */
-static int sh_tcp_sock[SH_SOCKMAX] = { -1 };
-static int sh_tcp_sock_n = 0;
-
-static int do_socket(int domain, int type, int protocol,
-		     struct sockaddr * sa, int salen)
-{
-  int sock = -1;
-  int errnum = 0;
-  int flag   = 1; /* non-zero to enable an option */
-
-  /* fprintf(stderr, "FIXME IPVX: bind addr %s (%d) :%d\n", 
-	  sh_ipvx_print_sockaddr (sa, domain), salen,
-	  sh_ipvx_get_port(sa, domain)); */
-
-  /* create the socket, bind() it and listen()
-   */
-  if ((sock = socket(domain, type, protocol)) < 0 )
-    {
-      errnum = errno; 
-      sh_forward_printerr (_("socket"), errnum, server_port, __LINE__);
-      return -1;
-    }
-  (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 );
- 
-  if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-		  (void *) &flag, sizeof(flag)) < 0 )
-    {
-      errnum = errno;
-      sh_forward_printerr (_("setsockopt"), errnum, server_port, __LINE__);
-      sl_close_fd (FIL__, __LINE__, sock);
-      return -1;
-    }
-  
-  if ( bind(sock, (struct sockaddr *) sa, salen) < 0) 
-    {
-      if (errno != EADDRINUSE)
-	{
-	  errnum = errno;
-	  sh_forward_printerr (_("bind"), errnum, server_port, __LINE__);
-	  sl_close_fd (FIL__, __LINE__, sock);
-	  return -1;
-	}
-      else
-	{
-	  sl_close_fd (FIL__, __LINE__, sock);
-	  return -2;
-	}
-    }
-  
-  if ( retry_fcntl( FIL__, __LINE__, sock, F_SETFL, O_NONBLOCK ) < 0 )
-    {
-      errnum = errno;
-      sh_forward_printerr (_("fcntl"), errnum, server_port, __LINE__);
-      sl_close_fd (FIL__, __LINE__, sock);
-      return -1;
-    }
-  
-  if ( listen(sock, 64) < 0)
-    {
-      errnum = errno;
-      sh_forward_printerr (_("listen"), errnum, server_port, __LINE__);
-      sl_close_fd (FIL__, __LINE__, sock);
-      return -1;
-    }
-
-  return sock;
-}
-
-int sh_create_tcp_socket (void)
-{
-#if defined(USE_IPVX)
-  struct addrinfo *ai;
-  struct addrinfo *p;
-  struct addrinfo hints;
-  char            port[32];
-#else
-  struct sockaddr_in addr;
-  int addrlen      = sizeof(addr);
-#endif
-
-  int sock   = -1;
-
-  SL_ENTER(_("sh_create_tcp_socket"));
-
-  sh_forward_printerr (NULL, 0, server_port, __LINE__);
-
-#if defined(USE_IPVX)
-  if (use_server_interface == 0)
-    {
-      memset (&hints, '\0', sizeof (hints));
-      hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
-      hints.ai_socktype = SOCK_STREAM;
-      hints.ai_family   = AF_UNSPEC;
-      sl_snprintf(port, sizeof(port), "%d", server_port);
-
-      if (getaddrinfo (NULL, port, &hints, &ai) != 0)
-	{
-	  int errnum = errno;
-	  sh_forward_printerr (_("getaddrinfo"), errnum, server_port, __LINE__);
-	  sl_close_fd (FIL__, __LINE__, sock);
-	  SL_RETURN((-1), _("sl_create_tcp_socket"));
-	}
-      
-      p = ai;
-      
-      while (p != NULL && sh_tcp_sock_n < SH_SOCKMAX)
-	{
-	  sock = do_socket(p->ai_family, p->ai_socktype, p->ai_protocol,
-			   p->ai_addr, p->ai_addrlen);
-	  
-	  if (sock >= 0) {
-	    if (sh_tcp_sock_n < SH_SOCKMAX) {
-	      sh_tcp_sock[sh_tcp_sock_n] = sock;
-	      ++sh_tcp_sock_n;
-	    }
-	    else {
-	      sl_close_fd (FIL__, __LINE__, sock);
-	    }    
-	  } else if (sock == -1) {
-	    freeaddrinfo (ai);
-	    goto end;
-	  }
-	  p = p->ai_next;
-	}
-      
-      freeaddrinfo (ai);
-    }
-  else
-    {
-      sh_ipvx_set_port(&server_interface, server_port);
-
-      sock = do_socket(server_interface.ss_family, SOCK_STREAM, 0, 
-		       sh_ipvx_sockaddr_cast(&server_interface), 
-		       SH_SS_LEN(server_interface));
-      
-      if (sock >= 0) {
-	sh_tcp_sock[0] = sock;
-	sh_tcp_sock_n  = 1;
-      }
-    }	       
-#else
-  if (use_server_interface == 0)
-    addr.sin_addr.s_addr = INADDR_ANY;
-  else
-    memcpy(&addr, sh_ipvx_sockaddr_cast(&server_interface), addrlen);
-  addr.sin_family      = AF_INET;
-  addr.sin_port        = htons(server_port);
-  
-  sock = do_socket(AF_INET, SOCK_STREAM, 0, (struct sockaddr *) &addr, addrlen);
-
-  if (sock >= 0) {
-      sh_tcp_sock[0] = sock;
-      sh_tcp_sock_n  = 1;
-  }
-
-#endif
-
-#if defined(USE_IPVX)
- end:
-#endif
-  if (sh_tcp_sock_n > 1)
-    SH_MINSOCK += (sh_tcp_sock_n - 1);
-
-  SL_RETURN((sh_tcp_sock_n), _("sl_create_tcp_socket"));
-}
-
-/*****************************************
- *
- * This is the server main loop.
- *
- * The server is set up for listening, and
- * and starts a select() loop.
- *
- *****************************************/
-
-void sh_receive()
-{
-#ifdef SH_USE_XML
-  extern int  sh_log_file    (char * message, char * inet_peer);
-#endif
-
-  /* Use volatile to circumvent a gcc4 problem on RH/CentOS 4.8 (?) */
-  volatile int       sock = -1;
-  sh_conn_t        * cx;
-  fd_set             readset;
-  fd_set             writeset;
-  struct timeval     tv;
-  int                num_sel;
-  int                errnum;
-  int                nowconn;
-  int                status;
-  int                high_fd = -1;
-  register int       i;
-  long               dummy = 0;
-  unsigned long      time_now;
-  unsigned long      time_last = 0;
-  unsigned long      time_out = time_out_val;  
-  
-  time_t told;
-  time_t tcurrent;
-
-  unsigned long tchkold;
-
-  int setsize_fd;
-
-  int sock_tcp[2];
-  int sock_unix;
-#ifdef INET_SYSLOG
-  int sock_log[2];
-#endif
-  
-  SL_ENTER(_("sh_receive"));
-
-  if ( sh_forward_printerr_final(0) < 0)
-    {
-      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-    }
-
-  sock = sh_tcp_sock[0];
-
-  /* ****************************************************************
-   *
-   * This is a non-forking server. We use select() on the listen()
-   * socket to watch for new connections. For new connections, accept()
-   * will return a new socket that is put in the read/write filesets.
-   * Data about active connections are kept in the 'conns' table. 
-   *
-   ******************************************************************/
-  
-  /* The table to hold info on sockets.
-   * We reserve 6 file descriptors for misc. use.
-   * The POSIX lower limit on open files seems to be eight. 
-   */
-  maxconn    = get_open_max() - 6;
-
-  /* ugly fix for FreeBSD compiler warning; casting FD_SETSIZE in the
-   * conditional expression does not suppress the warning... */
-  setsize_fd = (int)FD_SETSIZE;
-  maxconn = (setsize_fd < maxconn) ? setsize_fd : maxconn;
-
-  if (maxconn < 0 || !sl_ok_muls(maxconn, sizeof(sh_conn_t)))
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV,
-		      0, sock);
-      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
-    }
-  conns   = SH_ALLOC (sizeof(sh_conn_t) * maxconn);
-
-  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV,
-		  (maxconn-1), sock);
-
-  /* timer
-   */
-  tcurrent                   = (unsigned long) time (NULL);
-  told                       = tcurrent;
-
-  tchkold                    = tcurrent;
-  
-  for (i = SH_MINSOCK; i < maxconn; ++i)
-    {
-      conns[i].buf         = NULL;
-      conns[i].K           = NULL;
-      conns[i].A           = NULL;
-      conns[i].M1          = NULL;
-      conns[i].FileName    = NULL;
-      conns[i].fd          = -1;
-      sh_forward_do_free ( &conns[i]);
-    }
-  
-  /* status init
-   */
-  server_status.conn_open  = 0;
-  server_status.conn_total = 0;
-  server_status.conn_max   = maxconn-1;
-  server_status.start      = time (NULL);
-  server_status.last       = (time_t) 0;
-
-  nowconn    = 1;
-  tv.tv_sec  = 5;
-  tv.tv_usec = 0;
-  
-  /* conns[0] is the listen() socket. Always in read mode.
-   */
-  sock = 0;
-
-  sock_tcp[0] = 0;
-  while (sock < sh_tcp_sock_n)
-    {
-      conns[sock].fd    = sh_tcp_sock[sock];
-      conns[sock].state = CONN_READING;
-      /* high_fd = (sh_tcp_sock[sock] > high_fd) ? sh_tcp_sock[sock] : high_fd; */
-      ++sock;
-    }
-  sock_tcp[1] = sock;
-  
-  conns[sock].fd    = pf_unix_fd;
-  conns[sock].state = CONN_READING;
-  /* high_fd = (pf_unix_fd > high_fd) ? pf_unix_fd : high_fd; */
-
-  sock_unix = sock;
-
-  ++sock;
-
-#ifdef INET_SYSLOG
-  conns[sock].fd = -1;
-
-  if ( sh_forward_printerr_final(1) < 0)
-    {
-      SH_FREE(conns);
-      conns = NULL;
-      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-    }
-
-  sock_log[0] = sock;
-  sock_log[1] = sock;
-
-  if (syslog_sock_n > 0)
-    {
-      int s2;
-      for (s2 = 0; s2 < syslog_sock_n; ++s2)
-	{
-	  conns[sock].fd    = syslog_sock[s2];
-	  conns[sock].state = CONN_READING;
-	  /* high_fd = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd; */
-	  ++sock;
-	}
-      sock_log[1] = sock;
-
-    }
-#endif
-  
-  sh_html_write(all_clients);
-  
-  /* This is the select() loop.
-   */
-  while (1 == 1)
-    {
-
-    if (sig_raised > 0)
-      {
-	TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
-
-	if (sig_termfast == 1)  /* SIGTERM */
-	  {
-	    TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
-	    strncpy (sh_sig_msg, _("SIGTERM"), 20);
-	    --sig_raised; --sig_urgent;
-	    aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
-	  }
-	  
-	if (sig_config_read_again == 1)
-	  {
-	    TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")));
-	    sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
-
-
-	    /* -- Delete the name server cache. --
-	     */
-
-	    delete_cache();
-#if defined(WITH_EXTERNAL)
-	    /* -- Delete list of external tasks. --
-	     */
-	    (void) sh_ext_cleanup();
-#endif
-#if defined(SH_WITH_MAIL)
-	      sh_nmail_free();
-#endif
-	    /* - mark all clients dead
-	     * - read configuration file
-	     * - remove clients still dead
-	     */
-	    sh_forward_mark_dead ();
-
-	    reset_count_dev_console();
-	    reset_count_dev_time();
-	    sl_trust_purge_user();
-
-	    (void) sh_readconf_read ();
-
-	    for (i = SH_MINSOCK; i < maxconn; ++i)
-	      if (conns[i].state != CONN_FREE   && 
-		  conns[i].client_entry != NULL &&
-		  conns[i].client_entry->dead_flag == 1)
-		sh_forward_do_free ( &conns[i]);
-	    sh_forward_clean_tree ();
-
-	    sig_config_read_again = 0;
-	    --sig_raised;
-	  }
-
-	if (sig_fresh_trail == 1) /* SIGIOT */
-	  {
-	    /* Logfile access 
-	     */
-#ifdef SH_USE_XML
-	    sh_log_file (NULL, NULL);
-#endif
-	    TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
-	    sh_error_only_stderr (S_TRUE);
-	    sh_unix_rm_lock_file(sh.srvlog.name);
-	    retry_msleep(3, 0);
-	    sh.flag.log_start = S_TRUE;
-	    sh_error_only_stderr (S_FALSE);
-	    sig_fresh_trail       = 0;
-	    --sig_raised;
-	  }
-	
-	  
-	if (sig_terminate == 1 && nowconn < 2)  /* SIGQUIT */
-	  {
-	    TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
-	    strncpy (sh_sig_msg, _("SIGQUIT"), 20);
-	    --sig_raised; --sig_urgent;
-	    aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
-	  }
-	
-	  
-	if (sig_debug_switch == 1)  /* SIGUSR1 */
-	  {
-	    TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
-	    sh_error_dbg_switch();
-	    sig_debug_switch = 0;
-	    --sig_raised;
-	  }
-	
-	if (sig_suspend_switch > 0)  /* SIGUSR2 */
-	  {
-	    TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
-	    if (sh_global_suspend_flag == 1) {
-	      sh_global_suspend_flag = 0;
-	    } else {
-	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, 
-			      sh.prg_name);
-	      sh_global_suspend_flag = 1;
-	    }
-	    --sig_suspend_switch;
-	    --sig_raised; --sig_urgent;
-	  }
-
-	sig_raised = (sig_raised < 0) ? 0 : sig_raised;
-	sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
-	TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
-      }
-      
-      if (sh_global_suspend_flag == 1)
-	{
-	  (void) retry_msleep (1, 0);
-	  continue;
-	}
-
-      /* Recompute the descriptor set. select() modifies it,
-       * thus we update it using the info from the connection table.
-       * Also recompute the number of open connections.
-       */
-      FD_ZERO( &readset );
-      FD_ZERO( &writeset );
-      high_fd = conns[0].fd;
-
-      for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock)
-	{
-	  FD_SET(conns[sock].fd, &readset );
-	  high_fd   = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd;
-	}
-
-      if (conns[sock_unix].fd > -1)
-	{
-	  FD_SET(conns[sock_unix].fd, &readset );
-	  high_fd   = (high_fd > conns[sock_unix].fd) ? high_fd : conns[sock_unix].fd;
-	}
-
-#ifdef INET_SYSLOG
-      for (sock = sock_log[0]; sock < sock_log[1]; ++sock)
-	{
-	  if (conns[sock].fd > -1)
-	    {
-	      FD_SET(conns[sock].fd, &readset );
-	      high_fd   = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd;
-	    }
-	}
-#endif
-
-      time_now  = (unsigned long) time (NULL);
-      nowconn   = 1;
-      
-      for (i = SH_MINSOCK; i < maxconn; ++i)
-	{
-	  /* eliminate timed out connections
-	   */
-	  if (conns[i].state != CONN_FREE) 
-	    {
-	      if (time_now-conns[i].timer > time_out)
-		{
-		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMOUT,
-				  conns[i].peer);
-		  sh_forward_do_free ( &conns[i]);
-		}
-	      else
-		++nowconn;
-	    }
-	  
-	  
-	  if       (conns[i].state   == CONN_READING)
-	    { 
-	      FD_SET(conns[i].fd, &readset);
-	      high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd);
-	    }
-	  else if  (conns[i].state   == CONN_SENDING)
-	    {
-	      FD_SET(conns[i].fd, &writeset);
-	      high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd);
-	    }
-	}
-
-      /* -- Exponentially reduce timeout limit if more than 1/2 full. --
-       */
-      /* Eliminate this, will cause problems when too much clients are
-       * starting up. */
-#if 0
-      if (nowconn > (maxconn/2))
-	time_out = ( (time_out/2) > 1) ? (time_out/2) : 1;
-      else
-	time_out = time_out_val;
-#endif
-      
-      
-      /* -- Do the select(). --
-       */
-      num_sel = select(high_fd+1, &readset, &writeset, NULL, &tv);
-      errnum  = errno;
-      
-      /* reset timeout - modified by select() on some systems
-       */
-      tv.tv_sec  = 5;
-      tv.tv_usec = 0;
-      
-
-      if ( (time_now - time_last) > 2L)
-	{
-	  time_last = time_now;
-	  if (sh_html_write(all_clients) < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML);
-	}
-      
-      
-      /* Error handling.
-       */
-      if ( num_sel < 0 )        /* some error             */
-	{
-	  char errbuf[SH_ERRBUF_SIZE];
-
-	  if (sig_raised == 1)
-	    {
-	      sig_raised = 2;
-	      continue;
-	    }
-
-	  if ( errnum == EINTR)
-	    continue;	  /* try again              */
-
-	  if ( errnum == EBADF)
-	    {
-	      /* seek and destroy the bad fd
-	       */
-	      for (i = SH_MINSOCK; i < high_fd; ++i)
-		{
-		  if ((conns[i].state == CONN_READING) ||
-		      (conns[i].state == CONN_SENDING))
-		    {
-		      if (-1 == retry_fcntl(FIL__, __LINE__, 
-					    conns[i].fd, F_GETFL, dummy))
-			sh_forward_do_free ( &conns[i]);
-		    }
-		}
-	      continue;
-	    }
-
-	  sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_EXIT_ABORTS,
-			  sh_error_message(errnum, errbuf, sizeof(errbuf)), 
-			  sh.prg_name,
-			  _("select"));
-	  aud_exit(FIL__, __LINE__,  EXIT_FAILURE );
-	}
-      
-
-      /* log the timestamp
-       */
-      if ((tcurrent - told) > sh.looptime )
-	{
-	  told = tcurrent;
-#ifdef MEM_DEBUG
-	  sh_mem_check();
-	  sh_unix_count_mlock();
-#else
-	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_STAMP);
-#endif
-	}
-
-#if defined(SH_WITH_MAIL)
-      /* 
-       * flush the mail queue
-       */
-      if (tcurrent - sh.mailTime.alarm_last > sh.mailTime.alarm_interval) 
-	{
-	  TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
-	  (void) sh_nmail_flush ();
-	  sh.mailTime.alarm_last = tcurrent;
-	}
-#endif
-#ifdef MEM_DEBUG
-      sh_mem_dump();
-#endif
-
-      tcurrent = (unsigned long) time (NULL);
-
-      /* check for time limit exceeded
-       */
-      if ((tcurrent - tchkold) > (unsigned int) 3 )
-	{
-	  tchkold = tcurrent;
-	  client_time_check(/* all_clients */);
-	  /* reset cache */
-	  sh_userid_destroy();
-	}
-      
-      /* seed / re-seed the PRNG if required
-       */
-      (void) taus_seed();
-
-      /* select() timeout handling.
-       */
-      if ( num_sel == 0 )       /* timeout - no connection */ 
-	{
-	  if (sh_html_write(all_clients) < 0)
-	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML);
-	  continue;
-	}
-
-      /* New connection.
-       */
-      for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock)
-	{
-	  if ( FD_ISSET(conns[sock].fd , &readset )) /* a new connection   */
-	    {
-	      --num_sel;
-	      status = 0;
-	      if (nowconn < maxconn && sig_terminate == 0 && sig_termfast == 0)
-		{
-		  /* Find a free slot to accept the connection
-		   */
-		  i = SH_MINSOCK;
-		  while (i < maxconn)
-		    {
-		      if (conns[i].state == CONN_FREE)
-			{
-			  /* Here we run the accept() and copy the peer to
-			   * the free slot. 
-			   */
-			  status = sh_forward_accept(conns[sock].fd, &conns[i]);
-			  
-			  if (status == 0)
-			    {
-			      high_fd = 
-				(high_fd > conns[i].fd ? high_fd : conns[i].fd);
-			      ++server_status.conn_open;
-			      ++server_status.conn_total;
-			      server_status.last = time (NULL);
-			    }
-			  break;
-			}
-		      ++i;
-		    }
-		}
-	      /* This re-runs select to accept data on the new
-	       * connection, rather than first dealing with old
-	       * connections.
-	       */
-	      if (status == 0) 
-		continue;
-	    }
-	}
-      
-      /* check for commands on the socket
-       */
-      if (conns[sock_unix].fd > (-1) && FD_ISSET(conns[sock_unix].fd , &readset ))
-	{
-	  sh_socket_poll();
-	}
-
-#ifdef INET_SYSLOG
-      for (sock = sock_log[0]; sock < sock_log[1]; ++sock)
-	{
-	  if (conns[sock].fd > (-1) && FD_ISSET(conns[sock].fd , &readset ))
-	    {
-	      recv_syslog_socket (conns[sock].fd);
-	    }
-	}
-#endif
-
-      /* Check for pending read/write on the rest of the sockets.
-       */
-      for ( i = SH_MINSOCK; num_sel > 0 && i < maxconn; ++i )
-	{
-	  if (sig_termfast == 1)
-	    break;
-
-	  cx = &conns[i];
-	  if ( cx->state == CONN_READING &&
-	       FD_ISSET( cx->fd, &readset ) )
-	    {
-	      --num_sel;
-	      sh_forward_do_read ( cx );
-	    }
-	  else if ( cx->state == CONN_SENDING &&
-		    FD_ISSET( cx->fd, &writeset ) )
-	    {
-	      --num_sel;
-	      sh_forward_do_write ( cx );
-	    }
-	}
-      /* continue */
-    }
-  /* notreached */
-}
-
-void  free_client_tree (void)
-{
-  SL_ENTER(_("free_client_tree"));
-  zAVLFreeTree (all_clients, free_client);
-  SL_RET0(_("free_client_tree"));
-}
-
-void sh_forward_free_all ()
-{
-  register int i;
-  
-  SL_ENTER(_("sh_forward_free_all"));
-
-  if (conns != NULL)
-    for (i = SH_MINSOCK; i < maxconn; ++i)
-      {
-	sh_forward_do_free ( &conns[i]);
-      }
-
-
-  free_client_tree ();
-
-  if (conns != NULL)
-    SH_FREE (conns);
-
-  SL_RET0(_("sh_forward_free_all"));
-}
-
-#ifdef INET_SYSLOG
-
-/* Unlike Linux / FreeBSD, most systems don't define the stuff below
- * in syslog.h
- */
-
-#ifndef LOG_FAC
-#define LOG_FAC(p)      (((p) & LOG_FACMASK) >> 3)
-#endif
-
-#ifndef LOG_PRI
-#define LOG_PRI(p)      ((p) & LOG_PRIMASK)
-#endif
-
-typedef struct sh_code {
-        char    *c_name;
-        int     c_val;
-} SH_CODE;
-
-SH_CODE sh_facilitynames[] =
-{
-#ifdef LOG_AUTH
-  { N_("auth"), LOG_AUTH },
-#endif
-#ifdef LOG_AUTHPRIV 
-  { N_("authpriv"), LOG_AUTHPRIV },
-#endif
-#ifdef LOG_CRON
-  { N_("cron"), LOG_CRON },
-#endif
-#ifdef LOG_DAEMON
-  { N_("daemon"), LOG_DAEMON },
-#endif
-#ifdef LOG_FTP
-  { N_("ftp"), LOG_FTP },
-#endif
-#ifdef LOG_KERN
-  { N_("kern"), LOG_KERN },
-#endif
-#ifdef LOG_LPR
-  { N_("lpr"), LOG_LPR },
-#endif
-#ifdef LOG_MAIL
-  { N_("mail"), LOG_MAIL },
-#endif
-#ifdef INTERNAL_MARK
-  { N_("mark"), INTERNAL_MARK },          /* INTERNAL */
-#endif
-#ifdef LOG_NEWS
-  { N_("news"), LOG_NEWS },
-#endif
-#ifdef LOG_AUTH
-  { N_("security"), LOG_AUTH },           /* DEPRECATED */
-#endif
-#ifdef LOG_SYSLOG
-  { N_("syslog"), LOG_SYSLOG },
-#endif
-#ifdef LOG_USER
-  { N_("user"), LOG_USER },
-#endif
-#ifdef LOG_UUCP
-  { N_("uucp"), LOG_UUCP },
-#endif
-#ifdef LOG_LOCAL0
-  { N_("local0"), LOG_LOCAL0 },
-#endif
-#ifdef LOG_LOCAL1
-  { N_("local1"), LOG_LOCAL1 },
-#endif
-#ifdef LOG_LOCAL2 
-  { N_("local2"), LOG_LOCAL2 },
-#endif
-#ifdef LOG_LOCAL3
-  { N_("local3"), LOG_LOCAL3 },
-#endif
-#ifdef LOG_LOCAL4
-  { N_("local4"), LOG_LOCAL4 },
-#endif
-#ifdef LOG_LOCAL5
-  { N_("local5"), LOG_LOCAL5 },
-#endif
-#ifdef LOG_LOCAL6
-  { N_("local6"), LOG_LOCAL6 },
-#endif
-#ifdef LOG_LOCAL7
-  { N_("local7"), LOG_LOCAL7 },
-#endif
-  { NULL, -1 }
-};
- 
-
-SH_CODE sh_prioritynames[] =
-{  
-#ifdef LOG_ALERT
-  { N_("alert"), LOG_ALERT },
-#endif
-#ifdef LOG_CRIT
-  { N_("crit"), LOG_CRIT },
-#endif
-#ifdef LOG_DEBUG
-  { N_("debug"), LOG_DEBUG },
-#endif
-#ifdef LOG_EMERG
-  { N_("emerg"), LOG_EMERG },
-#endif
-#ifdef LOG_ERR
-  { N_("err"), LOG_ERR },
-#endif
-#ifdef LOG_ERR
-  { N_("error"), LOG_ERR },               /* DEPRECATED */
-#endif
-#ifdef LOG_INFO
-  { N_("info"), LOG_INFO },
-#endif
-#ifdef INTERNAL_NOPRI
-  { N_("none"), INTERNAL_NOPRI },         /* INTERNAL */
-#endif
-#ifdef LOG_NOTICE
-  { N_("notice"), LOG_NOTICE },
-#endif
-#ifdef LOG_EMERG
-  { N_("panic"), LOG_EMERG },             /* DEPRECATED */
-#endif
-#ifdef LOG_WARNING
-  { N_("warn"), LOG_WARNING },            /* DEPRECATED */
-#endif
-#ifdef LOG_WARNING
-  { N_("warning"), LOG_WARNING },
-#endif
-  { NULL, -1 }
-};
-
-static int enable_syslog_socket = S_FALSE;
-
-static int recv_syslog_socket (int fd)
-{
-  static time_t      return_next = 0;
-  int                priority = 0;
-  int                fac, pri;
-  int                i;
-  char             * cfac = NULL;
-  char             * cpri = NULL;
-  int                res;
-  char             * tmp;
-  char             * bptr;
-  char             * ptr = NULL;
-  char               buf[1048];
-  struct sockaddr_in from;
-  char errbuf[SH_ERRBUF_SIZE];
-
-  struct sh_sockaddr ss;
-  struct sockaddr * sa = (struct sockaddr *) &from;
-  char   namebuf[SH_BUFSIZE];
-
-  /* The 6th argument in recvfrom is *socklen_t in Linux and *BSD, 
-   * but *int everywhere else. Because socklen_t is unsigned int, there
-   * should be no problem as long as  sizeof(struct sockaddr_in) < INT_MAX ...
-   */
-  unsigned int fromlen = sizeof(from);
-
-  if (enable_syslog_socket == S_FALSE)
-    return 0;
-
-  SL_ENTER(_("recv_syslog_socket"));
-
-  if (return_next > 0)
-    {
-      if ( (time(NULL) - return_next) < 2)
-	SL_RETURN( 0, _("recv_syslog_socket"));
-      else
-	return_next = 0;
-    }
-
-  res = recvfrom(fd,  buf,  1047, 0, (struct sockaddr *) &from, &fromlen);
-
-  sh_ipvx_save(&ss, sa->sa_family, (struct sockaddr *) &from);
-  sh_ipvx_ntoa(namebuf, sizeof(namebuf), &ss);
-
-  if (res > 0)
-    {
-      res = (res < 1047) ? res : 1047; 
-      buf[res] = '\0';
-      if (res > 1 && buf[res-1] == '\n')
-	buf[res-1] = '\0';
-
-      /* here we expect an xml formatted message, thus we don't
-	 escape xml special chars (flag == 0) */
-      /* commented out to not escape twice    */
-      /* bptr = sh_tools_safe_name(buf, 0);   */
-      bptr = buf;
-
-      if (!bptr || !(*bptr))
-	{
-	  res = errno;
-	  TPT(( 0, FIL__, __LINE__, _("msg=<UDP error: %d>\n"), res));
-	  sh_error_handle((-1), FIL__, __LINE__, res, MSG_ERR_SYSLOG,
-			  sh_error_message(res, errbuf, sizeof(errbuf)), 
-			  namebuf);
-	  SL_RETURN( (-1), _("recv_syslog_socket"));
-	}      
-
-      TPT(( 0, FIL__, __LINE__, _("msg=<UDP message from %s>\n"), namebuf ));
-
-      ptr = bptr;
-      i = 0;
-      if (*ptr == '<') 
-	{
-	  ++ptr; ++i;
-	  while (i < res &&
-		 (unsigned char) *ptr > 47 && (unsigned char) *ptr < 58)
-	    {
-	      priority = 10 * priority + (*ptr - '0');
-	      ++ptr;
-	      ++i;
-	    }
-	  if (*ptr == '>')
-	    ++ptr;
-	}
-      fac = LOG_FAC(priority);
-      i = 0; 
-      while (sh_facilitynames[i].c_name != NULL)
-	{
-	  if (sh_facilitynames[i].c_val == (fac<<3))
-	    { cfac = sh_util_strdup(_(sh_facilitynames[i].c_name)); break; }
-	  ++i;
-	}
-      pri = LOG_PRI(priority);
-      i = 0; 
-      while (sh_prioritynames[i].c_name != NULL)
-	{
-	  if (sh_prioritynames[i].c_val == pri)
-	    { cpri = sh_util_strdup(_(sh_prioritynames[i].c_name)); break; }
-	  ++i;
-	}
-
-      /* here we do not expect an xml formatted message, thus we escape
-	 xml special chars (flag == 1) */
-      tmp = sh_tools_safe_name (ptr, 1);
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_INET_SYSLOG,
-		      namebuf, 
-		      (cfac == NULL) ? _("none") : cfac, 
-		      (cpri == NULL) ? _("none") : cpri, 
-		      (tmp  == NULL) ? _("none") : tmp);
-      if (cfac != NULL)
-	SH_FREE(cfac);
-      if (cpri != NULL)
-	SH_FREE(cpri);
-      SH_FREE(tmp);
-      /* SH_FREE(bptr); */
-    }
-
-  else if (res < 0 && errno != EINTR)
-    {
-      res = errno;
-      TPT(( 0, FIL__, __LINE__, _("msg=<UDP error: %d>\n"), res));
-      sh_error_handle((-1), FIL__, __LINE__, res, MSG_ERR_SYSLOG,
-		      sh_error_message(res, errbuf, sizeof(errbuf)), 
-		      namebuf);
-
-      /* don't accept anything the next 2 seconds
-       */
-      return_next = time(NULL);
-      SL_RETURN( (-1), _("recv_syslog_socket"));
-    }      
-  SL_RETURN( (0), _("recv_syslog_socket"));
-}
-
-int set_syslog_active(const char * c)
-{
-  return sh_util_flagval(c, &enable_syslog_socket);
-}
-
-static int do_syslog_socket(int domain, int type, int protocol,
-			    struct sockaddr * sa, int salen)
-{
-  int                flag = 1;  /* non-zero to enable an option */
-  int sock;
-  int errnum;
-  int res;
-
-  /* create the socket, bind() it and listen()
-   */
-  sock = socket(domain, type, protocol);
-
-  if (sock < 0)
-    {
-      errnum = errno; 
-      sh_forward_printerr (_("syslog socket"), errnum, 514, __LINE__);
-      return -1;
-    }
-  (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 );
-  
-  if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-		  (void *) &flag, sizeof(flag)) < 0 )
-    {
-      errnum = errno;
-      sh_forward_printerr (_("syslog setsockopt SO_REUSEADDR"), 
-			   errnum, 514, __LINE__);
-      return -1;
-    }
-
-#if defined(SO_BSDCOMPAT)
-  if ( setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
-		  (void *) &flag, sizeof(flag)) < 0 )
-    {
-      errnum = errno;
-      sh_forward_printerr (_("syslog setsockopt SO_BSDCOMPAT"), 
-			   errnum, 514, __LINE__);
-      return -1;
-    }
-#endif
-  
-  res = bind(sock, sa, salen);
-
-  if ( res < 0) 
-    {
-      errnum = errno;
-      sh_forward_printerr (_("syslog bind"), errnum, 514, __LINE__);
-      sl_close_fd(FIL__, __LINE__, sock);
-      return -1;
-    }
-  return sock;
-}
-
-/* callerFlag == S_TRUE means override the enable_syslog_socket flag
- */
-int create_syslog_socket (int callerFlag)
-{
-  int sock;
-
-#if defined(USE_IPVX)
-  struct addrinfo *ai;
-  struct addrinfo *p;
-  struct addrinfo hints;
-#else
-  struct sockaddr_in addr;
-  int addrlen      = sizeof(addr);
-#endif
-
-  SL_ENTER(_("create_syslog_socket"));
-
-  if (callerFlag == S_FALSE)
-    {
-      if (enable_syslog_socket == S_FALSE && syslog_sock_n > 0)
-	{
-	  /* user does not wish to use this facility
-	   */
-	  TPT(( 0, FIL__, __LINE__, _("msg=<close syslog socket>\n")));
-	  for (sock = 0; sock < syslog_sock_n; ++sock)
-	    {
-	      sl_close_fd(FIL__, __LINE__, syslog_sock[sock]);
-	      syslog_sock[0] = -1;
-	    }
-	}
-      SL_RETURN((-1), _("create_syslog_socket"));
-    }
-
-  sh_forward_printerr (NULL, 0, 514, __LINE__);
-
-#if !defined(USE_IPVX)
-
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family      = AF_INET;
-  addr.sin_port        = htons(514);
-  
-  sock = do_syslog_socket(AF_INET, SOCK_DGRAM, 0, 
-			  (struct sockaddr *) &addr, addrlen);
-
-  if (sock >= 0) {
-    syslog_sock[0] = sock;
-    syslog_sock_n  = 1;
-  }
-
-#else
-  memset (&hints, '\0', sizeof (hints));
-  hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
-  hints.ai_socktype = SOCK_DGRAM;
-  if (getaddrinfo (NULL, "syslog", &hints, &ai) != 0)
-    {
-      int errnum = errno;
-      sh_forward_printerr (_("getaddrinfo"), errnum, 514, __LINE__);
-      SL_RETURN((-1), _("create_syslog_socket"));
-    }
-  
-  p = ai;
-
-  while (p != NULL && syslog_sock_n < SH_SOCKMAX)
-    {
-      sock = do_syslog_socket(p->ai_family, p->ai_socktype, p->ai_protocol,
-			      p->ai_addr, p->ai_addrlen);
-      
-      if (sock >= 0) {
-	if (syslog_sock_n < SH_SOCKMAX) {
-	  syslog_sock[syslog_sock_n] = sock;
-	  ++syslog_sock_n;
-	}
-	else {
-	  sl_close_fd (FIL__, __LINE__, sock);
-	}    
-      } else if (sock == -1) {
-	freeaddrinfo (ai);
-	goto end;
-      }
-      p = p->ai_next;
-    }
-  freeaddrinfo (ai);
-
- end:
-#endif
-  if (syslog_sock_n > 1)
-    SH_MINSOCK += (syslog_sock_n - 1);
-
-  SL_RETURN((syslog_sock_n), _("create_syslog_socket"));
-}
-/* #ifdef INET_SYSLOG */
-#endif
-
-
-
-/* #ifdef SH_WITH_SERVER */
-#endif
-
-
-  
-
-
-
Index: trunk/src/sh_getopt.c
===================================================================
--- trunk/src/sh_getopt.c	(revision 476)
+++ trunk/src/sh_getopt.c	(revision 481)
@@ -34,6 +34,10 @@
 #include "sh_utils.h"
 #include "sh_mail.h"
-#include "sh_forward.h"
+#include "sh_xfer.h"
 #include "sh_hash.h"
+#include "sh_dbIO.h"
+#include "sh_dbCheck.h"
+#include "sh_dbCreate.h"
+#include "sh_sem.h"
 
 #if defined(WITH_EXTERNAL)
@@ -64,4 +68,5 @@
 #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
 static int sh_getopt_forever (const char * dummy);
+static int sh_getopt_outpath (const char * dummy);
 #endif
 static int sh_getopt_copyright (const char * dummy);
@@ -92,10 +97,10 @@
     N_("Set the server port to connect to"),  
     HAS_ARG_YES, 
-    sh_forward_server_port },
+    sh_xfer_server_port },
   { N_("server-host"),  
     '-', 
     N_("Set the server host to connect to"),  
     HAS_ARG_YES, 
-    sh_forward_setlogserver },
+    sh_xfer_set_logserver },
 #endif
 #ifdef SH_WITH_SERVER
@@ -109,5 +114,5 @@
     N_("Log fully qualified name of client host"),  
     HAS_ARG_NO, 
-    sh_forward_set_strip },
+    sh_xfer_set_strip },
   { N_("chroot"),  
     '-', 
@@ -222,10 +227,10 @@
     N_("Compute a client registry entry for password"),  
     HAS_ARG_YES, 
-    sh_forward_make_client },
+    sh_xfer_make_client },
   { N_("gen-password"),  
     'G', 
     N_("Generate a random password"),  
     HAS_ARG_NO, 
-    sh_forward_create_password },
+    sh_xfer_create_password },
 #endif
 
@@ -236,29 +241,59 @@
     HAS_ARG_NO, 
     sh_getopt_forever},
+  { N_("outfile"),  
+    'o', 
+    N_("Pathname for output file"),  
+    HAS_ARG_YES, 
+    sh_getopt_outpath},
   { N_("list-file"),  
     '-', 
-    N_("Modify -d to list content of a single file"),  
+    N_("Modify -d to show content of a single file"),  
     HAS_ARG_YES, 
     set_list_file},
+  { N_("list-filter"),  
+    '-', 
+    N_("Modify -d to filter by file list given in text file"),  
+    HAS_ARG_YES, 
+    sh_dbIO_list_filter},
   { N_("full-detail"),  
     'a', 
-    N_("Modify -d to list full details"),  
+    N_("Modify -d to show full details"),  
     HAS_ARG_NO, 
     set_full_detail},
   { N_("delimited"),  
     '-', 
-    N_("Modify -d to list full details, comma delimited"),  
+    N_("Modify -d to show full details, comma delimited"),  
     HAS_ARG_NO, 
     set_list_delimited},
+  { N_("binary"),  
+    '-', 
+    N_("Modify -d to output in binary database format"),  
+    HAS_ARG_NO, 
+    sh_dbIO_list_binary},
   { N_("list-database"),  
     'd', 
     N_("List database content (like ls -l)"),  
     HAS_ARG_YES, 
-    sh_hash_list_db},
+    sh_dbIO_list_db},
   { N_("init2stdout"),  
     '-', 
     N_("Write database to stdout on init"),  
     HAS_ARG_NO, 
-    sh_hash_pushdata_stdout},
+    sh_dbIO_writeout_stdout},
+  { N_("verify-database"),  
+    '-', 
+    N_("Verify the given database"),  
+    HAS_ARG_YES, 
+    sh_dbCheck_verify},
+  { N_("create-database"),  
+    '-', 
+    N_("Create database from file list"),  
+    HAS_ARG_YES, 
+    sh_dbCreate},
+  { N_("wait-on-check"),  
+    'w', 
+    N_("Timed wait for end of filecheck (0 for no timeout)"),  
+    HAS_ARG_YES, 
+    sh_sem_wait},
 #endif
   { N_("trace-logfile"),  
@@ -744,4 +779,16 @@
   sh.flag.loop = S_TRUE;
   SL_RETURN(0, _("sh_getopt_forever"));
+}
+
+static int sh_getopt_outpath (const char * str)
+{
+  if (str)
+    {
+      if (sh.outpath)
+	SH_FREE(sh.outpath);
+      sh.outpath = sh_util_strdup(str);
+      return 0;
+    }
+  return -1;
 }
 #endif  
Index: trunk/src/sh_gpg.c
===================================================================
--- trunk/src/sh_gpg.c	(revision 476)
+++ trunk/src/sh_gpg.c	(revision 481)
@@ -60,4 +60,5 @@
 #include "sh_static.h"
 #endif
+#include "sh_gpg.h"
 
 static struct {
@@ -128,9 +129,5 @@
   SL_ENTER(_("sh_gpg_checksum"));
 
-#if defined(WITH_PGP)
-  test_gpg = sh_tiger_hash_gpg (DEFAULT_PGP_PATH, checkfd, TIGER_NOLIM);
-#else
   test_gpg = sh_tiger_hash_gpg (DEFAULT_GPG_PATH, checkfd, TIGER_NOLIM);
-#endif
   
   test_ptr1 = strchr(GPG_HASH, ':');
@@ -252,14 +249,10 @@
   char   cc1[32];
   char   cc2[32];
-#if defined(WITH_PGP)
-  char   cc3[32];
-  char   cc0[3] = "-f";
-#endif
-#if defined(WITH_GPG)
+
   char   cc0[2] = "-";
   char   cc3[32];
   char   cc4[SH_PATHBUF+32];
   char   cc5[32];
-#endif
+
 
   char * arg[9];
@@ -279,5 +272,4 @@
   SL_ENTER(_("sh_gpg_popen"));
 
-#if defined(WITH_GPG)
   /* -- GnuPG -- */
   sl_strlcpy (path,  DEFAULT_GPG_PATH,  256);
@@ -387,33 +379,4 @@
   (void) mode;
   (void) id;
-#elif defined(WITH_PGP)
-  /* -- PGP -- */
-  sl_strlcpy (path,  DEFAULT_PGP_PATH, 256);
-  if (mode == 0)
-    {
-      sl_strlcpy (cc1,   _("+language=en"),  32);
-      sl_strlcpy (cc2,   _("-o"),     32);
-      sl_strlcpy (cc3,   _("/dev/null"),     32);
-      
-      arg[0] = path; 
-      arg[1] = cc1;
-      arg[2] = cc2; 
-      arg[3] = cc3; 
-      arg[4] = cc0;
-      arg[5] = NULL;
-    }
-  else
-    {
-      sl_strlcpy (cc1,   _("+language=en"),  32);
-      sl_strlcpy (cc2,   _("-kvc"),     32);       
-      
-      arg[0] = path; 
-      arg[1] = cc1;
-      arg[2] = cc2;
-      arg[3] = id;
-      arg[4] = NULL;
-      arg[5] = NULL;
-    }
-#endif
 
   /* use homedir of effective user
@@ -467,16 +430,4 @@
       sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
       
-
-#if defined(WITH_PGP)
-      if (mode == 0) 
-	{
-	  if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
-	    {
-	      TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
-	      dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
-	      aud__exit(FIL__, __LINE__, EXIT_FAILURE);
-	    }
-	}
-#else
       if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
 	{
@@ -485,11 +436,10 @@
 	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
 	}
-#endif
  
       /* don't leak file descriptors
        */
-      sh_unix_closeall (3, -1, SL_TRUE); /* in child process */
-
-      if (flag_err_debug != SL_TRUE)
+      sh_unix_closeall (3, -1, S_TRUE); /* in child process */
+
+      if (flag_err_debug != S_TRUE)
 	{
 	  if (NULL == freopen(_("/dev/null"), "r+", stderr))
@@ -530,9 +480,5 @@
        * --  emulate an fexecve with checksum testing
        */
-#if defined(WITH_PGP)
-      checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_NOPRIV);
-#else
       checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV);
-#endif
 
       if (0 != sh_gpg_checksum(checkfd, 0))
@@ -580,9 +526,7 @@
       for (i = 0; i < myrand; ++i)
 	{
-#if defined(WITH_PGP)
-	  checkfd = sl_open_fastread(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_NOPRIV);
-#else
-	  checkfd = sl_open_fastread(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV);
-#endif
+	  checkfd = sl_open_fastread(FIL__, __LINE__, 
+				     DEFAULT_GPG_PATH, SL_NOPRIV);
+
 	  if (0 != sh_gpg_checksum(checkfd, 0)) {
 	    aud__exit(FIL__, __LINE__, EXIT_FAILURE);
@@ -591,13 +535,8 @@
 	}
 #endif
-			       
-
-#if defined(WITH_GPG)
+
       retry_aud_execve (FIL__, __LINE__, DEFAULT_GPG_PATH, arg, envp);
       dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
 	   DEFAULT_GPG_PATH);
-#elif defined(WITH_PGP)
-      retry_aud_execve (FIL__, __LINE__, DEFAULT_PGP_PATH, arg, envp);
-#endif
       
       /* failed 
@@ -659,7 +598,4 @@
   sh_gpg_popen_t  source;
   int have_id = BAD, have_fp = BAD, status = 0;
-#ifdef WITH_PGP
-  char *ptr;
-#endif
 
 #ifdef HAVE_GPG_CHECKSUM
@@ -671,6 +607,4 @@
   /* check whether GnuPG exists and has the correct checksum
    */
-#if defined(WITH_GPG)
-
   TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
   TPT(((0), FIL__, __LINE__, _("msg=<gpg is %s>\n"), DEFAULT_GPG_PATH));
@@ -701,37 +635,4 @@
     }
   sl_close(checkfd);
-#endif
-
-#elif defined(WITH_PGP)
-
-  TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
-  TPT(((0), FIL__, __LINE__, _("msg=<pgp is %s>\n"), DEFAULT_PGP_PATH));
-
-  if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_PGP_PATH, &buf))
-    {
-      char errbuf[SH_ERRBUF_SIZE];
-
-      status = errno;
-      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
-		      sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_PGP_PATH);
-      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-    }
-  if (0 != tf_trust_check (DEFAULT_PGP_PATH, SL_YESPRIV))
-    SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-
-#ifdef HAVE_GPG_CHECKSUM
-  checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_PGP_PATH, SL_YESPRIV);
-
-  if (0 != sh_gpg_checksum(checkfd, 1))
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      _("Checksum mismatch"), 
-		      _("gpg_check_file_sign"));
-      sl_close(checkfd);
-      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-    }
-  sl_close(checkfd);
-#endif
-
 #endif
 
@@ -768,5 +669,5 @@
       if (sl_strlen(line) < 18) 
 	continue;
-#if defined(WITH_GPG)
+
       /* Sun May 27 18:40:05 CEST 2001
        */
@@ -821,37 +722,10 @@
 	  have_fp = GOOD;
 	}
-#elif defined(WITH_PGP)
-      if (0 == sl_strncmp(_("Bad signature"), line, 13) ||
-	  0 == sl_strncmp(_("Error"), line, 5) ||
-	  0 == sl_strncmp(_("Malformed"), line, 9) ||
-	  0 == sl_strncmp(_("WARNING"), line, 7) ||
-	  0 == sl_strncmp(_("ERROR"), line, 5) 
-	  )
-	{
-	  have_fp = BAD; have_id = BAD;
-	  break;
-	}
-      if (0 == sl_strncmp(_("Good signature"), line, 14))
-	{
-	  ptr = strchr ( line, '"');
-	  ++ptr;
-	  if (ptr)
-	    {
-	      sl_strlcpy (sign_id, ptr, SH_MINIBUF+1);
-	      sign_id[sl_strlen(sign_id)-1] = '\0'; /* remove trailing dot */
-	      sign_id[sl_strlen(sign_id)-2] = '\0'; /* remove trailing '"' */
-	    }
-	  else
-	    {
-	      sl_strlcpy (sign_id, _("(null)"), SH_MINIBUF+1);
-	    }
-	  have_id = GOOD;
-	}
-#endif
     }
 
   if (ferror(source.pipe) && errno == EAGAIN) 
     {
-      retry_msleep(0,10); /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
+      /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
+      retry_msleep(0,10); 
       clearerr(source.pipe);
       goto xagain;
@@ -862,91 +736,11 @@
   TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
 
-#ifdef WITH_PGP
-  /* get the fingerprint */
-
-  source.pipe   = sh_gpg_popen  ( &source, fd, 1,  sign_id, homedir);
-  if (NULL == source.pipe)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      _("Could not open pipe for fp"), 
-		      _("gpg_check_file_sign"));
-      SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-    }
-
-  TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
-
- yagain:
-
-  errno = 0;
-
-  while (NULL != fgets(line, sizeof(line), source.pipe))
-    {
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
-      char * saveptr = NULL;
-#endif
-      if (line[strlen(line)-1] == '\n')
-	line[strlen(line)-1] = ' ';
-      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      line, 
-		      _("gpg_check_file_sign"));
-
-      if (sl_strlen(line) < 18) 
-	continue;
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
-      ptr = strtok_r (line, " ", &saveptr);
-#else
-      ptr = strtok (line, " ");
-#endif
-      while (ptr)
-	{
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
-	  ptr = strtok_r (NULL, " ", &saveptr);
-#else
-	  ptr = strtok (NULL, " ");
-#endif
-	  if (ptr && 0 == sl_strncmp (ptr, _("fingerprint"), 11))
-	    {
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
-	      ptr = strtok_r (NULL, " ", &saveptr); /* to '=' */
-#else
-	      ptr = strtok (NULL, " "); /* to '=' */
-#endif
-	      sign_fp[0] = '\0';
-	      while (ptr)
-		{
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
-		  ptr = strtok_r (NULL, " ", &saveptr); /* part of fingerprint */
-#else
-		  ptr = strtok (NULL, " "); /* part of fingerprint */
-#endif
-		  sl_strlcat (sign_fp, ptr, SH_MINIBUF+1);
-		}
-	      /* sign_fp[sl_strlen(sign_fp)-1] = '\0'; remove trailing '\n' */
-	      if (sl_strlen(sign_fp) > 0) 
-		have_fp = GOOD;
-	      break;
-	    } 
-	} 
-    }
-
-  if (ferror(source.pipe) && errno == EAGAIN) 
-    {
-      retry_msleep(0,10); /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
-      clearerr(source.pipe);
-      goto yagain;
-    }
- 
-  sh_gpg_pclose (&source);
-#endif
-
   if (have_id == GOOD)
     {
       TPT(((0), FIL__, __LINE__, _("msg=<Got signator ID>\n")));
-      ;
     }
   if (have_fp == GOOD)
     {
       TPT(((0), FIL__, __LINE__, _("msg=<Got fingerprint>\n")));
-      ;
     }
 
@@ -969,17 +763,24 @@
 int get_the_fd(SL_TICKET file_1);
 
-int sh_gpg_check_sign (long file_1, long file_2, int what)
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && \
+  defined(HAVE_GETPWNAM_R)
+#define USE_GETPWNAM_R 1
+#endif
+
+int sh_gpg_check_sign (long file, int what)
 {
   int status = SH_GPG_BAD;
-  int fd1 = 0;
-  int fd2 = 0;
+  int fd = 0;
+
   static int smsg = S_FALSE;
   char  * tmp;
-  char  * tmp2;
+
+  char  * sig_id;
+  char  * sig_fp;
 
   char  * homedir = sh.effective.home;
 #if defined(SH_WITH_SERVER)
   struct passwd * tempres;
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+#if defined(USE_GETPWNAM_R)
   struct passwd    pwd;
   char           * buffer = SH_ALLOC(SH_PWBUF_SIZE);
@@ -994,36 +795,27 @@
 
 
-  if (what == 0 || what == 1)
-    fd1 = get_the_fd(file_1);
-  if (what == 0 || what == 2)
-    fd2 = get_the_fd(file_2);
-
-
-  if (fd1 < 0 || fd2 < 0)
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD1 = %d>\n"), fd1));
-      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD2 = %d>\n"), fd2));
+  if (what == SIG_CONF)
+    fd = get_the_fd(file);
+  if (what == SIG_DATA)
+    fd = get_the_fd(file);
+
+
+  if (fd < 0)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
       dlog(1, FIL__, __LINE__, 
 	   _("This looks like an unexpected internal error.\n"));
-      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
-      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+      SH_FREE(buffer);
+#endif
+      SL_RETURN( (-1), _("sh_gpg_check_sign"));
+    }
+  
 #if defined(SH_WITH_SERVER)
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
-      SH_FREE(buffer);
-#endif
-#endif
-      SL_RETURN( (-1), _("sh_gpg_check_sign"));
-    }
-  
-  if (what == 0 || what == 1)
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD1 = %d>\n"), fd1));
-#if defined(SH_WITH_SERVER)
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+#if defined(USE_GETPWNAM_R)
       sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
 #else
       tempres = sh_getpwnam(DEFAULT_IDENT);
 #endif
-
       if ((tempres != NULL) && (0 == sl_ret_euid()))
 	{
@@ -1032,132 +824,81 @@
 	}
 #endif
-      status = sh_gpg_check_file_sign(fd1, gp.conf_id, gp.conf_fp, homedir, 1);
+
+  if (what == SIG_CONF)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+      status = sh_gpg_check_file_sign(fd, gp.conf_id, gp.conf_fp, homedir, 1);
       TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGUSR: |%s|>\n"), gp.conf_id));
       TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGFP:  |%s|>\n"), gp.conf_fp));
-    }
-
-  if ((what == 0 && SH_GPG_OK == status) || what == 2)
-    {
-      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD2 = %d>\n"), fd2));
-#if defined(SH_WITH_SERVER)
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
-      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
-#else
-      tempres = sh_getpwnam(DEFAULT_IDENT);
-#endif
-
-      if ((tempres != NULL) && (0 == sl_ret_euid()))
-	{
-	  /* privileges not dropped yet*/
-	  homedir = tempres->pw_dir;
-	}
-#endif
-      status = sh_gpg_check_file_sign(fd2, gp.data_id, gp.data_fp, homedir, 2);
+      sig_id =  gp.conf_id; sig_fp = gp.conf_fp;
+    }
+
+  if (what == SIG_DATA)
+    {
+      TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+      status = sh_gpg_check_file_sign(fd, gp.data_id, gp.data_fp, homedir, 2);
       TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGUSR: |%s|>\n"), gp.data_id));
       TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGFP:  |%s|>\n"), gp.data_fp));
+      sig_id =  gp.data_id; sig_fp = gp.data_fp;
     }
   
-  if (SH_GPG_OK == status && what == 1)
+  if (SH_GPG_OK == status)
     {
 #ifdef USE_FINGERPRINT
-      if ((sl_strcmp(SH_GPG_FP, gp.conf_fp) == 0))
+      if ((sl_strcmp(SH_GPG_FP, sig_fp) == 0))
 	{
 	  int i;
 
-	  for(i = 0; i < (int) sl_strlen(gp.conf_fp); ++i)
-	    {
-	      if (gpgfp[i] != gp.conf_fp[i]) 
-		{
-		  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
-				  MSG_E_GPG_FP, 
-				  gpgfp, gp.conf_fp);
-		  break;
-		}
-	    }
-
-	  if (smsg == S_FALSE)
-	    {
-	      tmp  = sh_util_safe_name(gp.conf_id);
-	      sh_gpg_fill_startup (__LINE__,
-				   /* sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH, */
+	  for(i = 0; i < (int) sl_strlen(sig_fp); ++i) {
+	      if (gpgfp[i] != sig_fp[i]) {
+		sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
+				MSG_E_GPG_FP, gpgfp, sig_fp);
+		break; }
+	  }
+
+	  if (smsg == S_FALSE) {
+	    tmp  = sh_util_safe_name(sig_id);
+	    sh_gpg_fill_startup (__LINE__, sh.prg_name, sh.real.uid,
+				 (sh.flag.hidefile == S_TRUE) ? 
+				 _("(hidden)") : file_path('C', 'R'), 
+				 tmp, 
+				 sig_fp);
+	    SH_FREE(tmp); }
+	  smsg = S_TRUE;
+
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+	  SH_FREE(buffer);
+#endif
+	  SL_RETURN(0, _("sh_gpg_check_sign"));
+	}
+      else
+	{
+	  /* fp mismatch */
+	  dlog(1, FIL__, __LINE__, 
+	       _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"), 
+	       sig_fp, SH_GPG_FP);
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Fingerprint mismatch"), _("gpg_check_sign"));
+	  status = SH_GPG_BADSIGN;
+	}
+#else /* ifdef USE_FINGERPRINT */
+      if (smsg == S_FALSE)
+	{
+	  tmp = sh_util_safe_name(sig_id);
+	  sh_gpg_fill_startup (__LINE__,
 			       sh.prg_name, sh.real.uid,
 			       (sh.flag.hidefile == S_TRUE) ? 
 			       _("(hidden)") : file_path('C', 'R'), 
-			       tmp, 
-			       gp.conf_fp);
-	      SH_FREE(tmp);
-	    }
-	  smsg = S_TRUE;
-#if defined(SH_WITH_SERVER)
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
-	  SH_FREE(buffer);
-#endif
-#endif
-	  SL_RETURN(0, _("sh_gpg_check_sign"));
-	}
-      else
-	{
-	  /* fp mismatch
-	   */
-	  dlog(1, FIL__, __LINE__, 
-	       _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"), 
-	       gp.conf_fp, SH_GPG_FP);
-	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
-		      _("Fingerprint mismatch"), 
-		      _("gpg_check_sign"));
-	  status = SH_GPG_BADSIGN;
-	}
-#else
-      if (smsg == S_FALSE)
-	{
-	  tmp = sh_util_safe_name(gp.conf_id);
-	  sh_gpg_fill_startup (__LINE__,
-	  /* sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH, */
-			   sh.prg_name, sh.real.uid,
-			   (sh.flag.hidefile == S_TRUE) ? 
-			   _("(hidden)") : file_path('C', 'R'), 
-			   tmp, 
-			   gp.conf_fp);
+			       tmp,  sig_fp);
 	  SH_FREE(tmp);
 	}
       smsg = S_TRUE;
-#if defined(SH_WITH_SERVER)
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
       SH_FREE(buffer);
 #endif
-#endif
+
       SL_RETURN(0, _("sh_gpg_check_sign"));
-#endif
-    }
-  
-  else if (SH_GPG_OK == status && (what == 2 || what == 0))
-    {
-      if ((sl_strcmp(gp.data_id, gp.conf_id) == 0) &&
-	  (sl_strcmp(gp.data_fp, gp.conf_fp) == 0))
-	{
-#if defined(SH_WITH_SERVER)
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
-	  SH_FREE(buffer);
-#endif
-#endif
-	  SL_RETURN(0, _("sh_gpg_check_sign"));
-	}
-      else
-	{
-	  /* ID or fp not equal 
-	   */
-	  dlog(1, FIL__, __LINE__, 
-	       _("The fingerprint or ID of the signing key is not the same for the\nconfiguration file and the file signature database.\nTherefore the signature could not be verified.\n"));
-	  tmp  = sh_util_safe_name (gp.conf_id);
-	  tmp2 = sh_util_safe_name (gp.data_id);
-	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_GH2,
-			   sh.prg_name, sh.real.uid,
-			   (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'),
-			   tmp,  gp.conf_fp,
-			   (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('D', 'R'),
-			   tmp2, gp.data_fp);
-	  SH_FREE(tmp);
-	  SH_FREE(tmp2);
-	}
+#endif /* !ifdef USE_FINGERPRINT */
     }
 
@@ -1168,5 +909,5 @@
 
 #if defined(SH_WITH_SERVER)
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+#if defined(USE_GETPWNAM_R)
       struct passwd    e_pwd;
       char          *  e_buffer = SH_ALLOC(SH_PWBUF_SIZE);
@@ -1186,22 +927,13 @@
       dlog(1, FIL__, __LINE__, 
 	   _("The signature of the configuration file or the file signature database\ncould not be verified. Possible reasons are:\n - gpg binary (%s) not found\n - invalid signature\n - the signature key is not in the private keyring of UID %d,\n - there is no keyring in %s/.gnupg, or\n - the file is not signed - did you move /filename.asc to /filename ?\nTo create a signed file, use (remove old signatures before):\n   gpg -a --clearsign --not-dash-escaped FILE\n   mv FILE.asc FILE\n"),
-#if defined(WITH_GPG) 
 	   DEFAULT_GPG_PATH,
-#else
-	   DEFAULT_PGP_PATH,
-#endif
 	   (int) e_uid, e_home);
 
-#if defined(SH_WITH_SERVER)
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
       SH_FREE(e_buffer);
 #endif
-#endif
     }
 
   TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
-
-  sh_error_handle((-1), FIL__, __LINE__, status, MSG_EXIT_ABORT1, sh.prg_name);
-  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
 
   return (-1); /* make compiler happy */
@@ -1223,4 +955,12 @@
    */
   fdTmp = open_tmp();
+  if (SL_ISERROR(fdTmp))
+    {
+      dlog(1, FIL__, __LINE__, _("Error opening temporary file.\n")); 
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+		      _("Error opening temporary file."), 
+		      _("sh_gpg_extract_signed"));
+      return -1;
+    }
 
   fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
Index: trunk/src/sh_guid.c
===================================================================
--- trunk/src/sh_guid.c	(revision 481)
+++ trunk/src/sh_guid.c	(revision 481)
@@ -0,0 +1,376 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 2015 Rainer Wichmann                                      */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+#include "samhain.h"
+#include "sh_utils.h"
+
+#include <stdio.h>
+#include <string.h>
+
+/*
+ * gen_uuid.c --- generate a DCE-compatible uuid
+ *
+ * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
+ *
+ * %Begin-Header%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * %End-Header%
+ */
+
+#define UUID_SIZE 36
+
+struct uuid {
+        UINT32        time_low;
+        UINT16        time_mid;
+        UINT16        time_hi_and_version;
+        UINT16        clock_seq;
+        UBYTE node[6];
+};
+
+typedef unsigned char uuid_t[16];
+
+
+static void uuid_pack(const struct uuid *uu, uuid_t ptr)
+{
+  UINT32          tmp;
+  unsigned char   *out = ptr;
+  
+  tmp = uu->time_low;
+  out[3] = (unsigned char) tmp;
+  tmp >>= 8;
+  out[2] = (unsigned char) tmp;
+  tmp >>= 8;
+  out[1] = (unsigned char) tmp;
+  tmp >>= 8;
+  out[0] = (unsigned char) tmp;
+  
+  tmp = uu->time_mid;
+  out[5] = (unsigned char) tmp;
+  tmp >>= 8;
+  out[4] = (unsigned char) tmp;
+  
+  tmp = uu->time_hi_and_version;
+  out[7] = (unsigned char) tmp;
+  tmp >>= 8;
+  out[6] = (unsigned char) tmp;
+  
+  tmp = uu->clock_seq;
+  out[9] = (unsigned char) tmp;
+  tmp >>= 8;
+  out[8] = (unsigned char) tmp;
+  
+  memcpy(out+10, uu->node, 6);
+  return;
+}
+
+static void uuid_unpack(const uuid_t in, struct uuid *uu)
+{
+  const uint8_t	*ptr = in;
+  uint32_t		tmp;
+  
+  tmp = *ptr++;
+  tmp = (tmp << 8) | *ptr++;
+  tmp = (tmp << 8) | *ptr++;
+  tmp = (tmp << 8) | *ptr++;
+  uu->time_low = tmp;
+  
+  tmp = *ptr++;
+  tmp = (tmp << 8) | *ptr++;
+  uu->time_mid = tmp;
+  
+  tmp = *ptr++;
+  tmp = (tmp << 8) | *ptr++;
+  uu->time_hi_and_version = tmp;
+  
+  tmp = *ptr++;
+  tmp = (tmp << 8) | *ptr++;
+  uu->clock_seq = tmp;
+  
+  memcpy(uu->node, ptr, 6);
+  return;
+}
+
+static void get_random_bytes(unsigned char * buf, size_t len)
+{
+  unsigned int j;
+
+  union {
+    UINT32 i;
+    char c[sizeof(UINT32)];
+  } u;
+
+  do {
+    u.i = taus_get();
+
+    for (j= 0; j < sizeof(UINT32); j++)
+      {
+	if (len) {
+	  --len;
+	  *buf = u.c[j];
+	  ++buf;
+	}
+      }
+  } while (len);
+
+  return;
+}
+
+static void uuid_generate_random(uuid_t out)
+{
+  uuid_t  buf;
+  struct uuid uu;
+
+  get_random_bytes(buf, sizeof(buf));
+  uuid_unpack(buf, &uu);
+
+  /* Version and variant 
+   */
+  uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
+  uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
+    | 0x4000;
+  uuid_pack(&uu, out);
+  return;
+}
+
+static const char *fmt_lower =	N_("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x");
+
+static void uuid_unparse(const uuid_t uu, char *out, size_t len)
+{
+  struct uuid uuid;
+  char fmt[80];
+  
+
+  sl_strlcpy(fmt, _(fmt_lower), sizeof(fmt));
+
+  uuid_unpack(uu, &uuid);
+
+  sl_snprintf (out, len, fmt,
+	       uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
+	       uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
+	       uuid.node[0], uuid.node[1], uuid.node[2],
+	       uuid.node[3], uuid.node[4], uuid.node[5]);
+
+  return;
+}
+
+#if defined(__linux__)
+static char * uuid_generate_random_linux(char * out, size_t len)
+{
+  FILE * fd = fopen(_("/proc/sys/kernel/random/uuid"), "r");
+
+  if (fd)
+    {
+      if (NULL != fgets(out, len, fd))
+	{
+	  size_t ll = strlen(out);
+	  if (ll > 0 && out[ll-1] == '\n') {
+	    --ll;
+	    out[ll] = '\0';
+	  }
+	}
+      fclose(fd);
+    }
+  return out;
+}
+#endif
+
+static char * uuid_generate_random_gen(char * out, size_t len)
+{
+  uuid_t u;
+
+  uuid_generate_random(u);
+  uuid_unparse(u, out, len);
+
+  return out;
+}
+
+char * sh_uuid_generate_random(char * out, size_t len)
+{
+  *out = '\0';
+
+#if defined(__linux__)
+  uuid_generate_random_linux(out, len);
+  if (UUID_SIZE == strlen(out))
+    return out;
+#endif
+
+  uuid_generate_random_gen(out, len);
+  return out;
+}
+
+#include <ctype.h>
+int sh_uuid_check(const char * in)
+{
+  int 		i;
+  const char	*cp;
+
+  if (strlen(in) != UUID_SIZE)
+    return -1;
+  for (i=0, cp = in; i <= UUID_SIZE; i++,cp++) {
+    if ((i == 8) || (i == 13) || (i == 18) ||
+	(i == 23)) {
+      if (*cp == '-')
+	continue;
+      else
+	return -1;
+    }
+    if (i== UUID_SIZE)
+      if (*cp == 0)
+	continue;
+    if (!isxdigit(*cp))
+      return -1;
+  }
+  return 0;
+}
+
+
+#ifdef SH_CUTEST
+#include "CuTest.h"
+
+#include <stdlib.h>
+
+static int uuid_type(const uuid_t uu)
+{
+  struct uuid		uuid;
+  
+  uuid_unpack(uu, &uuid);
+  return ((uuid.time_hi_and_version >> 12) & 0xF);
+}
+
+#define UUID_VARIANT_NCS	0
+#define UUID_VARIANT_DCE	1
+#define UUID_VARIANT_MICROSOFT	2
+#define UUID_VARIANT_OTHER	3
+
+#define UUID_TYPE_DCE_TIME   1
+#define UUID_TYPE_DCE_RANDOM 4
+
+static int uuid_variant(const uuid_t uu)
+{
+  struct uuid		uuid;
+  int			var;
+  
+  uuid_unpack(uu, &uuid);
+  var = uuid.clock_seq;
+  
+  if ((var & 0x8000) == 0)
+    return UUID_VARIANT_NCS;
+  if ((var & 0x4000) == 0)
+    return UUID_VARIANT_DCE;
+  if ((var & 0x2000) == 0)
+    return UUID_VARIANT_MICROSOFT;
+  return UUID_VARIANT_OTHER;
+}
+
+static int uuid_parse(const char *in, uuid_t uu)
+{
+  struct uuid	uuid;
+  int 		i;
+  const char	*cp;
+  char		buf[3];
+  
+  if (sh_uuid_check(in) < 0)
+    return -1;
+    
+  uuid.time_low = strtoul(in, NULL, 16);
+  uuid.time_mid = strtoul(in+9, NULL, 16);
+  uuid.time_hi_and_version = strtoul(in+14, NULL, 16);
+  uuid.clock_seq = strtoul(in+19, NULL, 16);
+  cp = in+24;
+  buf[2] = 0;
+  for (i=0; i < 6; i++) {
+    buf[0] = *cp++;
+    buf[1] = *cp++;
+    uuid.node[i] = strtoul(buf, NULL, 16);
+  }
+  
+  uuid_pack(&uuid, uu);
+  return 0;
+}
+
+void Test_uuid (CuTest *tc) {
+
+  char * p; int res;
+  char out[80];
+  size_t len = sizeof(out);
+  uuid_t uu;
+  int type, variant;
+
+  p = uuid_generate_random_gen(out, len);
+  CuAssertPtrNotNull(tc, p);
+  res = strlen(p);
+  CuAssertIntEquals(tc,UUID_SIZE,res);
+  res = uuid_parse(p, uu);
+  CuAssertIntEquals(tc,0,res);
+  type = uuid_type(uu); 
+  CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type);
+  variant = uuid_variant(uu);
+  CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant);
+
+#if defined(__linux__)
+  p = uuid_generate_random_linux(out, len);
+  CuAssertPtrNotNull(tc, p);
+  res = strlen(p);
+  CuAssertIntEquals(tc,UUID_SIZE,res);
+  res = uuid_parse(p, uu);
+  CuAssertIntEquals(tc,0,res);
+  type = uuid_type(uu); 
+  CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type);
+  variant = uuid_variant(uu);
+  CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant);
+#endif
+
+  p = sh_uuid_generate_random(out, len);
+  CuAssertPtrNotNull(tc, p);
+  res = strlen(p);
+  CuAssertIntEquals(tc,UUID_SIZE,res);
+  res = uuid_parse(p, uu);
+  CuAssertIntEquals(tc,0,res);
+  type = uuid_type(uu); 
+  CuAssertIntEquals(tc,UUID_TYPE_DCE_RANDOM,type);
+  variant = uuid_variant(uu);
+  CuAssertIntEquals(tc,UUID_VARIANT_DCE,variant);
+
+}
+#endif
Index: trunk/src/sh_hash.c
===================================================================
--- trunk/src/sh_hash.c	(revision 476)
+++ trunk/src/sh_hash.c	(revision 481)
@@ -20,12 +20,4 @@
 #include "config_xor.h"
 
-/* define this if you want version 1.3 style database file */
-/* #define OLD_BUG */
-
-/* make sure state changes of a file are always reported, even
- *  with reportonlyonce=true
- */
-/* #define REPLACE_OLD *//* moved to samhain.h */
-
 #include <stdlib.h>
 #include <string.h>
@@ -48,8 +40,13 @@
 #endif
 
+
 #if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
 
+#include "samhain.h"
+#include "sh_utils.h"
+#include "sh_unix.h"
+#include "sh_dbIO_int.h"
+#include "sh_dbIO.h"
 #include "sh_hash.h"
-#include "sh_utils.h"
 #include "sh_error.h"
 #include "sh_tiger.h"
@@ -61,5 +58,5 @@
 
 #if defined(SH_WITH_CLIENT)
-#include "sh_forward.h"
+#include "sh_xfer.h"
 #endif
 
@@ -71,240 +68,36 @@
 #define FIL__  _("sh_hash.c")
 
-SH_MUTEX_STATIC(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
-
-const char notalink[2] = { '-', '\0' };
+SH_MUTEX_INIT(mutex_hash,PTHREAD_MUTEX_INITIALIZER);
 
 static char * all_items (file_type * theFile, char * fileHash, int is_new);
 
-#define QUOTE_CHAR '='
-
-char * unquote_string (const char * str, size_t len)
-{
-  int    i = 0, t1, t2;
-  char * tmp = NULL;
-  size_t l2, j, k = 0;
-
-  SL_ENTER(_("unquote_string"));
-
-  if (str != NULL)
-    {
-      l2  = len - 2;
-      tmp = SH_ALLOC(len + 1);
-
-      for (j = 0; j <= len; ++j)
-	{
-	  if (str[j] != QUOTE_CHAR)
-	    {
-	      tmp[k] = str[j];
-	    }
-	  else if (str[j] == QUOTE_CHAR && j < l2)
-	    {
-	      t1 = sh_util_hexchar(str[j+1]);
-	      t2 = sh_util_hexchar(str[j+2]);
-	      if ((t1|t2) >= 0)
-		{
-		  i = 16 * t1 + t2;
-		  tmp[k] = i; 
-		  j += 2;
-		}
-	      else
-		{
-		  tmp[k] = str[j];
-		}
-	    }
-	  else
-	    tmp[k] = str[j];
-	  ++k;
-	}
-    }
-  SL_RETURN(tmp, _("unquote_string"));
-}
-
-
-static char * int2hex (unsigned char i, char * i2h)
-{
-  static char hexchars[] = "0123456789ABCDEF";
-
-  i2h[0] = hexchars[(((i) & 0xF0) >> 4)]; /* high */
-  i2h[1] = hexchars[((i) & 0x0F)];        /* low  */
-
-  return i2h;
-}
-
-
-char * quote_string (const char * str, size_t len)
-{
-  char * tmp;
-  char * tmp2;
-  size_t l2, j, i = 0, k = 0;
-  char   i2h[2];
-
-  SL_ENTER(_("quote_string"));
-
-  if (str == NULL)
-    {
-      SL_RETURN(NULL, _("quote_string"));
-    }
-
-  for (j = 0; j < len; ++j)
-    if (str[j] == '\n' || str[j] == QUOTE_CHAR) ++i;
-
-  l2 = len + 1;
-  if (sl_ok_muls(3, i) && sl_ok_adds(l2, (3*i)))
-    {
-      tmp = SH_ALLOC(len + 1 + 3*i);
-    }
-  else
-    {
-      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-		      _("integer overflow"), 
-		      _("quote_string"));
-      SL_RETURN(NULL, _("quote_string"));
-    }
-
-  for (j = 0; j <= len; ++j)
-    {
-      if (str[j] == '\n')
-	{
-	  tmp2 = int2hex((unsigned char) '\n', i2h); /* was 'n', fixed in 1.5.4 */
-	  tmp[k] = QUOTE_CHAR; ++k;
-	  tmp[k] = tmp2[0];    ++k;
-	  tmp[k] = tmp2[1];
-	}
-      else if (str[j] == QUOTE_CHAR)
-	{
-	  tmp2 = int2hex((unsigned char) QUOTE_CHAR, i2h);
-	  tmp[k] = QUOTE_CHAR; ++k;
-	  tmp[k] = tmp2[0];    ++k;
-	  tmp[k] = tmp2[1];
-	}
-      else
-	{
-	  tmp[k] = str[j];
-	}
-      ++k;
-    }
-  SL_RETURN(tmp, _("quote_string"));
-}
-
-static UINT32 * swap_32 (UINT32 * iptr)
-{
-#ifdef WORDS_BIGENDIAN
-  unsigned char swap;
-  unsigned char * ii = (unsigned char *) iptr;
-  swap = ii[0]; ii[0] = ii[3]; ii[3] = swap;
-  swap = ii[1]; ii[1] = ii[2]; ii[2] = swap;
-  return iptr;
-#else
-  return iptr;
-#endif
-}
-
-static UINT64 *  swap_64 (UINT64 * iptr)
-{
-#ifdef WORDS_BIGENDIAN
-#ifdef UINT64_IS_32
-  swap_32 ((UINT32*) iptr);
-#else
-  unsigned char swap;
-  unsigned char * ii = (unsigned char *) iptr;
-  swap = ii[0]; ii[0] = ii[7]; ii[7] = swap;
-  swap = ii[1]; ii[1] = ii[6]; ii[6] = swap;
-  swap = ii[2]; ii[2] = ii[5]; ii[5] = swap;
-  swap = ii[3]; ii[3] = ii[4]; ii[4] = swap;
-#endif
-  return iptr;
-#else
-  return iptr;
-#endif
-}
-
-static unsigned short *  swap_short (unsigned short * iptr)
-{
-#ifdef WORDS_BIGENDIAN
-  if (sizeof(short) == 4)
-    swap_32 ((UINT32*) iptr);
-  else
-    {
-      /* alignment problem */
-      unsigned char swap;
-      static unsigned short ooop;
-      unsigned char * ii;
-      ooop = *iptr;
-      ii = (unsigned char *) &ooop;
-      /* printf("SWAP0: %hd  %d\n", *iptr, sizeof(unsigned short)); */
-      swap = ii[0]; ii[0] = ii[1]; ii[1] = swap;
-      /* printf("SWAP1: %hd\n", (unsigned short) ooop); */
-#ifndef OLD_BUG
-      return &ooop;
-#endif
-    }
-  return iptr;
-#else
-  return iptr;
-#endif
-}
-
-
-typedef struct store_info {
-
-  UINT32           mode;
-  UINT32           linkmode;
-
-  UINT64           dev;
-  UINT64           rdev;
-  UINT32           hardlinks;
-  UINT32           ino;
-  UINT64           size;
-  UINT64           atime;
-  UINT64           mtime;
-  UINT64           ctime;
-  UINT32           owner;
-  UINT32           group;
-
-#ifdef OLD_BUG
-#if defined(__linux__)
-  UINT32           attributes;
-  char             c_attributes[ATTRBUF_SIZE];
-#endif
-#else
-  /* #if defined(__linux__) */
-  UINT32           attributes;
-  char             c_attributes[ATTRBUF_SIZE];
-  /* endif                  */
-#endif
-  unsigned short   mark;
-  char             c_owner[USER_MAX+2];
-  char             c_group[GROUP_MAX+2];
-  char             c_mode[CMODE_SIZE];
-  char             checksum[KEY_LEN+1];
-} sh_filestore_t;
-  
-typedef struct file_info {
-  sh_filestore_t   theFile;
-  char           * fullpath;
-  char           * linkpath;
-  char           * attr_string;
-  int              fflags;
-  unsigned long    modi_mask;
-  struct           file_info * next;
-} sh_file_t;
-
-  static const char  *policy[] = {
-    N_("[]"),
-    N_("[ReadOnly]"),
-    N_("[LogFiles]"),
-    N_("[GrowingLogs]"),
-    N_("[IgnoreNone]"),
-    N_("[IgnoreAll]"),
-    N_("[Attributes]"),
-    N_("[User0]"),
-    N_("[User1]"),
-    N_("[User2]"),
-    N_("[User3]"),
-    N_("[User4]"),
-    N_("[Prelink]"),
-    NULL
-  };
+static const char  *policy[] = {
+  N_("[]"),
+  N_("[ReadOnly]"),
+  N_("[LogFiles]"),
+  N_("[GrowingLogs]"),
+  N_("[IgnoreNone]"),
+  N_("[IgnoreAll]"),
+  N_("[Attributes]"),
+  N_("[User0]"),
+  N_("[User1]"),
+  N_("[User2]"),
+  N_("[User3]"),
+  N_("[User4]"),
+  N_("[Prelink]"),
+  NULL
+};
+
+static int report_checkflags = S_FALSE;
+int set_report_checkflags(const char * c)
+{
+  return sh_util_flagval(c, &report_checkflags);
+}
+int get_report_checkflags()
+{
+  return report_checkflags;
+}
+
+
 
 const char * sh_hash_getpolicy(int class)
@@ -324,24 +117,4 @@
 #include "sh_hash.h"
 
-/* must fit an int              */
-/* #define TABSIZE 2048         */
-#define TABSIZE 65536
-
-/* must fit an unsigned short   */
-/* changed for V0.8, as the     */
-/* database format has changed  */
-
-/* changed again for V0.9       */
-/* #define REC_MAGIC 19         */
-/* changed again for V1.3       */
-#ifdef OLD_BUG
-#define REC_MAGIC 20
-#else
-/* changed again for V1.4       */
-#define REC_MAGIC 21
-#endif
-
-#define REC_FLAGS_ATTR (1<<8)
-#define REC_FLAGS_MASK 0xFF00
 
 /**************************************************************
@@ -350,5 +123,5 @@
  *
  **************************************************************/
-static file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash)
+file_type * sh_hash_create_ft (const sh_file_t * p, char * fileHash)
 {
   file_type * theFile;
@@ -391,4 +164,5 @@
   theFile->dev   =  p->theFile.dev;
   theFile->hardlinks = p->theFile.hardlinks;
+  theFile->check_flags = p->theFile.checkflags;
 
   if (p->attr_string)
@@ -408,5 +182,17 @@
 static int hashsearch_prev (const char * s, struct two_sh_file_t * a, int * index); 
 
+
+/**************************************************************
+ *
+ * >>>> The internal database <<<
+ *
+ **************************************************************/
+
 static sh_file_t * tab[TABSIZE];
+
+sh_file_t ** get_default_data_table()
+{
+  return tab;
+}
 
 /**************************************************************
@@ -499,6 +285,5 @@
   if (p->linkpath)
     {
-      if (p->linkpath != notalink)
-	SH_FREE(p->linkpath);
+      SH_FREE(p->linkpath);
       p->linkpath = NULL;
     }
@@ -521,7 +306,5 @@
   char   fileHash[KEY_LEN + 1];
   file_type * theFile;
-
   char * str;
-
 
   SL_ENTER(_("hash_unvisited"));
@@ -552,5 +335,5 @@
   if (((!SH_FFLAG_VISITED_SET(p->fflags)) || SH_FFLAG_CHECKED_SET(p->fflags)) 
       && (!SH_FFLAG_REPORTED_SET(p->fflags))
-      && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)))
+      /* && (!SH_FFLAG_ALLIGNORE_SET(p->fflags)) */)
     {
       i = retry_lstat(FIL__, __LINE__, p->fullpath, &buf);
@@ -565,5 +348,5 @@
 	      /* If any of the parent directories is under IgnoreAll
 	       */
-	      if (0 != sh_files_is_allignore(ptr))
+	      if ((0 != sh_files_is_allignore(ptr)) || SH_FFLAG_ALLIGNORE_SET(p->fflags))
 		level = ShDFLevel[SH_LEVEL_ALLIGNORE];
 	      SH_FREE(ptr);
@@ -599,5 +382,4 @@
 	      (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(p->fullpath)))
 	    {
-#ifdef REPLACE_OLD
 	      /* Remove the old entry
 	       */
@@ -610,7 +392,4 @@
 
 	      SL_RET0(_("hash_unvisited"));
-#else
-	      SET_SH_FFLAG_REPORTED(p->fflags); 
-#endif
 	    }
 	}
@@ -679,40 +458,39 @@
  *
  *********************************************************************/
-void sh_hash_remove (const char * path)
+void sh_hash_remove_unconditional (const char * path)
 {
   struct two_sh_file_t entries;
   int index;
 
+  SL_ENTER(_("sh_hash_remove_unconditional"));
+
+  SH_MUTEX_LOCK(mutex_hash);
+  if (0 == hashsearch_prev (path, &entries, &index))
+    {
+      sh_file_t * p = entries.this;
+      
+      /* Remove the old entry
+       */
+      if (entries.prev == p)
+	tab[index] = p->next;
+      else
+	entries.prev->next = p->next;
+      
+      delete_db_entry(p);
+    }
+  SH_MUTEX_UNLOCK(mutex_hash);
+
+  SL_RET0(_("sh_hash_remove_unconditional"));
+}
+
+void sh_hash_remove (const char * path)
+{
   SL_ENTER(_("sh_hash_remove"));
-
-  SH_MUTEX_LOCK(mutex_hash);
 
   if ((sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE) || 
       (S_TRUE == sh.flag.update && S_TRUE == sh_util_ask_update(path)))
     {
-      if (0 == hashsearch_prev (path, &entries, &index))
-	{
-	  sh_file_t * p = entries.this;
-#ifdef REPLACE_OLD
-	  /* Remove the old entry
-	   */
-	  if (entries.prev == p)
-	    tab[index] = p->next;
-	  else
-	    entries.prev->next = p->next;
-	  
-	  delete_db_entry(p);
-	  
-	  goto end;
-#else
-	  SET_SH_FFLAG_REPORTED(p->fflags); 
-#endif
-	}
-    }
-
- end:
-  ; /* 'label at end of compound statement' */
-  SH_MUTEX_UNLOCK(mutex_hash);
-
+      sh_hash_remove_unconditional (path);
+    }
   SL_RET0(_("sh_hash_remove"));
 }
@@ -811,6 +589,5 @@
   if (p->linkpath)
     {
-      if (p->linkpath != notalink)
-	SH_FREE(p->linkpath);
+      SH_FREE(p->linkpath);
       p->linkpath = NULL;
     }
@@ -856,24 +633,18 @@
     {
       *index = hashfunc(s);
-
-      this = tab[*index];
-
-      prev  = this;
+      this   = tab[*index];
+      prev   = this;
 
       if (this)
 	{
 	  do {
-	    
 	    if ((this->fullpath != NULL) && (0 == strcmp(s, this->fullpath)))
 	      {
 		a->prev = prev;
-		a->this = this;
-		
+		a->this = this;	
 		SL_RETURN( 0, _("hashsearch_prev"));
 	      }
-	    
 	    prev = this;
 	    this = this->next;
-	    
 	  } while(this);
 	} 
@@ -888,5 +659,5 @@
  *
  ***********************************************************************/
-static void hashinsert (sh_file_t * s) 
+void hashinsert (sh_file_t * mtab[TABSIZE], sh_file_t * s) 
 {
   sh_file_t * p;
@@ -898,28 +669,24 @@
   key = hashfunc(s->fullpath);
 
-  if (tab[key] == NULL) 
-    {
-      tab[key] = s;
-      tab[key]->next = NULL;
+  if (mtab[key] == NULL) 
+    {
+      mtab[key] = s;
+      mtab[key]->next = NULL;
       SL_RET0(_("hashinsert"));
     } 
   else 
     {
-      p = tab[key];
+      p = mtab[key];
       while (1) 
 	{
-	  if (p && p->fullpath && 
-	      0 == strcmp(s->fullpath, p->fullpath))
+	  if (p && p->fullpath && 0 == strcmp(s->fullpath, p->fullpath))
 	    {
 	      q = p->next;
 	      SH_FREE(p->fullpath);
-	      if(p->linkpath && p->linkpath != notalink)
-		SH_FREE(p->linkpath);
-	      if(p->attr_string)
-		SH_FREE(p->attr_string);
+	      if(p->linkpath)    SH_FREE(p->linkpath);
+	      if(p->attr_string) SH_FREE(p->attr_string);
 	      memcpy(p, s, sizeof(sh_file_t));
 	      p->next = q;
-	      SH_FREE(s);
-	      s = NULL;
+	      SH_FREE(s); s = NULL;
 	      SL_RET0(_("hashinsert"));
 	    }
@@ -940,361 +707,24 @@
 
 
+
 /******************************************************************
  *
- * Get a single line
+ * ------- Check functions -------
  *
  ******************************************************************/
-static FILE * sh_fin_fd = NULL;
-
-static int sh_hash_getline (FILE * fd, char * line, int sizeofline)
-{
-  register int  n = 0;
-  char        * res;
-
-  if (sizeofline < 2) {
-    if (sizeofline > 0) line[0] = '\0';
-    return 0;
-  }
-  res = fgets(line, sizeofline, fd);
-  if (res == NULL)
-    {
-      line[0] = '\0';
-      return -1;
-    }
-  n = strlen(line);
-  if (n > 0) {
-    --n;
-    line[n] = '\0'; /* remove terminating '\n' */
-  }
-  return n;
-}
-
-static void sh_hash_getline_end (void)
-{
-  sl_fclose (FIL__, __LINE__, sh_fin_fd);
-  sh_fin_fd = NULL;
+
+static int IsInit = 0;
+
+void sh_hash_set_initialized()
+{
+  IsInit = 1;
   return;
 }
 
-/******************************************************************
- *
- * ------- Check functions -------
- *
- ******************************************************************/
-
-static int IsInit = 0;
-
-
-/******************************************************************
- *
- * Fast forward to start of data
- *
- ******************************************************************/
-int sh_hash_setdataent (SL_TICKET fd, char * line, int size, const char * file)
-{
-  long i;
-  extern int get_the_fd (SL_TICKET ticket);
-
-  SL_ENTER(_("sh_hash_setdataent"));
-
-  sl_rewind (fd);
-
-  if (sh_fin_fd != NULL)
-    {
-      sl_fclose (FIL__, __LINE__, sh_fin_fd);
-      sh_fin_fd = NULL;
-    }
-
-  sh_fin_fd = fdopen(dup(get_the_fd(fd)), "rb");
-  if (!sh_fin_fd)
-    {
-      dlog(1, FIL__, __LINE__, 
-	   _("The file signature database: %s is not readable.\n"),
-	   (NULL == file) ? _("(null)") : file);
-      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
-		       ( (NULL == file) ? _("(null)") : file)
-		       );
-      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
-    }
-
-  while (1) 
-    {
-      i =  sh_hash_getline (sh_fin_fd, line, size);
-      if (i < 0 ) 
-	{
-	  SH_FREE(line);
-	  dlog(1, FIL__, __LINE__, 
-	       _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
-	       (NULL == file) ? _("(null)") : file);
-	       
-	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
-			   ( (NULL == file) ? _("(null)") : file)
-			   );
-	  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
-	}
-
-#if defined(SH_STEALTH)
-      if (0 == sl_strncmp (line, N_("[SOF]"), 5)) 
-#else
-      if (0 == sl_strncmp (line, _("[SOF]"),  5)) 
-#endif
-	break;
-    }
-  SL_RETURN( 1, _("sh_hash_setdataent"));
-}
-
-static int sh_hash_setdataent_old (SL_TICKET fd, char * line, int size, 
-				   char * file)
-{
-  long i;
-
-  SL_ENTER(_("sh_hash_setdataent_old"));
-
-  sl_rewind (fd);
-
-  while (1) 
-    {
-      i =  sh_unix_getline (fd, line, size-1);
-      if (i < 0 ) 
-	{
-	  SH_FREE(line);
-	  dlog(1, FIL__, __LINE__, 
-	       _("The file signature database: %s does not\ncontain any data, or the start-of-file marker is missing (unlikely,\nunless modified by hand).\n"),
-	       (NULL == file) ? _("(null)") : file);
-	       
-	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
-			   ( (NULL == file) ? _("(null)") : file)
-			   );
-	  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
-	}
-
-#if defined(SH_STEALTH)
-      if (0 == sl_strncmp (line, N_("[SOF]"), 5)) 
-#else
-      if (0 == sl_strncmp (line, _("[SOF]"),  5)) 
-#endif
-	break;
-    }
-  SL_RETURN( 1, _("sh_hash_setdataent_old"));
-}
-
-/******************************************************************
- *
- * Read next record
- *
- ******************************************************************/
-sh_file_t *  sh_hash_getdataent (SL_TICKET fd, char * line, int size)
-{
-  sh_file_t * p;
-  sh_filestore_t ft;
-  long i;
-  size_t len;
-  char * fullpath;
-  char * linkpath;
-  char * attr_string = NULL;
-  char * tmp;
-
-  SL_ENTER(_("sh_hash_getdataent"));
-
-  (void) fd;
-
-  /* Read next record -- Part One 
-   */
-  p = SH_ALLOC(sizeof(sh_file_t));
-
-  i = fread (&ft, sizeof(sh_filestore_t), 1, sh_fin_fd);
-  /* i = sl_read(fd, &ft, sizeof(sh_filestore_t)); */
-  /* if ( SL_ISERROR(i) || i == 0) */
-  if (i < 1)
-    {
-      SH_FREE(p);
-      SL_RETURN( NULL, _("sh_hash_getdataent"));
-    }
-
-  swap_32(&(ft.mode));
-  swap_32(&(ft.linkmode));
-  swap_64(&(ft.dev));
-  swap_64(&(ft.rdev));
-  swap_32(&(ft.hardlinks));
-  swap_32(&(ft.ino));
-  swap_64(&(ft.size));
-  swap_64(&(ft.atime));
-  swap_64(&(ft.mtime));
-  swap_64(&(ft.ctime));
-  swap_32(&(ft.owner));
-  swap_32(&(ft.group));
-#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
-  swap_32(&(ft.attributes));
-#endif
-#ifdef OLD_BUG
-  swap_short(&(ft.mark));
-#else
-  ft.mark = *(swap_short(&(ft.mark)));
-#endif
-
-  if ((ft.mark & ~REC_FLAGS_MASK) != REC_MAGIC)
-    {
-      SH_FREE(p);
-      SL_RETURN( NULL, _("sh_hash_getdataent"));
-    }
-
-  /* Read next record -- Part Two -- Fullpath
-   */
-  i =  sh_hash_getline (sh_fin_fd, line, size);
-  if (i <= 0 ) 
-    {
-      SH_FREE(line);
-      SH_FREE(p);
-      dlog(1, FIL__, __LINE__, 
-	   _("There is a corrupt record in the file signature database: %s\nThe file path is missing.\n"),
-	   (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
-      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
-			   ( (NULL == file_path('D', 'R')) ? _("(null)") :
-			     file_path('D', 'R'))
-			    );
-      aud_exit (FIL__, __LINE__,EXIT_FAILURE);
-    }
-
-  tmp = unquote_string (line, i);
-  len = sl_strlen(tmp)+1;
-  fullpath = SH_ALLOC(len);
-  (void) sl_strlcpy (fullpath, tmp, len);
-  if (tmp)
-    SH_FREE(tmp);
-  if (fullpath[len-2] == '\n')
-    fullpath[len-2] = '\0';
-
-  /* Read next record -- Part Three -- Linkpath
-   */
-  i =  sh_hash_getline (sh_fin_fd, line, size);
-  if (i <= 0 ) 
-    {
-      SH_FREE(line);
-      SH_FREE(fullpath);
-      SH_FREE(p);
-      dlog(1, FIL__, __LINE__, 
-	   _("There is a corrupt record in the file signature database: %s\nThe link path (or its placeholder) is missing.\n"),
-	   (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
-      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
-		       ( (NULL == file_path('D', 'R')) ? _("(null)") :
-			 file_path('D', 'R'))
-		       );
-      aud_exit (FIL__, __LINE__,EXIT_FAILURE);
-    }
-
-  tmp = unquote_string (line, i);
-
-  if ( tmp && tmp[0] == '-' && 
-       (tmp[1] == '\0' || (tmp[1] == '\n' && tmp[2] == '\0')))
-    {
-      linkpath = (char *)notalink;
-    }
-  else
-    {
-      len = sl_strlen(tmp);
-      linkpath = sh_util_strdup_l(tmp, len);
-      if (len > 0 && linkpath[len-1] == '\n')
-	linkpath[len-1] = '\0';
-    }
-
-  if (tmp)
-    SH_FREE(tmp);
-
-  /* Read next record -- Part Four -- attr_string
-   */
-  if ((ft.mark & REC_FLAGS_ATTR) != 0)
-    {
-      i =  sh_hash_getline (sh_fin_fd, line, size);
-      if (i <= 0 ) 
-	{
-	  SH_FREE(line);
-	  SH_FREE(fullpath);
-	  if (linkpath != notalink)
-	    SH_FREE(linkpath);
-	  SH_FREE(p);
-	  dlog(1, FIL__, __LINE__, 
-	       _("There is a corrupt record in the file signature database: %s\nThe attribute string is missing.\n"),
-	       (NULL == file_path('D', 'R'))? _("(null)"):file_path('D', 'R'));
-	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_P_NODATA,
-			   ( (NULL == file_path('D', 'R')) ? _("(null)") :
-			     file_path('D', 'R'))
-			   );
-	  aud_exit (FIL__, __LINE__,EXIT_FAILURE);
-	}
-
-      tmp = unquote_string (line, i);
-
-      len = sl_strlen(tmp)+1;
-      attr_string = SH_ALLOC(len);
-      (void) sl_strlcpy (attr_string, tmp, len);
-      if (tmp)
-	SH_FREE(tmp);
-      if (attr_string[len-2] == '\n')
-	attr_string[len-2] = '\0';
-    }
-
-  /* Read next record -- Part Four -- Decode
-   */
-#if defined(SH_STEALTH)
-  sh_do_decode(fullpath,    sl_strlen(fullpath));
-  
-#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
-  sh_do_decode(ft.c_attributes,   sl_strlen(ft.c_attributes));
-#endif
-  
-  sh_do_decode(ft.c_mode,   sl_strlen(ft.c_mode));
-  sh_do_decode(ft.c_owner,  sl_strlen(ft.c_owner));
-  sh_do_decode(ft.c_group,  sl_strlen(ft.c_group));
-  sh_do_decode(ft.checksum, sl_strlen(ft.checksum));
-  
-  /* TXT entries are c_mode[0] != 'l' and do not get decoded 
-   */
-  if (ft.c_mode[0] == 'l' && linkpath != notalink)
-    {  
-      sh_do_decode(linkpath, sl_strlen(linkpath));
-    }
-
-  if ((ft.mark & REC_FLAGS_ATTR) != 0)
-    {  
-      sh_do_decode(attr_string, sl_strlen(attr_string));
-    }
-#endif
-
-  memcpy( &(*p).theFile, &ft, sizeof(sh_filestore_t) );
-
-  /* init fflags, such that suid files in 
-   * database are recognized as such 
-   */
-  {
-    mode_t mode = (mode_t) ft.mode;
-
-    if (S_ISREG(mode) &&
-	(0 !=(S_ISUID & mode) ||
-#if defined(HOST_IS_LINUX)
-	 (0 !=(S_ISGID & mode) && 
-	  0 !=(S_IXGRP & mode)) 
-#else  
-	 0 !=(S_ISGID & mode)
-#endif
-	 )
-	)
-      p->fflags = SH_FFLAG_SUIDCHK;
-
-    else
-      p->fflags = 0;
-  }
-      
-  p->modi_mask = 0L;
-  p->fullpath  = fullpath;
-  p->linkpath  = linkpath;
-
-  p->attr_string = attr_string;
-
-  /* set to an invalid value 
-   */
-  ft.mark = (REC_MAGIC + 5);
-
-  SL_RETURN( p, _("sh_hash_getdataent"));
-}
+int sh_hash_get_initialized()
+{
+  return IsInit;
+}
+
 
 /******************************************************************
@@ -1305,20 +735,4 @@
 void sh_hash_init ()
 {
-
-#define FGETS_BUF 16384
-
-  sh_file_t * p;
-  SL_TICKET fd;
-  long i;
-  int count = 0;
-  char * line = NULL;
-
-#if defined(WITH_GPG) || defined(WITH_PGP)
-  extern int get_the_fd (SL_TICKET ticket);
-
-  SL_TICKET fdTmp = (-1);
-#endif
-  char hashbuf[KEYBUF_SIZE];
-
   volatile int  retval  = 0;
   volatile int  exitval = EXIT_SUCCESS;
@@ -1341,155 +755,12 @@
     }
 
-  fd = (-1);
-
-#if defined(SH_WITH_CLIENT)
-
-  /* Data file from Server
-   */
-
-  if (fd == (-1) && 0 == sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
-    {
-      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_DSTART);
-      fd = sh_forward_req_file(_("DATA"));
-      if (SL_ISERROR(fd))
-	{
-	  dlog(1, FIL__, __LINE__, 
-	       _("Could not retrieve the file signature database from the server(errnum = %ld).\nPossible reasons include:\n - the server is not running,\n - session key negotiation failed (see the manual for proper setup), or\n - the server cannot access the file.\n"), fd); 
-	  sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1, 
-			   sh.prg_name);
-	  retval = 1; exitval = EXIT_FAILURE;
-	  goto unlock_and_return;
-	}
-      sl_rewind (fd);
-
-      sl_strlcpy (sh.data.hash, 
-		  sh_tiger_hash (file_path('D', 'R'),  
-				 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
-		  KEY_LEN+1);
-      sl_rewind (fd);
-    }
-  else 
-#endif
-    /* Local data file
-     */
-
-    if (fd == (-1))
-      {
-	if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, 
-					  file_path('D', 'R'), SL_YESPRIV))) 
-	  {
-	    TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s>\n"), 
-		  file_path('D', 'R')));
-	    dlog(1, FIL__, __LINE__, 
-		 _("Could not open the local file signature database for reading because\nof the following error: %s (errnum = %ld)\nIf this is a permission problem, you need to change file permissions\nto make the file readable for the effective UID: %d\n"), 
-		 sl_get_errmsg(), fd, (int) sl_ret_euid());
-	    sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_EXIT_ABORT1, 
-			     sh.prg_name);
-	    retval = 1; exitval = EXIT_FAILURE;
-	    goto unlock_and_return;
-	  }
-	
-	TPT(( 0, FIL__, __LINE__, _("msg=<Opened database: %s>\n"), 
-	      file_path('D', 'R')));
-
-	if (0 != sl_strncmp(sh.data.hash, 
-			    sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM, 
-					   hashbuf, sizeof(hashbuf)),
-			    KEY_LEN)
-	    && sh.flag.checkSum != SH_CHECK_INIT) 
-	  {
-	    dlog(1, FIL__, __LINE__, 
-		 _("The checksum of the file signature database has changed since startup: %s -> %s\n"),
-		 sh.data.hash, sh_tiger_hash (file_path('D', 'R'), fd, TIGER_NOLIM, 
-					   hashbuf, sizeof(hashbuf)));
-	    sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_AUTH,
-			     ( (NULL == file_path('D', 'R')) ? _("(null)") :
-			       file_path('D', 'R') )
-			     );
-	    retval = 1; exitval = EXIT_FAILURE;
-	    goto unlock_and_return;
-	  }
-	sl_rewind (fd);
-
-      } /* new 1.4.8 */
-
-  if (sig_termfast == 1)  /* SIGTERM */
-    {
-      TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
-      --sig_raised; --sig_urgent;
-      retval = 1; exitval = EXIT_SUCCESS;
-      goto unlock_and_return;
-    }
-
-#if defined(WITH_GPG) || defined(WITH_PGP)
-
-  /* extract the data and copy to temporary file
-   */
-  fdTmp = sh_gpg_extract_signed(fd);
-
-  if (sig_termfast == 1)  /* SIGTERM */
-    {
-      TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
-      --sig_raised; --sig_urgent;
-      retval = 1; exitval = EXIT_SUCCESS;
-      goto unlock_and_return;
-    }
-
-  sl_close(fd);
-  fd = fdTmp;
-
-  /* Validate signature of open file.
-   */
-  if (0 != sh_gpg_check_sign (0, fd, 2))
-    {
-      retval = 1; exitval = EXIT_FAILURE;
-      goto unlock_and_return;
-    }
-  sl_rewind (fd);
-#endif
-
-  line = SH_ALLOC(MAX_PATH_STORE+2);
-
-  /* fast forward to start of data
-   */
-  sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, file_path('D', 'R'));
-
-  for (i = 0; i < TABSIZE; ++i) 
-    tab[i] = NULL;
-
-  while (1) 
-    {
-      if (sig_termfast == 1)  /* SIGTERM */
-	{
-	  TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
-	  --sig_raised; --sig_urgent;
-	  retval = 1; exitval = EXIT_SUCCESS;
-	  SH_FREE(line);
-	  line = NULL;
-	  goto unlock_and_return;
-	}
-
-      p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
-      if (p != NULL)
-	{
-	  hashinsert (p); 
-	  ++count;
-	}
-      else
-	break;
-    }
-
   /* Initialization completed.
    */
-  IsInit = 1;
-
-  if (line != NULL)
-    SH_FREE(line);
-
-  /* Always keep db in memory, so we have no open file
-   */
-  sl_close (fd);
-  sh_hash_getline_end();
-  /* fd = -1; */
+  retval = sh_dbIO_load_db(tab);
+
+  if (0 == retval)
+    IsInit = 1;
+  else
+    exitval = EXIT_FAILURE;
 
  unlock_and_return:
@@ -1500,5 +771,28 @@
       SL_RET0(_("sh_hash_init"));
     }
+  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
   aud_exit (FIL__, __LINE__, exitval);
+}
+
+void sh_hash_init_and_checksum()
+{
+  TPT((0, FIL__, __LINE__, _("msg=<Get checksum of the database.>\n")))
+  if (sh.flag.checkSum == SH_CHECK_CHECK) 
+    {
+      if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
+	{
+	  char hashbuf[KEYBUF_SIZE];
+	  (void) sl_strlcpy(sh.data.hash,
+			    sh_tiger_hash (file_path('D', 'R'), 
+					   TIGER_FILE, TIGER_NOLIM, 
+					   hashbuf, sizeof(hashbuf)), 
+			    KEY_LEN+1);
+	}
+
+      /* this eventually fetches the file from server to get checksum
+       */
+      sh_hash_init ();
+    }
+  return;
 }
   
@@ -1536,41 +830,4 @@
 }
 
-/******************************************************************
- *
- * Insert a file into the database.
- *
- ******************************************************************/ 
-static int       pushdata_isfirst =  1;
-static SL_TICKET pushdata_fd      = -1;
-
-static int       pushdata_stdout  =  S_FALSE;
-
-static char * sh_db_version_string = NULL;
-
-int sh_hash_pushdata_stdout (const char * str)
-{
-  if (!str)
-    { pushdata_stdout  =  S_TRUE; return 0; }
-  return -1;
-}
-
-int sh_hash_version_string(const char * str)
-{
-  if (str)
-    {
-      if (sh_db_version_string != NULL) {
-	SH_FREE(sh_db_version_string);
-      }
-      if (0 == sl_strncmp(str, _("NULL"), 4))
-	{
-	  sh_db_version_string = NULL;
-	  return 0;
-	}
-      sh_db_version_string = sh_util_strdup(str);
-      return 0;
-    }
-  return -1;
-}
-
 static int sh_loosedircheck = S_FALSE;
 
@@ -1581,495 +838,4 @@
 
 
-static void sh_hash_pushdata_int (file_type * buf, char * fileHash)
-{
-  static long p_count = 0;
-
-  int         status = 0;
-
-  char      * tmp;
-  size_t      tmp_len = 0;
-  size_t      old_len = 0;
-  size_t      path_len = 0;
-
-  sh_filestore_t p;
-
-  struct stat sbuf;
-
-  char *  fullpath = NULL;
-  char *  linkpath = NULL;
-  char *  attr_string = NULL;
-
-  char * line = NULL;
-
-  char   timestring[81];
-
-#if !defined(__linux__) && !defined(HAVE_STAT_FLAGS)
-  int    i;
-#endif
-
-  SL_ENTER(_("sh_hash_pushdata_int"));
-
-  fullpath = SH_ALLOC(MAX_PATH_STORE+1);
-  linkpath = SH_ALLOC(MAX_PATH_STORE+1);
-
-  linkpath[0] =  '-'; 
-  linkpath[1] = '\0'; 
-  fullpath[0] =  '-'; 
-  fullpath[1] = '\0';
-
-  if (!buf) {
-    memset(&p, '\0', sizeof(sh_filestore_t));
-  }
-
-  if ((pushdata_stdout == S_TRUE) && (sh.flag.update == S_TRUE))
-    {
-      dlog(1, FIL__, __LINE__, 
-	   _("You cannot write the database to stdout when you use update rather than init.\n"));
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
-		      _("Writing database to stdout with update"), 
-		      sh.prg_name, 
-		      _("sh_hash_pushdata_int"));
-      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-    }
-
-  if ((pushdata_stdout == S_TRUE) && (sl_is_suid()))
-    {
-      dlog(1, FIL__, __LINE__, 
-	   _("You cannot write the database to stdout when running with suid privileges.\n"));
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
-		      _("Writing database to stdout when suid"), 
-		      sh.prg_name, 
-		      _("sh_hash_pushdata_int"));
-      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-    }
-
-
-  if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE) && 
-      ( (NULL == file_path('D', 'W')) || 
-	(0 == sl_strcmp(file_path('D', 'W'), _("REQ_FROM_SERVER"))) ))
-    {
-      dlog(1, FIL__, __LINE__, 
-	   _("You need to configure a local path for initializing the database\nlike ./configure --with-data-file=REQ_FROM_SERVER/some/local/path\n"));
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORTS,
-		      _("No local path for database specified"), 
-		      sh.prg_name, 
-		      _("sh_hash_pushdata_int"));
-      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-    }
-
-
-  if ((pushdata_isfirst == 1) && (pushdata_stdout == S_FALSE))  
-    {
-      /* Warn that file already exists; file_path != NULL here because
-       * checked above
-       */
-      if (0 == retry_lstat(FIL__, __LINE__, file_path('D', 'W'), &sbuf))
-	{
-	  if (sh.flag.update == S_FALSE)
-	    {
-	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_FI_DBEX,
-			      file_path('D', 'W'));
-	    }
-	}
-    }
-
-
-  if (sh.flag.update == S_FALSE)
-    {
-      if (pushdata_stdout == S_FALSE && pushdata_fd == -1)
-	{
-	  if ( SL_ISERROR(pushdata_fd = sl_open_write(FIL__, __LINE__, 
-						      file_path('D', 'W'), 
-						      SL_YESPRIV))) 
-	    {
-	      SH_FREE(fullpath);
-	      SH_FREE(linkpath);
-	      sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
-			      geteuid(), file_path('D', 'W'));
-	      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-	    }
-
-	  if (SL_ISERROR(status = sl_lock (pushdata_fd)))
-	    {
-	      SH_FREE(fullpath);
-	      SH_FREE(linkpath);
-	      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
-			      _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
-			      file_path('D', 'W'));
-	      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-	    }
-
-	  if ( SL_ISERROR(status = sl_forward(pushdata_fd))) 
-	    {
-	      SH_FREE(fullpath);
-	      SH_FREE(linkpath);
-	      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
-			      _("Failed to seek to end of baseline database"),
-			      _("sh_hash_pushdata_int"),
-			      file_path('D', 'W'));
-	      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-	    }
-	}
-    }
-  else /* update == TRUE */
-    {
-      if (pushdata_isfirst == 1)
-	{
-	  TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")))
-	    if ( SL_ISERROR(pushdata_fd = sl_open_rdwr(FIL__, __LINE__, 
-						       file_path('D', 'W'), 
-						       SL_YESPRIV))){
-	      SH_FREE(fullpath);
-	      SH_FREE(linkpath);
-	      sh_error_handle((-1), FIL__, __LINE__, pushdata_fd, MSG_E_ACCESS,
-			      geteuid(), file_path('D', 'W'));
-	      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-	    }
-
-	  if (SL_ISERROR(status = sl_lock (pushdata_fd)))
-	    {
-	      SH_FREE(fullpath);
-	      SH_FREE(linkpath);
-	      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGPATH,
-			      _("Failed to lock baseline database"), _("sh_hash_pushdata_int"),
-			      file_path('D', 'W'));
-	      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-	    }
-
-	  line = SH_ALLOC(MAX_PATH_STORE+1);
-	  if (SL_ISERROR(sh_hash_setdataent_old (pushdata_fd, line, 
-						 MAX_PATH_STORE, 
-						 file_path('D', 'W'))))
-	    {
-	      SH_FREE(fullpath);
-	      SH_FREE(linkpath);
-	      SH_FREE(line);
-	      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
-	    }
-	  SH_FREE(line);
-	}
-    }
-	 
-  if (buf != NULL) {
-
-    old_len = sl_strlen(buf->fullpath);
-#if defined(SH_STEALTH)
-    sh_do_encode(buf->fullpath, old_len);
-#endif
-    tmp = quote_string(buf->fullpath, old_len);
-    tmp_len = sl_strlen(tmp);
-#if defined(SH_STEALTH)
-    sh_do_decode(buf->fullpath, old_len);
-#endif
-
-    if (tmp && tmp_len <= MAX_PATH_STORE) 
-      {
-	sl_strlcpy(fullpath, buf->fullpath, MAX_PATH_STORE+1);
-      } 
-    else 
-      {
-	char hashbuf[KEYBUF_SIZE];
-
-	sl_strlcpy(fullpath, 
-		   sh_tiger_hash (buf->fullpath,
-				  TIGER_DATA, old_len, 
-				  hashbuf, sizeof(hashbuf)), 
-		   KEY_LEN+1);
-      }
-    if (tmp) SH_FREE(tmp);
-  }
-
-  path_len = sl_strlen(fullpath);
-#if defined(SH_STEALTH)
-  sh_do_encode(fullpath, path_len);
-#endif
-
-  tmp = quote_string(fullpath, path_len);
-  if (tmp) {
-    sl_strlcpy(fullpath, tmp, MAX_PATH_STORE+1);
-    SH_FREE(tmp);
-  }
-
-  /* NOTE: TXT entries are c_mode[0] != 'l' and do not get decoded 
-   */
-  if (buf != NULL /* && buf->c_mode[0] == 'l' */ && buf->link_path != NULL) 
-    {  
-
-      old_len = sl_strlen(buf->link_path);
-#if defined(SH_STEALTH)
-      if (buf->c_mode[0] == 'l')
-	sh_do_encode(buf->link_path, old_len);
-#endif
-      tmp = quote_string(buf->link_path, old_len);
-      tmp_len = sl_strlen(tmp);
-#if defined(SH_STEALTH)
-      if (buf->c_mode[0] == 'l')
-	sh_do_decode(buf->link_path, old_len);
-#endif
-
-      if (tmp && tmp_len <= MAX_PATH_STORE) 
-	{
-	  sl_strlcpy(linkpath, buf->link_path, MAX_PATH_STORE+1);  
-	} 
-      else 
-	{
-	  char hashbuf[KEYBUF_SIZE];
-	  sl_strlcpy(linkpath, 
-		     sh_tiger_hash (buf->link_path,
-				    TIGER_DATA, old_len,
-				    hashbuf, sizeof(hashbuf)),
-		     KEY_LEN+1);
-	}
-      if (tmp) SH_FREE(tmp);
-
-      path_len = sl_strlen(linkpath);
-#if defined(SH_STEALTH)
-      if (buf->c_mode[0] == 'l')
-	sh_do_encode(linkpath, path_len);
-#endif
-      tmp = quote_string(linkpath, path_len);
-      if (tmp)
-	{
-	  sl_strlcpy(linkpath, tmp, MAX_PATH_STORE+1);
-	  SH_FREE(tmp);
-	}
-    }
-
-  if (buf != NULL && buf->attr_string != NULL) 
-    {
-      old_len = sl_strlen(buf->attr_string);
-#if defined(SH_STEALTH)
-      sh_do_encode(buf->attr_string, old_len);
-#endif
-      tmp = quote_string(buf->attr_string, old_len);
-      if (tmp)
-	{
-	  attr_string = tmp;
-	  tmp = NULL;
-	}
-#if defined(SH_STEALTH)
-      sh_do_decode(buf->attr_string, old_len);
-#endif
-    }
-
-
-  if (buf != NULL) {
-    p.mark = REC_MAGIC;
-    if (attr_string)
-      p.mark |= REC_FLAGS_ATTR;
-    sl_strlcpy(p.c_mode,   buf->c_mode,   CMODE_SIZE);
-    sl_strlcpy(p.c_group,  buf->c_group,  GROUP_MAX+1);
-    sl_strlcpy(p.c_owner,  buf->c_owner,  USER_MAX+1);
-    if (fileHash) {
-      sl_strlcpy(p.checksum, fileHash,      KEY_LEN+1);
-    }
-#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
-    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
-    
-#if defined(SH_STEALTH)
-    sh_do_encode(p.c_mode,   sl_strlen(p.c_mode));
-    sh_do_encode(p.c_owner,  sl_strlen(p.c_owner));
-    sh_do_encode(p.c_group,  sl_strlen(p.c_group));
-    sh_do_encode(p.checksum, sl_strlen(p.checksum));
-
-    sh_do_encode(p.c_attributes,   sl_strlen(p.c_attributes));
-#endif
-    
-#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
-    p.attributes  = (UINT32) buf->attributes;
-#else
-    p.attributes  = 0;
-#endif
-    p.linkmode    = (UINT32) buf->linkmode;
-    p.hardlinks   = (UINT32) buf->hardlinks;
-    p.dev   = (UINT64) buf->dev;
-    p.rdev  = (UINT64) buf->rdev;
-    p.mode  = (UINT32) buf->mode;
-    p.ino   = (UINT32) buf->ino;
-    p.size  = (UINT64) buf->size;
-    p.mtime = (UINT64) buf->mtime;
-    p.atime = (UINT64) buf->atime;
-    p.ctime = (UINT64) buf->ctime;
-    p.owner = (UINT32) buf->owner;
-    p.group = (UINT32) buf->group;
-    
-    swap_32(&(p.mode));
-    swap_32(&(p.linkmode));
-    swap_64(&(p.dev));
-    swap_64(&(p.rdev));
-    swap_32(&(p.hardlinks));
-    swap_32(&(p.ino));
-    swap_64(&(p.size));
-    swap_64(&(p.atime));
-    swap_64(&(p.mtime));
-    swap_64(&(p.ctime));
-    swap_32(&(p.owner));
-    swap_32(&(p.group));
-    swap_32(&(p.attributes));
-
-#ifdef OLD_BUG
-    swap_short(&(p.mark));
-#else
-    p.mark = *(swap_short(&(p.mark)));
-#endif
-  }
-
-  /* write the start marker 
-   */
-  if (pushdata_isfirst == 1) 
-    {
-      if (sh.flag.update == S_FALSE)
-	{
-	  if (sh_db_version_string != NULL)
-	    {
-	      if (pushdata_stdout == S_FALSE)
-		{
-		  sl_write (pushdata_fd, _("\n#Host "), 7);
-		  sl_write (pushdata_fd, sh.host.name, 
-			    sl_strlen(sh.host.name));
-		  sl_write (pushdata_fd, _(" Version "), 9);
-		  sl_write (pushdata_fd, sh_db_version_string, 
-			    sl_strlen(sh_db_version_string));
-		  sl_write (pushdata_fd, _(" Date "), 6);
-		  (void) sh_unix_time(0, timestring, sizeof(timestring));
-		  sl_write (pushdata_fd, timestring, strlen(timestring));
-		  sl_write (pushdata_fd,        "\n", 1);
-		} else {
-		  printf ("%s",_("\n#Host "));
-		  printf ("%s", sh.host.name);
-		  printf ("%s",_(" Version "));
-		  printf ("%s", sh_db_version_string);
-		  printf ("%s",_(" Date "));
-		  (void) sh_unix_time(0, timestring, sizeof(timestring));
-		  printf ("%s\n", timestring);
-		}
-	    }
-
-	  if (pushdata_stdout == S_FALSE)
-	    {
-#if defined(SH_STEALTH)
-	      sl_write      (pushdata_fd,        "\n", 1);
-	      sl_write_line (pushdata_fd, N_("[SOF]"), 5);
-#else
-	      sl_write_line (pushdata_fd, _("\n[SOF]"),  6);
-#endif
-	    }
-	  else 
-	    {
-#if defined(SH_STEALTH)
-	      printf ("\n%s\n", N_("[SOF]"));
-#else
-	      printf ("%s\n", _("\n[SOF]"));
-#endif
-	    }
-	}
-      pushdata_isfirst = 0;
-    }
-      
-  if (pushdata_stdout == S_FALSE)
-    {
-      sl_write      (pushdata_fd,       &p, sizeof(sh_filestore_t));
-      sl_write_line_fast (pushdata_fd, fullpath, sl_strlen(fullpath));
-      sl_write_line_fast (pushdata_fd, linkpath, sl_strlen(linkpath));
-      if (attr_string)
-	sl_write_line_fast (pushdata_fd, attr_string, sl_strlen(attr_string));
-    } else {
-      if (fwrite (&p, sizeof(sh_filestore_t), 1, stdout))
-	{
-	  printf ("%s\n", fullpath);
-	  printf ("%s\n", linkpath);
-	  if (attr_string)
-	    printf ("%s\n", attr_string);
-	}
-      else
-	{
-	  perror(_("Error writing database"));
-	  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
-	}
-    }
-
-  ++p_count;
-
-  if ((sh.flag.update != S_TRUE) && (pushdata_stdout == S_FALSE))
-    {
-      if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
-	{
-	  sl_close (pushdata_fd);
-	  pushdata_fd = -1;
-	}
-    }
-
-  SH_FREE(fullpath);
-  SH_FREE(linkpath);
-  if (attr_string)
-    SH_FREE(attr_string);
-
-  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()
-{
-  sh_file_t * p;
-  int         i;
-  file_type * f;
-  char   fileHash[KEY_LEN + 1];
-
-  SL_ENTER(_("sh_hash_writeout"));
-
-  if (S_TRUE == file_is_remote())
-    {
-      sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN, 
-		      _("Baseline database is remote"), _("sh_hash_writeout"));
-      SL_RETURN (1, _("sh_hash_writeout"));
-    }
-
-  SH_MUTEX_LOCK(mutex_writeout); 
-  if (!SL_ISERROR(pushdata_fd))
-    {
-      sl_close(pushdata_fd);
-      pushdata_fd = -1;
-    }
-  pushdata_isfirst =  1;
-
-
-  SH_MUTEX_LOCK(mutex_hash);
-  for (i = 0; i < TABSIZE; ++i)
-    {
-      for (p = tab[i]; p; p = p->next)
-	{
-	  f = sh_hash_create_ft (p, fileHash);
-	  sh_hash_pushdata_int (f, fileHash);
-	  if (f->attr_string) SH_FREE(f->attr_string);
-	  if (f->link_path)   SH_FREE(f->link_path);
-	  SH_FREE(f);
-	}
-    }
-  SH_MUTEX_UNLOCK(mutex_hash);
-
-  if (!SL_ISERROR(pushdata_fd))
-    {
-      sl_close(pushdata_fd);
-      pushdata_fd = -1;
-    }
-  pushdata_isfirst =  1;
-  SH_MUTEX_UNLOCK(mutex_writeout); 
-
-  SL_RETURN (0, _("sh_hash_writeout"));
-}
 
 
@@ -2378,4 +1144,6 @@
   sl_strlcpy(tmpFile->c_group, _("root"), 5);
 
+  tmpFile->check_flags = 0;
+
   if ((str != NULL) && (size < (PATH_MAX/2)-1))
     {
@@ -2404,6 +1172,6 @@
 
   if (sh.flag.checkSum == SH_CHECK_INIT)
-    sh_hash_pushdata (tmpFile, 
-		      (save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
+    sh_dbIO_data_write (tmpFile, 
+			(save->checksum[0] == '\0') ? SH_KEY_NULL : save->checksum);
   else
     sh_hash_pushdata_memory (tmpFile, 
@@ -2524,4 +1292,6 @@
   p.group = (UINT32) buf->group;
 
+  p.checkflags = (UINT32) buf->check_flags;
+
   memcpy( &(*fp).theFile, &p, sizeof(sh_filestore_t) );
   fp->fflags    = 0;  /* init fflags */
@@ -2623,4 +1393,14 @@
   msg[0] = '\0';
 
+  if (report_checkflags != S_FALSE)
+    {
+      if (is_new)
+	format = _("checkflags_new=\"0%lo\" ");
+      else
+	format = _("checkflags_old=\"0%lo\" ");
+      sl_snprintf(tmp, SH_MSG_BUF, format,
+		  (unsigned long) theFile->check_flags);
+      sl_strlcat(msg, tmp, SH_MSG_BUF); 
+    }
 
 #if defined(__linux__) || defined(HAVE_STAT_FLAGS)
@@ -2790,4 +1570,15 @@
   msg[0] = '\0';
 
+  if (report_checkflags == S_TRUE)
+    {
+      if (is_new)
+	format = _("checkflags_new=<0%lo> ");
+      else
+	format = _("checkflags_old=<0%lo> ");
+      sl_snprintf(tmp, SH_MSG_BUF, format,
+		  (unsigned long) theFile->check_flags);
+      sl_strlcat(msg, tmp, SH_MSG_BUF); 
+    }
+
 
 #if defined(__linux__) || defined(HAVE_STAT_FLAGS)
@@ -2952,6 +1743,6 @@
     {
       SH_MUTEX_LOCK(mutex_hash);
-      hashinsert (p);
-      p->modi_mask = theFile->check_mask;
+      hashinsert (tab, p);
+      p->modi_mask = theFile->check_flags;
       SH_MUTEX_UNLOCK(mutex_hash);
     }
@@ -2960,4 +1751,104 @@
 }
 
+int sh_hash_is_null_file(file_type * theFile)
+{
+  if (theFile->hardlinks == SH_DEADFILE && theFile->mode  == 0 &&
+      theFile->ino == 0                 && theFile->ctime == 0)
+    {
+      return S_TRUE;
+    }
+  return S_FALSE;
+}
+
+int sh_hash_is_null_record(sh_filestore_t * theFile)
+{
+  if (theFile->hardlinks == SH_DEADFILE && theFile->mode  == 0 &&
+      theFile->ino == 0                 && theFile->ctime == 0)
+    {
+      return S_TRUE;
+    }
+  return S_FALSE;
+}
+
+void sh_hash_insert_null(char * str)
+{
+  file_type theFile = { 0, 0, {'\0'}, 0, 0, 0, 0, 0, 
+#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
+			0, {'\0'},
+#endif
+			{'\0'}, 0, {'\0'}, 0, {'\0'}, 
+			0, 0, 0, 0, 0, 0, 0, NULL,  0, {'\0'}, 0, NULL
+  }; /* clang compiler bails out on standard conforming init with just {0} */
+  char      fileHash[KEY_LEN+1];
+  char      hashbuf[KEYBUF_SIZE];
+
+  sl_strlcpy(fileHash, SH_KEY_NULL, sizeof(fileHash));
+  theFile.hardlinks = SH_DEADFILE;
+
+  if (sl_strlen(str) < PATH_MAX)
+    sl_strlcpy(theFile.fullpath, str, PATH_MAX);
+  else 
+     sl_strlcpy(theFile.fullpath, 
+		sh_tiger_hash(str, TIGER_DATA, sl_strlen(str),
+			      hashbuf, sizeof(hashbuf)),
+		PATH_MAX);
+
+  sh_hash_pushdata_memory(&theFile, fileHash);
+  return;
+}
+
+static int handle_notfound(int  log_severity, int class,
+			   file_type * theFile, char * fileHash)
+{
+  sh_file_t * p;
+  int         retval = 0;
+
+  if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
+    {
+      char * tmp = sh_util_safe_name(theFile->fullpath);
+      char * str;
+
+      sh_files_fixup_mask(class, &(theFile->check_flags));
+      str = all_items (theFile, fileHash, 1);
+      
+      sh_error_handle (log_severity, FIL__, __LINE__, 0, 
+		       MSG_FI_ADD2, 
+		       tmp, str);
+      ++sh.statistics.files_report;
+      SH_FREE(str);
+      SH_FREE(tmp);
+    }
+  
+  if (sh.flag.reportonce == S_TRUE)
+    SET_SH_FFLAG_REPORTED(theFile->file_reported);
+  
+  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
+    {
+      p = sh_hash_push_int(theFile, fileHash);
+      if (p)
+	{
+	  hashinsert (tab, p);
+	  p->modi_mask = theFile->check_flags;
+	  p->theFile.checkflags = p->modi_mask;
+	}
+    }
+  
+  else if (S_TRUE == sh.flag.update)
+    {
+      if (S_TRUE == sh_util_ask_update (theFile->fullpath))
+	{
+	  p = sh_hash_push_int(theFile, fileHash);
+	  if (p)
+	    {
+	      hashinsert (tab, p);
+	      p->modi_mask = theFile->check_flags;
+	      p->theFile.checkflags = p->modi_mask;
+	    }
+	}
+      else
+	retval = 1;
+    }
+  return retval;
+}
 
 /*****************************************************************
@@ -2975,6 +1866,4 @@
   char * tmp_lnk;
   char * tmp_lnk_old;
-
-  char * str;
 
   char timstr1c[32];
@@ -2996,4 +1885,8 @@
   volatile int  log_severity;
   char hashbuf[KEYBUF_SIZE];
+  struct {
+    unsigned long oldflags;
+    unsigned long newflags;
+  } cf_report;
 
   int  retval;
@@ -3033,49 +1926,5 @@
   if (p == NULL) 
     {
-      if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
-	{
-	  tmp = sh_util_safe_name(theFile->fullpath);
-
-	  str = all_items (theFile, fileHash, 1);
-	  sh_error_handle (log_severity, FIL__, __LINE__, 0, 
-			   MSG_FI_ADD2, 
-			   tmp, str);
-	  ++sh.statistics.files_report;
-	  SH_FREE(str);
-
-	  SH_FREE(tmp);
-	}
-
-      if (sh.flag.reportonce == S_TRUE)
-	SET_SH_FFLAG_REPORTED(theFile->file_reported);
-
-      if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
-	{
-	  p = sh_hash_push_int(theFile, fileHash);
-	  if (p)
-	    {
-	      hashinsert (p);
-	      p->modi_mask = theFile->check_mask;
-	    }
-	}
-
-      else if (S_TRUE == sh.flag.update)
-	{
-	  if (S_TRUE == sh_util_ask_update (theFile->fullpath))
-	    {
-	      p = sh_hash_push_int(theFile, fileHash);
-	      if (p)
-		{
-		  hashinsert (p);
-		  p->modi_mask = theFile->check_mask;
-		}
-	    }
-	  else
-	    {
-	      retval = 1;
-	      goto unlock_and_return;
-	    }
-	}
-
+      retval = handle_notfound(log_severity, class, theFile, fileHash);
       goto unlock_and_return;
     }
@@ -3086,8 +1935,15 @@
   if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
     {
+      MODI_SET(theFile->check_flags, MODI_NOCHECK);
+      p->modi_mask = theFile->check_flags;
+      p->theFile.checkflags = p->modi_mask;
       goto unlock_and_return;
     }
 
-  p->modi_mask = theFile->check_mask;
+  cf_report.oldflags = p->theFile.checkflags;
+  cf_report.newflags = theFile->check_flags;
+
+  p->modi_mask = theFile->check_flags;
+  p->theFile.checkflags = p->modi_mask;
 
   /* initialize change_code */
@@ -3101,7 +1957,7 @@
   if ( (fileHash != NULL) &&
        (strncmp (fileHash, p->theFile.checksum, KEY_LEN) != 0) && 
-       (theFile->check_mask & MODI_CHK) != 0)
-    {
-      if ((theFile->check_mask & MODI_SGROW) == 0)
+       (theFile->check_flags & MODI_CHK) != 0)
+    {
+      if ((theFile->check_flags & MODI_SGROW) == 0)
 	{
 	  modi_mask |= MODI_CHK;
@@ -3114,5 +1970,6 @@
 	    {
 	      if (S_FALSE == sh_check_rotated_log (theFile->fullpath, (UINT64) p->theFile.size, 
-						   (UINT64) p->theFile.ino, p->theFile.checksum))
+						   (UINT64) p->theFile.ino, p->theFile.checksum,
+						   p->theFile.checkflags))
 		{
 		  modi_mask |= MODI_CHK;
@@ -3139,5 +1996,5 @@
     {
       if (!(theFile->link_path) &&
-	  (theFile->check_mask & MODI_LNK) != 0)
+	  (theFile->check_flags & MODI_LNK) != 0)
 	{
 	  linkComp = NULL;
@@ -3166,5 +2023,5 @@
 	  
 	  if ( sl_strncmp (linkComp, p->linkpath, maxcomp) != 0 &&
-	       (theFile->check_mask & MODI_LNK) != 0)
+	       (theFile->check_flags & MODI_LNK) != 0)
 	    {
 	      modi_mask |= MODI_LNK;
@@ -3179,5 +2036,5 @@
       if ( ( major(theFile->rdev) != major((dev_t)p->theFile.rdev) || 
 	     minor(theFile->rdev) != minor((dev_t)p->theFile.rdev) ) &&
-	   (theFile->check_mask & MODI_RDEV) != 0)
+	   (theFile->check_flags & MODI_RDEV) != 0)
 	{
 	  modi_mask |= MODI_RDEV;
@@ -3190,5 +2047,5 @@
    */
   if ( (UINT32) theFile->ino != (UINT32) p->theFile.ino  &&
-       (theFile->check_mask & MODI_INO) != 0)
+       (theFile->check_flags & MODI_INO) != 0)
     {
       modi_mask |= MODI_INO;
@@ -3198,5 +2055,5 @@
     
   if ( theFile->hardlinks != (nlink_t) p->theFile.hardlinks &&
-       (theFile->check_mask & MODI_HLN) != 0)
+       (theFile->check_flags & MODI_HLN) != 0)
     {
       modi_mask |= MODI_HLN;
@@ -3220,5 +2077,5 @@
 #endif
 	  )
-       && (theFile->check_mask & MODI_MOD) != 0)
+       && (theFile->check_flags & MODI_MOD) != 0)
     {
       modi_mask |= MODI_MOD;
@@ -3228,5 +2085,5 @@
        * report link path if switch link/no link 
        */
-      if ((theFile->check_mask & MODI_LNK) != 0 &&
+      if ((theFile->check_flags & MODI_LNK) != 0 &&
 	  (theFile->c_mode[0] != p->theFile.c_mode[0]) &&
 	  (theFile->c_mode[0] == 'l' || p->theFile.c_mode[0] == 'l'))
@@ -3239,5 +2096,5 @@
 
   if ( theFile->owner != (uid_t) p->theFile.owner &&
-       (theFile->check_mask & MODI_USR) != 0)
+       (theFile->check_flags & MODI_USR) != 0)
     {
       modi_mask |= MODI_USR;
@@ -3247,5 +2104,5 @@
 
   if ( theFile->group != (gid_t) p->theFile.group &&
-       (theFile->check_mask & MODI_GRP) != 0)
+       (theFile->check_flags & MODI_GRP) != 0)
     {
       modi_mask |= MODI_GRP;
@@ -3256,5 +2113,5 @@
   
   if ( theFile->mtime != (time_t) p->theFile.mtime &&
-       (theFile->check_mask & MODI_MTM) != 0)
+       (theFile->check_flags & MODI_MTM) != 0)
     {
       modi_mask |= MODI_MTM;
@@ -3263,5 +2120,5 @@
     } 
   
-  if ( (theFile->check_mask & MODI_ATM) != 0 &&
+  if ( (theFile->check_flags & MODI_ATM) != 0 &&
        theFile->atime != (time_t) p->theFile.atime)
     {
@@ -3276,5 +2133,5 @@
    */
   if ( theFile->ctime != (time_t) p->theFile.ctime &&
-       (theFile->check_mask & MODI_CTM) != 0)
+       (theFile->check_flags & MODI_CTM) != 0)
     {
       modi_mask |= MODI_CTM;
@@ -3284,7 +2141,7 @@
 
   if ( theFile->size != (off_t) p->theFile.size &&
-       (theFile->check_mask & MODI_SIZ) != 0)
-    {
-      if ((theFile->check_mask & MODI_SGROW) == 0 || 
+       (theFile->check_flags & MODI_SIZ) != 0)
+    {
+      if ((theFile->check_flags & MODI_SGROW) == 0 || 
 	  theFile->size < (off_t) p->theFile.size)
 	{
@@ -3309,5 +2166,5 @@
   if (modi_mask != 0 && sh.flag.fulldetail == S_TRUE)
     {
-      if ((theFile->check_mask & MODI_ATM) == 0)
+      if ((theFile->check_flags & MODI_ATM) == 0)
 	modi_mask = MASK_READONLY_;
       else
@@ -3322,4 +2179,18 @@
       msg = SH_ALLOC(SH_MSG_BUF);
       msg[0] = '\0';
+
+      sh_files_fixup_mask(class, &(cf_report.newflags));
+
+      if ( (report_checkflags != S_FALSE) && (cf_report.oldflags != cf_report.newflags))
+	{
+	  sl_snprintf(tmp, SH_MSG_BUF,
+#ifdef SH_USE_XML
+		      _("checkflags_old=\"0%lo\" checkflags_new=\"0%lo\" "),
+#else
+		      _("checkflags_old=<0%lo>, checkflags_new=<0%lo>, "),
+#endif
+		      cf_report.oldflags,  cf_report.newflags);
+	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
+	}
 
       if (   ((modi_mask & MODI_MOD) != 0)
@@ -3374,5 +2245,4 @@
 #endif
 
-#ifdef REPLACE_OLD
 	  if ((modi_mask & MODI_MOD) != 0)
 	    {
@@ -3405,5 +2275,5 @@
 		}
 	    }
-#endif
+
 	}
 
@@ -3419,8 +2289,7 @@
 		      (unsigned long) theFile->hardlinks);
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    p->theFile.hardlinks = theFile->hardlinks;
-#endif
 	}
 
@@ -3443,8 +2312,7 @@
 		      );
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    p->theFile.rdev = theFile->rdev;
-#endif
 	}
 
@@ -3460,5 +2328,5 @@
 		      (unsigned long) theFile->ino);
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    {
@@ -3466,5 +2334,4 @@
 	      p->theFile.dev = theFile->dev;
 	    }
-#endif
 	}
 
@@ -3488,8 +2355,7 @@
 		      );
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    p->theFile.dev = theFile->dev;
-#endif
 	}
 #endif
@@ -3512,5 +2378,5 @@
 		      );
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if ((modi_mask & MODI_USR) != 0) {
 	    if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
@@ -3520,5 +2386,4 @@
 	      }
 	  }
-#endif
 	}
 
@@ -3542,5 +2407,5 @@
 
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
           if ((modi_mask & MODI_GRP) != 0) {
 	    if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
@@ -3550,5 +2415,4 @@
 	      }
 	  }
-#endif
 	}
 
@@ -3559,8 +2423,7 @@
 		      (UINT64) theFile->size);
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    p->theFile.size = theFile->size;
-#endif
 	}
 
@@ -3577,8 +2440,7 @@
 #endif
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    p->theFile.ctime = theFile->ctime;
-#endif
 	}
 
@@ -3595,8 +2457,7 @@
 #endif
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    p->theFile.atime = theFile->atime;
-#endif
 	}
 
@@ -3613,8 +2474,7 @@
 #endif
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    p->theFile.mtime = theFile->mtime;
-#endif
 	}
 
@@ -3630,13 +2490,13 @@
 		      p->theFile.checksum, fileHash);
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    {
 	      sl_strlcpy(p->theFile.checksum, fileHash, KEY_LEN+1);
-	      if ((theFile->check_mask & MODI_SGROW) != 0)	      
+	      if ((theFile->check_flags & MODI_SGROW) != 0)	      
 		p->theFile.size  = theFile->size;
 	    }
-#endif
-	  /* FIXME is this correct? */
+
+
 	  if (theFile->c_mode[0] != 'l' && theFile->link_path &&
 	      strlen(theFile->link_path) > 2)
@@ -3665,19 +2525,17 @@
 	  SH_FREE(tmp_lnk_old);
 	  sl_strlcat(msg, tmp, SH_MSG_BUF); 
-#ifdef REPLACE_OLD
+
 	  if (sh.flag.reportonce == S_TRUE && sh.flag.update == S_FALSE)
 	    {
-	      if (p->linkpath != NULL && p->linkpath != notalink)
+	      if (p->linkpath != NULL)
 		SH_FREE(p->linkpath);
-	      if (!(theFile->link_path) || 
-		  (theFile->link_path[0] == '-' && theFile->link_path[1] == '\0'))
-		p->linkpath = (char *)notalink;
+	      if (!(theFile->link_path))
+		p->linkpath = sh_util_strdup("-");
 	      else
 		p->linkpath = sh_util_strdup(theFile->link_path);
 	    }
-#endif
-	}
-
-      if (MODI_AUDIT_ENABLED(theFile->check_mask))
+	}
+
+      if (MODI_AUDIT_ENABLED(theFile->check_flags))
 	{
 	  char result[256];
@@ -3701,4 +2559,9 @@
 	}
 
+      /****************************************************
+       *
+       * REPORT on file change
+       *
+       ****************************************************/
       tmp_path = sh_util_safe_name(theFile->fullpath);
       sh_error_handle(log_severity, FIL__, __LINE__, 
@@ -3711,8 +2574,4 @@
       SH_FREE(tmp);
       SH_FREE(msg);
-
-#ifndef REPLACE_OLD
-      SET_SH_FFLAG_REPORTED(p->fflags);
-#endif
 
       if (S_TRUE  == sh.flag.update)
@@ -3757,5 +2616,5 @@
 		  if (theFile->link_path)
 		    SH_FREE(theFile->link_path);
-		  if (p->linkpath && p->linkpath != notalink)
+		  if (p->linkpath)
 		    theFile->link_path = sh_util_strdup(p->linkpath);
 		  else
@@ -3815,5 +2674,5 @@
 	      if (theFile->c_mode[0] == 'l' || theFile->link_path)
 		{
-                  if (p->linkpath != NULL && p->linkpath != notalink)
+                  if (p->linkpath != NULL)
 		    SH_FREE(p->linkpath);
 		  p->linkpath = sh_util_strdup(theFile->link_path);
@@ -3821,8 +2680,7 @@
 	      else
 		{
-	          if (p->linkpath != NULL && p->linkpath != notalink) {
+	          if (p->linkpath != NULL)
 		    SH_FREE(p->linkpath);
-		  }
-		  p->linkpath = (char *)notalink;
+		  p->linkpath = sh_util_strdup("-");
 		}
 	      
@@ -3955,6 +2813,8 @@
 	    {
 	      /* if (0 == strncmp(s, p->fullpath, len_s)) *//* old */
-	      if (S_TRUE == hash_remove_tree_test(s, p->fullpath, len_s)) 
+	      if (S_TRUE == hash_remove_tree_test(s, p->fullpath, len_s)) {
 		SET_SH_FFLAG_ALLIGNORE(p->fflags);
+		MODI_SET(p->theFile.checkflags, MODI_ALLIGNORE);
+	      }
 	    } /* if path is not null */
 
@@ -3984,4 +2844,8 @@
   ListFile = sh_util_strdup(c);
   return 0;
+}
+char * get_list_file()
+{
+  return ListFile;
 }
 
@@ -4231,23 +3095,48 @@
   time_t now  = time(NULL);
   time_t then = (time_t) p->theFile.mtime;
+  struct tm   * time_ptr;
 
 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
-  struct tm   * time_ptr;
   struct tm     time_tm;
-
+#endif
+
+  if (ListFullDetail != S_FALSE)
+    {
+      sh_hash_list_db_entry_full_detail (p);
+      return;
+    }
+
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
   time_ptr = gmtime_r(&then, &time_tm);
+  if (!time_ptr)
+    return;
   strftime(thetime, 127, _("%b %d  %Y"), time_ptr);
   time_ptr = gmtime_r(&now,  &time_tm);
+  if (!time_ptr)
+    return;
   strftime(nowtime, 127, _("%b %d  %Y"), time_ptr);
   if (0 == strncmp(&nowtime[7], &thetime[7], 4))
     {
       time_ptr = gmtime_r(&then, &time_tm);
+      if (!time_ptr)
+	return;
       strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
     }
 #else
-  strftime(thetime, 127, _("%b %d  %Y"), gmtime(&then));
-  strftime(nowtime, 127, _("%b %d  %Y"), gmtime(&now));
+  time_ptr = gmtime(&then);
+  if (!time_ptr)
+    return;
+  strftime(thetime, 127, _("%b %d  %Y"), time_ptr);
+  time_ptr = gmtime(&now);
+  if (!time_ptr)
+    return;
+  strftime(nowtime, 127, _("%b %d  %Y"), time_ptr);
   if (0 == strncmp(&nowtime[7], &thetime[7], 4))
-    strftime(thetime, 127, _("%b %d %H:%M"), gmtime(&then));
+    {
+      time_ptr = gmtime(&then);
+      if (!time_ptr)
+	return;
+      strftime(thetime, 127, _("%b %d %H:%M"), time_ptr);
+    }
 #endif
 
@@ -4327,102 +3216,4 @@
 }
 
-int sh_hash_list_db (const char * db_file)
-{
-  sh_file_t * p;
-  SL_TICKET fd;
-  char * line;
-  int  flag = 0;
-
-  if (!db_file)
-    {
-      _exit(EXIT_FAILURE);
-      return -1; 
-    }
-  if (sl_is_suid())
-    {
-      fprintf(stderr, "%s",_("ERROR: insufficient privilege\n"));
-      _exit (EXIT_FAILURE);
-      return -1; /* for Mac OSX compiler */
-    }
-  if (0 == strcmp(db_file, _("default")))
-    db_file = file_path('D', 'W');
-  if (!db_file)
-    {
-      _exit(EXIT_FAILURE);
-      return -1; 
-    }
-
-  line = SH_ALLOC(MAX_PATH_STORE+2);
-
-  if ( SL_ISERROR(fd = sl_open_read(FIL__, __LINE__, db_file, SL_YESPRIV))) 
-    {
-      fprintf(stderr, _("ERROR: can't open %s for read (errnum = %ld)\n"), 
-	      db_file, fd);
-      _exit(EXIT_FAILURE);
-      return -1; 
-    }
-
-  /* fast forward to start of data
-   */
-  sh_hash_setdataent(fd, line, MAX_PATH_STORE+1, db_file);
-
-  while (1) 
-    {
-      p = sh_hash_getdataent (fd, line, MAX_PATH_STORE+1);
-      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
-	    {
-	      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, "%s",_("File is a link\n"));
-		  _exit(EXIT_FAILURE);
-		  return -1;
-		}
-	      break;
-	    }
-	}
-      else if (p == NULL)
-	{
-	  break;
-	}
-    }
-
-  if (line != NULL)
-    SH_FREE(line);
-  sl_close (fd);
-
-  fflush(NULL);
-
-  if (flag == 0)
-    {
-      fprintf(stderr, "%s",_("File not found\n"));
-      _exit(EXIT_FAILURE);
-    }
-  _exit(EXIT_SUCCESS);
-  return 0; 
-}
-
 /* if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE) */
 #endif
Index: trunk/src/sh_html.c
===================================================================
--- trunk/src/sh_html.c	(revision 476)
+++ trunk/src/sh_html.c	(revision 481)
@@ -41,5 +41,5 @@
 
 #include "samhain.h"
-#include "sh_forward.h"
+#include "sh_xfer.h"
 #include "sh_error.h"
 #include "sh_unix.h"
@@ -159,4 +159,6 @@
 	  if (time_ptr != NULL) 
 	    strftime (ts1, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr);
+	  else
+	    sl_strlcpy(ts1, _("01-01-1970 00:00:00"), sizeof(ts1));
 	  now = time(NULL);
 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
@@ -167,4 +169,6 @@
 	  if (time_ptr != NULL) 
 	    strftime (ts2, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr);
+	  else
+	    sl_strlcpy(ts2, _("01-01-1970 00:00:00"), sizeof(ts2));
 
 	  sl_snprintf(outline, 1023, 
@@ -193,4 +197,6 @@
 	      if (time_ptr != NULL) 
 		strftime (ts1, 80, _("%d-%m-%Y %H:%M:%S"), time_ptr);
+	      else
+		sl_strlcpy(ts1, _("01-01-1970 00:00:00"), sizeof(ts1));
 	      sl_snprintf(outline, 1023, 
 			  _("<p>Last connection at %s</p>"), 
@@ -416,5 +422,5 @@
   int status;
   int clt_status;
-  int i, n;
+  unsigned int i, n;
 
   SL_ENTER(_("sh_html_print_one"));
Index: trunk/src/sh_ignore.c
===================================================================
--- trunk/src/sh_ignore.c	(revision 476)
+++ trunk/src/sh_ignore.c	(revision 481)
@@ -73,5 +73,5 @@
   SL_ENTER(_("sh_ignore_add"));
 
-  if ( (addpath == NULL) || (sl_ok_adds(2, strlen(addpath)) == SL_FALSE) )
+  if ( (addpath == NULL) || (sl_ok_adds(2, strlen(addpath)) == S_FALSE) )
     {
       SL_RETURN(list, _("sh_ignore_add"));
Index: trunk/src/sh_inotify.c
===================================================================
--- trunk/src/sh_inotify.c	(revision 476)
+++ trunk/src/sh_inotify.c	(revision 481)
@@ -135,5 +135,5 @@
   int    class;
   int    rdepth;
-  unsigned long check_mask;
+  unsigned long check_flags;
   char * file;
 } sh_watch;
@@ -236,5 +236,5 @@
   int     ifd = sh_inotify_getfd();
 
-  len = sl_read_timeout_fd (ifd, buffer, count, timeout, SL_FALSE);
+  len = sl_read_timeout_fd (ifd, buffer, count, timeout, S_FALSE);
 
   return len;
@@ -364,5 +364,5 @@
 
 char * sh_inotify_pop_dormant(sh_watches * watches, 
-			      int * class, unsigned long * check_mask, 
+			      int * class, unsigned long * check_flags, 
 			      int * type, int * rdepth)
 {
@@ -384,5 +384,5 @@
       *type   = this->watch->type;
       *rdepth = this->watch->rdepth;
-      *check_mask = this->watch->check_mask;
+      *check_flags = this->watch->check_flags;
       popret  = sh_util_strdup_track(this->watch->file, __FILE__, __LINE__);
 
@@ -424,5 +424,5 @@
 static zAVLKey sh_inotify_getkey(void const *item)
 {
-  return (&((sh_watch *)item)->watch);
+  return (&((const sh_watch *)item)->watch);
 }
 
@@ -490,5 +490,5 @@
 int sh_inotify_add_watch_later(const char * filename, sh_watches * watches, 
 			       int * errnum,
-			       int class, unsigned long check_mask, int type, 
+			       int class, unsigned long check_flags, int type, 
 			       int rdepth)
 {
@@ -500,5 +500,5 @@
   item->type       = (short) type;
   item->rdepth     = (short) rdepth;
-  item->check_mask = check_mask;
+  item->check_flags = check_flags;
 
   sh_inotify_add_dormant(watches, item);
@@ -548,5 +548,5 @@
 
   extern void sh_fInotify_report_add(char * path, 
-				     int class, unsigned long check_mask);
+				     int class, unsigned long check_flags);
 
   sh_dummy_litem = (void*) &litem;
@@ -575,5 +575,5 @@
 	      SH_MUTEX_UNLOCK(mutex_watches);
 
-	      sh_fInotify_report_add(litem->file, litem->class, litem->check_mask);
+	      sh_fInotify_report_add(litem->file, litem->class, litem->check_flags);
 
 	      litem = sh_inotify_list_del_cur(&listcursor, save);
@@ -592,5 +592,5 @@
  */
 int sh_inotify_add_watch(char * filename, sh_watches * watches, int * errnum,
-			 int class, unsigned long check_mask, int type, int rdepth)
+			 int class, unsigned long check_flags, int type, int rdepth)
 {
   volatile int retval = 0;
@@ -637,5 +637,5 @@
 	  item->type       = type;
 	  item->rdepth     = rdepth;
-	  item->check_mask = check_mask;
+	  item->check_flags = check_flags;
 	  
 	  if (NULL == watches->list_of_watches)
@@ -692,5 +692,5 @@
 
 char * sh_inotify_search_item(sh_watches * watches, int watch, 
-			      int * class, unsigned long * check_mask, 
+			      int * class, unsigned long * check_flags, 
 			      int * type, int * rdepth)
 {
@@ -709,5 +709,5 @@
     {
       *class      = item->class;
-      *check_mask = item->check_mask;
+      *check_flags = item->check_flags;
       *type       = item->type;
       *rdepth     = item->rdepth;
@@ -882,10 +882,10 @@
 
 int sh_inotify_add_watch(char * filename, sh_watches * watches, int  * errnum,
-			 int class, unsigned long check_mask, int type, int rdepth)
+			 int class, unsigned long check_flags, int type, int rdepth)
 {
   (void) filename;
   (void) watches;
   (void) class;
-  (void) check_mask;
+  (void) check_flags;
   (void) type;
   (void) rdepth;
@@ -898,10 +898,10 @@
 int sh_inotify_add_watch_later(const char * filename, sh_watches * watches, 
 			       int  * errnum,
-			       int class, unsigned long check_mask, int type, int rdepth)
+			       int class, unsigned long check_flags, int type, int rdepth)
 {
   (void) filename;
   (void) watches;
   (void) class;
-  (void) check_mask;
+  (void) check_flags;
   (void) type;
   (void) rdepth;
@@ -927,5 +927,5 @@
   int type;
   int rdepth;
-  unsigned long check_mask;
+  unsigned long check_flags;
   int           nrun = 0;
 
@@ -1022,12 +1022,12 @@
     CuAssertIntEquals(tc, count, 5);
     
-    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask, &type, &rdepth);
+    p = sh_inotify_pop_dormant(&twatch, &class, &check_flags, &type, &rdepth);
     CuAssertStrEquals(tc, p, "a5");
     
-    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask, &type, &rdepth);
+    p = sh_inotify_pop_dormant(&twatch, &class, &check_flags, &type, &rdepth);
     CuAssertStrEquals(tc, p, "a3");
     CuAssertIntEquals(tc, class, 3);
     
-    p = sh_inotify_pop_dormant(&twatch, &class, &check_mask, &type, &rdepth);
+    p = sh_inotify_pop_dormant(&twatch, &class, &check_flags, &type, &rdepth);
     CuAssertTrue(tc, NULL == p);
     CuAssertTrue(tc, NULL == twatch.dormant_watches);
Index: trunk/src/sh_ipvx.c
===================================================================
--- trunk/src/sh_ipvx.c	(revision 476)
+++ trunk/src/sh_ipvx.c	(revision 481)
@@ -165,8 +165,4 @@
 			name, name_size, NULL, 0, NI_NUMERICHOST);
 
-
-  /* fprintf(stderr, "FIXME: Error %s (%d), name %s (%d)\n", 
-     gai_strerror(ret), ret, name, name_size); */
-
   if (ret != 0 && name_size > 0)
     {
@@ -343,5 +339,5 @@
 }
 
-static void * sh_dummy_out;
+void * sh_dummy_341_out;
 
 char * sh_ipvx_canonical(const char * hostname, char * numeric, size_t nlen)
@@ -361,5 +357,5 @@
   numeric[0] = '\0';
 
-  sh_dummy_out = (void *) &out;
+  sh_dummy_341_out = (void *) &out;
  
   if (sh_ipvx_is_numeric(hostname))
@@ -426,5 +422,5 @@
   numeric[0] = '\0';
 
-  sh_dummy_out = (void *) &out;
+  sh_dummy_341_out = (void *) &out;
 
   if (sh_ipvx_is_numeric(hostname))
Index: trunk/src/sh_kern.c
===================================================================
--- trunk/src/sh_kern.c	(revision 476)
+++ 	(revision )
@@ -1,2148 +1,0 @@
-/* SAMHAIN file system integrity testing                                   */
-/* Copyright (C) 2001 Rainer Wichmann                                      */
-/*                                                                         */
-/*  This program is free software; you can redistribute it                 */
-/*  and/or modify                                                          */
-/*  it under the terms of the GNU General Public License as                */
-/*  published by                                                           */
-/*  the Free Software Foundation; either version 2 of the License, or      */
-/*  (at your option) any later version.                                    */
-/*                                                                         */
-/*  This program is distributed in the hope that it will be useful,        */
-/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
-/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
-/*  GNU General Public License for more details.                           */
-/*                                                                         */
-/*  You should have received a copy of the GNU General Public License      */
-/*  along with this program; if not, write to the Free Software            */
-/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
-
-
-#include "config_xor.h"
-
-#define SH_SYSCALL_CODE
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <sys/mman.h>
-
-
-#ifdef SH_USE_KERN
-
-#undef  FIL__
-#define FIL__  _("sh_kern.c")
-
-#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
-
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-
-#include "samhain.h"
-#include "sh_pthread.h"
-#include "sh_utils.h"
-#include "sh_error.h"
-#include "sh_modules.h"
-#include "sh_kern.h"
-#include "sh_ks_xor.h"
-
-#include "sh_unix.h"
-#include "sh_hash.h"
-
-
-
-sh_rconf sh_kern_table[] = {
-  {
-    N_("severitykernel"),
-    sh_kern_set_severity
-  },
-  {
-    N_("kernelcheckactive"),
-    sh_kern_set_activate
-  },
-  {
-    N_("kernelcheckinterval"),
-    sh_kern_set_timer
-  },
-  {
-    N_("kernelcheckidt"),
-    sh_kern_set_idt
-  },
-  {
-    N_("kernelcheckpci"),
-    sh_kern_set_pci
-  },
-  {
-    N_("kernelcheckproc"),
-    sh_kern_set_proc
-  },
-  {
-    N_("kernelsystemcall"),
-    sh_kern_set_sc_addr
-  },
-  {
-    N_("kernelsyscalltable"),
-    sh_kern_set_sct_addr
-  },
-  {
-    N_("kernelprocrootlookup"),
-    sh_kern_set_proc_root_lookup
-  },
- {
-    N_("kernelprocrootiops"),
-    sh_kern_set_proc_root_iops
-  },
-  {
-    N_("kernelprocroot"),
-    sh_kern_set_proc_root
-  },
-  {
-    NULL,
-    NULL
-  },
-};
-
-
-static time_t  lastcheck;
-static int     ShKernActive   = S_TRUE;
-static int     ShKernInterval = 300;
-static int     ShKernSeverity = SH_ERR_SEVERE;
-static int     ShKernDelay    = 100; /* milliseconds */
-static int     ShKernIDT      = S_TRUE;
-static int     ShKernPCI      = S_TRUE;
-static int     ShKernPROC     = S_TRUE;
-
-/* The address of system_call
- */
-#ifdef SH_SYS_CALL_ADDR
-static unsigned long system_call_addr = SH_SYS_CALL_ADDR;
-#else
-static unsigned long system_call_addr = 0;
-#endif
-
-/* The address of the sys_call_table
- */
-#ifdef SH_SYS_CALL_TABLE
-static unsigned long  kaddr = SH_SYS_CALL_TABLE;
-#else
-static unsigned long  kaddr = 0;
-#endif
-
-#ifdef PROC_ROOT_LOC
-static unsigned long proc_root = PROC_ROOT_LOC;
-#else
-static unsigned long proc_root = 0;
-#endif
-#ifdef PROC_ROOT_IOPS_LOC
-static unsigned long proc_root_iops = PROC_ROOT_IOPS_LOC;
-#else
-static unsigned long proc_root_iops = 0;
-#endif
-#ifdef PROC_ROOT_LOOKUP_LOC
-static unsigned long proc_root_lookup = PROC_ROOT_LOOKUP_LOC;
-#else
-static unsigned long proc_root_lookup = 0;
-#endif
-
-/* This is the module 'reconfigure' function, which is a no-op.
- */
-int sh_kern_null()
-{
-  return 0;
-}
-
-#define SH_KERN_DBPUSH 0
-#define SH_KERN_DBPOP  1
-
-char * sh_kern_db_syscall (int num, char * prefix,
-			   void * in_name, unsigned long * addr,
-			   unsigned int * code1, unsigned int * code2,
-			   int * size, int direction)
-{
-  char            path[128];
-  char          * p = NULL;
-
-  unsigned char * name = (unsigned char *) in_name;
-  struct store2db save;
-
-  sl_snprintf(path, 128, "K_%s_%04d", prefix, num);
-
-  memset(&save, '\0', sizeof(struct store2db));
-
-  if (direction == SH_KERN_DBPUSH) 
-    {
-      save.val0 = *addr;
-      save.val1 = *code1;
-      save.val2 = *code2;
-      save.str  = name;
-      save.size = (name == NULL) ? 0 : (*size);
-
-      sh_hash_push2db (path, &save);
-    }
-  else
-    {
-      p = sh_hash_db2pop (path, &save);
-
-      *addr  = (unsigned long) save.val0;
-      *code1 = (unsigned int)  save.val1;
-      *code2 = (unsigned int)  save.val2;
-
-      *size  = (int)           save.size;
-    }
-  return p;
-}
-
-static char * sh_kern_pathmsg (char * msg, size_t msg_len,
-			       int num, char * prefix,
-			       unsigned char * old, size_t old_len,
-			       unsigned char * new, size_t new_len)
-{
-  size_t k;
-  char   tmp[128];
-  char  *p;
-  char  *linkpath_old;
-  char  *linkpath_new;
-  char   i2h[2];
-
-#ifdef SH_USE_XML
-  sl_snprintf(tmp, sizeof(tmp), _("path=\"K_%s_%04d\" "), 
-	      prefix, num);
-#else
-  sl_snprintf(tmp, sizeof(tmp), _("path=<K_%s_%04d> "), 
-	      prefix, num);
-#endif
-  sl_strlcpy(msg, tmp, msg_len);
-
-  if (SL_TRUE == sl_ok_muls(old_len, 2) &&
-      SL_TRUE == sl_ok_adds(old_len * 2, 1))
-    linkpath_old = SH_ALLOC(old_len * 2 + 1);
-  else
-    return msg;
-
-  if (SL_TRUE == sl_ok_muls(new_len, 2) &&
-      SL_TRUE == sl_ok_adds(new_len * 2, 1))
-    linkpath_new = SH_ALLOC(new_len * 2 + 1);
-  else
-    return msg;
-
-  for (k = 0; k < old_len; ++k)
-    {
-      p = sh_util_charhex (old[k], i2h);
-      linkpath_old[2*k]   = p[0];
-      linkpath_old[2*k+1] = p[1];
-      linkpath_old[2*k+2] = '\0';
-    }
-
-  for (k = 0; k < new_len; ++k)
-    {
-      p = sh_util_charhex (new[k], i2h);
-      linkpath_new[2*k]   = p[0];
-      linkpath_new[2*k+1] = p[1];
-      linkpath_new[2*k+2] = '\0';
-    
-}
-#ifdef SH_USE_XML
-  sl_strlcat(msg, _("link_old=\""),    msg_len);
-  sl_strlcat(msg, linkpath_old,        msg_len);
-  sl_strlcat(msg, _("\" link_new=\""), msg_len);
-  sl_strlcat(msg, linkpath_new,        msg_len);
-  sl_strlcat(msg, _("\""),             msg_len);
-#else
-  sl_strlcat(msg, _("link_old=<"),     msg_len);
-  sl_strlcat(msg, linkpath_old,        msg_len);
-  sl_strlcat(msg, _(">, link_new=<"),  msg_len);
-  sl_strlcat(msg, linkpath_new,        msg_len);
-  sl_strlcat(msg, _(">"),              msg_len);
-#endif
-
-  SH_FREE(linkpath_old);
-  SH_FREE(linkpath_new);
-
-  return msg;
-}
- 
-#ifdef HOST_IS_LINUX
-
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-#endif
-
-/*
- * Interrupt Descriptor Table
- */
-#ifdef HAVE_ASM_SEGMENT_H
-#include <asm/segment.h>
-#endif
-
-#define SH_MAXIDT   256
-
-static unsigned char sh_idt_table[SH_MAXIDT * 8];
-
-static char * sh_strseg(unsigned short segment)
-{
-  static int flip = 0;
-  static char one[32];
-  static char two[32];
-
-  switch (segment) {
-#ifdef __KERNEL_CS
-  case __KERNEL_CS:
-    return _("KERNEL_CS");
-#endif
-#ifdef __KERNEL_DS
-  case __KERNEL_DS:
-    return _("KERNEL_DS");
-#endif
-#ifdef __USER_CS
-  case __USER_CS:
-    return _("USER_CS");
-#endif
-#ifdef __USER_DS
-  case __USER_DS:
-    return _("USER_DS");
-#endif
-  default:
-    if (flip == 0)
-      {
-	snprintf(one, sizeof(one), "%hX", segment);
-	flip = 1;
-	return one;
-      }
-    else
-      {
-	snprintf(two, sizeof(two), "%hX", segment);
-	flip = 0;
-	return two;
-      }
-  }
-}
-
-
-static int sh_kern_data_init ()
-{
-  unsigned long store0 = 0;
-  unsigned int  store1 = 0, store2 = 0;
-  int           datasize, i, j;
-  char        * databuf;
-
-  /* system_call code
-   */
-  databuf = sh_kern_db_syscall (0, _("system_call"), 
-				NULL, &store0, &store1, &store2,
-				&datasize, SH_KERN_DBPOP);
-  if (datasize == sizeof(system_call_code))
-    {
-      memcpy (system_call_code, databuf, sizeof(system_call_code));
-      SH_FREE(databuf);
-    }
-  else
-    {
-      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		      _("system_call_code not found in database"), 
-		      _("sh_kern_data_init"));
-      return -1;
-    }
-
-  /* syscall address and code
-   */ 
-  for (i = 0; i < SH_MAXCALLS; ++i) 
-    {
-      databuf = sh_kern_db_syscall (i, _("syscall"), 
-				    NULL, &store0, &store1, &store2,
-				    &datasize, SH_KERN_DBPOP);
-      sh_syscalls[i].addr = store0;
-      if (store0 == 0) {
-	sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, i, MSG_E_SUBGEN,
-			_("syscall address not found in database"), 
-			_("sh_kern_data_init"));
-	return -1;
-      }
-
-      sh_syscalls[i].code[0] = (unsigned int) store1; 
-      sh_syscalls[i].code[1] = (unsigned int) store2;
-      if ((store1 == 0) || (store2 == 0)) {
-	sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, i, MSG_E_SUBGEN,
-			_("syscall code not found in database"), 
-			_("sh_kern_data_init"));
-      }
-
-      if (databuf != NULL) {
-	SH_FREE(databuf);
-      }
-      
-    }
-
-  if (ShKernIDT == S_TRUE)
-    {
-      for (j = 0; j < SH_MAXIDT; ++j) 
-	{
-	  databuf = sh_kern_db_syscall (j, _("idt_table"), 
-					NULL, 
-					&store0, &store1, &store2,
-					&datasize, SH_KERN_DBPOP);
-	  if (datasize == 8) {
-	    memcpy(&idt_table[j*8], databuf, 8);
-	    SH_FREE(databuf);
-	  } else {
-	    sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, j, MSG_E_SUBGEN,
-			    _("idt table not found in database"), 
-			    _("sh_kern_data_init"));
-	    return -1;
-	  }
-	}
-    }
-
-  return 0;
-}
-
-
-/*
- * Defined in include/linux/fs.h
- */
-
-/* Here. we are only interested in 'lookup'. I.e. the struct
- * must be <= the real one, and 'lookup' must be at the 
- * correct position.
- */
-struct inode_operations {
-  int (*create) (int *,int *,int);
-  int * (*lookup) (int *,int *);
-  int (*link) (int *,int *,int *);
-  int (*unlink) (int *,int *);
-  int (*symlink) (int *,int *,const char *);
-  int (*mkdir) (int *,int *,int);
-  int (*rmdir) (int *,int *);
-  int (*mknod) (int *,int *,int,int);
-  int (*rename) (int *, int *,
-                 int *, int *);
-  /* flawfinder: ignore */
-  int (*readlink) (int *, char *,int);
-  int (*follow_link) (int *, int *);
-  void (*truncate) (int *);
-  int (*permission) (int *, int);
-  int (*revalidate) (int *);
-  /*
-    int (*setattr) (int *, int *);
-    int (*getattr) (int *, int *);
-    int (*setxattr) (int *, const char *, void *, size_t, int);
-    ssize_t (*getxattr) (int *, const char *, void *, size_t);
-    ssize_t (*listxattr) (int *, char *, size_t);
-    int (*removexattr) (int *, const char *);
-  */
-};
-
-/* 
- * this one is just for dummy purposes
- */
-struct file_operations {
-  int (*create) (int *,int *,int);
-};
-
-/* Defined in include/linux/proc_fs.h
- * Here we are interested in the 'proc_iops' member.
- */
-struct proc_dir_entry {
-  unsigned short low_ino;
-  unsigned short namelen;
-  const char * name;
-  mode_t mode;
-  nlink_t nlink;
-  uid_t uid;
-  gid_t gid;
-#if defined  TWO_SIX_SEVENTEEN_PLUS
-  /* size is loff_t in 2.6.17+ kernels */
-  unsigned long dummy; 
-#endif
-  unsigned long size;
-  struct inode_operations * proc_iops;
-  struct file_operations * proc_fops;
-  /*
-  get_info_t *get_info;
-  struct module *owner;
-  struct proc_dir_entry *next, *parent, *subdir;
-  void *data;
-  read_proc_t *read_proc;
-  write_proc_t *write_proc;
-  atomic_t count;         
-  int deleted;  
-  */          
-};
-
-
-static int sh_kern_kmem_read (int fd, unsigned long addr, 
-			      unsigned char * buf, int len)
-{
-  if (lseek(fd, addr, SEEK_SET) == (off_t) (-1))
-    {
-      return -1;
-    }
-  if (read(fd, buf, len) < 0)
-    {
-      return -1;
-    }
-  return 0;
-}
-
-static int sh_kern_read_data (int fd, unsigned long addr, 
-			      unsigned char * buf, size_t len)
-{
-  size_t    moff, roff;
-  size_t    sz;
-  char    * kmap;
-
-  /* next, try mmap()
-   */
-  sz = getpagesize(); /* unistd.h */
-
-  moff = ((size_t)(addr/sz)) * sz;                 /* lower page boundary */
-  roff = addr - moff;    /* off relative to lower address of mmapped area */
-
-  kmap = mmap(0, len+sz, PROT_READ, MAP_PRIVATE, fd, moff);/* sys/mman.h */
-
-  if (kmap == MAP_FAILED)
-    {
-      /* then, try read()
-       */
-      if (0 == sh_kern_kmem_read (fd, addr, buf, len))
-	return 0;
-
-      memset(buf, '\0', len);
-      return -1;
-    }
-
-  memcpy (buf, &kmap[roff], len);
-  return munmap(kmap, len+sz);
-}
-
-
-static int check_init (int * init_retval)
-{
-  static int is_init = 0;
-
-  SL_ENTER(_("check_init"));
-
-  if (is_init == 0)
-    {
-      if (sh.flag.checkSum != SH_CHECK_INIT && sh.flag.update != S_TRUE)
-	{
-	  if (0 == sh_kern_data_init()) {
-	    is_init = 1;
-	  } else {
-	    sh_error_handle (ShKernSeverity, FIL__, __LINE__, 1, 
-			     MSG_E_SUBGEN,
-			     _("could not initialize kernel check - switching off"),
-			     _("check_init") );
-	    ShKernActive = S_FALSE;
-	    *init_retval = is_init;
-	    SL_RETURN( (-1), _("check_init"));
-	  }
-	}
-      else if ((sh.flag.checkSum == SH_CHECK_INIT || 
-		sh.flag.checkSum == SH_CHECK_CHECK) && 
-	       (sh.flag.update == S_TRUE))
-	{
-	  if (0 == sh_kern_data_init()) {
-	    is_init = 1;
-	  } else {
-	    sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 0, 
-			     MSG_E_SUBGEN,
-			     _("no or incomplete data in baseline database for kernel check"),
-			     _("check_init") );
-	  }
-	}
-    }
-  *init_retval = is_init;
-  SL_RETURN( (0), _("check_init"));
-}
-
-#define SH_KERN_SIZ 512
-#define SH_KERN_SCC 256
-
-static void run_child(int kd, int mpipe[2])
-{
-  int j;
-
-  unsigned long kmem_call_table[SH_KERN_SIZ];
-  unsigned int  kmem_code_table[SH_KERN_SIZ][2];
-
-  unsigned char new_system_call_code[SH_KERN_SCC];
-
-  struct inode_operations proc_root_inode;
-  struct proc_dir_entry   proc_root_dir;
-
-  int status = sl_close_fd(FIL__, __LINE__, mpipe[0]);
-
-  setpgid(0, 0);
-	  
-  /* Seek to the system call table (at kaddr) and read it into
-   * the kmem_call_table array
-   */
-  if(status == 0)
-    {
-      retry_msleep (0, ShKernDelay); /* milliseconds */
-      
-      if (sh_kern_read_data (kd, kaddr, 
-			     (unsigned char *) &kmem_call_table, 
-			     sizeof(kmem_call_table)))
-	{
-	  status = -2;
-	}
-    }
-
-  /* 
-   * Seek to the system call address (at sh_syscalls[j].addr) and 
-   * read first 8 bytes into the array kmem_code_table[j][] (2 * unsigned int)
-   */
-  if(status == 0)
-    {
-      memset(kmem_code_table, 0, sizeof(kmem_code_table));
-      for (j = 0; j < SH_MAXCALLS; ++j) 
-	{
-	  if (sh_syscalls[j].addr == 0UL) {
-	    sh_syscalls[j].addr = kmem_call_table[j];
-	  }
-
-	  if (sh_syscalls[j].name == NULL || 
-	      sh_syscalls[j].addr == 0UL)
-	    break;
-
-	  if ((sh.flag.checkSum == SH_CHECK_INIT || 
-	       sh.flag.checkSum == SH_CHECK_CHECK) && 
-	      (sh.flag.update == S_TRUE))
-	    {
-	      if (sh_kern_read_data (kd, kmem_call_table[j], 
-				     (unsigned char *) &(kmem_code_table[j][0]),
-				     2 * sizeof(unsigned int)))
-		status = -3;
-	    }
-	  else
-	    {
-	      if (sh_kern_read_data (kd, sh_syscalls[j].addr, 
-				     (unsigned char *) &(kmem_code_table[j][0]),
-				     2 * sizeof(unsigned int)))
-		status = -4;
-	    }
-	}
-    }
-
-  if(status == 0)
-    {
-      /* 
-       * Get the address and size of Interrupt Descriptor Table,
-       * and read the content into the global array sh_idt_table[]
-       */
-      struct {
-	char pad[6];
-	unsigned short size;
-	unsigned long  addr;
-      } idt;
-
-      __asm__ volatile ("sidt %0": "=m" (idt.size));
-
-      idt.size = (idt.size + 1)/8;
-      
-      if (idt.size > SH_MAXIDT)
-	idt.size = SH_MAXIDT;
-      
-      memset(sh_idt_table, '\0', SH_MAXIDT*8);
-      if (sh_kern_read_data (kd, idt.addr, 
-			     (unsigned char *) sh_idt_table, idt.size*8))
-	status = -5;
-    }
-
-  /* 
-   * Seek to the system_call address (at system_call_addr) and 
-   * read first 256 bytes into new_system_call_code[]
-   *
-   * system_call_addr is defined in the include file.
-   */
-  if(status == 0)
-    {
-      if (sh_kern_read_data (kd, system_call_addr, 
-			     (unsigned char *) new_system_call_code, 
-			     SH_KERN_SCC))
-	status = -6;
-    }
-  
-  /* 
-   * Seek to proc_root and read the structure.
-   * Seek to proc_root_inode_operations and get the structure.
-   */
-  if(status == 0)
-    {
-      if (sh_kern_read_data (kd, proc_root, 
-			     (unsigned char *) &proc_root_dir, 
-			     sizeof(proc_root_dir)))
-	status = -7;
-    }
-/* 2.6.21 (((2) << 16) + ((6) << 8) + (21)) */
-#if SH_KERNEL_NUMBER < KERNEL_VERSION(2,6,21)
-  if(status == 0)
-    {
-      if (sh_kern_read_data (kd, proc_root_iops, 
-			     (unsigned char *) &proc_root_inode, 
-			     sizeof(proc_root_inode)))
-	status = -8;
-    }
-#else
-    memset(&proc_root_inode, '\0', sizeof(proc_root_inode));
-#endif
-  
-  /*
-   * Write out data to the pipe
-   */
-  status = write(mpipe[1], &status, sizeof(int));
-
-  if (status > 0)
-    status = write(mpipe[1], &kmem_call_table, sizeof(kmem_call_table));
-  
-  if(status > 0)
-    status = write(mpipe[1], &kmem_code_table, sizeof(kmem_code_table));
-  
-  if(status > 0)
-    status = write(mpipe[1], &sh_idt_table, sizeof(sh_idt_table));
-  
-  if(status > 0)
-    status = write(mpipe[1], new_system_call_code, SH_KERN_SCC);
-  
-  if(status > 0)
-    status = write(mpipe[1], &proc_root_dir, sizeof(proc_root_dir));
-  
-  if(status > 0)
-    status = write(mpipe[1], &proc_root_inode, sizeof(proc_root_inode));
-
-  _exit( (status >= 0) ? 0 : status);
-}
-
-struct sh_kernel_info {
-  unsigned long kmem_call_table[SH_KERN_SIZ];
-  unsigned int  kmem_code_table[SH_KERN_SIZ][2];
-
-  unsigned char new_system_call_code[SH_KERN_SCC];
-
-  struct inode_operations proc_root_inode;
-  struct proc_dir_entry   proc_root_dir;
-};
-
-static int read_from_child(pid_t mpid, int * mpipe, 
-			   struct sh_kernel_info * kinfo)
-{
-  int  res;
-  int  status;
-  long size;
-  int  errcode;
-
-#ifdef WCONTINUED
-      int wflags = WNOHANG|WUNTRACED|WCONTINUED;
-#else
-      int wflags = WNOHANG|WUNTRACED;
-#endif
-
-  /* Close reading side of pipe, and wait some milliseconds
-   */
-  sl_close_fd (FIL__, __LINE__, mpipe[1]);
-  retry_msleep (0, ShKernDelay); /* milliseconds */
-
-  if (sizeof(int) != read(mpipe[0], &errcode, sizeof(int)))
-    status = -3;
-  else
-    status = 0;
-
-  if (errcode)
-    status = errcode - 100;
-
-  if(status == 0)
-    {
-      size = SH_KERN_SIZ * sizeof(unsigned long);
-
-      if (size != read(mpipe[0], &(kinfo->kmem_call_table), size))
-	status = -4;
-      else
-	status = 0;
-    }
-
-  if(status == 0)
-    {
-      size = sizeof(unsigned int) * 2 * SH_KERN_SIZ;
-
-      if (size != read(mpipe[0], &(kinfo->kmem_code_table), size))
-	status = -5;
-      else
-	status = 0;
-    }
-
-  if(status == 0)
-    {
-      memset(sh_idt_table, '\0', SH_MAXIDT*8);
-      if (sizeof(sh_idt_table) != 
-	  read(mpipe[0], &sh_idt_table, sizeof(sh_idt_table)))
-	status = -5;
-      else
-	status = 0;
-    }
-
-  if(status == 0)
-    {
-      size = SH_KERN_SCC;
-
-      if (size != read(mpipe[0], &(kinfo->new_system_call_code), size))
-	status = -6;
-      else
-	status = 0;
-    }
-  
-  if(status == 0)
-    {
-      size = sizeof (struct proc_dir_entry);
-
-      if (size != read(mpipe[0], &(kinfo->proc_root_dir), size))
-	status = -7;
-      else
-	status = 0;
-    }
-
-  if(status == 0)
-    {
-      size = sizeof (struct inode_operations);
-
-      if (size != read(mpipe[0], &(kinfo->proc_root_inode), size))
-	status = -8;
-      else
-	status = 0;
-    }
-
-  if (status < 0)
-    res = waitpid(mpid, NULL,    wflags);
-  else 
-    {
-      res = waitpid(mpid, &status, wflags);
-      if (res == 0 && 0 != WIFEXITED(status))
-	status = WEXITSTATUS(status);
-    }
-  sl_close_fd (FIL__, __LINE__, mpipe[0]);
-  if (res <= 0)
-    {
-      aud_kill(FIL__, __LINE__, mpid, 9);
-      waitpid(mpid, NULL, 0);
-    }
-  return status;
-}
-
-
-static void check_idt_table(int is_init)
-{
-  int            i, j;
-
-  unsigned short idt_offset_lo, idt_offset_hi, idt_selector;
-  unsigned char  /* idt_reserved, */ idt_flag;
-  unsigned short sh_idt_offset_lo, sh_idt_offset_hi, sh_idt_selector;
-  unsigned char  /* sh_idt_reserved, */ sh_idt_flag;
-  int            dpl;
-  unsigned long  idt_iaddr;
-  int            sh_dpl;
-  unsigned long  sh_idt_iaddr;
-  char           idt_type, sh_idt_type;
-
-  unsigned long store0;
-  unsigned int  store1, store2;
-  int           datasize;
-  char          msg[2*SH_BUFSIZE];
-
-  if (ShKernIDT == S_TRUE)
-    {
-      if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
-	{
-	  datasize = 8;
-	  for (j = 0; j < SH_MAXIDT; ++j) 
-	    {
-	      sh_kern_db_syscall (j, _("idt_table"), 
-				  &sh_idt_table[j*8], 
-				  &store0, &store1, &store2,
-				  &datasize, SH_KERN_DBPUSH);
-	    }
-	}
-
-      if ((sh.flag.checkSum != SH_CHECK_INIT) || 
-	  (sh.flag.update == S_TRUE && is_init == 1))
-	{
-	  /* Check the Interrupt Descriptor Table
-	   *
-	   * Stored(old) is idt_table[]
-	   */
-	  for (j = 0; j < SH_MAXIDT; ++j)
-	    {
-	      i = j * 8;
-	  
-	      sh_idt_offset_lo = *((unsigned short *) &sh_idt_table[i]);
-	      sh_idt_selector  = *((unsigned short *) &sh_idt_table[i+2]);
-	      /* sh_idt_reserved  = (unsigned char) sh_idt_table[i+4]; */
-	      sh_idt_flag      = (unsigned char) sh_idt_table[i+5];
-	      sh_idt_offset_hi = *((unsigned short *) &sh_idt_table[i+6]);
-	      sh_idt_iaddr = (unsigned long)(sh_idt_offset_hi << 16) 
-		+ sh_idt_offset_lo;
-	      
-	      if (sh_idt_iaddr == 0)
-		{
-		  sh_idt_table[i+2] = '\0';
-		  sh_idt_table[i+3] = '\0';
-		  sh_idt_table[i+5] = '\0';
-
-		  idt_offset_lo = *((unsigned short *) &idt_table[i]);
-		  idt_offset_hi = *((unsigned short *) &idt_table[i+6]);
-		  idt_iaddr = (unsigned long)(idt_offset_hi << 16) 
-		    + idt_offset_lo;
-		  if (idt_iaddr == 0)
-		    {
-		      idt_table[i+2] = '\0';
-		      idt_table[i+3] = '\0';
-		      idt_table[i+5] = '\0';
-		    }
-		  
-		}
-	  
-	      if (memcmp(&sh_idt_table[i], &idt_table[i], 8) != 0)
-		{
-		  
-		  idt_offset_lo = *((unsigned short *) &idt_table[i]);
-		  idt_selector  = *((unsigned short *) &idt_table[i+2]);
-		  /* idt_reserved  = (unsigned char) idt_table[i+4]; */
-		  idt_flag      = (unsigned char) idt_table[i+5];
-		  idt_offset_hi = *((unsigned short *) &idt_table[i+6]);
-		  idt_iaddr = (unsigned long)(idt_offset_hi << 16) 
-		    + idt_offset_lo;
-	      
-		  if (idt_iaddr != 0)
-		    {
-		      if (idt_flag & 64) { dpl = 3; }
-		      else               { dpl = 0; }
-		      if (idt_flag & 1)  { 
-			if (dpl == 3) idt_type = 'S'; 
-			else idt_type = 'T'; }
-		      else               { idt_type = 'I'; }
-		    }
-		  else { dpl = -1; idt_type = 'U'; }
-		  
-		  if (sh_idt_iaddr != 0)
-		    {
-		      if (sh_idt_flag & 64) { sh_dpl = 3; }
-		      else               { sh_dpl = 0; }
-		      if (sh_idt_flag & 1)  { 
-			if (sh_dpl == 3) sh_idt_type = 'S'; 
-			else sh_idt_type = 'T'; }
-		      else               { sh_idt_type = 'I'; }
-		    }
-		  else { sh_dpl = -1; sh_idt_type = 'U'; }
-		  
-		  sh_kern_pathmsg (msg, SH_BUFSIZE,
-				   j, _("idt_table"),
-				   &idt_table[i], 8,
-				   &sh_idt_table[i], 8);
-
-		  sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
-				   0, MSG_KERN_IDT,
-				   j, 
-				   sh_idt_iaddr, sh_strseg(sh_idt_selector), 
-				   (int) sh_dpl, sh_idt_type, 
-				   idt_iaddr, sh_strseg(idt_selector),
-				   (int) dpl, idt_type, msg);
-		  
-		  memcpy(&idt_table[i], &sh_idt_table[i], 8);
-		}
-	    }
-	}
-    }
-}
-
-
-#define SYS_BUS_PCI _("/sys/bus/pci/devices")
-#include <dirent.h>
-
-static void check_rom (char * pcipath, char * name)
-{
-  file_type       theFile;
-  char            fileHash[2*(KEY_LEN + 1)];
-  int             status;
-  char          * tmp;
-  extern unsigned long sh_files_maskof (int class);
-
-  (void) sl_strlcpy (theFile.fullpath, pcipath, PATH_MAX);
-  theFile.check_mask  = sh_files_maskof(SH_LEVEL_READONLY);
-  theFile.check_mask &= ~(MODI_MTM|MODI_CTM|MODI_INO);
-  CLEAR_SH_FFLAG_REPORTED(theFile.file_reported);
-  theFile.attr_string = NULL;
-  theFile.link_path   = NULL;
-  
-  status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_RO], 
-			    name, &theFile, fileHash, 0);
-
-  if (status != 0)
-    {
-      tmp = sh_util_safe_name(pcipath);
-      sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
-		       0, MSG_E_SUBGPATH,
-		       _("Could not check PCI ROM"),
-		       _("check_rom"),
-		       tmp);
-      SH_FREE(tmp);
-      goto out;
-    }
-
-  if ( sh.flag.checkSum == SH_CHECK_INIT ) 
-    {
-      sh_hash_pushdata (&theFile, fileHash);
-    }
-  else if (sh.flag.checkSum == SH_CHECK_CHECK ) 
-    {
-      sh_hash_compdata (SH_LEVEL_READONLY, &theFile, fileHash, NULL, -1);
-    }
-
- out:
-  if (theFile.attr_string) SH_FREE(theFile.attr_string);
-  if (theFile.link_path)   SH_FREE(theFile.link_path);
-  return;
-}
-
-static void check_pci_rom (char * pcipath, char * name)
-{
-  struct stat buf;
-  int         fd;
-  int         status;
-
-  if (0 == stat(pcipath, &buf))
-    {
-      /* Need to write "1" to the file to enable the ROM. Afterwards,
-       * write "0" to disable it.
-       */
-      fd = open ( pcipath, O_RDWR );
-      if (fd)
-	{
-	  do {
-	    status = write( fd, "1", 1 );
-	  } while (status < 0 && errno == EINTR);
-	  sl_close_fd (FIL__, __LINE__,  fd );
-
-	  if (status > 0)
-	    {
-	      check_rom(pcipath, name);
-	      
-	      fd = open ( pcipath, O_RDWR );
-	      if (fd)
-		{
-		  do {
-		    status = write( fd, "0", 1 );
-		  } while (status < 0 && errno == EINTR);
-		  sl_close_fd (FIL__, __LINE__,  fd );
-		}
-	    }
-	}
-    }
-  return;
-}
-
-static void check_pci()
-{
-  char pci_dir[256];
-  char * pcipath;
-  DIR * df;
-  struct dirent * entry;
-
-  if (ShKernPCI != S_TRUE)
-    return;
-
-  sl_strlcpy(pci_dir, SYS_BUS_PCI, sizeof(pci_dir));
-
-  df = opendir(pci_dir);
-  if (df)
-    {
-      while (1)
-	{
-	  SH_MUTEX_LOCK(mutex_readdir);
-	  entry = readdir(df);
-	  SH_MUTEX_UNLOCK(mutex_readdir);
-
-	  if (entry == NULL)
-	    break;
-
-	  if (0 == strcmp(entry->d_name, ".") && 
-	      0 == strcmp(entry->d_name, ".."))
-	    continue;
-
-	  pcipath = sh_util_strconcat(pci_dir, "/", 
-				      entry->d_name, "/rom", NULL);
-	  check_pci_rom(pcipath, entry->d_name);
-	  SH_FREE(pcipath);
-	}
-
-      closedir(df);
-    }
-  return;
-}
-
-/* -- Check the proc_root inode.
- *
- * This will detect adore-ng.
- */
-static void check_proc_root (struct sh_kernel_info * kinfo)
-{
-  struct proc_dir_entry     proc_root_dir;
-  int                       proc_root_inode_op_flag = 0;
-
-/* 2.6.21 (((2) << 16) + ((6) << 8) + (21)) */
-#if SH_KERNEL_NUMBER < KERNEL_VERSION(2,6,21)
-  struct inode_operations proc_root_inode;
-#endif
-
-  if (ShKernPROC != S_TRUE)
-    return;
-
-/* 2.6.21 (((2) << 16) + ((6) << 8) + (21)) */
-#if SH_KERNEL_NUMBER < KERNEL_VERSION(2,6,21)
-  memcpy (&proc_root_inode, &(kinfo->proc_root_inode), sizeof(struct inode_operations));
-
-  /* Seems that the info does not relate anymore to proc_root_lookup(?)
-   */
-  if ( (unsigned int) *proc_root_inode.lookup != proc_root_lookup)
-    {
-      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_KERN_PROC,
-		       _("proc_root_inode_operations.lookup != proc_root_lookup"));
-    }
-#endif
-
-  memcpy (&proc_root_dir,   &(kinfo->proc_root_dir),   sizeof(struct proc_dir_entry));
-
-  if (((unsigned long) * &proc_root_dir.proc_iops) == proc_root_iops)
-    {
-      proc_root_inode_op_flag = 1;
-    }
-  else if (proc_root_dir.size == proc_root_iops)
-    {
-      proc_root_inode_op_flag = 1;
-    }
-  else if ((unsigned long) * &proc_root_dir.proc_fops == proc_root_iops)
-    {
-      proc_root_inode_op_flag = 1;
-    }
-
-  if (0 == proc_root_inode_op_flag)
-    {
-      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_KERN_PROC,
-		       _("proc_root.proc_iops != proc_root_inode_operations"));
-    }
-
-  return;
-}
-
-/* -- Check the system_call syscall gate.
- *
- * Stored(old) is system_call_code[]
- */
-static void check_syscall_gate(int is_init, struct sh_kernel_info * kinfo)
-{
-  int           i, j;
-  unsigned long store0;
-  unsigned int  store1, store2;
-  int           datasize;
-  int           max_system_call = (SYS_CALL_LOC < 128) ? 128 : SYS_CALL_LOC;
-  char          msg[2*SH_BUFSIZE];
-  
-  if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
-    {
-      store0 = 0; store1 = 0; store2 = 0;
-      datasize = SH_KERN_SCC;
-      sh_kern_db_syscall (0, _("system_call"), 
-			  &(kinfo->new_system_call_code), &store0, &store1, &store2,
-			  &datasize, SH_KERN_DBPUSH);
-    }
-
-  if ((sh.flag.checkSum != SH_CHECK_INIT) || 
-      (sh.flag.update == S_TRUE && is_init == 1))
-    {
-      for (i = 0; i < (max_system_call + 4); ++i) 
-	{
-	  if (system_call_code[i] != kinfo->new_system_call_code[i])
-	    {
-
-	      sh_kern_pathmsg (msg, sizeof(msg),
-			       0, _("system_call"),
-			       system_call_code, SH_KERN_SCC,
-			       kinfo->new_system_call_code, SH_KERN_SCC);
-
-	      sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
-			       0, MSG_KERN_GATE,
-			       kinfo->new_system_call_code[i], 0,
-			       system_call_code[i], 0,
-			       0, _("system_call (interrupt handler)"),
-			       msg);
-	      
-	      for (j = 0; j < (max_system_call + 4); ++j)
-		system_call_code[j] = kinfo->new_system_call_code[j];
-	      break;
-	    }
-	}
-    }
-  return;
-}
-
-static void check_system_calls (int is_init, struct sh_kernel_info * kinfo)
-{
-  int           i;
-
-#ifdef SH_USE_LKM
-  static int check_getdents      = 0;
-  /* #ifdef __NR_getdents64 */
-  static int check_getdents64    = 0;
-  /* #endif */
-  static int copy_if_next        = -1;
-  static int copy_if_next_64     = -1;
-#endif
-
-  unsigned long store0;
-  unsigned int  store1, store2;
-  int           mod_syscall_addr = 0;
-  int           mod_syscall_code = 0;
-  UINT64        size_old  = 0, size_new = 0;
-  UINT64        mtime_old = 0, mtime_new = 0;
-  UINT64        ctime_old = 0, ctime_new = 0;
-  char          tmp[128];
-  char          msg[2*SH_BUFSIZE];
-  char timstr_o[32];
-  char timstr_n[32];
-
-  if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
-    {
-      for (i = 0; i < SH_MAXCALLS; ++i) 
-	{
-	  store0 = kinfo->kmem_call_table[i]; 
-	  store1 = kinfo->kmem_code_table[i][0]; store2 = kinfo->kmem_code_table[i][1];
-	  sh_kern_db_syscall (i, _("syscall"), 
-			      NULL, &store0, &store1, &store2,
-			      0, SH_KERN_DBPUSH);
-	}
-    }
-
-  if ((sh.flag.checkSum != SH_CHECK_INIT) || 
-      (sh.flag.update == S_TRUE && is_init == 1))
-    {
-      for (i = 0; i < SH_MAXCALLS; ++i) 
-	{
-	  if (sh_syscalls[i].name == NULL /* || sh_syscalls[i].addr == 0UL */)
-	    break;
-
-#ifdef SH_USE_LKM
-	  if (sh_syscalls[i].addr != kinfo->kmem_call_table[i])
-	    {
-	      if (check_getdents == 0 && 
-		  0 == strcmp(_(sh_syscalls[i].name), _("sys_getdents")))
-		{
-		  check_getdents = 1;
-		  sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 
-				   0, MSG_E_SUBGEN,
-				   _("Modified kernel syscall (expected)."),
-				   _(sh_syscalls[i].name) );
-		  copy_if_next = i;
-		  sh_syscalls[i].addr = kinfo->kmem_call_table[i];
-		  continue;
-		}
-	      /* #ifdef __NR_getdents64 */
-	      else if  (check_getdents64 == 0 && 
-			0 == strcmp(_(sh_syscalls[i].name), 
-				    _("sys_getdents64")))
-		{
-		  check_getdents64 = 1;
-		  sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, 
-				   0, MSG_E_SUBGEN,
-				   _("Modified kernel syscall (expected)."),
-				   _(sh_syscalls[i].name) );
-		  copy_if_next_64 = i;
-		  sh_syscalls[i].addr = kinfo->kmem_call_table[i];
-		  continue;
-		}
-	      /* #endif */
-	      else
-		{
-		  size_old = sh_syscalls[i].addr;
-		  size_new = kinfo->kmem_call_table[i];
-		  mod_syscall_addr = 1;
-		}
-	      sh_syscalls[i].addr = kinfo->kmem_call_table[i];
-	    }
-#else
-	  if (sh_syscalls[i].addr != kinfo->kmem_call_table[i])
-	    {
-	      size_old = sh_syscalls[i].addr;
-	      size_new = kinfo->kmem_call_table[i];
-	      mod_syscall_addr = 1;
-	      sh_syscalls[i].addr = kinfo->kmem_call_table[i];
-	    }
-#endif
-
-
-	  /* -- Check the code at syscall address
-	   *
-	   * Stored(old) is sh_syscalls[]
-	   */
-	  if ( (mod_syscall_addr == 0) && 
-	       ((sh_syscalls[i].code[0] != kinfo->kmem_code_table[i][0]) || 
-		(sh_syscalls[i].code[1] != kinfo->kmem_code_table[i][1]))
-	       )
-	    {
-	      mtime_old = sh_syscalls[i].code[0];
-	      mtime_new = kinfo->kmem_code_table[i][0];
-	      ctime_old = sh_syscalls[i].code[1];
-	      ctime_new = kinfo->kmem_code_table[i][1];
-	      mod_syscall_code = 1;
-
-#ifdef SH_USE_LKM
-	      if (i == copy_if_next)
-		{
-		  mod_syscall_code =  0;
-		  copy_if_next     = -1;
-		}
-	      if (i == copy_if_next_64)
-		{
-		  mod_syscall_code =  0;
-		  copy_if_next_64  = -1;
-		}
-#endif
-
-	      sh_syscalls[i].code[0] = kinfo->kmem_code_table[i][0];
-	      sh_syscalls[i].code[1] = kinfo->kmem_code_table[i][1];
-	    }
-
-	  /* Build the error message, if something has been
-	   * detected.
-	   */
-	  if ((mod_syscall_addr != 0) || (mod_syscall_code != 0))
-	    {
-#ifdef SH_USE_XML
-	      sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ", 
-			  _("syscall"), i);
-#else
-	      sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ", 
-			  _("syscall"), i);
-#endif
-	      sl_strlcpy(msg, tmp, SH_BUFSIZE);
-
-	      if (mod_syscall_addr != 0)
-		{
-		  sl_snprintf(tmp, 128, sh_hash_size_format(),
-			      size_old, size_new);
-		  sl_strlcat(msg, tmp, SH_BUFSIZE); 
-		}
-	      if (mod_syscall_code != 0)
-		{
-		  (void) sh_unix_gmttime (ctime_old, timstr_o, sizeof(timstr_o));
-		  (void) sh_unix_gmttime (ctime_new, timstr_n, sizeof(timstr_n));
-#ifdef SH_USE_XML
-		  sl_snprintf(tmp, 128, 
-			      _("ctime_old=\"%s\" ctime_new=\"%s\" "), 
-			      timstr_o, timstr_n);
-#else
-		  sl_snprintf(tmp, 128, 
-			      _("ctime_old=<%s>, ctime_new=<%s>, "), 
-			      timstr_o, timstr_n);
-#endif
-		  sl_strlcat(msg, tmp, SH_BUFSIZE); 
-		  (void) sh_unix_gmttime (mtime_old, timstr_o, sizeof(timstr_o));
-		  (void) sh_unix_gmttime (mtime_new, timstr_n, sizeof(timstr_n));
-#ifdef SH_USE_XML
-		  sl_snprintf(tmp, 128, 
-			      _("mtime_old=\"%s\" mtime_new=\"%s\" "), 
-			      timstr_o, timstr_n);
-#else
-		  sl_snprintf(tmp, 128, 
-			      _("mtime_old=<%s>, mtime_new=<%s> "), 
-			      timstr_o, timstr_n);
-#endif
-		  sl_strlcat(msg, tmp, SH_BUFSIZE); 
-		}
-	      sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
-			       0, MSG_KERN_SYSCALL,
-			       i, _(sh_syscalls[i].name), msg);
-	      mod_syscall_addr = 0;
-	      mod_syscall_code = 0;
-	    }
-	}
-    }
-  return;
-}
- 
-int sh_kern_check_internal ()
-{
-  int kd;
-  int is_init;
-  pid_t mpid;
-  int mpipe[2];
-  int status = 0;
-
-  struct sh_kernel_info kinfo;
-
-
-  SL_ENTER(_("sh_kern_check_internal"));
-
-  /* -- Check whether initialisation is required; if yes, initialize.
-   */
-
-  if (0 != check_init(&is_init))
-    {
-      SL_RETURN( (-1), _("sh_kern_check_internal"));
-    }
-
-
-  /* -- Open /dev/kmem and fork subprocess to read from it.
-   */
-   
-  if (kaddr == (unsigned int) -1) /* kaddr = address of the sys_call_table */
-    {
-      sh_error_handle (ShKernSeverity, FIL__, __LINE__, status, MSG_E_SUBGEN,
-		       _("no address for sys_call_table - switching off"),
-		       _("kern_check_internal") );
-      ShKernActive = S_FALSE;
-      SL_RETURN( (-1), _("sh_kern_check_internal"));
-    }
-  
-  kd = aud_open(FIL__, __LINE__, SL_YESPRIV, _("/dev/kmem"), O_RDONLY, 0);
-  
-  if (kd < 0)
-    {
-      kd = aud_open(FIL__, __LINE__, SL_YESPRIV, _("/proc/kmem"), O_RDONLY, 0);
-    }
-
-  if (kd < 0)
-    {
-      status = errno;
-      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-		       _("error opening /dev/kmem"),
-		       _("kern_check_internal") );
-      SL_RETURN( (-1), _("sh_kern_check_internal"));
-    }
-
-  status = aud_pipe(FIL__, __LINE__, mpipe);
-
-  if (status == 0)
-    {
-      mpid = aud_fork(FIL__, __LINE__);
-
-      switch (mpid) 
-	{
-	case -1:
-	  status = -1;
-	  break;
-	case 0: 
-
-	  /* -- Child process reads /dev/kmem and writes to pipe
-	   */
-	  run_child(kd, mpipe);
-	  break;
-	  
-	  /* -- Parent process reads from child via pipe
-	   */
-	default:
-	  sl_close_fd(FIL__, __LINE__, kd);
-	  status = read_from_child(mpid, mpipe, &kinfo);
-	  break;
-	}
-    }
-
-  if ( status < 0)
-    {
-      char errmsg[SH_ERRBUF_SIZE];
-      sl_snprintf(errmsg, SH_ERRBUF_SIZE, 
-		  _("error reading from /dev/kmem: %d"), status);
-      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-		       errmsg,
-		       _("kern_check_internal") );
-      SL_RETURN( (-1), _("sh_kern_check_internal"));
-    }
-
-  /* -- Check the proc_root inode.
-   *
-   * This will detect adore-ng.
-   */
-  check_proc_root( &kinfo );
-
-
-  /* -- Check the system_call syscall gate.
-   *
-   * Stored(old) is system_call_code[]
-   */
-  check_syscall_gate( is_init, &kinfo );
-
-  /* -- Check the individual syscalls
-   *
-   * Stored(old) is sh_syscalls[] array.
-   */
-  check_system_calls ( is_init, &kinfo );
-
-  /* -- Check the Interrupt Descriptor Table
-   */
-  check_idt_table(is_init);
-
-  /* -- Check PCI ROM
-   */
-  check_pci();
-
-  SL_RETURN( (0), _("sh_kern_check_internal"));
-}
-/* ifdef HOST_IS_LINUX */
-#else
-
-/********************************************************
- *
- *  --- BSD ---
- *
- ********************************************************/
-
-#include <err.h>
-#include <kvm.h>
-#include <nlist.h>
-
-/* not OpenBSD */
-#if defined(HOST_IS_FREEBSD)
-#include <sys/sysent.h>
-#endif
-
-#include <sys/syscall.h>
-#ifndef  SYS_MAXSYSCALL
-#define  SYS_MAXSYSCALL	512
-#endif
-
-#ifdef __OpenBSD__
-struct proc;
-struct sysent {
-	short sy_narg;
-	short sy_argsize;
-	int   (*sy_call)(struct proc *, void *, register_t *);
-};
-#endif
-
-int sh_kern_data_init ()
-{
-  unsigned long store0 = 0;
-  unsigned int  store1 = 0, store2 = 0;
-  int           datasize, i;
-  char        * databuf = NULL;
-
-  /* syscall address and code
-   */ 
-  for (i = 0; i < SH_MAXCALLS; ++i) 
-    {
-      databuf = sh_kern_db_syscall (i, _("syscall"), 
-				    NULL, &store0, &store1, &store2,
-				    &datasize, SH_KERN_DBPOP);
-      sh_syscalls[i].addr = store0;
-      if (databuf != NULL) { SH_FREE(databuf); }
-      if (store0 == 0) {
-	sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-			_("syscall address not found in database"), 
-			_("sh_kern_data_init"));
-	return -1;
-      }
-
-      sh_syscalls[i].code[0] = (unsigned int) store1; 
-      sh_syscalls[i].code[1] = (unsigned int) store2;
-      if ((store1 == 0) || (store2 == 0)) {
-	sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-			_("syscall code not found in database"), 
-			_("sh_kern_data_init"));
-	return -1;
-      }
-
-    }
-
-  return 0;
-}
-
-int sh_kern_check_internal ()
-{
-  struct sysent  sy;
-  kvm_t * kd;
-  int     i;
-  int     status = -1;
-  char    errbuf[_POSIX2_LINE_MAX+1];
-  struct  nlist * sys_list;
-  struct  nlist list[2];
-
-  unsigned long offset = 0L;
-  unsigned int  syscall_code[2];  /* 8 bytes */
-  unsigned long syscall_addr;
-
-  unsigned long store0 = 0;
-  unsigned int  store1 = 0, store2 = 0;
-
-  UINT64        size_old  = 0, size_new = 0;
-  UINT64        mtime_old = 0, mtime_new = 0;
-  UINT64        ctime_old = 0, ctime_new = 0;
-  char          tmp[128];
-  char          msg[2*SH_BUFSIZE];
-  char timstr_o[32];
-  char timstr_n[32];
-
-  static int is_init = 0;
-
-  SL_ENTER(_("sh_kern_check_internal"));
-
-  if (is_init == 0)
-    { 
-      if (sh.flag.checkSum != SH_CHECK_INIT && sh.flag.update != S_TRUE)
-	{
-	  if (0 == sh_kern_data_init()) {
-	    is_init = 1;
-	  } else {
-	    sh_error_handle (ShKernSeverity, FIL__, __LINE__, status, 
-			     MSG_E_SUBGEN,
-			     _("could not initialize - switching off"),
-			     _("kern_check_internal") );
-	    ShKernActive = S_FALSE;
-	    SL_RETURN( (-1), _("sh_kern_check_internal"));
-	  }
-	}
-      else if ((sh.flag.checkSum == SH_CHECK_INIT ||
-		sh.flag.checkSum == SH_CHECK_CHECK) && 
-	       (sh.flag.update == S_TRUE))
-	{	
-	  if (0 == sh_kern_data_init()) {
-	    is_init = 1;
-	  } else {
-	    sh_error_handle (ShKernSeverity, FIL__, __LINE__, status, 
-			     MSG_E_SUBGEN,
-			     _("no or incomplete data in baseline database"),
-			     _("kern_check_internal") );
-	  }
-	}
-    }
-
-  /* defined, but not used
-   */
-  ShKernDelay    = 0;
-   
-  list[0].n_name = "_sysent";
-  list[1].n_name = NULL;
-
-  kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
-  if (!kd)
-    {
-      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-		       errbuf,
-		       _("kvm_openfiles") );
-      SL_RETURN( (-1), _("sh_kern_check_internal"));
-    }
-
-  i = kvm_nlist(kd, list);
-  if (i == -1)
-    {
-      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-		       kvm_geterr(kd),
-		       _("kvm_nlist (_sysent)") );
-      kvm_close(kd);
-      SL_RETURN( (-1), _("sh_kern_check_internal"));
-    }
-
-  sys_list = SH_ALLOC((SYS_MAXSYSCALL+1) * sizeof(struct nlist));
-
-  for (i = 0; i < SH_MAXCALLS; ++i)
-    sys_list[i].n_name = sh_syscalls[i].name;
-  sys_list[SH_MAXCALLS].n_name = NULL;
-
-  i = kvm_nlist(kd, sys_list);
-  if (i == -1)
-    {
-      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-		       kvm_geterr(kd),
-		       _("kvm_nlist (syscalls)") );
-      kvm_close(kd);
-      SH_FREE(sys_list);
-      SL_RETURN( (-1), _("sh_kern_check_internal"));
-    }
-  else if (i > 0)
-    {
-      sl_snprintf(tmp, 128,
-                  _("%d invalid syscalls"), i);
-      /*
-      for (i = 0; i < SH_MAXCALLS; ++i) {
-        if (sys_list[i].n_type == 0 && sys_list[i].n_value == 0)
-          fprintf(stderr, "invalid: [%3d] %s\n", i, sh_syscalls[i].name);
-      }
-      */
-      sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
-                       tmp,
-                       _("kvm_nlist (syscalls)") );
-    }
-
-  /* Check the individual syscalls
-   *
-   * Stored(old) is sh_syscalls[] array.
-   */
-  if (sh.flag.checkSum == SH_CHECK_INIT || sh.flag.update == S_TRUE)
-    {
-      for (i = 0; i < SH_MAXCALLS; ++i) 
-	{
-	  if (sh_syscalls[i].name == NULL)
-	    {
-	      sl_snprintf(tmp, 128, 
-			  _("too few entries in sh_syscalls[]: have %d, expect %d"), 
-			  i, SH_MAXCALLS);
-
-	      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-			       tmp,
-			       _("sh_kern_check_internal") );
-	      break;
-	    }
-
-	  /* read address of syscall from sysent table
-	   */
-	  offset = list[0].n_value + (i*sizeof(struct sysent));
-	  if (kvm_read(kd, offset, &sy, sizeof(struct sysent)) < 0)
-	    {
-	      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-			       kvm_geterr(kd),
-			       _("kvm_read (syscall table)") );
-	      kvm_close(kd);
-	      SH_FREE(sys_list);
-	      SL_RETURN( (-1), _("sh_kern_check_internal"));
-	    }
-	  syscall_addr = (unsigned long) sy.sy_call;
-	  store0 = syscall_addr;
-	  
-	  /* read the syscall code
-	   */
-	  if(kvm_read(kd, (unsigned int) sy.sy_call, &(syscall_code[0]), 
-		      2 * sizeof(unsigned int)) < 0)
-	    {
-	      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-			       kvm_geterr(kd),
-			       _("kvm_read (syscall code)") );
-	      kvm_close(kd);
-	      SH_FREE(sys_list);
-	      SL_RETURN( (-1), _("sh_kern_check_internal"));
-	    }
-	  store1 = syscall_code[0]; store2 = syscall_code[1];
-	  
-	  sh_kern_db_syscall (i, _("syscall"), 
-			      NULL, &store0, &store1, &store2,
-			      0, SH_KERN_DBPUSH);
-	}
-    }
-
-  if ((sh.flag.checkSum != SH_CHECK_INIT) || 
-      (sh.flag.update == S_TRUE && is_init == 1))
-    {
-      for (i = 0; i < SH_MAXCALLS; ++i)
-	{
-	  if (sh_syscalls[i].name == NULL)
-	    {
-	      sl_snprintf(tmp, 128, 
-			  _("too few entries in sh_syscalls[]: have %d, expect %d"), 
-			  i, SH_MAXCALLS);
-
-	      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-			       tmp,
-			       _("sh_kern_check_internal") );
-	      break;
-	    }
-	  
-	  /* read address of syscall from sysent table
-	   */
-	  offset = list[0].n_value + (i*sizeof(struct sysent));
-	  if (kvm_read(kd, offset, &sy, sizeof(struct sysent)) < 0)
-	    {
-	      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-			       kvm_geterr(kd),
-			       _("kvm_read (syscall table)") );
-	      kvm_close(kd);
-	      SH_FREE(sys_list);
-	      SL_RETURN( (-1), _("sh_kern_check_internal"));
-	    }
-	  syscall_addr = (unsigned long) sy.sy_call;
-	  
-	  if (sh_syscalls[i].addr != syscall_addr)
-	    {
-#ifdef SH_USE_XML
-	      sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ", 
-			  _("syscall"), i);
-#else
-	      sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ", 
-			  _("syscall"), i);
-#endif
-	      sl_strlcpy(msg, tmp, SH_BUFSIZE);
-
-	      size_old = sh_syscalls[i].addr; 
-	      size_new = syscall_addr;
-	      sl_snprintf(tmp, 128, sh_hash_size_format(),
-			  size_old, size_new);
-	      sl_strlcat(msg, tmp, SH_BUFSIZE);
- 
-	      sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
-			       status, MSG_KERN_SYSCALL,
-			       i, _(sh_syscalls[i].name),
-			       msg);
-	      sh_syscalls[i].addr = syscall_addr;
-	    }
-	  else
-	    {    
-	      /* read the syscall code
-	       */
-	      if(kvm_read(kd, (unsigned int) sy.sy_call, &(syscall_code[0]), 
-			  2 * sizeof(unsigned int)) < 0)
-		{
-		  sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-				   kvm_geterr(kd),
-				   _("kvm_read (syscall code)") );
-		  kvm_close(kd);
-		  SH_FREE(sys_list);
-		  SL_RETURN( (-1), _("sh_kern_check_internal"));
-		}
-	      
-	      if (sh_syscalls[i].code[0] != syscall_code[0] || 
-		  sh_syscalls[i].code[1] != syscall_code[1])
-		{
-		  mtime_old = sh_syscalls[i].code[0];
-		  mtime_new = syscall_code[0];
-		  ctime_old = sh_syscalls[i].code[1];
-		  ctime_new = syscall_code[1];
-
-#ifdef SH_USE_XML
-		  sl_snprintf(tmp, 128, "path=\"K_%s_%04d\" ", 
-			      _("syscall"), i);
-#else
-		  sl_snprintf(tmp, 128, "path=<K_%s_%04d>, ", 
-			      _("syscall"), i);
-#endif
-		  sl_strlcpy(msg, tmp, SH_BUFSIZE);
-
-		  (void) sh_unix_gmttime (ctime_old, timstr_o, sizeof(timstr_o));
-		  (void) sh_unix_gmttime (ctime_new, timstr_n, sizeof(timstr_n));
-#ifdef SH_USE_XML
-		  sl_snprintf(tmp, 128, 
-			      _("ctime_old=\"%s\" ctime_new=\"%s\" "), 
-			      timstr_o, timstr_n);
-#else
-		  sl_snprintf(tmp, 128, 
-			      _("ctime_old=<%s>, ctime_new=<%s>, "), 
-			      timstr_o, timstr_n);
-#endif
-		  sl_strlcat(msg, tmp, SH_BUFSIZE); 
-		  (void) sh_unix_gmttime (mtime_old, timstr_o, sizeof(timstr_o));
-		  (void) sh_unix_gmttime (mtime_new, timstr_n, sizeof(timstr_n));
-#ifdef SH_USE_XML
-		  sl_snprintf(tmp, 128, 
-			      _("mtime_old=\"%s\" mtime_new=\"%s\" "), 
-			      timstr_o, timstr_n);
-#else
-		  sl_snprintf(tmp, 128, 
-			      _("mtime_old=<%s>, mtime_new=<%s> "), 
-			      timstr_o, timstr_n);
-#endif
-		  sl_strlcat(msg, tmp, SH_BUFSIZE); 
-
-		  sh_error_handle (ShKernSeverity, FIL__, __LINE__, 
-				   status, MSG_KERN_SYSCALL,
-				   i, _(sh_syscalls[i].name),
-				   msg);
-		  sh_syscalls[i].code[0] = syscall_code[0];
-		  sh_syscalls[i].code[1] = syscall_code[1];
-		}
-	    }
-	}
-    }
-  SH_FREE(sys_list);
-  if(kvm_close(kd) < 0)
-    {
-      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
-                       kvm_geterr(kd),
-                       _("kvm_close") );
-      exit(EXIT_FAILURE);
-    }
-
-  SL_RETURN( (0), _("sh_kern_check_internal"));
-}
-
-#endif
-
-/*************
- *
- * module init
- *
- *************/
-#if defined(HOST_IS_LINUX)
-#include <sys/utsname.h>
-#endif
-
-static int AddressReconf = 0;
-
-int sh_kern_init (struct mod_type * arg)
-{
-#if defined(HOST_IS_LINUX)
-  struct utsname buf;
-  char         * str;
-#endif
-  (void) arg;
-
-  SL_ENTER(_("sh_kern_init"));
-  if (ShKernActive == S_FALSE)
-    SL_RETURN( (-1), _("sh_kern_init"));
-
-#if defined(HOST_IS_LINUX)
-  uname(&buf);
-
-  if ((AddressReconf < 5) && (0 != strcmp(SH_KERNEL_VERSION, buf.release)))
-    {
-      str = SH_ALLOC(256);
-      sl_snprintf(str, 256, 
-		  "Compiled for kernel %s, but current kernel is %s, and kernel addresses have not been re-configured",
-		  SH_KERNEL_VERSION, buf.release);
-      sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_SUBGEN,
-		       str,
-		       _("kern_check") );
-      SH_FREE(str);
-      ShKernActive = S_FALSE;
-      SL_RETURN( (-1), _("sh_kern_init"));
-    }
-#endif
-
-  lastcheck  = time (NULL);
-  if (sh.flag.checkSum != SH_CHECK_INIT)
-    {
-      sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		       _("Checking kernel syscalls"),
-		       _("kern_check") );
-    }
-  sh_kern_check_internal ();
-  SL_RETURN( (0), _("sh_kern_init"));
-}
-
-/*************
- *
- * module cleanup
- *
- *************/
-int sh_kern_end ()
-{
-  return (0);
-}
-
-
-/*************
- *
- * module timer
- *
- *************/
-int sh_kern_timer (time_t tcurrent)
-{
-  if (ShKernActive == S_FALSE)
-    return 0;
-
-  if ((int) (tcurrent - lastcheck) >= ShKernInterval)
-    {
-      lastcheck  = tcurrent;
-      return (-1);
-    }
-  return 0;
-}
-
-/*************
- *
- * module check
- *
- *************/
-int sh_kern_check ()
-{
-  sh_error_handle (SH_ERR_INFO, FIL__, __LINE__, EINVAL, MSG_E_SUBGEN,
-		   _("Checking kernel syscalls"),
-		   _("kern_check") );
-  return (sh_kern_check_internal ());
-}
-
-/*************
- *
- * module setup
- *
- *************/
-
-int sh_kern_set_severity  (const char * c)
-{
-  char tmp[32];
-  tmp[0] = '='; tmp[1] = '\0';
-  sl_strlcat (tmp, c, 32);
-  sh_error_set_level (tmp, &ShKernSeverity);
-  return 0;
-}
-
-int sh_kern_set_timer (const char * c)
-{
-  long val;
-
-  SL_ENTER(_("sh_kern_set_timer"));
-
-  val = strtol (c, (char **)NULL, 10);
-  if (val <= 0)
-    sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
-                      _("kern timer"), c);
-
-  val = (val <= 0 ? 60 : val);
-
-  ShKernInterval = (time_t) val;
-  SL_RETURN( 0, _("sh_kern_set_timer"));
-}
-
-int sh_kern_set_activate (const char * c)
-{
-  int i;
-  SL_ENTER(_("sh_kern_set_activate"));
-  i = sh_util_flagval(c, &ShKernActive);
-  SL_RETURN(i, _("sh_kern_set_activate"));
-}
-
-int sh_kern_set_idt (const char * c)
-{
-  int i;
-  SL_ENTER(_("sh_kern_set_idt"));
-  i = sh_util_flagval(c, &ShKernIDT);
-  SL_RETURN(i, _("sh_kern_set_idt"));
-}
-
-int sh_kern_set_pci (const char * c)
-{
-  int i;
-  SL_ENTER(_("sh_kern_set_pci"));
-  i = sh_util_flagval(c, &ShKernPCI);
-  SL_RETURN(i, _("sh_kern_set_pci"));
-}
-
-int sh_kern_set_proc (const char * c)
-{
-  int i;
-  SL_ENTER(_("sh_kern_set_proc"));
-  i = sh_util_flagval(c, &ShKernPROC);
-  SL_RETURN(i, _("sh_kern_set_proc"));
-}
-
-int sh_kern_set_sc_addr (const char * c)
-{
-  char * endptr;
-  unsigned long value;
-
-  SL_ENTER(_("sh_kern_set_sc_addr"));
-  errno = 0;
-  value = strtoul(c, &endptr, 16);
-  if ((ULONG_MAX == value) && (errno == ERANGE))
-    {
-      SL_RETURN((-1), _("sh_kern_set_sc_addr"));
-    }
-  if ((*c == '\0') || (*endptr != '\0'))
-    {
-      SL_RETURN((-1), _("sh_kern_set_sc_addr"));
-    }
-  system_call_addr = value;
-  ++AddressReconf;
-  SL_RETURN((0), _("sh_kern_set_sc_addr"));
-}
-
-int sh_kern_set_sct_addr (const char * c)
-{
-  char * endptr;
-  unsigned long value;
-
-  SL_ENTER(_("sh_kern_set_sct_addr"));
-  errno = 0;
-  value = strtoul(c, &endptr, 16);
-  if ((ULONG_MAX == value) && (errno == ERANGE))
-    {
-      SL_RETURN((-1), _("sh_kern_set_sct_addr"));
-    }
-  if ((*c == '\0') || (*endptr != '\0'))
-    {
-      SL_RETURN((-1), _("sh_kern_set_sct_addr"));
-    }
-  kaddr = (unsigned int) value;
-  ++AddressReconf;
-  SL_RETURN((0), _("sh_kern_set_sct_addr"));
-}
-
-int sh_kern_set_proc_root (const char * c)
-{
-  char * endptr;
-  unsigned long value;
-
-  SL_ENTER(_("sh_kern_set_proc_root"));
-  errno = 0;
-  value = strtoul(c, &endptr, 16);
-  if ((ULONG_MAX == value) && (errno == ERANGE))
-    {
-      SL_RETURN((-1), _("sh_kern_set_proc_root"));
-    }
-  if ((*c == '\0') || (*endptr != '\0'))
-    {
-      SL_RETURN((-1), _("sh_kern_set_proc_root"));
-    }
-  
-  proc_root = value;
-  ++AddressReconf;
-  SL_RETURN((0), _("sh_kern_set_proc_root"));
-}
-
-int sh_kern_set_proc_root_iops (const char * c)
-{
-  char * endptr;
-  unsigned long value;
-
-  SL_ENTER(_("sh_kern_set_proc_root_iops"));
-  errno = 0;
-  value = strtoul(c, &endptr, 16);
-  if ((ULONG_MAX == value) && (errno == ERANGE))
-    {
-      SL_RETURN((-1), _("sh_kern_set_proc_root_iops"));
-    }
-  if ((*c == '\0') || (*endptr != '\0'))
-    {
-      SL_RETURN((-1), _("sh_kern_set_proc_root_iops"));
-    }
-  
-  proc_root_iops = value;
-  ++AddressReconf;
-  SL_RETURN((0), _("sh_kern_set_proc_root_iops"));
-}
-
-int sh_kern_set_proc_root_lookup (const char * c)
-{
-  char * endptr;
-  unsigned long value;
-
-  SL_ENTER(_("sh_kern_set_proc_root_lookup"));
-  errno = 0;
-  value = strtoul(c, &endptr, 16);
-  if ((ULONG_MAX == value) && (errno == ERANGE))
-    {
-      SL_RETURN((-1), _("sh_kern_set_proc_root_lookup"));
-    }
-  if ((*c == '\0') || (*endptr != '\0'))
-    {
-      SL_RETURN((-1), _("sh_kern_set_proc_root_lookup"));
-    }
-  proc_root_lookup = value;
-  ++AddressReconf;
-  SL_RETURN((0), _("sh_kern_set_proc_root_lookup"));
-}
-
-#endif
-
-/* #ifdef SH_USE_KERN */
-#endif
Index: trunk/src/sh_log_check.c
===================================================================
--- trunk/src/sh_log_check.c	(revision 476)
+++ trunk/src/sh_log_check.c	(revision 481)
@@ -143,5 +143,5 @@
 		  size_t  plen = strlen(entry->d_name) + 1;
 
-		  if (SL_TRUE == sl_ok_adds(plen, dlen))
+		  if (S_TRUE == sl_ok_adds(plen, dlen))
 		    {
 		      plen += dlen;
@@ -180,5 +180,5 @@
       plen = strlen(dir);
 
-      if (SL_TRUE == sl_ok_adds(plen, 130))
+      if (S_TRUE == sl_ok_adds(plen, 130))
 	{
 	  plen += 130; /* 64 + 64 + 2 */
@@ -500,5 +500,5 @@
  * by longjmp' warning. And no, 'volatile' proved insufficient.
  */
-static void * sh_dummy_thisfile = NULL;
+void * sh_dummy_502_thisfile = NULL;
 
 void sh_check_watches()
@@ -512,5 +512,5 @@
    * Avoids the 'clobbered by longjmp' warning. 
    */
-  sh_dummy_thisfile = (void*) &thisfile;
+  sh_dummy_502_thisfile = (void*) &thisfile;
 
   while (thisfile)
Index: trunk/src/sh_log_correlate.c
===================================================================
--- trunk/src/sh_log_correlate.c	(revision 476)
+++ trunk/src/sh_log_correlate.c	(revision 481)
@@ -105,6 +105,6 @@
 int sh_keep_comp(const void * a, const void * b)
 {
-  return ( (int)(((struct sh_keep *)a)->last) - 
-	   (int)(((struct sh_keep *)b)->last) );
+  return ( (int)(((const struct sh_keep *)a)->last) - 
+	   (int)(((const struct sh_keep *)b)->last) );
 }
 
Index: trunk/src/sh_log_evalrule.c
===================================================================
--- trunk/src/sh_log_evalrule.c	(revision 476)
+++ trunk/src/sh_log_evalrule.c	(revision 481)
@@ -470,6 +470,6 @@
 }
 
-static struct sh_qeval ** dummy_queue;
-static char            ** dummy_dstr;
+struct sh_qeval ** sh_dummy_472_queue;
+char            ** sh_dummy_473_dstr;
 
 int sh_eval_radd (const char * str)
@@ -477,5 +477,5 @@
   struct sh_geval * nr;
   struct sh_geval * tmp;
-  struct sh_qeval * queue = NULL;
+  struct sh_qeval * queue;
   pcre *  rule;
   pcre_extra * rule_extra;
@@ -506,6 +506,8 @@
   splits = split_array(new, &nfields, ':', lengths);
 
-  dummy_queue = &queue;
-  dummy_dstr  = &dstr;
+  sh_dummy_472_queue = &queue;
+  sh_dummy_473_dstr  = &dstr;
+
+  queue = NULL;
 
   if (nfields < 2 || nfields > 3)
@@ -593,5 +595,5 @@
   pcre_fullinfo(rule, rule_extra, PCRE_INFO_CAPTURECOUNT, &captures);
 
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       char * emsg = SH_ALLOC(SH_ERRBUF_SIZE);
@@ -654,5 +656,5 @@
   if (group_open)
     {
-      if (flag_err_debug == SL_TRUE)
+      if (flag_err_debug == S_TRUE)
 	{
 	  char * emsg = SH_ALLOC(SH_ERRBUF_SIZE);
@@ -826,5 +828,5 @@
  * filled in
  */
-static struct sh_geval ** dummy1;
+struct sh_geval ** sh_dummy_828_rule;
 
 static struct sh_geval * test_rule (struct sh_geval * rule, sh_string *msg, time_t tstamp)
@@ -834,5 +836,5 @@
   volatile time_t timestamp = tstamp;
 
-  dummy1 = &rule;
+  sh_dummy_828_rule = &rule;
 
   if (!rule)
@@ -844,5 +846,5 @@
       do {
 
-	if (flag_err_debug == SL_TRUE)
+	if (flag_err_debug == S_TRUE)
 	  {
 	    char * emsg = SH_ALLOC(SH_ERRBUF_SIZE);
@@ -864,5 +866,5 @@
 	    rule->ovecnum = res;
 
-	    if (flag_err_debug == SL_TRUE)
+	    if (flag_err_debug == S_TRUE)
 	      {
 		char * emsg = SH_ALLOC(SH_ERRBUF_SIZE);
@@ -900,5 +902,5 @@
 	  }
 
-	if (flag_err_debug == SL_TRUE)
+	if (flag_err_debug == S_TRUE)
 	  {
 	    char * emsg = SH_ALLOC(SH_ERRBUF_SIZE);
@@ -919,5 +921,5 @@
     DEBUG("debug: no match found\n");
   /* If there was no match, this is NULL */
-  dummy1 = NULL;
+  sh_dummy_828_rule = NULL;
   return rule;
 }
@@ -926,6 +928,6 @@
  * against msg
  */
-static struct sh_geval ** dummy2;
-static struct sh_geval ** dummy3;
+struct sh_geval ** sh_dummy_928_result;
+struct sh_geval ** sh_dummy_929_group;
 
 static struct sh_geval * test_grules (struct sh_heval * host, 
@@ -936,6 +938,6 @@
   struct sh_geval * group  = host->rulegroups;
 
-  dummy2 = &result;
-  dummy3 = &group;
+  sh_dummy_928_result = &result;
+  sh_dummy_929_group  = &group;
 
   if (group && sh_string_len(msg) < (size_t)INT_MAX)
@@ -947,5 +949,5 @@
 	    /* this is a rule group */
 
-	    if (flag_err_debug == SL_TRUE)
+	    if (flag_err_debug == S_TRUE)
 	      {
 		char * emsg = SH_ALLOC(SH_ERRBUF_SIZE);
@@ -975,5 +977,5 @@
 	     */
 
-	    if (flag_err_debug == SL_TRUE)
+	    if (flag_err_debug == S_TRUE)
 	      {
 		char * emsg = SH_ALLOC(SH_ERRBUF_SIZE);
@@ -995,6 +997,6 @@
     }
 
-  dummy2 = NULL;
-  dummy3 = NULL;
+  sh_dummy_928_result = NULL;
+  sh_dummy_929_group  = NULL;
   return result;
 }
@@ -1113,5 +1115,5 @@
 static zAVLKey sh_eval_getkey(void const *item)
 {
-  return ((struct sh_ceval *)item)->hostname->str;
+  return ((const struct sh_ceval *)item)->hostname->str;
 }
 
Index: trunk/src/sh_log_mark.c
===================================================================
--- trunk/src/sh_log_mark.c	(revision 476)
+++ trunk/src/sh_log_mark.c	(revision 481)
@@ -68,5 +68,5 @@
 static zAVLKey sh_log_mark_getkey(void const *item)
 {
-  return ((struct sh_mark_event *)item)->label->str;
+  return ((const struct sh_mark_event *)item)->label->str;
 }
 
Index: trunk/src/sh_log_parse_apache.c
===================================================================
--- trunk/src/sh_log_parse_apache.c	(revision 476)
+++ trunk/src/sh_log_parse_apache.c	(revision 481)
@@ -63,7 +63,7 @@
  * by longjmp' warning. And no, 'volatile' proved insufficient.
  */
-static void * sh_dummy_new = NULL;
-static void * sh_dummy_fti = NULL;
-static void * sh_dummy_ftr = NULL;
+void * sh_dummy_65_new = NULL;
+void * sh_dummy_66_fti = NULL;
+void * sh_dummy_67_ftr = NULL;
 
 void * sh_eval_fileinfo_apache(char * str)
@@ -88,7 +88,7 @@
    * Avoids the 'clobbered by longjmp' warning. 
    */
-  sh_dummy_new = (void*) &new;
-  sh_dummy_fti = (void*) &f_time;
-  sh_dummy_ftr = (void*) &result;
+  sh_dummy_65_new = (void*) &new;
+  sh_dummy_66_fti = (void*) &f_time;
+  sh_dummy_67_ftr = (void*) &result;
 
   if (0 == strncmp("common", str, 6))
@@ -109,5 +109,5 @@
     }
 
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       SH_MUTEX_LOCK(mutex_thread_nolog);
@@ -251,5 +251,5 @@
   sh_string_add_from_char(re_string, "$");
 
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       SH_MUTEX_LOCK(mutex_thread_nolog);
@@ -304,5 +304,5 @@
   char         tstr[128];
   char         sstr[128];
-  char       * hstr;
+  const char * hstr;
   int          res;
   const char **hstr_addr = (const char **) &hstr;
@@ -310,5 +310,5 @@
   struct sh_fileinfo_apache * info = (struct sh_fileinfo_apache *) fileinfo;
 
-  if (sh_string_len(logline) > 0 && flag_err_debug == SL_TRUE)
+  if (sh_string_len(logline) > 0 && flag_err_debug == S_TRUE)
     {
       SH_MUTEX_LOCK(mutex_thread_nolog);
@@ -409,5 +409,5 @@
       record->pid       = PID_INVALID;
 
-      pcre_free(hstr); 
+      pcre_free_substring(hstr); 
       return record;
     }
Index: trunk/src/sh_log_parse_generic.c
===================================================================
--- trunk/src/sh_log_parse_generic.c	(revision 476)
+++ trunk/src/sh_log_parse_generic.c	(revision 481)
@@ -46,5 +46,6 @@
 static void default_time (struct sh_logrecord * record)
 {
-  struct tm ts;
+  struct tm   ts;
+  struct tm * ts_ptr;
   char   tmp[80];
   size_t len;
@@ -53,10 +54,17 @@
   
 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
-  localtime_r (&(record->timestamp), &ts);
+  ts_ptr = localtime_r (&(record->timestamp), &ts);
 #else
-  memcpy(&ts, localtime(&(record->timestamp)), sizeof(struct tm));
+  ts_ptr = localtime(&(record->timestamp));
+  if (ts_ptr)
+    memcpy(&ts, ts_ptr, sizeof(struct tm));
 #endif
-  len = strftime(tmp, sizeof(tmp), _("%Y-%m-%dT%H:%M:%S"), &ts);
-
+  if (ts_ptr)
+    len = strftime(tmp, sizeof(tmp), _("%Y-%m-%dT%H:%M:%S"), &ts);
+  else
+    {
+      sl_strlcpy(tmp, _("1970-01-01T00:00:00"), sizeof(tmp));
+      len = strlen(tmp);
+    } 
   record->timestr   = sh_string_new_from_lchar(tmp, len);
 
Index: trunk/src/sh_log_parse_pacct.c
===================================================================
--- trunk/src/sh_log_parse_pacct.c	(revision 476)
+++ trunk/src/sh_log_parse_pacct.c	(revision 481)
@@ -292,5 +292,5 @@
 }
 
-static void * sh_dummy_record = NULL;
+void * sh_dummy_294_record = NULL;
 
 struct sh_logrecord * sh_parse_pacct (sh_string * logline, void * fileinfo)
@@ -303,7 +303,7 @@
   (void) fileinfo;
 
-  sh_dummy_record = (void *) &record;
-
-  if (sh_string_len(logline) > 0 && flag_err_debug == SL_TRUE)
+  sh_dummy_294_record = (void *) &record;
+
+  if (sh_string_len(logline) > 0 && flag_err_debug == S_TRUE)
     {
       SH_MUTEX_LOCK(mutex_thread_nolog);
Index: trunk/src/sh_log_parse_syslog.c
===================================================================
--- trunk/src/sh_log_parse_syslog.c	(revision 476)
+++ trunk/src/sh_log_parse_syslog.c	(revision 481)
@@ -78,5 +78,5 @@
 
 
-  if (flag_err_debug == SL_TRUE && sh_string_len(logline) > 0)
+  if (flag_err_debug == S_TRUE && sh_string_len(logline) > 0)
     {
       SH_MUTEX_LOCK(mutex_thread_nolog);
Index: trunk/src/sh_mail.c
===================================================================
--- trunk/src/sh_mail.c	(revision 476)
+++ trunk/src/sh_mail.c	(revision 481)
@@ -69,5 +69,5 @@
 #undef  BAD
 
-static int failedMail = SL_FALSE;
+static int failedMail = S_FALSE;
 
 static dnsrep * return_mx (char *domain);
@@ -337,5 +337,5 @@
   SL_ENTER(_("sh_mail_pushstack"));
 
-  if (msg == NULL || failedMail == SL_TRUE /* || sh.srvmail.name[0] == '\0' */) 
+  if (msg == NULL || failedMail == S_TRUE /* || sh.srvmail.name[0] == '\0' */) 
     SL_RETURN((0), (_("sh_mail_pushstack")));
 
@@ -550,5 +550,5 @@
      * Return if we cannot mail.
      */
-    if (failedMail == SL_TRUE) 
+    if (failedMail == S_TRUE) 
       SL_RETURN((-1), _("sh_mail_msg"));
 
@@ -564,5 +564,5 @@
 	sh_mail_emptystack();
 	sh.mailNum.alarm_last = 0;
-	failedMail = SL_TRUE;
+	failedMail = S_TRUE;
 	SL_RETURN((-1), _("sh_mail_msg"));
       }
@@ -1259,14 +1259,21 @@
   my_time = time(NULL);
 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
-  my_tm   = localtime_r(&my_time, &time_tm);
+  my_tm = localtime_r(&my_time, &time_tm);
 #else
-  my_tm   = localtime(&my_time);
-#endif
-
+  my_tm = localtime(&my_time);
+#endif
+  
+  if (!my_tm) 
+    {
+      sl_strlcpy(my_tbuf, _("Thu, 01 Jan 1970 00:00:00 +00:00"), sizeof(my_tbuf));
+    }
+  else
+    {
 #if defined(HAVE_STRFTIME_Z)
-  (void)    strftime(my_tbuf, 127, _("%a, %d %b %Y %H:%M:%S %z"), my_tm);
+      (void) strftime(my_tbuf, 127, _("%a, %d %b %Y %H:%M:%S %z"), my_tm);
 #else
-  (void)    strftime(my_tbuf, 127, _("%a, %d %b %Y %H:%M:%S %Z"), my_tm);
-#endif
+      (void) strftime(my_tbuf, 127, _("%a, %d %b %Y %H:%M:%S %Z"), my_tm);
+#endif
+    }
 
   TPT(( 0, FIL__, __LINE__,  _("msg=<From: <%s>%c%cTo: <%s>%c%cDate: %s>%c%c"),
@@ -1339,5 +1346,5 @@
   char * tmp;
 
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       tmp = sh_util_safe_name_keepspace(reply);
@@ -1382,5 +1389,5 @@
   reply[0] = '\0';
 
-  while (sl_read_timeout_fd (ma_socket, &c, 1, time_wait, SL_FALSE) > 0) {
+  while (sl_read_timeout_fd (ma_socket, &c, 1, time_wait, S_FALSE) > 0) {
 
     if (ireply < (sizeof(reply) - 1))
Index: trunk/src/sh_mem.c
===================================================================
--- trunk/src/sh_mem.c	(revision 476)
+++ trunk/src/sh_mem.c	(revision 481)
@@ -112,5 +112,5 @@
 #endif
 
-static memlist_t ** sh_mem_merr_1;
+memlist_t ** sh_dummy_114_merrlist;
 
 void sh_mem_stat ()
@@ -121,5 +121,5 @@
   SL_ENTER(_("sh_mem_stat"));
 
-  sh_mem_merr_1 = (memlist_t **) &merrlist;
+  sh_dummy_114_merrlist = (memlist_t **) &merrlist;
 
   if (Alloc_Count == Free_Count) 
@@ -166,5 +166,5 @@
 }
 
-static memlist_t ** sh_mem_merr_2;
+memlist_t ** sh_dummy_168_merrlist;
 
 void sh_mem_check ()
@@ -177,5 +177,5 @@
   SL_ENTER(_("sh_mem_check"));
 
-  sh_mem_merr_2 = (memlist_t **) &merrlist;
+  sh_dummy_168_merrlist = (memlist_t **) &merrlist;
 
   sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MSTAMP,
Index: trunk/src/sh_modules.c
===================================================================
--- trunk/src/sh_modules.c	(revision 476)
+++ trunk/src/sh_modules.c	(revision 481)
@@ -12,5 +12,4 @@
 #include "sh_mounts.h"
 #include "sh_userfiles.h"
-#include "sh_kern.h"
 #include "sh_suidchk.h"
 #include "sh_processcheck.h"
@@ -68,21 +67,4 @@
     N_("[UserFiles]"),
     sh_userfiles_table,
-    PTHREAD_MUTEX_INITIALIZER,
-  },
-#endif
-
-#ifdef SH_USE_KERN
-  {
-    N_("KERNEL"),
-    -1,
-    0,
-    sh_kern_init,
-    sh_kern_timer,
-    sh_kern_check,
-    sh_kern_end,
-    sh_kern_null,
-
-    N_("[Kernel]"),
-    sh_kern_table,
     PTHREAD_MUTEX_INITIALIZER,
   },
Index: trunk/src/sh_nmail.c
===================================================================
--- trunk/src/sh_nmail.c	(revision 476)
+++ trunk/src/sh_nmail.c	(revision 481)
@@ -329,5 +329,5 @@
 				      const void * rcv_info)
 {
-  struct alias * rcv = (struct alias *) rcv_info;
+  const struct alias * rcv = (const struct alias *) rcv_info;
 
   if (!alias || 0 == strcmp(alias, sh_string_str(rcv->recipient)))
Index: trunk/src/sh_port2proc.c
===================================================================
--- trunk/src/sh_port2proc.c	(revision 476)
+++ trunk/src/sh_port2proc.c	(revision 481)
@@ -945,10 +945,4 @@
       continue;
 
-    /* fprintf(stderr, "FIXME: %d %d, %d %d, %d %d, %d, %d\n", s->proto, proto,
-       s->family, AF_INET,
-       sport, ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port),
-       (int) xf->xf_uid, (int)xf->xf_pid);
-    */
-
     if (s->proto != proto)
       continue;
@@ -970,7 +964,4 @@
       haddr6 = &((struct sockaddr_in6 *)(&s->laddr))->sin6_addr;
     
-
-    /* fprintf(stderr, "FIXME: %s\n", inet_ntoa(*haddr)); */
-    /* fprintf(stderr, "FIXME: %s\n", inet_ntoa(*saddr)); */
 
     if ( (s->family == AF_INET && 
Index: trunk/src/sh_portcheck.c
===================================================================
--- trunk/src/sh_portcheck.c	(revision 476)
+++ trunk/src/sh_portcheck.c	(revision 481)
@@ -529,10 +529,11 @@
  * by longjmp' warning. And no, 'volatile' proved insufficient.
  */
-static void * sh_dummy_pre = NULL;
-static void * sh_dummy_ptr = NULL;
+void * sh_dummy_531_pre = NULL;
+void * sh_dummy_532_ptr = NULL;
 
 /* check the list of open ports for any that are marked as UNKN
  */
-static void sh_portchk_check_list (struct sh_portentry ** head, int proto, int report)
+static void sh_portchk_check_list (struct sh_portentry ** head, 
+				   int proto, int report)
 {
   struct sh_portentry * ptr = *head;
@@ -543,6 +544,6 @@
    * Avoids the 'clobbered by longjmp' warning. 
    */
-  sh_dummy_pre = (void*) &pre;
-  sh_dummy_ptr = (void*) &ptr;
+  sh_dummy_531_pre = (void*) &pre;
+  sh_dummy_532_ptr = (void*) &ptr;
  
   while (ptr)
@@ -616,6 +617,6 @@
     }
 
-  sh_dummy_ptr = NULL;
-  sh_dummy_pre = NULL;
+  sh_dummy_532_ptr = NULL;
+  sh_dummy_531_pre = NULL;
 
   return;
@@ -1561,5 +1562,5 @@
 /* Subroutine to add an interface
  */
-static void * sh_dummy_str    = NULL; /* fix clobbered by.. warning */
+void * sh_dummy_1564_str    = NULL; /* fix clobbered by.. warning */
 
 static int sh_portchk_add_interface (const char * str)
@@ -1569,5 +1570,5 @@
   char buf[64];
 
-  sh_dummy_str    = (void*) &str;
+  sh_dummy_1564_str    = (void*) &str;
 
   if (iface_initialized == 0)
@@ -1610,5 +1611,5 @@
   } while (*str);
 
-  sh_dummy_str = NULL;
+  sh_dummy_1564_str = NULL;
   return 0;
 }
Index: trunk/src/sh_prelink.c
===================================================================
--- trunk/src/sh_prelink.c	(revision 476)
+++ trunk/src/sh_prelink.c	(revision 481)
@@ -87,5 +87,5 @@
     return S_FALSE;
 
-  status = sl_read_timeout (fd, magic, 4, alert_timeout, SL_FALSE);
+  status = sl_read_timeout (fd, magic, 4, alert_timeout, S_FALSE);
   (void) sl_rewind(fd);
   if (status == 4)
@@ -156,5 +156,5 @@
 /* returns static storage
  */
-int sh_prelink_run (char * path, char * file_hash, int alert_timeout)
+int sh_prelink_run (char * path, char * file_hash, int alert_timeout, unsigned long mask)
 {
   static int      init = S_FALSE;
@@ -262,4 +262,5 @@
     char hashbuf[KEYBUF_SIZE];
     UINT64 length_nolim = TIGER_NOLIM;
+    if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(mask);
     sl_strlcpy(file_hash,
 	       sh_tiger_generic_hash (path, task.pipeTI, &length_nolim, alert_timeout,
Index: trunk/src/sh_processcheck.c
===================================================================
--- trunk/src/sh_processcheck.c	(revision 476)
+++ trunk/src/sh_processcheck.c	(revision 481)
@@ -411,5 +411,5 @@
  * by longjmp' warning. And no, 'volatile' proved insufficient.
  */
-static void * sh_dummy_watchlist = NULL;
+void * sh_dummy_413_watchlist = NULL;
 
 static void check_watchlist (short * res)
@@ -422,5 +422,5 @@
    * Avoids the 'clobbered by longjmp' warning. 
    */
-  sh_dummy_watchlist = (void*) &list;
+  sh_dummy_413_watchlist = (void*) &list;
 
   while (list) 
@@ -468,5 +468,5 @@
     }
 
-  sh_dummy_watchlist = NULL;
+  sh_dummy_413_watchlist = NULL;
   return;
 }
@@ -625,5 +625,5 @@
   value = (size_t) strtoul(str, &foo, 0);
 
-  if (*foo == '\0' && SL_TRUE == sl_ok_adds(value, 1)) {
+  if (*foo == '\0' && S_TRUE == sl_ok_adds(value, 1)) {
     sh_prochk_maxpid = value + 1;
     userdef_maxpid   = 1;
@@ -934,5 +934,5 @@
 	    { 
 	      tstr[pos-1] = '\0';
-	      if (flag_err_debug == SL_TRUE)
+	      if (flag_err_debug == S_TRUE)
 		{
 		  SH_MUTEX_LOCK(mutex_thread_nolog);
Index: trunk/src/sh_readconf.c
===================================================================
--- trunk/src/sh_readconf.c	(revision 476)
+++ trunk/src/sh_readconf.c	(revision 481)
@@ -33,7 +33,8 @@
 #include "sh_unix.h"
 #include "sh_files.h"
-#include "sh_forward.h"
+#include "sh_xfer.h"
 #include "sh_gpg.h"
 #include "sh_hash.h"
+#include "sh_dbIO.h"
 #include "sh_ignore.h"
 #include "sh_database.h"
@@ -49,5 +50,5 @@
 #include "sh_utils.h"
 #include "sh_restrict.h"
-
+#include "sh_socket.h"
 
 extern int set_reverse_lookup (const char * c);
@@ -137,6 +138,7 @@
 {
 #ifdef SH_EVAL_SHELL
-  char * tmp = (char*)str;
+  char * tmp = sh_util_strdup(str);
   char * out;
+  char * tmp_orig = tmp;
 
   while (tmp && isspace((int)*tmp)) ++tmp;
@@ -150,7 +152,9 @@
 	  tmp[len-1] = '\0';
 	  out = sh_ext_popen_str(&tmp[2]);
+	  SH_FREE(tmp_orig);
 	  return out;
 	}
     }
+  SH_FREE(tmp_orig);
 #endif
   return sh_util_strdup(str);
@@ -384,5 +388,5 @@
       sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_D_START);
 
-      fd = sh_forward_req_file(_("CONF"));
+      fd = sh_xfer_request_file(_("CONF"));
 
       if (!SL_ISERROR(fd))
@@ -392,8 +396,10 @@
       else if (sh.flag.checkSum != SH_CHECK_INIT)
 	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FBAD);
 	  aud_exit (FIL__, __LINE__, EXIT_FAILURE);
 	}
       else
 	{
+	  sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_TCP_FBAD);
 	  sh_error_handle ((-1), FIL__, __LINE__, fd, MSG_D_FAIL);
 	  local_file = 1;
@@ -490,7 +496,8 @@
   /* Validate signature of open file.
    */
-  if (0 != sh_gpg_check_sign (fd, 0, 1))
+  if (0 != sh_gpg_check_sign (fd, SIG_CONF))
     {
       SH_FREE(line_in);
+      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
       aud_exit (FIL__, __LINE__, EXIT_FAILURE);
     }
@@ -830,4 +837,17 @@
 }
 
+
+#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
+static int sh_readconf_set_delay (const char * c)
+{
+  unsigned long i = atol (c);
+
+  if (i  > INT_MAX)
+    return -i;
+  sh.delayload = (int) i;
+  return 0;
+}
+#endif
+
 #ifdef FANCY_LIBCAP
 int sh_readconf_setCaps(const char * c)
@@ -965,14 +985,14 @@
     sh_files_pushfile_prelink },
 
-  { N_("ignoreadded"),   SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("ignoreadded"),          SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_ignore_add_new },
-  { N_("ignoremissing"), SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("ignoremissing"),        SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_ignore_add_del },
-  { N_("ignoremodified"), SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("ignoremodified"),       SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_ignore_add_mod },
 
-  { N_("skipchecksum"),  SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("skipchecksum"),         SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_restrict_define },
-  { N_("filetype"),      SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("filetype"),             SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_restrict_add_ftype },
 
@@ -983,51 +1003,57 @@
     sh_set_schedule_two },
 
-  { N_("usehardlinkcheck"),   SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("usehardlinkcheck"),     SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_files_check_hardlinks },
-  { N_("usersrccheck"),       SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("usersrccheck"),         SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_files_use_rsrc },
-  { N_("hardlinkoffset"),     SH_SECTION_MISC,   SH_SECTION_NONE,
+  { N_("hardlinkoffset"),       SH_SECTION_MISC,   SH_SECTION_NONE,
     sh_files_hle_reg },
 #if defined(USE_XATTR)
-  { N_("useselinuxcheck"),    SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("useselinuxcheck"),      SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_unix_setcheckselinux },
 #endif
 #if defined(USE_ACL)
-  { N_("useaclcheck"),        SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("useaclcheck"),          SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_unix_setcheckacl },
 #endif
-  { N_("loosedircheck"),      SH_SECTION_MISC,   SH_SECTION_NONE,
+  { N_("loosedircheck"),        SH_SECTION_MISC,   SH_SECTION_NONE,
     sh_hash_loosedircheck },
-  { N_("addokchars"),         SH_SECTION_MISC,   SH_SECTION_NONE,
+  { N_("addokchars"),           SH_SECTION_MISC,   SH_SECTION_NONE,
     sh_util_obscure_ok },
-  { N_("filenamesareutf8"),   SH_SECTION_MISC,   SH_SECTION_NONE,
+  { N_("filenamesareutf8"),     SH_SECTION_MISC,   SH_SECTION_NONE,
     sh_util_obscure_utf8 },
-  { N_("setrecursionlevel"),  SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("setrecursionlevel"),    SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_files_setrecursion },
-  { N_("checksumtest"),       SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("checksumtest"),         SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_util_setchecksum },
-  { N_("reportonlyonce"),     SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("reportonlyonce"),       SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_files_reportonce },
-  { N_("reportfulldetail"),   SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("reportfulldetail"),     SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_files_fulldetail },
-  { N_("uselocaltime"),       SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("uselocaltime"),         SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_unix_uselocaltime },
 
-  { N_("setnicelevel"),   SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("setnicelevel"),         SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_readconf_set_nice },
 
+  { N_("startuploaddelay"),     SH_SECTION_MISC,   SH_SECTION_NONE, 
+    sh_readconf_set_delay },
+
 #if defined(FANCY_LIBCAP)
-  { N_("usecaps"),        SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("usecaps"),              SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_readconf_setCaps },
 #endif
 
-  { N_("setdropcache"),   SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("reportcheckflags"),     SH_SECTION_MISC,   SH_SECTION_NONE, 
+    set_report_checkflags },
+
+  { N_("setdropcache"),         SH_SECTION_MISC,   SH_SECTION_NONE, 
     sl_set_drop_cache },
 
-  { N_("setiolimit"),   SH_SECTION_MISC,   SH_SECTION_NONE, 
+  { N_("setiolimit"),           SH_SECTION_MISC,   SH_SECTION_NONE, 
     sh_unix_set_io_limit },
 
   { N_("versionstring"),        SH_SECTION_MISC,   SH_SECTION_NONE,
-    sh_hash_version_string },
+    sh_dbIO_version_string },
 
   { N_("digestalgo"),           SH_SECTION_MISC,   SH_SECTION_NONE, 
@@ -1092,5 +1118,5 @@
     sh_socket_password },
   { N_("setstripdomain"),      SH_SECTION_SRV,  SH_SECTION_MISC, 
-    sh_forward_set_strip },
+    sh_xfer_set_strip },
   { N_("useseparatelogs"),     SH_SECTION_SRV,  SH_SECTION_MISC, 
     set_flag_sep_log },
@@ -1098,21 +1124,21 @@
     sh_unix_set_chroot },
   { N_("setclienttimelimit"),  SH_SECTION_SRV,  SH_SECTION_MISC, 
-    sh_forward_set_time_limit },
+    sh_xfer_set_time_limit },
   { N_("setconnectiontimeout"),SH_SECTION_SRV,  SH_SECTION_MISC, 
-    sh_forward_set_timeout },
+    sh_xfer_set_timeout },
   { N_("useclientseverity"),   SH_SECTION_SRV,  SH_SECTION_MISC, 
-  sh_forward_use_clt_sev },
+  sh_xfer_use_clt_sev },
   { N_("useclientclass"),      SH_SECTION_SRV,  SH_SECTION_MISC, 
-  sh_forward_use_clt_class },
+  sh_xfer_use_clt_class },
   { N_("severitylookup"),      SH_SECTION_SRV,  SH_SECTION_MISC, 
-  sh_forward_lookup_level },
+  sh_xfer_lookup_level },
   { N_("setclientfromaccept"), SH_SECTION_SRV,  SH_SECTION_MISC, 
     set_socket_peer },
   { N_("setserverport"),       SH_SECTION_SRV,  SH_SECTION_MISC, 
-    sh_forward_set_port },
+    sh_xfer_set_port },
   { N_("setserverinterface"),  SH_SECTION_SRV,  SH_SECTION_MISC, 
-    sh_forward_set_interface },
+    sh_xfer_set_interface },
   { N_("client"),              SH_SECTION_CLIENTS,           SH_SECTION_NONE, 
-    sh_forward_register_client },
+    sh_xfer_register_client },
 #endif
 
@@ -1124,10 +1150,14 @@
 #if defined(SH_WITH_SERVER)
   { N_("setlogserver"),        SH_SECTION_SRV,  SH_SECTION_MISC, 
-    sh_forward_setlogserver },
+    sh_xfer_set_logserver },
 #else
   { N_("setlogserver"),        SH_SECTION_CLT,  SH_SECTION_MISC, 
-    sh_forward_setlogserver },
+    sh_xfer_set_logserver },
   { N_("setthrottle"),         SH_SECTION_CLT,  SH_SECTION_MISC, 
-    sh_forward_set_throttle_delay},
+    sh_xfer_set_throttle_delay},
+  { N_("setdeltaretrycount"),   SH_SECTION_CLT,  SH_SECTION_MISC, 
+    set_delta_retry_count},
+  { N_("setdeltaretryinterval"),SH_SECTION_CLT,  SH_SECTION_MISC, 
+    set_delta_retry_interval},
 #endif
 #endif
@@ -1274,4 +1304,5 @@
   char * key;
   const char * value;
+  char * value_dup;
   char * tmp;
   int    i;
@@ -1394,12 +1425,15 @@
    * If !defined(SH_EVAL_SHELL), this will reduce to a strdup.
    */
-  value = sh_readconf_expand_value(value);
-
-  if (!value || (*value) == '\0')
-    {
-      TPT(( 0, FIL__, __LINE__, _("msg=<ConfigFile: empty after shell expansion: %s>\n"),
+  value_dup = sh_readconf_expand_value(value);
+
+  if (!value_dup || (*value_dup) == '\0')
+    {
+      TPT(( 0, FIL__, __LINE__, 
+	    _("msg=<ConfigFile: empty after shell expansion: %s>\n"),
 	    line));
       SL_RETURN(good_opt, _("sh_readconf_line"));
     }
+
+  value = value_dup;
 
 #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) 
@@ -1467,8 +1501,8 @@
     }
 
-  SH_FREE((char*)value);
+  SH_FREE(value_dup);
 
   SL_RETURN(good_opt, _("sh_readconf_line"));
 }
-  
+
     
Index: trunk/src/sh_registry.c
===================================================================
--- trunk/src/sh_registry.c	(revision 476)
+++ trunk/src/sh_registry.c	(revision 481)
@@ -889,5 +889,5 @@
       size_t  tlen    = sl_strlen(tmp);
 
-      if (SL_TRUE == sl_ok_adds(64, tlen))
+      if (S_TRUE == sl_ok_adds(64, tlen))
 	{
 	  char * errbuf;
@@ -905,5 +905,5 @@
 			       0, NULL );
 
-	  if (elen > 0 && SL_TRUE == sl_ok_adds(elen, tlen))
+	  if (elen > 0 && S_TRUE == sl_ok_adds(elen, tlen))
 	    {
 	      tlen += elen;
@@ -978,5 +978,5 @@
       size_t tlen = sl_strlen(tmp);
 
-      if (SL_TRUE == sl_ok_adds(64, tlen))
+      if (S_TRUE == sl_ok_adds(64, tlen))
 	{
 	  char * errbuf = SH_ALLOC(64 + tlen);
Index: trunk/src/sh_schedule.c
===================================================================
--- trunk/src/sh_schedule.c	(revision 476)
+++ trunk/src/sh_schedule.c	(revision 481)
@@ -55,4 +55,5 @@
 #include "samhain.h"
 #include "sh_mem.h"
+#include "sh_error_min.h"
 
 /* TESTONLY */
@@ -143,4 +144,12 @@
   tval = localtime(&now);
 #endif
+
+  if (!tval)
+    {
+      sh_error_handle ((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
+                       _("localime() failed"), _("test_sched_int") );
+      return 0;
+    }
+
   count = 0;
   for (i = 0; i < 5; ++i)
Index: trunk/src/sh_sem.c
===================================================================
--- trunk/src/sh_sem.c	(revision 481)
+++ trunk/src/sh_sem.c	(revision 481)
@@ -0,0 +1,310 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 1999, 2000, 2015 Rainer Wichmann                          */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+#include <stdlib.h>
+#include <stdio.h>
+
+#if defined(HAVE_SYS_SEM_H) && defined(HAVE_UNISTD_H)
+#include "samhain.h"
+#include "sh_sem.h"
+#include "sh_error_min.h"
+
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <unistd.h>
+
+#undef  FIL__
+#define FIL__  _("sh_sem.c")
+
+typedef enum {
+  exit_ok   = 0,
+  exit_fail = 1,
+  exit_time = 2,
+  exit_err  = 3
+} sh_estat;
+
+#if 0
+/* FreeBSD 6.1 defines this in <sys/sem.h> too...     */
+#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
+/* union semun is defined by including <sys/sem.h>    */
+#else
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+  int val;
+  struct semid_ds *buf;
+  unsigned short *array;
+};
+#endif
+#endif
+
+#define SH_SEMVMX 32767
+
+static int get_semaphore (void) 
+{
+  key_t  key = ftok(DEFAULT_DATAROOT, '#');
+  int    semid;
+
+  if (key < 0)
+    return -1;
+  semid = semget (key, 0, IPC_PRIVATE);
+  if (semid < 0)
+    return -1;
+  return semid;
+}
+
+static void sem_purge(int sem_id)
+{
+  if (sem_id != -1)
+    semctl(sem_id, 0, IPC_RMID, (int)0);
+  return;
+}
+
+static void sem_purge_stale()
+{
+  int stale_ID = get_semaphore();
+  if (stale_ID != -1)
+    sem_purge(stale_ID);
+  return;
+}
+
+static int report_err(int errnum, char * file, int line, char * func)
+{
+  char errbuf[SH_ERRBUF_SIZE];
+  sh_error_message(errnum, errbuf, sizeof(errbuf));
+  sh_error_handle((-1), file, line, errnum, MSG_E_SUBGEN,
+		  errbuf, func);
+  return -1;
+}
+
+static int init_semaphore (int nsems) 
+{
+  int    i;
+  mode_t mask;
+  int    semid;
+  int    errnum;
+  key_t  key = ftok(DEFAULT_DATAROOT, '#');
+
+  if (key < 0)
+    return report_err(errno, FIL__, __LINE__, _("ftok"));
+
+  mask   = umask(0);
+  semid  = semget (key, nsems, IPC_CREAT | IPC_EXCL | 0660);
+  errnum = errno;
+  umask(mask);
+
+  if (semid < 0)
+    return report_err(errnum, FIL__, __LINE__, _("semget"));
+  for (i=0; i<nsems; ++i)
+    if (semctl (semid, i, SETVAL, (int) 1) == -1)
+      return report_err(errnum, FIL__, __LINE__, _("semclt"));
+  return semid;
+}
+
+
+static int sem_set(int semid, int sem_no, int val)
+{
+  if (semid < 0)
+    return -1;
+  if (semctl (semid, sem_no, SETVAL, val) == -1)
+    return -1;
+  return 0;
+}
+
+static int sem_get(int semid, int sem_no)
+{
+  if (semid < 0)
+    return -1;
+  return semctl (semid, sem_no, GETVAL, (int) 0);
+}
+
+
+static int sem_change(int semid, int sem_no, int amount)
+{
+  struct sembuf tmp;
+  int retval;
+
+  tmp.sem_num = sem_no;
+  tmp.sem_flg = SEM_UNDO;
+  tmp.sem_op  = amount;
+
+  do { retval = semop(semid, &tmp, 1);
+  } while (retval == -1 && errno == EINTR);
+
+  return retval;
+}
+
+static int sem_try_change(int semid, int sem_no, int amount)
+{
+  struct sembuf tmp;
+  int retval;
+
+  tmp.sem_num = sem_no;
+  tmp.sem_flg = IPC_NOWAIT|SEM_UNDO;
+  tmp.sem_op  = amount;
+
+  do { retval = semop(semid, &tmp, 1);
+  } while (retval == -1 && errno == EINTR);
+
+  return retval;
+}
+
+#define SH_SEMAPHORE_EXTERN(S)  int S = get_semaphore()
+#define SH_SEMAPHORE_INIT(S, N) int S = init_semaphore(N)
+#define SH_SEMAPHORE_TRYLOCK(S) sem_try_change(S, 0, SH_SEM_LOCK)
+#define SH_SEMAPHORE_LOCK(S)    sem_change(S, 0, SH_SEM_LOCK)
+#define SH_SEMAPHORE_UNLOCK(S)  sem_change(S, 0, SH_SEM_UNLOCK)
+#define SH_SEMAPHORE_PURGE(S)   sem_purge(S)
+
+static int sem_ID = -1;
+
+void sh_sem_open()
+{
+  if (sh.flag.isdaemon != S_TRUE)
+    return;
+
+  if (sem_ID < 0)
+    {
+      sem_purge_stale();
+      sem_ID = init_semaphore(2);
+      sem_set(sem_ID, 1, (int) 0);
+    }
+
+  return;
+}
+
+void sh_sem_trylock()
+{
+  SH_SEMAPHORE_TRYLOCK(sem_ID);
+  return;
+}
+
+void sh_sem_lock()
+{
+  SH_SEMAPHORE_LOCK(sem_ID);
+  return;
+}
+
+void sh_sem_unlock (long val)
+{
+  if (val >= 0)
+    {
+      val = (val > SH_SEMVMX) ? SH_SEMVMX : val; /* signed short int maxval */
+      sem_set(sem_ID, 1, (int) val);
+    }
+  SH_SEMAPHORE_UNLOCK(sem_ID);
+  return;
+}
+
+void sh_sem_close()
+{
+  SH_SEMAPHORE_PURGE(sem_ID);
+  return;
+}
+
+static volatile int alarm_triggered = 0;
+static void alarm_handler(int sig)
+{
+  (void) sig;
+  alarm_triggered = 1;
+  return;
+}
+
+int  sh_sem_wait(const char * wait)
+{
+  int rc, flag = 0;
+  int time_wait = atoi(wait);
+
+  SH_SEMAPHORE_EXTERN(sem_id);
+
+  if (time_wait < 0) { time_wait *= (-1); time_wait -= 1; flag = 1; }
+  if (time_wait < 0 || time_wait > (24*3600))
+    {
+      fprintf(stderr, _("Invalid argument <%d>.\n"), time_wait);
+      _exit(exit_err);
+    }
+  if (sem_id == -1)
+    {
+      if (flag && errno == ENOENT) { 
+	do { retry_msleep(1, 0); rc = get_semaphore(); } while (rc == -1);
+	sem_id = rc;
+      } else {
+	if (errno == ENOENT) {
+	  fputs(_("Samhain IPC not initialized.\n"), stderr);
+	  _exit(exit_err); }
+	else if (errno == EACCES)
+	  fputs(_("No permission to access Samhain IPC.\n"), stderr);
+	_exit(exit_err);
+      }
+    }
+
+  retry_msleep(0, 50);
+
+  if (time_wait > 0)
+    {
+      signal(SIGALRM, alarm_handler);
+      alarm(time_wait);
+    }
+  rc = SH_SEMAPHORE_LOCK(sem_id);
+  if (rc == -1 && errno == EINTR)
+    {
+      if (alarm_triggered)
+        {
+	  fputs(_("Timeout on wait.\n"), stderr);
+	  _exit(exit_time);
+        }
+    }
+  else if (rc == -1)
+    {
+      if (errno == EACCES)
+	fputs(_("No permission to access Samhain IPC.\n"), stderr);
+      else
+	perror(_("semop"));
+      _exit(exit_err);
+    }
+
+  rc = sem_get(sem_id, 1);
+  if (rc == 0)    
+    _exit(exit_ok);
+  else if (rc == SH_SEMVMX)
+    fprintf(stdout, _("%d or more issues reported\n"), rc);
+  else
+    fprintf(stdout, _("%d issues reported\n"), rc);
+  _exit(exit_fail);
+}
+
+#else
+
+void sh_sem_open()    { return; }
+void sh_sem_trylock() { return; }
+void sh_sem_lock()    { return; }
+void sh_sem_unlock(long val)  { (void) val; return; }
+void sh_sem_close()   { return; }
+int  sh_sem_wait(const char * wait)
+{
+  (void) wait;
+  fputs(_("Function not implemented (OS does not support SysV semaphores).\n"),
+	stderr);
+  exit(exit_err);
+}
+
+#endif /* defined(HAVE_SYS_SEM_H) && defined(HAVE_UNISTD_H) */
Index: trunk/src/sh_socket.c
===================================================================
--- trunk/src/sh_socket.c	(revision 476)
+++ trunk/src/sh_socket.c	(revision 481)
@@ -33,4 +33,15 @@
 #include <string.h>
 
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
 #include "samhain.h"
 #include "sh_socket.h"
@@ -38,4 +49,7 @@
 #include "sh_unix.h"
 #include "sh_calls.h"
+#include "sh_guid.h"
+#include "sh_fifo.h"
+#include "sh_utils.h"
 
 #undef  FIL__
@@ -46,4 +60,145 @@
 #include <signal.h>
 
+typedef struct delta_tofetch {
+  char            uuid[SH_UUID_BUF];
+  time_t          last_time;
+  unsigned int    count;
+} SH_DELTA_DB;
+
+static SH_DELTA_DB * parse_entry(SH_DELTA_DB * db, const char * str)
+{
+  long last_time;
+  unsigned int count;
+  char buf[SH_UUID_BUF];
+  int res = sscanf(str, _("%u:%ld:%36s"), &count, &last_time, buf);
+  if (res == 3)
+    {
+      db->count = count;
+      db->last_time  = (time_t) last_time;
+      sl_strlcpy(db->uuid, buf, SH_UUID_BUF);
+      return db;
+    }
+  return NULL;
+}
+
+static char * unparse_entry(const SH_DELTA_DB * db, char * str, size_t len)
+{
+  int nbytes = sl_snprintf(str, len, _("%u:%ld:%s"), 
+			   db->count, (long) db->last_time, db->uuid);
+  if (nbytes < 0 || nbytes >= (int) len)
+    return NULL;
+  return str;
+}
+
+static SH_FIFO xfifo = SH_FIFO_INITIALIZER;
+
+int sh_socket_store_uuid(const char * cmd)
+{
+  char * p = sh_util_strdup(cmd);
+  char * q = strchr(cmd, ':');
+  char   entry[SH_BUFSIZE];
+  SH_DELTA_DB db;
+
+  if (!q) { SH_FREE(p); return -1; }
+
+  ++q;
+
+  if (0 != sh_uuid_check(q)) { SH_FREE(p); return -1; }
+
+  db.count = 0;
+  db.last_time = (time_t) 0;
+  sl_strlcpy(db.uuid, q, SH_UUID_BUF);
+  SH_FREE(p);
+
+  if (NULL != unparse_entry(&db, entry, sizeof(entry)))
+    {
+      sh_fifo_push(&xfifo, entry);
+      return 0;
+    }
+  return -1;
+}
+
+static unsigned int try_interval = 60;
+static unsigned int try_max = 2;
+
+int set_delta_retry_interval(const char * str)
+{
+  long val = strtol (str, (char **)NULL, 10);
+
+  if (val < 0 || val > INT_MAX)
+    return -1;
+  try_interval = (unsigned int) val;
+  return 0;
+}
+int set_delta_retry_count(const char * str)
+{
+  long val = strtol (str, (char **)NULL, 10);
+
+  if (val < 0 || val > INT_MAX)
+    return -1;
+  try_max = (unsigned int) val;
+  return 0;
+}
+
+char * sh_socket_get_uuid(int * errflag, unsigned int * count, time_t * last)
+{
+  char * entry = sh_fifo_pop(&xfifo);
+  char * uuid = NULL;
+
+  if (entry)
+    {
+      SH_DELTA_DB db;
+      time_t      now;
+      
+      if (NULL == parse_entry(&db, entry))
+	{
+	  SH_FREE(entry);
+	  sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
+			  _("Bad entry in fifo"), 
+			  _("sh_socket_get_uuid"));
+	  *errflag = -1;
+	  return NULL;
+	}
+
+      now = time(NULL);
+
+      if ( (db.count > 0) && ((unsigned long)(now - db.last_time) < try_interval) )
+	{
+	  sh_fifo_push_tail(&xfifo, entry);
+	  SH_FREE(entry);
+	  *errflag = -1;
+	  return NULL;
+	}
+
+      SH_FREE(entry);
+      uuid   = sh_util_strdup(db.uuid);
+      *count = db.count;
+      *last  = db.last_time;
+    }
+
+  *errflag = 0;
+  return uuid;
+}
+
+int sh_socket_return_uuid (const char * uuid, unsigned int count, time_t last)
+{
+  (void) last;
+
+  if (count < try_max)
+    {
+      char   entry[SH_BUFSIZE];
+      SH_DELTA_DB db;
+      time_t now = time(NULL);
+
+      db.count     = count + 1;
+      db.last_time = now;
+      sl_strlcpy(db.uuid, uuid, SH_UUID_BUF);
+
+      if (NULL != unparse_entry(&db, entry, sizeof(entry)))
+	return sh_fifo_push_tail(&xfifo, entry); /* >0 for success */
+    }
+  return -1;
+}
+
 void sh_socket_server_cmd(const char * srvcmd)
 {
@@ -54,6 +209,6 @@
       SL_RET0(_("sh_socket_server_cmd"));
     }
-  if ((srvcmd[0] == 'S') && (srvcmd[1] == 'T') && 
-      (srvcmd[2] == 'O') && (srvcmd[3] == 'P'))
+
+  if (0 == strncmp(srvcmd, _("STOP"), 4))
     {
       TPT((0, FIL__, __LINE__, _("msg=<stop command from server>\n")));
@@ -65,7 +220,6 @@
 #endif
     } 
-  else if ((srvcmd[0] == 'R') && (srvcmd[1] == 'E') &&
-	   (srvcmd[2] == 'L') && (srvcmd[3] == 'O') &&
-	   (srvcmd[4] == 'A') && (srvcmd[5] == 'D'))
+
+  else if (0 == strncmp(srvcmd, _("RELOAD"), 6))
     {
       TPT((0, FIL__, __LINE__, _("msg=<reload command from server>\n")));
@@ -77,9 +231,20 @@
 #endif
     }
-  else if ((srvcmd[0] == 'S') && (srvcmd[1] == 'C') &&
-	   (srvcmd[2] == 'A') && (srvcmd[3] == 'N'))
+
+  else if (0 == strncmp(srvcmd, _("DELTA:"), 6))
+    {
+      TPT((0, FIL__, __LINE__, _("msg=<delta load command from server>\n")));
+
+      if (sh_socket_store_uuid(srvcmd) == 0)
+	{
+	  ++sh_load_delta_flag;
+	  ++sig_raised;
+	}
+    }
+
+  else if (0 == strncmp(srvcmd, _("SCAN"), 4))
     {
       TPT((0, FIL__, __LINE__, _("msg=<scan command from server>\n")));
-      if (sh.flag.isdaemon == ON) 
+      if (sh.flag.isdaemon == S_TRUE) 
 	{ 
 #ifdef SIGTTOU
@@ -96,7 +261,10 @@
 	}
     }
+
+  /* Unknown command 
+   */
   else
     {
-      sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
+      sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
 		      srvcmd, 
 		      _("sh_socket_server_cmd"));
@@ -104,7 +272,5 @@
   SL_RET0(_("sh_socket_server_cmd"));
 }
-/* #if defined (SH_WITH_CLIENT)
- */
-#endif
+#endif  /* #if defined (SH_WITH_CLIENT) */
 
 #if defined(SH_WITH_SERVER)
@@ -225,15 +391,7 @@
   struct stat buf;
 
-#ifdef SH_DEBUG_SOCKET
-  fprintf(stderr, "PROBE\n");
-#endif
-
   for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
        item = (client_t *) zAVLNext(&avlcursor))
     {
-#ifdef SH_DEBUG_SOCKET
-      fprintf(stderr, "%s %d\n", item->hostname, (int)item->status_now);
-#endif
-
       if (item->status_now != CLT_INACTIVE)
 	{
@@ -242,7 +400,4 @@
 	  file = get_client_conf_file (item->hostname, &dummy);
 
-#ifdef SH_DEBUG_SOCKET
-	  fprintf(stderr, "%s\n", file);
-#endif
 	  if (0 == stat (file, &buf))
 	    {
@@ -250,16 +405,8 @@
 	      while (new)
 		{
-#ifdef SH_DEBUG_SOCKET
-		  fprintf(stderr, "%s <> %s\n", new->clt, item->hostname);
-#endif
 		  if (0 == sl_strcmp(new->clt, item->hostname))
 		    {
 		      flag = 1; /* Client is in list already */
 
-#ifdef SH_DEBUG_SOCKET
-		      fprintf(stderr, "%lu <> %lu\n", 
-			      (unsigned long) buf.st_mtime, 
-			      (unsigned long)new->cti);
-#endif
 		      if (buf.st_mtime > new->cti)
 			{
@@ -368,5 +515,4 @@
 
 #define NEED_PASSWORD_AUTH
-
 #endif
 
@@ -540,18 +686,5 @@
   SL_RETURN( (0), _("sh_socket_open_int"));
 }
-/* #if !defined(HAVE_CMSGCRED) || !defined(SO_PEERCRED) */
-/* #endif */
-
-/*
-#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
-static 
-int sh_socket_read (struct socket_cmd * srvcmd)
-{
-  srvcmd->cmd[0] = '\0';
-  srvcmd->clt[0] = '\0';
-  return 0;
-}
-#else
-*/
+
 
 /*
@@ -582,125 +715,14 @@
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  */
-static 
-int sh_socket_read (struct socket_cmd * srvcmd)
-{
-  struct socket_cmd * list_cmd;
-  char message[SH_MAXMSG];
-  struct sockaddr_un name;
-  ACCEPT_TYPE_ARG3 size = sizeof(name);
-
+
+static int receive_message(int talkfd, struct msghdr * msg, size_t message_size)
+{
+  unsigned int retry = 0;
   int nbytes;
-  int talkfd;
-  int retry = 0;
-
-  char * cmd = NULL;
-  char * clt = NULL;
-
-  int  client_uid = -1;
+  char * message = msg->msg_iov->iov_base;
   char errbuf[SH_ERRBUF_SIZE];
 
-
-  struct msghdr msg;
-  struct iovec iov;
-
-#if defined(NEED_PASSWORD_AUTH)
-  char * eopw = NULL;
-  char * goodpassword = NULL;
-#endif
-
-#if defined(HAVE_GETPEEREID)
-  uid_t peer_uid;
-  gid_t peer_gid;
-#elif defined(SO_PEERCRED) 
-  struct ucred cr;
-#ifdef HAVE_SOCKLEN_T
-  socklen_t cl = sizeof(cr);
-#else
-  int       cl = sizeof(cr);
-#endif 
-
-#elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
-
-#ifdef HAVE_STRUCT_CMSGCRED
-  typedef struct cmsgcred Cred;
-#define CRED_UID cmcred_uid 
-
-#elif HAVE_STRUCT_FCRED
-  typedef struct fcred Cred;
-#define CRED_UID fc_uid 
-
-#elif HAVE_STRUCT_SOCKCRED
-  typedef struct sockcred Cred;
-#define CRED_UID sc_uid 
-
-#endif
-  Cred       *cred;
-
-  /* Compute size without padding */
-  char   cmsgmem[ALIGN(sizeof(struct cmsghdr)) + ALIGN(sizeof(Cred))];   
-  /* for NetBSD */
-
-  /* Point to start of first structure */
-  struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem;
-#endif
-
-  if (pf_unix_fd  < 0)
-    {
-      return 0;
-    }
-
-  iov.iov_base = (char *) &message;
-  iov.iov_len  = sizeof(message);
-
-  memset (&msg, 0, sizeof (msg));
-  msg.msg_iov = &iov;
-  msg.msg_iovlen = 1;
-
-#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
-#if defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
-  msg.msg_control = (char *) cmsg;
-  msg.msg_controllen = sizeof (cmsgmem);
-  memset (cmsg, 0, sizeof (cmsgmem));
-#endif
-#endif
-
-  /* the socket is non-blocking 
-   * 'name' is the address of the sender socket
-   */
   do {
-    talkfd = accept(pf_unix_fd, (struct sockaddr *) &name, &size);
-  } while (talkfd < 0 && errno == EINTR);
-
-  if ((talkfd < 0) && (errno == EAGAIN))
-    {
-      return 0;
-    }
-  else if (talkfd < 0)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
-		      sh_error_message (errno, errbuf, sizeof(errbuf)), 
-		      _("sh_socket_read: accept"));
-      return -1;
-    }
-
-
-#if defined(LOCAL_CREDS) && !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
-  /* Set the socket to receive credentials on the next message 
-   */
-  {
-    int on = 1;
-    if (setsockopt (talkfd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0)
-      {
-	sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
-			sh_error_message (errno, errbuf, sizeof(errbuf)), 
-			_("sh_socket_read: setsockopt"));
-	sl_close_fd(FIL__, __LINE__, talkfd);
-	return -1;
-      }
-  }
-#endif
-
-  do {
-    nbytes = recvmsg (talkfd, &msg, 0);
+    nbytes = recvmsg (talkfd, msg, 0);
     if ((nbytes < 0) && (errno != EAGAIN))
       {
@@ -718,11 +740,7 @@
   } while ((nbytes < 0) && (retry < 3));
 
-#ifdef SH_DEBUG_SOCKET
-  fprintf(stderr, "%d bytes received\n", nbytes);
-#endif
-
   /* msg.msg_iov.iov_base, filled by recvmsg
    */
-  message[sizeof(message)-1] = '\0';
+  message[message_size-1] = '\0';
 
   if (nbytes < 0)
@@ -731,4 +749,7 @@
 	{
 	  /* no data */
+	  sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, errno, MSG_E_SUBGEN,
+			  sh_error_message (errno, errbuf, sizeof(errbuf)), 
+			  _("sh_socket_read: recvfrom"));
 	  sl_close_fd(FIL__, __LINE__, talkfd);
 	  return 0;
@@ -740,6 +761,15 @@
       return -1;
     }
+  return 0;
+}
 
 #if defined(HAVE_GETPEEREID)
+
+static int get_peer_uid(int talkfd)
+{
+  uid_t peer_uid;
+  gid_t peer_gid;
+  char errbuf[SH_ERRBUF_SIZE];
+
   if (0 != getpeereid(talkfd, &peer_uid, &peer_gid))
     {
@@ -750,7 +780,19 @@
       return -1;
     }
-  client_uid = peer_uid;
-  cmd = message;
-#elif defined(SO_PEERCRED)
+  return peer_uid;
+}
+
+#elif defined(SO_PEERCRED) 
+
+static int get_peer_uid(int talkfd)
+{
+  char errbuf[SH_ERRBUF_SIZE];
+  struct ucred cr;
+#ifdef HAVE_SOCKLEN_T
+  socklen_t cl = sizeof(cr);
+#else
+  int       cl = sizeof(cr);
+#endif 
+
   if (0 != getsockopt(talkfd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
     {
@@ -761,63 +803,16 @@
       return -1;
     }
-  client_uid = cr.uid;
-  cmd = message;
-#elif defined(HAVE_STRUCT_CMSGCRED) || defined(HAVE_STRUCT_FCRED) || (defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
-  if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
-		      _("Message from recvmsg() was not SCM_CREDS"), 
-		      _("sh_socket_read"));
-
-      /* Check for file descriptors sent using SCM_RIGHTS, and
-       * close them. If MSG_CTRUNC is set, the buffer was too small,
-       * and no fds are duped.
-       */
-      if (msg.msg_controllen >= sizeof(struct cmsghdr) &&
-	  (msg.msg_flags & MSG_CTRUNC) == 0)
-	{
-	  unsigned int     data_size;
-	  unsigned int     data_i;
-	  int              fdcount, fdmax;
-	  struct cmsghdr * cmptr;
-	  int              fdsbuf[1 + (sizeof(cmsgmem)/sizeof(int))];
-
-	  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
-	       cmptr = CMSG_NXTHDR(&msg, cmptr)) 
-	    {
-	      if (cmptr->cmsg_len > sizeof (cmsgmem) || 
-		  cmptr->cmsg_level != SOL_SOCKET ||
-		  cmptr->cmsg_type  != SCM_RIGHTS)
-		continue;
-
-	      /* Crappy way of finding the data length.
-	       * cmptr->cmsg_len includes both header and padding,
-	       * how are you supposed to find the data length?
-	       * cmptr->cmsg_len - ALIGN(sizeof(struct cmsghdr)) ?
-	       */
-	      data_size = 0;
-
-	      for (data_i = 0; data_i < cmptr->cmsg_len; ++data_i)
-		{
-		  if (CMSG_LEN(data_i) == cmptr->cmsg_len)
-		    {
-		      data_size = data_i;
-		      break;
-		    }
-		}
-	      memcpy(fdsbuf, CMSG_DATA(cmptr), data_size);
-	      fdmax = data_size / sizeof(int);
-	      for (fdcount = 0; fdcount < fdmax; ++fdcount)
-		(void) sl_close_fd(FIL__, __LINE__, fdsbuf[fdcount]);
-	    }
-	}
-      
-      sl_close_fd(FIL__, __LINE__, talkfd);
-      return -1;
-    }
-  cred = (Cred *) CMSG_DATA (cmsg);
-  client_uid = cred->CRED_UID;
-  cmd = message;
-#elif defined(NEED_PASSWORD_AUTH)
+  return cr.uid;
+}
+
+#endif
+
+#if defined(NEED_PASSWORD_AUTH)
+char * check_password(char * message, int * client_uid, int talkfd)
+{
+  char * cmd = NULL;
+  char * eopw = NULL;
+  char * goodpassword = NULL;
+
   goodpassword = sh_get_sockpass();
   eopw = strchr(message, '@');
@@ -830,5 +825,5 @@
       strlen(goodpassword) < (sizeof(message)/2))
     {
-      client_uid = sh_socket_flaguid;
+      *client_uid = sh_socket_flaguid;
       cmd = &message[strlen(goodpassword)+1];
       sh_set_sockpass();
@@ -841,6 +836,72 @@
       sh_set_sockpass();
       sl_close_fd(FIL__, __LINE__, talkfd);
+      return NULL;
+    }
+  return cmd;
+}
+#endif
+
+static int list_all (int talkfd, char * cmd);
+static int process_message(int talkfd, char * cmd, struct socket_cmd * srvcmd);
+
+static 
+int sh_socket_read (struct socket_cmd * srvcmd)
+{
+  char message[SH_MAXMSG];
+  struct sockaddr_un name;
+  ACCEPT_TYPE_ARG3 size = sizeof(name);
+  int talkfd;
+  char * cmd = NULL;
+  int  client_uid = -1;
+  char errbuf[SH_ERRBUF_SIZE];
+  struct msghdr msg;
+  struct iovec iov;
+  int status;
+
+  if (pf_unix_fd  < 0)
+    return 0;
+
+  iov.iov_base = (char *) &message;
+  iov.iov_len  = sizeof(message);
+
+  memset (&msg, 0, sizeof (msg));
+  msg.msg_iov = &iov;
+  msg.msg_iovlen = 1;
+
+  /* the socket is non-blocking 
+   * 'name' is the address of the sender socket
+   */
+  do {
+    talkfd = accept(pf_unix_fd, (struct sockaddr *) &name, &size);
+  } while (talkfd < 0 && errno == EINTR);
+
+  if ((talkfd < 0) && (errno == EAGAIN))
+    {
+      return 0;
+    }
+  else if (talkfd < 0)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
+		      sh_error_message (errno, errbuf, sizeof(errbuf)), 
+		      _("sh_socket_read: accept"));
       return -1;
     }
+
+  if (receive_message(talkfd, &msg, sizeof(message)) < 0)
+    return -1;
+
+  /* Authenticate request by peer uid or password.
+   */
+#if defined(HAVE_GETPEEREID)
+  client_uid = get_peer_uid(talkfd);
+  cmd = message;
+
+#elif defined(SO_PEERCRED)
+  client_uid = get_peer_uid(talkfd);
+  cmd = message;
+
+#elif defined(NEED_PASSWORD_AUTH)
+  cmd = check_password(message, &client_uid, talkfd);
+
 #else
   sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
@@ -851,9 +912,4 @@
 #endif
 
-#ifdef SH_DEBUG_SOCKET
-  fprintf(stderr, "Peer uid=%d, required=%d\n",
-	  client_uid, sh_socket_flaguid);
-#endif
-
   if (client_uid != sh_socket_flaguid)
     {
@@ -865,58 +921,109 @@
     }
 
-
-  /* Give a diagnostic message. 
-   */
-#ifdef SH_DEBUG_SOCKET
-  fprintf (stderr, "Server: got message: %s\n", cmd);
-#endif
-
-  clt = strchr(cmd, ':');
+  status = process_message(talkfd, cmd, srvcmd);
+
+  sl_close_fd(FIL__, __LINE__, talkfd);
+  return status;
+}
+
+static int check_valid_command(const char * str)
+{
+  unsigned int i = 0;
+  char * commands[] = { N_("DELTA"),  N_("RELOAD"),  N_("STOP"), N_("SCAN"),
+			N_("CANCEL"), N_("LISTALL"), N_("LIST"), N_("PROBE"), NULL };
+
+  while (commands[i])
+    {
+      if (0 == strcmp(_(commands[i]), str))
+	{
+	  return 0;
+	}
+      ++i;
+    }
+  return -1;
+}
+
+static int send_reply (int fd, char * msg)
+{
+  int nbytes = send (fd, msg, strlen(msg) + 1, 0);
+
+  if (nbytes < 0)
+    {
+      char errbuf[SH_ERRBUF_SIZE];
+      sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
+		      sh_error_message (errno, errbuf, sizeof(errbuf)), 
+		      _("send_reply"));
+      return -1;
+    }
+
+  return nbytes;
+}
+
+static int process_message(int talkfd, char * cmd, struct socket_cmd * srvcmd)
+{
+  int nbytes;
+  char error_type[SH_ERRBUF_SIZE] = { '\0' };
+  char * clt  = (cmd) ? strchr(cmd, ':') : NULL;
+
+  if (clt && 0 == strncmp(cmd, _("DELTA:"), 6))
+    {
+      /* DELTA:uuid:hostname 
+       */
+      char * uuid = clt;
+      
+      *uuid = '\0'; ++uuid;
+      clt = strchr(uuid, ':');
+      if (clt) { *clt = '\0'; ++clt; }
+      
+      if (sh_uuid_check(uuid) < 0)
+	{
+	  sl_strlcpy(error_type, _("!E:uuid-format:"), sizeof(error_type));
+	  sl_strlcat(error_type, uuid, sizeof(error_type));
+	  clt = NULL;
+	}
+      
+      --uuid; *uuid = ':';
+    }
+  else if (clt && *clt == ':')
+    { 
+      *clt = '\0'; ++clt; 
+      if (check_valid_command(cmd) < 0)
+	{
+	  sl_strlcpy(error_type, _("!E:cmd-invalid:"), sizeof(error_type));
+	  sl_strlcat(error_type, cmd, sizeof(error_type));
+	  clt = NULL;
+	}
+    }
+    
   if (clt != NULL) 
     {
-      *clt = '\0'; ++clt;
       if (sl_strlen(cmd) >= SH_MAXMSGLEN)
 	{
-#ifdef SH_DEBUG_SOCKET
-	  fprintf (stderr, "Server: command too long: %s\n", cmd);
-#endif
 	  sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
 			  _("Bad message format: command too long"), 
 			  _("sh_socket_read"));
-	  sl_close_fd(FIL__, __LINE__, talkfd);
+	  sl_strlcpy(error_type, _("!E:cmd-toolong"), sizeof(error_type));
+	  send_reply(talkfd, error_type);
 	  return -1;
 	}
       else if (sl_strlen(clt) >= SH_MAXMSGLEN)
 	{
-#ifdef SH_DEBUG_SOCKET
-	  fprintf (stderr, "Server: hostname too long: %s\n", clt);
-#endif
 	  sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
 			  _("Bad message format: hostname too long"), 
 			  _("sh_socket_read"));
-	  sl_close_fd(FIL__, __LINE__, talkfd);
+	  sl_strlcpy(error_type, _("!E:hostname-toolong"), sizeof(error_type));
+	  send_reply(talkfd, error_type);
 	  return -1;
 	}
-      if (cmd[0] == 'L' && cmd[1] == 'I' &&
-	  cmd[2] == 'S' && cmd[3] == 'T')
-	{
-#ifdef SH_DEBUG_SOCKET
-	  fprintf (stderr, "Server: list %s\n", clt);
-#endif
-	  goto list_all;
-	}
-      else if (cmd[0] == 'P' && cmd[1] == 'R' &&
-	  cmd[2] == 'O' && cmd[3] == 'B' && cmd[4] == 'E')
-	{
-#ifdef SH_DEBUG_SOCKET
-	  fprintf (stderr, "Server: probe start %s\n", clt);
-#endif
+
+      if (0 == strncmp(cmd, _("LIST"), 4))
+	return list_all(talkfd, cmd);
+      else if (0 == strncmp(cmd, _("PROBE"), 4))
+	{
 	  sh_socket_probe4reload();
-#ifdef SH_DEBUG_SOCKET
-	  fprintf (stderr, "Server: probe done  %s\n", clt);
-#endif
-	  cmd[0] = 'L'; cmd[1] = 'I'; cmd[2] = 'S'; cmd[3] = 'T';cmd[4] = '\0';
-	  goto list_all;
-	}
+	  sl_strlcpy(cmd, _("LIST"), 5);
+	  return list_all(talkfd, cmd);
+	}
+
       sl_strlcpy (srvcmd->cmd, cmd, SH_MAXMSGLEN);
       sl_strlcpy (srvcmd->clt, clt, SH_MAXMSGLEN);
@@ -925,60 +1032,35 @@
   else
     {
-#ifdef SH_DEBUG_SOCKET
-      fprintf (stderr, "Server: bad message\n");
-#endif
       sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
 		      _("Bad message format"), 
 		      _("sh_socket_read"));
-      sl_close_fd(FIL__, __LINE__, talkfd);
+      if (error_type[0] == '\0')
+	sl_strlcpy(error_type, _("!E:message-format"), sizeof(error_type));
+      send_reply(talkfd, error_type);
       return -1;
     }
 
   /* Bounce the message back to the sender. 
-   * 'name' is the receiver address; it has been been filled
-   *        with the sender address in the recvfrom call 
    */
-#ifdef SH_DEBUG_SOCKET
-  fprintf (stderr, "Server: send message: %s to %s\n", 
-	   cmd, name.sun_path);
-#endif
-  /*
-  nbytes = sendto (pf_unix_fd, message, nbytes, 0,
-                       (struct sockaddr *) & name, size);
-  */
-  nbytes = send (talkfd, cmd, strlen(cmd) + 1, 0);
-  sl_close_fd(FIL__, __LINE__, talkfd);
-  if (nbytes < 0)
-    {
-      sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
-		      sh_error_message (errno, errbuf, sizeof(errbuf)), 
-		      _("sh_socket_read: send"));
-      return -1;
-    }
-#ifdef SH_DEBUG_SOCKET
-  fprintf (stderr, "Server: message is out\n");
-#endif
+  nbytes = send_reply(talkfd, cmd);
+
   return nbytes;
-
- list_all:
-#ifdef SH_DEBUG_SOCKET
-  fprintf (stderr, "Server: list all\n");
-#endif
-  if (cmd[4] == 'A' && cmd[5] == 'L' && cmd[6] == 'L')
+}
+
+static int list_all (int talkfd, char * cmd)
+{
+  int nbytes;
+  struct socket_cmd * list_cmd;
+  char message[SH_MAXMSG];
+  char errbuf[SH_ERRBUF_SIZE];
+
+  if (0 == strncmp(cmd, _("LISTALL"), 7))
     {
       list_cmd = runlist;
       while (list_cmd)
 	{
-	  sl_snprintf(message, sizeof(message), _("SENT  %8s  %32s  %s"),
+	  sl_snprintf(message, sizeof(message), _("SENT  %42s  %32s  %s"),
 		      list_cmd->cmd, list_cmd->clt, list_cmd->cti);
-	  /*
-	  sl_strlcpy(message,     _("DONE"), SH_MAXMSG);
-	  sl_strlcat(message,          "  ", SH_MAXMSG);
-	  sl_strlcat(message, list_cmd->cmd, SH_MAXMSG);
-	  sl_strlcat(message,          "  ", SH_MAXMSG);
-	  sl_strlcat(message, list_cmd->clt, SH_MAXMSG);
-	  sl_strlcat(message,          "  ", SH_MAXMSG);
-	  sl_strlcat(message, list_cmd->cti, SH_MAXMSG);
-	  */
+
 	  nbytes = send (talkfd, message, sl_strlen(message) + 1, 0);
 	  if (nbytes < 0)
@@ -987,5 +1069,4 @@
 			      sh_error_message (errno, errbuf, sizeof(errbuf)), 
 			      _("sh_socket_read: sendto"));
-	      sl_close_fd(FIL__, __LINE__, talkfd);
 	      return -1;
 	    }
@@ -997,19 +1078,7 @@
   while (list_cmd)
     {
-      sl_snprintf(message, sizeof(message), _(">>>>  %8s  %32s  %s"),
+      sl_snprintf(message, sizeof(message), _(">>>>  %42s  %32s  %s"),
 		  list_cmd->cmd, list_cmd->clt, list_cmd->cti);
-      /*
-      sl_strlcpy(message,     _(">>>>"), SH_MAXMSG);
-      sl_strlcat(message,          "  ", SH_MAXMSG);
-      sl_strlcat(message, list_cmd->cmd, SH_MAXMSG);
-      sl_strlcat(message,          "  ", SH_MAXMSG);
-      sl_strlcat(message, list_cmd->clt, SH_MAXMSG);
-      sl_strlcat(message,          "  ", SH_MAXMSG);
-      sl_strlcat(message, list_cmd->cti, SH_MAXMSG);
-      */
-      /*
-      nbytes = sendto (pf_unix_fd, message, sl_strlen(message) + 1, 0,
-                       (struct sockaddr *) & name, size);
-      */
+
       nbytes = send (talkfd, message, sl_strlen(message) + 1, 0);
       if (nbytes < 0)
@@ -1018,5 +1087,4 @@
 			  sh_error_message (errno, errbuf, sizeof(errbuf)), 
 			  _("sh_socket_read: sendto"));
-	  sl_close_fd(FIL__, __LINE__, talkfd);
 	  return -1;
 	}
@@ -1024,46 +1092,20 @@
     }
 
-  /*
-  nbytes = sendto (pf_unix_fd, _("END"), 4, 0,
-		   (struct sockaddr *) & name, size);
-  */
-  /* nbytes = *//* never read */ send (talkfd, _("END"), 4, 0);
-  sl_close_fd(FIL__, __LINE__, talkfd);
+  send (talkfd, _("END"), 4, 0);
   return 0;
 }
-/* #if !defined(HAVE_CMSGCRED) || !defined(SO_PEERCRED) */
-/* #endif */
 
 static void sh_socket_add2list (struct socket_cmd * in)
 {
-  struct socket_cmd  * new;
-
-  new = SH_ALLOC(sizeof(struct socket_cmd));
-  sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
-  sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
-#ifdef SH_DEBUG_SOCKET
-  fprintf(stderr, "add2list: time set for %s\n", new->clt);
-#endif
-  (void) sh_unix_time(0, new->cti, sizeof(new->cti));
-  new->next = cmdlist;
-  cmdlist   = new;
-
-  return;
-}
-
-static void sh_socket_add2run (struct socket_cmd * in)
-{
-  struct socket_cmd  * new = runlist;
-  char * client_name       = in->clt;
+  struct socket_cmd  * new  = cmdlist;
+  struct socket_cmd  * last = cmdlist;
 
   while (new)
     {
-      if (0 == sl_strcmp(new->clt, client_name))
-	{
-	  sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
-	  sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
-#ifdef SH_DEBUG_SOCKET
-	  fprintf(stderr, "add2run: time reset for %s\n", new->clt);
-#endif
+      /* Only skip identical commands.
+       */
+      if (0 == sl_strcmp(new->clt,  in->clt) &&
+	  0 == sl_strcmp(new->cmd,  in->cmd))
+	{
 	  (void) sh_unix_time(0, new->cti, sizeof(new->cti));
 	  return;
@@ -1073,13 +1115,59 @@
 
   new = SH_ALLOC(sizeof(struct socket_cmd));
-  sl_strlcpy (new->cmd, in->cmd, sizeof(new->cmd));
-  sl_strlcpy (new->clt, in->clt, sizeof(new->clt));
+  sl_strlcpy (new->cmd,  in->cmd,  sizeof(new->cmd));
+  sl_strlcpy (new->clt,  in->clt,  sizeof(new->clt));
+  (void) sh_unix_time(0, new->cti, sizeof(new->cti));
+  new->next  = NULL;
+
+  if (last)
+    {
+      while (last->next) { last = last->next; }
+      last->next = new;
+    }
+  else
+    {
+      cmdlist = new;
+    }
+  return;
+}
+
+static void sh_socket_add2run (struct socket_cmd * in)
+{
+  struct socket_cmd  * new  = runlist;
+  struct socket_cmd  * last = runlist;
+
+  while (new)
+    {
+      /* Only skip identical commands. First 5 will
+       * make all 'DELTA' identical.
+       */
+      if (0 == sl_strcmp(new->clt,  in->clt) &&
+	  0 == sl_strncmp(new->cmd,  in->cmd, 5))
+	{
+	  sl_strlcpy (new->cmd,  in->cmd,  sizeof(new->cmd));
+	  (void) sh_unix_time(0, new->cti, sizeof(new->cti));
+	  return;
+	}
+      new = new->next;
+    }
+
+  new = SH_ALLOC(sizeof(struct socket_cmd));
+  sl_strlcpy (new->cmd,  in->cmd,  sizeof(new->cmd));
+  sl_strlcpy (new->clt,  in->clt,  sizeof(new->clt));
 #ifdef SH_DEBUG_SOCKET
   fprintf(stderr, "add2run: time set for %s\n", new->clt);
 #endif
   (void) sh_unix_time(0, new->cti, sizeof(new->cti));
-  new->next = runlist;
-  runlist   = new;
-
+  new->next  = NULL;
+
+  if (last)
+    {
+      while (last->next) { last = last->next; }
+      last->next = new;
+    }
+  else
+    {
+      runlist = new;
+    }
   return;
 }
@@ -1087,5 +1175,5 @@
 
 
-static void sh_socket_rm2list (const char * client_name)
+static void sh_socket_rm2list (const char * client_name, int remove_all)
 {
   struct socket_cmd * old = cmdlist;
@@ -1098,4 +1186,5 @@
 	  if ((new == cmdlist) && (new->next == NULL))
 	    {
+	      /* There is only one entry */
 	      cmdlist = NULL;
 	      SH_FREE(new);
@@ -1104,7 +1193,12 @@
 	  else if (new == cmdlist)
 	    {
+	      /* first entry: new = old = cmdlist */
 	      cmdlist = new->next;
 	      SH_FREE(new);
-	      return;
+	      if (remove_all == S_FALSE)
+		return;
+	      old = cmdlist;
+	      new = cmdlist;
+	      continue;
 	    }
 	  else
@@ -1112,5 +1206,7 @@
 	      old->next = new->next;
 	      SH_FREE(new);
-	      return;
+	      if (remove_all == S_FALSE)
+		return;
+	      new = old;
 	    }
 	}
@@ -1131,7 +1227,5 @@
 
   if (pf_unix_fd  < 0)
-    {
-      return 0;
-    }
+    return 0;
 
   sl_strlcpy(cancel_cmd, _("CANCEL"), sizeof(cancel_cmd)); 
@@ -1140,12 +1234,7 @@
     {
       if (0 == sl_strcmp(cmd.cmd, cancel_cmd))
-	{
-	  sh_socket_rm2list  (cmd.clt);
-	}
+	sh_socket_rm2list  (cmd.clt, S_TRUE);
       else
-	{
-	  sh_socket_rm2list  (cmd.clt);
-	  sh_socket_add2list (&cmd);
-	}
+	sh_socket_add2list (&cmd);
     }
   return 0;
@@ -1164,7 +1253,7 @@
       if (0 == sl_strcmp(new->clt, client_name))
 	{
-	  sl_strlcpy(out, new->cmd, sizeof(out));
+	  sl_strlcpy(out,  new->cmd,  sizeof(out));
 	  sh_socket_add2run (new);
-	  sh_socket_rm2list  (client_name);
+	  sh_socket_rm2list (client_name, S_FALSE);
 	  return out;
 	}
@@ -1173,7 +1262,140 @@
   return NULL;
 }
-
 /* #if defined (SH_WITH_SERVER)
  */
 #endif
 
+
+#ifdef SH_CUTEST
+#include "CuTest.h"
+
+void Test_cmdlist (CuTest *tc) {
+
+#if defined (SH_WITH_SERVER)
+  struct socket_cmd cmd;
+  char * p;
+
+  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
+
+  sh_socket_add2list (&cmd);
+  p = sh_socket_check("one");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "RELOAD", p);
+
+  p = sh_socket_check("one");
+  CuAssertPtrEquals(tc, NULL, p);
+
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.cmd, "STOP",   sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+
+  sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "STOP", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+
+  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "DELTA",   sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+
+  p = sh_socket_check("one");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "RELOAD", p);
+
+  sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+
+  p = sh_socket_check("one");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "STOP", p);
+  p = sh_socket_check("one");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "DELTA", p);
+  p = sh_socket_check("one");
+  CuAssertPtrEquals(tc, NULL, p);
+
+  /* Test removal in correct order */
+  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.cmd, "STOP",   sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.cmd, "DELTA",  sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.cmd, "FOOBAR", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  
+  sh_socket_rm2list ("one", S_FALSE);
+
+  p = sh_socket_check("one");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "STOP", p);
+
+  sh_socket_rm2list ("one", S_FALSE);
+  
+  p = sh_socket_check("one");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "FOOBAR", p);
+
+  p = sh_socket_check("one");
+  CuAssertPtrEquals(tc, NULL, p);
+
+  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.cmd, "STOP",   sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+
+  sl_strlcpy(cmd.clt, "two", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.clt, "three", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "RELOAD", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+
+  sl_strlcpy(cmd.clt, "one", sizeof(cmd.clt));
+  sl_strlcpy(cmd.cmd, "DELTA",  sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+  sl_strlcpy(cmd.cmd, "FOOBAR", sizeof(cmd.cmd));
+  sh_socket_add2list (&cmd);
+
+  sh_socket_rm2list ("one", S_TRUE);
+  p = sh_socket_check("one");
+  CuAssertPtrEquals(tc, NULL, p);
+
+  p = sh_socket_check("two");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "STOP", p);
+  p = sh_socket_check("two");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "RELOAD", p);
+  p = sh_socket_check("two");
+  CuAssertPtrEquals(tc, NULL, p);
+
+  p = sh_socket_check("three");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "STOP", p);
+  p = sh_socket_check("three");
+  CuAssertPtrNotNull(tc, p);
+  CuAssertStrEquals(tc, "RELOAD", p);
+  p = sh_socket_check("three");
+  CuAssertPtrEquals(tc, NULL, p);
+
+  p = sh_socket_check("four");
+  CuAssertPtrEquals(tc, NULL, p);
+#else
+  (void) tc;
+#endif
+}
+
+#endif  /* #ifdef SH_CUTEST */
+
+
+
Index: trunk/src/sh_static.c
===================================================================
--- trunk/src/sh_static.c	(revision 476)
+++ trunk/src/sh_static.c	(revision 481)
@@ -999,12 +999,23 @@
 		return -1;
 
-	while ((l = data[offset++])) {
+	while ((l = data[offset])) {
+
+	        if (offset < INT_MAX)
+	                offset++;
+		else
+		        return -1;
 
 		if ((l & 0xc0) == (0xc0)) {
-			offset++;
+		        if (offset < INT_MAX)
+			  offset++;
+			else
+			  return -1;
 			break;
 		}
 
-		offset += l;
+		if (offset <= (INT_MAX - l))
+		  offset += l;
+		else
+		  return -1;
 	}
 
@@ -1019,6 +1030,8 @@
 	if (i < 0)
 		return i;
-
-	return i + 4;
+	if (i < (INT_MAX - 4))
+	  return i + 4;
+	else
+	  return -1;
 }
 
@@ -1036,26 +1049,42 @@
 	if (!data)
 		return -1;
-
-	while ((l=data[offset++])) {
-		if (measure)
+	while ((l=data[offset])) {
+	        if (offset < INT_MAX) offset++;
+		else return -1;
+		if (measure && (total < INT_MAX))
 		    total++;
 		if ((l & 0xc0) == (0xc0)) {
-			if (measure)
+		        if (measure && (total < INT_MAX))
 				total++;
-			/* compressed item, redirect */
+		        /* compressed item, redirect */ 
 			offset = ((l & 0x3f) << 8) | data[offset];
+			if (offset < 0)
+			  return -1; 
 			measure = 0;
 			continue;
 		}
+	        
+		if (used >= (INT_MAX - l))
+		  return -1;
 
 		if ((used + l + 1) >= maxlen)
-			return -1;
+		  return -1; 
 
 		memcpy(dest + used, data + offset, l);
-		offset += l;
-		used += l;
-		if (measure)
+		
+		if (offset <= (INT_MAX - l))
+		  offset += l;
+		else
+		  return -1;
+
+		if (used <= (INT_MAX - l))
+		  used += l;
+		else
+		  return -1;
+		if (measure && (total <= (INT_MAX - l)))
 			total += l;
 
+		if (used == INT_MAX)
+		  return -1;
 		if (data[offset] != 0)
 			dest[used++] = '.';
@@ -1065,5 +1094,5 @@
 
 	/* The null byte must be counted too */
-	if (measure) {
+	if (measure && (total < INT_MAX)) {
 	    total++;
 	}
@@ -1078,5 +1107,5 @@
 {
 	char temp[256];
-	int i;
+	int i = 0;
 
 	i = __decode_dotted(message, offset, temp, sizeof(temp));
@@ -1084,5 +1113,8 @@
 		return i;
 
-	message += offset + i;
+	if (offset <= (INT_MAX - i))
+	  message += offset + i;
+	else
+	  return -1;
 
 	a->dotted = strdup(temp);
@@ -1101,5 +1133,12 @@
 	DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength);
 
-	return i + RRFIXEDSZ + a->rdlength;
+	if (RRFIXEDSZ <= (INT_MAX - i))
+	  i += RRFIXEDSZ;
+	else
+	  return -1;
+	if (a->rdlength <= (INT_MAX - i))
+	  return i + a->rdlength;
+	else
+	  return -1;
 }
 
@@ -1148,4 +1187,6 @@
 
 	dest += i;
+	if (maxlen < i)
+	  return -1;
 	maxlen -= i;
 
@@ -1158,5 +1199,8 @@
 	dest[3] = (q->qclass & 0x00ff) >> 0;
 
-	return i + 4;
+	if (i <= (INT_MAX - 4))
+	  return i + 4;
+	else
+	  return -1;
 }
 
Index: trunk/src/sh_string.c
===================================================================
--- trunk/src/sh_string.c	(revision 476)
+++ trunk/src/sh_string.c	(revision 481)
@@ -13,6 +13,6 @@
 
 extern int sl_ok_adds (size_t a, size_t b);
-#define SL_TRUE  1
-#define SL_FALSE 0
+#define S_TRUE  1
+#define S_FALSE 0
 
 #include <ctype.h>
@@ -389,5 +389,5 @@
 sh_string * sh_string_cat_lchar(sh_string * s, const char * str, size_t len)
 {
-  if (sl_ok_adds(len, s->siz) == SL_TRUE)
+  if (sl_ok_adds(len, s->siz) == S_TRUE)
     {
       if ((len + 1 + s->len) > s->siz)
@@ -453,9 +453,9 @@
   size_t len = 0;
 
-  if (sl_ok_adds(len1, len2) == SL_TRUE)
+  if (sl_ok_adds(len1, len2) == S_TRUE)
     len    = len1 + len2;
   else
     return NULL;
-  if (sl_ok_adds( len, len3) == SL_TRUE)
+  if (sl_ok_adds( len, len3) == S_TRUE)
     len    = len  + len3;
   else
@@ -482,5 +482,5 @@
     increase = SH_STRING_PARCEL;
   
-  if (s && sl_ok_adds(s->siz, increase) == SL_TRUE)
+  if (s && sl_ok_adds(s->siz, increase) == S_TRUE)
     {
       new = SH_ALLOC(s->siz + increase);
Index: trunk/src/sh_sub.c
===================================================================
--- trunk/src/sh_sub.c	(revision 476)
+++ trunk/src/sh_sub.c	(revision 481)
@@ -83,6 +83,4 @@
       close (child2parent[0]);
 
-      /* fprintf(stderr, "FIXME kill_sub %d\n", (int) sh_child_pid); */
-
       /* Let's be rude. */
       kill(sh_child_pid, SIGKILL);
@@ -210,6 +208,4 @@
 
 	  sh_child_pid = res;
-
-	  /* fprintf(stderr, "FIXME create_sub %d\n", (int) sh_child_pid); */
 	}
       else
@@ -252,5 +248,5 @@
 static ssize_t sh_sub_write(int fd, const void *buf, size_t count)
 {
-  char * mbuf = (char *) buf;
+  const char * mbuf = (const char *) buf;
   ssize_t rcount;
   int ttl = 5; /* 0, 1, 9, 81, 729 millisec */
@@ -296,6 +292,4 @@
   do {
 
-    /* fprintf(stderr, "FIXME wait_com polling..\n"); */
-
     do {
       ret = poll(&fds, 1, -1);
@@ -305,9 +299,4 @@
       {
 	ret = sh_sub_read(parent2child[0], &inbuf, sizeof(inbuf));
-
-	/*
-	fprintf(stderr, "FIXME wait_com stat %s (%s)\n",
-		inbuf.path, (inbuf.command == SH_COM_LSTAT) ? "lstat" : "stat");
-	*/
 
 	if (ret == 0)
@@ -328,10 +317,7 @@
 	    outbuf.errnum = errno;
 
-	    /* fprintf(stderr, "FIXME wait_com writing..\n"); */
-
 	    ret = sh_sub_write(child2parent[1], &outbuf, sizeof(outbuf));
 	    if (ret < 0)
 	      {
-		/* fprintf(stderr, "FIXME wait_com return 1\n"); */
 		return;
 	      }
@@ -339,11 +325,7 @@
 	else /* sh_sub_read() < 0 */
 	  {
-	    /* fprintf(stderr, "FIXME wait_com return 2\n"); */
 	    return;
 	  }
       }
-    
-    /* fprintf(stderr, "FIXME wait_com next..\n"); */
-
   } while (1 == 1);
 }
Index: trunk/src/sh_suidchk.c
===================================================================
--- trunk/src/sh_suidchk.c	(revision 476)
+++ trunk/src/sh_suidchk.c	(revision 481)
@@ -78,4 +78,5 @@
 #include "sh_suidchk.h"
 #include "sh_hash.h"
+#include "sh_dbIO.h"
 #include "sh_unix.h"
 #include "sh_files.h"
@@ -140,5 +141,5 @@
 static int     ShSuidchkActive   = S_TRUE;
 static time_t  ShSuidchkInterval = 7200;
-static long    ShSuidchkFps      = 0;
+static unsigned long    ShSuidchkFps      = 0;
 static int     ShSuidchkNosuid   = S_FALSE;
 static int     ShSuidchkYield    = S_FALSE;
@@ -150,6 +151,6 @@
 static time_t  FileLimNow        = 0;
 static time_t  FileLimStart      = 0;
-static long    FileLimNum        = 0;
-static long    FileLimTotal      = 0;
+static unsigned long    FileLimNum        = 0;
+static unsigned long    FileLimTotal      = 0;
 
 static sh_schedule_t * ShSuidchkSched = NULL;
@@ -1134,5 +1135,5 @@
     /* Rate limit (Fps == Files per second)
      */
-    if ((ShSuidchkFps > 0 && FileLimNum > ShSuidchkFps && FileLimTotal > 0)&&
+    if ((ShSuidchkFps > 0 && FileLimNum > ShSuidchkFps) &&
 	(ShSuidchkYield == S_FALSE))
       {
@@ -1222,19 +1223,17 @@
 	    int dummy;
 	    int class;
-	    unsigned long check_mask = 0;
+	    unsigned long check_flags = 0;
 
 	    theFile = SH_ALLOC(sizeof(file_type));
 
 	    (void) sl_strlcpy (theFile->fullpath, tmpcat, PATH_MAX);
-	    theFile->check_mask  = sh_files_maskof(SH_LEVEL_READONLY);
+	    theFile->check_flags  = sh_files_maskof(SH_LEVEL_READONLY);
 	    CLEAR_SH_FFLAG_REPORTED(theFile->file_reported);
 	    theFile->attr_string = NULL;
 	    theFile->link_path   = NULL;
 	    
-	    sh_files_search_file(tmpcat, &class,  &check_mask, &dummy);
-	    if ((check_mask & MODI_PREL) != 0)
-	      {
-		theFile->check_mask |= MODI_PREL;
-	      }
+	    sh_files_search_file(tmpcat, &class,  &check_flags, &dummy);
+	    if ((check_flags & MODI_PREL) != 0)
+	      MODI_SET(theFile->check_flags, MODI_PREL);
 
 	    status = sh_unix_getinfo (ShDFLevel[SH_ERR_T_RO], 
@@ -1303,5 +1302,5 @@
 		    /* Running init. Report on files detected.
 		     */
-		    sh_hash_pushdata (theFile, fileHash); /* no call to sh_error_handle */
+		    sh_dbIO_data_write (theFile, fileHash); /* no call to sh_error_handle */
 		    SH_MUTEX_LOCK(mutex_thread_nolog);
 		    sh_error_handle ((-1), FIL__, __LINE__, 
@@ -2215,16 +2214,10 @@
 }
 
-/* This variable is not used anywhere. It only exists
- * to assign &dirlist to it, which keeps gcc from
- * putting it into a register, and avoids the 'clobbered
- * by longjmp' warning. And no, 'volatile' proved insufficient.
- */
-static void * sh_dummy_type = NULL;
-
-
 /* Return a newly allocated string naming the type of filesystem that the
    file PATH, described by STATP, is on.
    RELPATH is the file name relative to the current directory.
    Return "unknown" if its filesystem type is unknown.  */
+
+void * sh_dummy_2229_type;
 
 static char *
@@ -2243,4 +2236,9 @@
   FILE *mfp;
   struct mntent *mnt;
+
+  /* Take the address to keep gcc from putting it into a register. 
+   * Avoids the 'clobbered by longjmp' warning. 
+   */
+  sh_dummy_2229_type = (void *) &type;
 
   if (path == NULL || relpath == NULL)
@@ -2257,9 +2255,4 @@
       return NULL;
     }
-
-  /* Take the address to keep gcc from putting it into a register. 
-   * Avoids the 'clobbered by longjmp' warning. 
-   */
-  sh_dummy_type = (void*) &type;
 
   /* Find the entry with the same device number as STATP, and return
Index: trunk/src/sh_tiger0.c
===================================================================
--- trunk/src/sh_tiger0.c	(revision 476)
+++ trunk/src/sh_tiger0.c	(revision 481)
@@ -55,4 +55,13 @@
 #endif
 
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#undef  SH_GNUC_ALIGN8
+#define SH_GNUC_ALIGN8   __attribute__((aligned(8)))
+#else
+#undef  SH_GNUC_ALIGN8
+#define SH_GNUC_ALIGN8
+#endif
+
+
 typedef unsigned char sh_byte;
 
@@ -121,5 +130,5 @@
   char    * tmp;
   sh_byte * bptr;
-  sh_byte   bbuf[64];
+  sh_byte   SH_GNUC_ALIGN8 bbuf[64];
   UINT64    bcount = 0;
 
@@ -186,5 +195,5 @@
 
 #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
-    if (skey->mlock_failed == SL_FALSE) 
+    if (skey->mlock_failed == S_FALSE) 
       {
         if ( (-1) == sh_unix_mlock(FIL__, __LINE__, 
@@ -193,13 +202,13 @@
 	  {
 	    SH_MUTEX_LOCK_UNSAFE(mutex_skey);  
-	    skey->mlock_failed = SL_TRUE;
+	    skey->mlock_failed = S_TRUE;
 	    SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
 	  }
       }
 #else
-    if (skey->mlock_failed == SL_FALSE)
+    if (skey->mlock_failed == S_FALSE)
       {
 	SH_MUTEX_LOCK_UNSAFE(mutex_skey);  
-	skey->mlock_failed = SL_TRUE;
+	skey->mlock_failed = S_TRUE;
 	SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
       }
@@ -215,5 +224,5 @@
       {
 	if (timeout > 0)
-	  count = sl_read_timeout (fd, buffer, PRIV_MAX, timeout, SL_TRUE);
+	  count = sl_read_timeout (fd, buffer, PRIV_MAX, timeout, S_TRUE);
 	else
 	  count = sl_read         (fd, buffer, PRIV_MAX);
@@ -903,5 +912,5 @@
 
       n = (off_t) sl_read_timeout (fd, buffer + sum, 
-				   (size_t) BLOCKSIZE - sum, timeout, SL_FALSE);
+				   (size_t) BLOCKSIZE - sum, timeout, S_FALSE);
 
       if (SL_ISERROR (n))
@@ -1450,5 +1459,5 @@
     do {
       n = (off_t) sl_read_timeout(fd, buffer + sum, 
-				  (size_t) BLOCKSIZE - sum, timeout, SL_FALSE);
+				  (size_t) BLOCKSIZE - sum, timeout, S_FALSE);
 
       if (SL_ISERROR (n))
@@ -1609,4 +1618,33 @@
 }
 
+void sh_tiger_get_mask_hashtype(unsigned long * mask)
+{
+  if (hash_type == SH_TIGER192) 
+    *mask |= MODI_TIGER192;
+  else if (hash_type == SH_SHA1)
+    *mask |= MODI_SHA1;
+  else if (hash_type == SH_MD5)
+    *mask |= MODI_MD5;
+  else if (hash_type == SH_SHA256)
+    *mask |= MODI_SHA256;
+  return;
+}
+
+void sh_tiger_set_hashtype_mask(unsigned long mask)
+{
+  unsigned long type = mask & MODI_HASHTYPE;
+
+  if (type == MODI_TIGER192)
+    hash_type = SH_TIGER192;
+  else if (type == MODI_SHA1)
+    hash_type = SH_SHA1;
+  else if (type == MODI_MD5)
+    hash_type = SH_MD5;
+  else if (type == MODI_SHA256)
+    hash_type = SH_SHA256;
+  return;
+}
+
+
 int sh_tiger_hashtype (const char * c)
 {
Index: trunk/src/sh_tiger1_64.c
===================================================================
--- trunk/src/sh_tiger1_64.c	(revision 476)
+++ trunk/src/sh_tiger1_64.c	(revision 481)
@@ -384,5 +384,5 @@
 void tiger_compress(const word64 *str, word64 state[3])
 {
-  tiger_compress_macro(((word64*)str), ((word64*)state));
+  tiger_compress_macro(((const word64*)str), ((word64*)state));
 }
 
@@ -419,5 +419,8 @@
   register word64 i;
   register word64 j = 0;
-  unsigned char temp[64];
+  union {
+    word64 w64_temp[8];
+    unsigned char temp[64];
+  } dd;
   union {
     word64 itmp;
@@ -435,6 +438,6 @@
 #ifdef BIG_ENDIAN
       for(j=0; j<64; j++)
-        temp[j^7] = ((sh_byte*)str)[j];
-      tiger_compress(((word64*)temp), res);
+        dd.temp[j^7] = ((sh_byte*)str)[j];
+      tiger_compress((dd.w64_temp), res);
 #else
       tiger_compress(str, res);
@@ -445,21 +448,21 @@
 #ifdef BIG_ENDIAN
   for(j=0; j<i; j++)
-    temp[j^7] = ((sh_byte*)str)[j];
-
-  temp[j^7] = 0x01;
+    dd.temp[j^7] = ((sh_byte*)str)[j];
+
+  dd.temp[j^7] = 0x01;
   j++;
   for(; j&7; j++)
-    temp[j^7] = 0;
+    dd.temp[j^7] = 0;
 #else
 
 #ifndef USE_MEMSET
   for(j=0; j<i; j++)
-    temp[j] = ((sh_byte*)str)[j];
-#else
-  memcpy( temp, str, j=i );
-#endif
-  temp[j++] = 0x01;
+    dd.temp[j] = ((const sh_byte*)str)[j];
+#else
+  memcpy( dd.temp, str, j=i );
+#endif
+  dd.temp[j++] = 0x01;
   for(; j&7; j++)
-	temp[j] = 0;
+	dd.temp[j] = 0;
 
 #endif
@@ -469,9 +472,9 @@
 #ifndef USE_MEMSET
       for(; j<64; j++)
-	temp[j] = 0;
-#else
-      memset( temp+j, 0, 64-j);
-#endif
-      tiger_compress(((word64*)temp), res);
+	dd.temp[j] = 0;
+#else
+      memset( (dd.temp)+j, 0, 64-j);
+#endif
+      tiger_compress((dd.w64_temp), res);
       j=0;
     }
@@ -479,7 +482,7 @@
 #ifndef USE_MEMSET
   for(; j<56; j++)
-    temp[j] = 0;
-#else
-  memset( temp+j, 0, 56-j);
+    dd.temp[j] = 0;
+#else
+  memset( (dd.temp)+j, 0, 56-j);
 #endif
 
@@ -488,7 +491,7 @@
   uu.itmp = ((word64)length)<<3;
   for (j=0; j<8; j++)
-        temp[56+j] = uu.ctmp[j];
-
-  tiger_compress(((word64*)temp), res);
+        dd.temp[56+j] = uu.ctmp[j];
+
+  tiger_compress((dd.w64_temp), res);
 }
 
Index: trunk/src/sh_tools.c
===================================================================
--- trunk/src/sh_tools.c	(revision 476)
+++ trunk/src/sh_tools.c	(revision 481)
@@ -109,5 +109,5 @@
     p = (_("Key passed is not valid"));
   else if (err_num == BAD_CIPHER_MODE) 
-    p = (_("Params struct passed to cipherInit invalid"));
+    p = (_("Params struct passed to rijndael_cipherInit invalid"));
   else if (err_num == BAD_CIPHER_STATE) 
     p = (_("Cipher in wrong state"));
@@ -1371,7 +1371,88 @@
 #if defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)
 
+#if defined (SH_WITH_CLIENT)
+
+static int           probe_done = S_FALSE;
+static unsigned char probe_flag = '\0';
+
+void sh_tools_probe_reset()
+{
+  probe_done = S_FALSE;
+  probe_flag = '\0';
+  return;
+}
+
+static int probe_ok(int flag)
+{
+  (void) flag;
+  if ((probe_flag & SH_PROTO_IVA) != 0)
+    return S_TRUE;
+  return S_FALSE;
+}
+
+static unsigned char probe_header_set(unsigned char protocol)
+{
+  if (probe_done || (protocol & SH_PROTO_SRP) == 0)
+    return 0;
+
+  return (char) SH_PROTO_IVA;
+}
+
+static void probe_header_get(unsigned char protocol)
+{
+  if (probe_done || (protocol & SH_PROTO_SRP) == 0)
+    return;
+
+  /* If the server doesn't know about it,
+   * it will simply mirror it back. */
+  
+  if ((protocol & SH_PROTO_IVA) != 0)
+    {
+      /* probe was mirrored */;
+    }
+  else
+    {
+      /* probe was UNset */
+      probe_flag |= SH_PROTO_IVA;
+    }
+  probe_done = S_TRUE;
+  return;
+}
+
+#else
+static unsigned char probe_header_set(unsigned char protocol) { 
+  (void) protocol; return 0; }
+static void probe_header_get(unsigned char protocol) { 
+  (void) protocol; return; }
+void sh_tools_probe_reset() { return; }
+
+unsigned char sh_tools_probe_store(unsigned char protocol, int * probe_flag)
+{
+  if ((protocol & SH_PROTO_SRP) == 0)
+    return protocol;
+
+  if ((protocol & SH_PROTO_IVA) != 0)
+    {
+      /* probe received */
+      *probe_flag |=  SH_PROTO_IVA;
+      protocol    &= ~SH_PROTO_IVA;
+    }
+  return protocol; 
+}
+
+static int probe_ok(int flag)
+{
+  if ((flag & SH_PROTO_IVA) != 0)
+    return S_TRUE;
+  return S_FALSE;
+}
+#endif
+
+
 void get_header (unsigned char * head, unsigned long * bytes, char * u)
 {
   SL_ENTER(_("get_header"));
+
+  probe_header_get(head[0]);
 
   *bytes = 
@@ -1393,5 +1474,5 @@
 #if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
 
-#ifdef  SH_ENCRYPT_2
+#ifdef  SH_ENCRYPT
 #define TRANS_BYTES 65120
 #else
@@ -1399,7 +1480,8 @@
 #endif
 
-void put_header (unsigned char * head, int protocol, 
+void put_header (unsigned char * head, const int protocol, 
 		 unsigned long * length, char * u)
 {
+  unsigned char probe = probe_header_set(protocol);
 
   /* static long transfer_limit = (8 * SH_BUFSIZE); V0.8 */
@@ -1408,5 +1490,5 @@
   SL_ENTER(_("put_header"));
 
-  head[0]   = protocol;
+  head[0]   = protocol|probe;
 
   ASSERT((*length < transfer_limit), _("*length < transfer_limit"))
@@ -1434,5 +1516,4 @@
   SL_RET0(_("put_header"));
 }
-#endif
 
 /* ------------------------------------------
@@ -1453,15 +1534,5 @@
  * only SH_V2_FULLSIZE is used, and only once
  */
-#if 0
-#ifdef SH_WITH_SERVER
-#define SH_V2_FULLSIZE  240
-#define SH_V2_PAYLOAD   224
-#define SH_V2_MESSAGE   176
-#else
-#define SH_V2_FULLSIZE 1024
-#define SH_V2_PAYLOAD  1008
-#define SH_V2_MESSAGE   960
-#endif
-#endif
+
 #define SH_V2_FULLSIZE 1024
 
@@ -1508,4 +1579,5 @@
 
 #ifdef SH_ENCRYPT
+
 /*
  * #define DEBUG_EN2
@@ -1514,26 +1586,29 @@
  * last 4 bytes of outgoing header are set to dummy value
  */
-char * sh_tools_makePack (unsigned char * header, 
+char * sh_tools_makePack (unsigned char * header, int flag,
 			  char * payload, unsigned long payload_size,
 			  keyInstance * keyInstE)
 {
-  UINT32 rpad[3];
+  BYTE            inBlock[B_SIZ]; 
+  BYTE            outBlock[B_SIZ];
+  char            ivBlock[B_SIZ];
+
+  UINT32          rpad[3];
   unsigned char   head[16];
-  double epad;
-  unsigned long    i_epad = 0;
-  unsigned long    i_blk = payload_size / 16;
-  unsigned long    i_blkmax = SH_V2_FULLSIZE / 16;
-  unsigned long    pads = 0;
-  size_t full_size;
-  char * full_ret;
-
-  char                  * p;
-  RIJ_BYTE                    inBlock[B_SIZ]; 
-  RIJ_BYTE                    outBlock[B_SIZ];
-  int                     j;
-  cipherInstance          cipherInst;
-  int                     err_num;
-  int                     blkfac;
-  int                     oflow = 0;
+  double          epad;
+  unsigned long   i_epad = 0;
+  unsigned long   i_blk = payload_size / 16;
+  unsigned long   i_blkmax = SH_V2_FULLSIZE / 16;
+  unsigned long   pads = 0;
+  size_t          full_size;
+  char          * full_ret;
+
+  unsigned char * p;
+  int             j;
+  cipherInstance  cipherInst;
+  int             err_num;
+  int             blkfac;
+  int             oflow = 0;
+  char expbuf[SH_ERRBUF_SIZE];
 
   /* 
@@ -1541,7 +1616,5 @@
   */
   if ((i_blk * 16) != payload_size) ++i_blk;
-#ifdef DEBUG_EN2
-  fprintf(stderr, "SEND <%d> blocks <%d>\n", payload_size, i_blk);
-#endif
+
   /* random_pad
    */
@@ -1553,8 +1626,4 @@
   memcpy (&head[8],  &rpad[2],    4);
 
-  /* protocol
-   */
-  /* memcpy (&head[8],  &header[3], 4); */
-
   /* size (payload)
    */ 
@@ -1566,14 +1635,7 @@
   if (i_blk < i_blkmax) 
   {
-    pads = i_blkmax - i_blk;
-    /* memcpy((char *) &rpad[2], &head[12], 4); */
-    epad = taus_get_double (&rpad);
-#ifdef DEBUG_EN2
-    fprintf(stderr, "PAD1 <%d> <%f>\n", pads, epad);
-#endif
+    pads   = i_blkmax - i_blk;
+    epad   = taus_get_double (&rpad);
     i_epad = (unsigned long) (pads * epad);
-#ifdef DEBUG_EN2
-    fprintf(stderr, "PAD2 <%d> <%d>\n", i_epad, (i_epad*16));
-#endif
   }
 
@@ -1596,21 +1658,15 @@
 
   full_ret = SH_ALLOC(full_size);
+
   memcpy(full_ret,                   head,    16);
   if (payload != NULL && !oflow)
-    {
-      memcpy(&full_ret[16],              payload, payload_size);
-    }
+    memcpy(&full_ret[16],              payload, payload_size);
+
   if ((i_blk*16) > payload_size && !oflow) 
     {
-#ifdef DEBUG_EN2
-      fprintf(stderr, "SEN2 <%d>\n", (i_blk*16) - payload_size);
-#endif
       memset(&full_ret[16+payload_size], '\0', (i_blk*16) - payload_size);
       payload_size = i_blk * 16;
     }
   memset(&full_ret[16+payload_size], '\0', i_epad*16);
-#ifdef DEBUG_EN2
-  fprintf(stderr, "SEN3 <%d> <%d>\n", full_size, i_epad*16);
-#endif
 
   /* rewrite header
@@ -1618,33 +1674,46 @@
   header[1]   = (unsigned int)(full_size/256);
   header[2]   = (unsigned int)(full_size - (256 * header[1]));
-  /* don't erase protocol from header 
-     memset(&header[3], '\0', 4);
-  */
-  p = full_ret; blkfac = full_size / 16;
-
-  err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
+
+  p      = (unsigned char *) full_ret; 
+  blkfac = full_size / B_SIZ;
+
+  err_num = rijndael_cipherInit (&cipherInst, MODE_CBC, NULL);
   
-  if (err_num < 0) 
-    {
-      char expbuf[SH_ERRBUF_SIZE];
-      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-		      errorExplain(err_num, expbuf, sizeof(expbuf)), 
-		      _("sh_tools_makePack: cipherInit"));
-    }
-  for (j = 0; j < blkfac; ++j)
-    {
+  if (err_num < 0) {
+    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+		    errorExplain(err_num, expbuf, sizeof(expbuf)), 
+		    _("sh_tools_makePack: rijndael_cipherInit")); }
+
+  if (probe_ok(flag)) {
+    memcpy(inBlock, p, B_SIZ);
+    err_num = rijndael_blockEncrypt(&cipherInst, keyInstE, 
+				    inBlock, 128, outBlock);
+    if (err_num >= 0) {
+      memcpy(p, outBlock, B_SIZ); p += B_SIZ;
+      memcpy(ivBlock, outBlock, sizeof(ivBlock));
+      err_num = rijndael_cipherInit (&cipherInst, MODE_CBC, ivBlock);
+      if (err_num >= 0) {
+	err_num = rijndael_blockEncrypt(&cipherInst, keyInstE, 
+					p, 128*(blkfac-1), p);
+      }
+    }
+  }
+
+  else {
+    for (j = 0; j < blkfac; ++j) {
       memcpy(inBlock, p, B_SIZ);
-      err_num = blockEncrypt(&cipherInst, keyInstE, 
-			     inBlock, 128 * BNUM, outBlock);
-      if (err_num < 0)
-	{
-	  char expbuf[SH_ERRBUF_SIZE];
-	  sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			  errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			  _("sh_tools_makePack: blockEncrypt"));
-	}
+      err_num = rijndael_blockEncrypt(&cipherInst, keyInstE, 
+				      inBlock, 128, outBlock);
+      
+      if (err_num < 0) {
+	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			errorExplain(err_num, expbuf, sizeof(expbuf)), 
+			_("sh_tools_makePack: rijndael_blockEncrypt"));
+	break; }
+      
       memcpy(p, outBlock, B_SIZ);
       p += B_SIZ;
     }
+  }
 
   return full_ret;
@@ -1654,14 +1723,15 @@
  * last 4 bytes of incoming header are dummy
  */
-char * sh_tools_revertPack (unsigned char * header, char * message, 
+char * sh_tools_revertPack (unsigned char * header, int flag, char * message, 
 			    keyInstance * keyInstD,
 			    unsigned long message_size)
 {
+  BYTE                    inBlock[B_SIZ]; 
+  BYTE                    outBlock[B_SIZ];
+  char                    ivBlock[B_SIZ];
   unsigned long   msg_size;
   char          * msg_ret;
 
-  char                  * p;
-  RIJ_BYTE                    inBlock[B_SIZ]; 
-  RIJ_BYTE                    outBlock[B_SIZ];
+  unsigned char         * p;
   int                     j;
   cipherInstance          cipherInst;
@@ -1671,17 +1741,10 @@
 
   msg_size = (256 * (unsigned int)header[1] + (unsigned int)header[2]);
-#ifdef DEBUG_EN2
-  fprintf(stderr, "RECV <%lu>\n", msg_size);
-#endif
-  if (msg_size > message_size) {
+  if (msg_size > message_size) 
     msg_size = message_size;
-#ifdef DEBUG_EN2
-    fprintf(stderr, "RECV TRUNC1 <%lu>\n", msg_size);
-#endif
-  }
-
-  p = message; blkfac = msg_size / 16;
-
-  err_num = cipherInit (&cipherInst, MODE_CBC, NULL);
+
+  p = (unsigned char *) message; blkfac = msg_size / 16;
+
+  err_num = rijndael_cipherInit (&cipherInst, MODE_CBC, NULL);
   
   if (err_num < 0) 
@@ -1689,21 +1752,39 @@
       sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
 		      errorExplain(err_num, expbuf, sizeof(expbuf)), 
-		      _("sh_tools_revertPack: cipherInit"));
-    }
-  for (j = 0; j < blkfac; ++j)
-    {
+		      _("sh_tools_revertPack: rijndael_cipherInit"));
+    }
+
+  if (probe_ok(flag)) {
+    memcpy(inBlock, p, B_SIZ);
+    err_num = rijndael_blockDecrypt(&cipherInst, keyInstD, 
+				    inBlock, 128, outBlock);
+    if (err_num >= 0) {
+      memcpy(p, outBlock, B_SIZ); p += B_SIZ;
+      memcpy(ivBlock, inBlock, sizeof(ivBlock));
+      err_num = rijndael_cipherInit (&cipherInst, MODE_CBC, ivBlock);
+      if (err_num >= 0) {
+	err_num = rijndael_blockDecrypt(&cipherInst, keyInstD, 
+					p, 128*(blkfac-1), p);
+      }
+    }
+  }
+
+  else {
+    for (j = 0; j < blkfac; ++j) {
       memcpy(inBlock, p, B_SIZ);
-      err_num = blockDecrypt(&cipherInst, keyInstD, 
-			     inBlock, 128 * BNUM, outBlock);
-      if (err_num < 0)
-	{
-	  sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
-			  errorExplain(err_num, expbuf, sizeof(expbuf)), 
-			  _("sh_tools_revertPack: blockDecrypt"));
-	}
+      err_num = rijndael_blockDecrypt(&cipherInst, keyInstD, 
+				      inBlock, 128, outBlock);
+  
+      if (err_num < 0) {
+	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			errorExplain(err_num, expbuf, sizeof(expbuf)), 
+			_("sh_tools_revertPack: rijndael_blockDecrypt"));
+	break; }
+      
       memcpy(p, outBlock, B_SIZ);
       p += B_SIZ;
     }
-  
+  }
+
   /* rewrite size in header
    */
@@ -1717,14 +1798,5 @@
       header[1]   = (unsigned int)(msg_size/256);
       header[2]   = (unsigned int)(msg_size - (256 * header[1]));
-#ifdef DEBUG_EN2
-      fprintf(stderr, "RECV TRUNC2 <%lu>\n", msg_size);
-#endif
-    }
-#ifdef DEBUG_EN2
-  fprintf(stderr, "REC2 <%lu>\n", msg_size);
-#endif
-  /* protocol
-   */
-  /* memcpy(&header[3], &message[8], 4); */
+    }
 
   /* payload 
@@ -1732,16 +1804,11 @@
   msg_ret = SH_ALLOC(msg_size+1);
   if (msg_size > 0)
-    {
-      memcpy(msg_ret, &message[16], msg_size);
-    }
+    memcpy(msg_ret, &message[16], msg_size);
   msg_ret[msg_size] = '\0';
-#ifdef DEBUG_EN2
-  fprintf(stderr, "REC3 <%lu>\n", msg_size);
-#endif
+
   SH_FREE(message);
-
   return msg_ret;
 }
-#endif
+#endif /* #ifdef SH_ENCRYPT */
 
 int sh_tools_hash_add(char * key, char * buf, int buflen)
@@ -1781,4 +1848,7 @@
   SL_RETURN((1), _("sh_tools_hash_vfy"));
 }
+
+#endif /* defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) */
+
 
 /* ------------------------------------------ */
@@ -1868,5 +1938,5 @@
 #if defined (SH_WITH_SERVER)
 
-char * get_client_conf_file (char * peer, unsigned long * length)
+char * get_client_conf_file (const char * peer, unsigned long * length)
 {
   char * ret;
@@ -1874,23 +1944,13 @@
   struct stat buf;
   char * base;
-  size_t size;
 
   SL_ENTER(_("get_client_conf_file"));
 
   base = sh_util_strdup(DEFAULT_DATAROOT);
-
-  size = sl_strlen(base);
-  if (sl_ok_adds(size, sl_strlen(peer)))
-      size += sl_strlen(peer);
-  if (sl_ok_adds(size, 6))
-    size += 6;
-
-  ret = SH_ALLOC(size);
-  sl_strlcpy(ret, base, size);
-  sl_strlcat(ret, _("/rc."), size);
-  sl_strlcat(ret, peer, size);
-  
+  ret = sh_util_strconcat(base, _("/rc."), peer, NULL);
+  if (!ret) 
+    { SH_FREE(base); *length = 0; SL_RETURN(NULL, _("get_client_conf_file")); }
+
   status = retry_stat (FIL__, __LINE__, ret, &buf);
-
   if (status == 0)
     goto lab_end;
@@ -1899,9 +1959,9 @@
 		    (long) sh.effective.uid, ret);
 
-  sl_strlcpy(ret, base, size);
-  sl_strlcat(ret, "/rc", size);
+  SH_FREE(ret); ret = sh_util_strconcat(base, _("/rc"), NULL);
+  if (!ret) 
+    { SH_FREE(base); *length = 0; SL_RETURN(NULL, _("get_client_conf_file")); }
   
   status = retry_stat (FIL__, __LINE__, ret, &buf);
-
   if (status == 0)
     goto lab_end;
@@ -1910,7 +1970,5 @@
 		    (long) sh.effective.uid, ret);
 
-  SH_FREE(base);
-  SH_FREE(ret);
-  *length=0;
+  SH_FREE(base); SH_FREE(ret); *length=0;
   SL_RETURN(NULL, _("get_client_conf_file"));
 
@@ -1920,38 +1978,27 @@
       sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
 		    _("File too large"), _("get_client_conf_file"));
-      SH_FREE(base);
+      SH_FREE(base); SH_FREE(ret); *length = 0;
       SL_RETURN(NULL, _("get_client_conf_file"));
     }
-  *length = (unsigned long) buf.st_size;
-  SH_FREE(base);
+
+  SH_FREE(base); *length = (unsigned long) buf.st_size;
   SL_RETURN(ret, _("get_client_conf_file"));
 }
 
-char * get_client_data_file (char * peer, unsigned long * length)
+char * get_client_data_file (const char * peer, unsigned long * length)
 {
   char * ret;
   int    status;
   struct stat buf;
-
   char * base;
-  size_t size;
 
   SL_ENTER(_("get_client_data_file"));
 
   base = sh_util_strdup(DEFAULT_DATAROOT);
-
-  size = sl_strlen(base);
-  if (sl_ok_adds(size, sl_strlen(peer)))
-      size += sl_strlen(peer);
-  if (sl_ok_adds(size, 8))
-    size += 8;
-
-  ret = SH_ALLOC(size);
-  sl_strlcpy(ret, base, size);
-  sl_strlcat(ret, _("/file."), size);
-  sl_strlcat(ret, peer, size);
-  
+  ret = sh_util_strconcat(base, _("/file."), peer, NULL);
+  if (!ret) 
+    { SH_FREE(base); *length = 0; SL_RETURN(NULL, _("get_client_data_file")); }
+
   status = retry_stat (FIL__, __LINE__, ret, &buf);
-
   if (status == 0)
     goto lab1_end;
@@ -1960,10 +2007,10 @@
 		    (long) sh.effective.uid, ret);
 
-
-  sl_strlcpy(ret, base, size);
-  sl_strlcat(ret, _("/file"), size);
-  
+  SH_FREE(ret); 
+  ret = sh_util_strconcat(base, _("/file"), NULL);
+  if (!ret) 
+    { SH_FREE(base); *length = 0; SL_RETURN(NULL, _("get_client_data_file")); }
+
   status = retry_stat (FIL__, __LINE__, ret, &buf);
-
   if (status == 0)
     goto lab1_end;
@@ -1972,8 +2019,5 @@
 		    (long) sh.effective.uid, ret);
 
-
-  *length = 0;
-  SH_FREE(base);
-  SH_FREE(ret);
+  *length = 0; SH_FREE(base); SH_FREE(ret);
   SL_RETURN(NULL, _("get_client_data_file"));
 
@@ -1983,12 +2027,47 @@
       sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
 		    _("File too large"), _("get_client_data_file"));
-      SH_FREE(base);
+      SH_FREE(base); SH_FREE(ret); *length = 0;
       SL_RETURN(NULL, _("get_client_data_file"));
     }
+
+  *length = (unsigned long) buf.st_size; SH_FREE(base);
+  SL_RETURN(ret, _("get_client_data_file"));
+}
+
+char * get_client_uuid_file (const char * peer, unsigned long * length, const char * uuid)
+{
+  char * ret;
+  int    status;
+  struct stat buf;
+  char * base;
+
+  SL_ENTER(_("get_client_uuid_file"));
+
+  base = sh_util_strdup(DEFAULT_DATAROOT);
+  ret = sh_util_strconcat(base, _("/file."), peer, ".", uuid, NULL);
+  SH_FREE(base);
+  if (!ret) 
+    { *length = 0; SL_RETURN(NULL, _("get_client_uuid_file")); }
+
+  status = retry_stat (FIL__, __LINE__, ret, &buf);
+  if (status != 0)
+    {
+      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_ACCESS,
+		      (long) sh.effective.uid, ret);
+      SH_FREE(ret); *length = 0;
+      SL_RETURN(NULL, _("get_client_uuid_file"));
+    }
+  else if (buf.st_size > 0x7fffffff)
+    {
+      sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_E_SUBGEN,
+		    _("File too large"), _("get_client_uuid_file"));
+      SH_FREE(ret); *length = 0;
+      SL_RETURN(NULL, _("get_client_data_file"));
+    }
+
   *length = (unsigned long) buf.st_size;
-  SH_FREE(base);
-  SL_RETURN(ret, _("get_client_data_file"));
-  
-}
+  SL_RETURN(ret, _("get_client_uuid_file"));
+}
+
 #endif
 
@@ -2091,10 +2170,9 @@
   if (SL_ISERROR(fd))
     {
-      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, fd, MSG_E_SUBGEN, 
+      sh_error_handle((-1), FIL__, __LINE__, fd, MSG_E_SUBGEN, 
 		      _("Error opening temporary file"), _("open_tmp"));
       TPT(( 0, FIL__, __LINE__, _("msg=<Error %d temporary file %s>\n"), 
 	    fd, file));
     }
-  
 
   SH_FREE (file);
Index: trunk/src/sh_unix.c
===================================================================
--- trunk/src/sh_unix.c	(revision 476)
+++ trunk/src/sh_unix.c	(revision 481)
@@ -103,4 +103,5 @@
 #include "sh_prelink.h"
 #include "sh_pthread.h"
+#include "sh_sem.h"
 
 /* moved here from far below
@@ -482,4 +483,6 @@
   sl_strlcat(msg, details, 128);
   (void) safe_logger (thesignal, method, msg);
+
+  close_ipc ();
   raise(SIGKILL);
 }
@@ -526,4 +529,5 @@
 	  } while (val_return < 0 && errno == EINTR);
 
+          close_ipc ();
 	  safe_logger (mysignal, 0, NULL);
 	}
@@ -594,7 +598,5 @@
       if (skey != NULL)
 	memset (skey, '\0', sizeof(sh_key_t));
-#ifdef WITH_MESSAGE_QUEUE
       close_ipc ();
-#endif
       safe_logger (mysignal, 0, NULL);
       do {
@@ -636,7 +638,5 @@
   if (skey != NULL)
     memset (skey, '\0', sizeof(sh_key_t));
-#ifdef WITH_MESSAGE_QUEUE
   close_ipc ();
-#endif
 
   do {
@@ -669,6 +669,6 @@
 #endif
 #ifdef SIGTTOU
-  if (mysignal == SIGTTOU)
-    sig_force_check = 1;
+  if (mysignal == SIGTTOU) {
+    sig_force_check = 1; sh_sem_trylock(); }
 #endif
 #ifdef SIGTTIN
@@ -682,8 +682,5 @@
 #ifdef SIGQUIT
   if (mysignal == SIGQUIT)
-    {
-      sig_terminate       = 1;
-      ++sig_urgent;
-    }
+    sig_terminate       = 1;
 #endif
 #ifdef SIGTERM
@@ -1042,5 +1039,5 @@
       if ((status == ERANGE) && (w == NULL)) 
 	{
-	  if (SL_TRUE ==  sl_ok_adds( gbufsize, SH_GRBUF_SIZE ))
+	  if (S_TRUE ==  sl_ok_adds( gbufsize, SH_GRBUF_SIZE ))
 	    {
 	      SH_FREE(buffer);
@@ -1722,5 +1719,5 @@
   struct utsname   buf;
   int              i;
-  int              ddot;
+  unsigned int     ddot;
   int              len;
   char           * p;
@@ -1892,5 +1889,5 @@
    */
 #if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
-  if (skey->mlock_failed == SL_FALSE)
+  if (skey->mlock_failed == S_FALSE)
     {
       if ( (-1) == sh_unix_mlock( FIL__, __LINE__, 
@@ -1898,13 +1895,13 @@
 	{
 	  SH_MUTEX_LOCK_UNSAFE(mutex_skey);
-	  skey->mlock_failed = SL_TRUE;
+	  skey->mlock_failed = S_TRUE;
 	  SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
 	}
     }
 #else
-  if (skey->mlock_failed == SL_FALSE)
+  if (skey->mlock_failed == S_FALSE)
     {
       SH_MUTEX_LOCK_UNSAFE(mutex_skey);
-      skey->mlock_failed = SL_TRUE;
+      skey->mlock_failed = S_TRUE;
       SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
     }
@@ -1980,5 +1977,5 @@
 
   if (dummy == NULL)
-    sh.flag.isdaemon = ON;
+    sh.flag.isdaemon = S_TRUE;
   else 
     res = sh_util_flagval (dummy, &sh.flag.isdaemon);
@@ -2003,5 +2000,5 @@
 
   if (dummy == NULL)
-    sh.flag.isdaemon = OFF;
+    sh.flag.isdaemon = S_FALSE;
   else 
     res = sh_util_flagval (dummy, &sh.flag.isdaemon);
@@ -2221,5 +2218,5 @@
     char * tz = sh_util_strdup(getenv("TZ")); /* flawfinder: ignore */
     size_t tzlen = strlen(tz);
-    if (SL_TRUE == sl_ok_adds (4, tzlen)) {
+    if (S_TRUE == sl_ok_adds (4, tzlen)) {
 	env[3] = SH_ALLOC(4+tzlen);
 	sl_strlcpy(env[3], "TZ=", 4);
@@ -2244,5 +2241,5 @@
       memset(skey, 0, sizeof(sh_key_t));
       (void) umask(S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
-      sh_unix_closeall (3, -1, SL_TRUE); /* in child process */
+      sh_unix_closeall (3, -1, S_TRUE); /* in child process */
       execve(path, arg, env);
       _exit(EXIT_FAILURE);
@@ -2284,4 +2281,7 @@
   struct tm   bb;
 
+  struct tm * aptr;
+  struct tm * bptr;
+
   int  sign =  0;
   int  diff =  0;
@@ -2292,37 +2292,47 @@
 
 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
-  gmtime_r (xx, &aa);
+  aptr = gmtime_r (xx, &aa);
 #else
-  memcpy (&aa, gmtime(xx), sizeof(struct tm));
+  aptr = gmtime(xx);
+  if (aptr)
+    memcpy (&aa, aptr, sizeof(struct tm));
 #endif
 
 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
-  localtime_r (xx, &bb);
+  bptr = localtime_r (xx, &bb);
 #else
-  memcpy (&bb, localtime(xx), sizeof(struct tm));
-#endif
-
-  /* Check for datum wrap-around.
-   */
-  if      (aa.tm_year < bb.tm_year)
-    sign = (-1);
-  else if (aa.tm_mon  < bb.tm_mon)
-    sign = (-1);
-  else if (aa.tm_mday < bb.tm_mday)
-    sign = (-1);
-  else if (bb.tm_year < aa.tm_year)
-    sign = ( 1);
-  else if (bb.tm_mon  < aa.tm_mon)
-    sign = ( 1);
-  else if (bb.tm_mday < aa.tm_mday)
-    sign = ( 1);
-
-  diff = aa.tm_hour * 60 + aa.tm_min;
-  diff = (bb.tm_hour * 60 + bb.tm_min) - diff;
-  diff = diff - (sign * 24 * 60);   /* datum wrap-around correction */
-  hh = diff / 60;
-  mm = diff - (hh * 60);
-  sprintf (tz, _("%+03d%02d"), hh, mm);                /* known to fit  */
-
+  bptr = localtime(xx);
+  if (bptr) 
+    memcpy (&bb, bptr, sizeof(struct tm));
+#endif
+
+  if (bptr && aptr)
+    {
+      /* Check for datum wrap-around.
+       */
+      if      (aa.tm_year < bb.tm_year)
+	sign = (-1);
+      else if (aa.tm_mon  < bb.tm_mon)
+	sign = (-1);
+      else if (aa.tm_mday < bb.tm_mday)
+	sign = (-1);
+      else if (bb.tm_year < aa.tm_year)
+	sign = ( 1);
+      else if (bb.tm_mon  < aa.tm_mon)
+	sign = ( 1);
+      else if (bb.tm_mday < aa.tm_mday)
+	sign = ( 1);
+      
+      diff = aa.tm_hour * 60 + aa.tm_min;
+      diff = (bb.tm_hour * 60 + bb.tm_min) - diff;
+      diff = diff - (sign * 24 * 60);   /* datum wrap-around correction */
+      hh = diff / 60;
+      mm = diff - (hh * 60);
+      sprintf (tz, _("%+03d%02d"), hh, mm);                /* known to fit  */
+    }
+  else
+    {
+      sprintf (tz, _("%+03d%02d"), 0, 0);
+    }
   SL_RETURN(tz, _("t_zone"));
 }
@@ -2560,5 +2570,5 @@
 static int sh_unix_use_localtime = S_FALSE;
 
-/* whether to use localtime for file timesatams in logs
+/* whether to use localtime for file timestamps in logs
  */
 int sh_unix_uselocaltime (const char * c)
@@ -3485,5 +3495,5 @@
 
 int sh_unix_checksum_size (char * filename, off_t size, int is_max_size, 
-			   char * fileHash, int alert_timeout, SL_TICKET fd)
+			   char * fileHash, int alert_timeout, SL_TICKET fd, unsigned long mask)
 {
   file_type * tmpFile;
@@ -3517,4 +3527,5 @@
       char hashbuf[KEYBUF_SIZE];
       UINT64 local_length = (UINT64) (tmpFile->size < 0 ? 0 : tmpFile->size);
+      if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(mask);
       sl_strlcpy(fileHash,
 		 sh_tiger_generic_hash (filename, fd, &(local_length), 
@@ -3541,5 +3552,5 @@
 
 int sh_check_rotated_log (const char * path,  
-			  UINT64 old_size, UINT64 old_inode, const char * old_hash)
+			  UINT64 old_size, UINT64 old_inode, const char * old_hash, unsigned long mask)
 {
   struct stat obuf;
@@ -3560,5 +3571,6 @@
 	  if (!SL_ISERROR(fd))
 	    {
-	      sh_unix_checksum_size (rotated_file, old_size, S_FALSE, hashbuf, 120 /* alert_timeout */, fd);
+	      sh_unix_checksum_size (rotated_file, old_size, S_FALSE, 
+				     hashbuf, 120 /* alert_timeout */, fd, mask);
 	      
 	      sl_close(fd);
@@ -3814,5 +3826,5 @@
   SL_ENTER(_("sh_unix_getinfo"));
 
-  if (!MODI_INITIALIZED(theFile->check_mask))
+  if (!MODI_INITIALIZED(theFile->check_flags))
     {
       tmp2 = sh_util_safe_name (theFile->fullpath);
@@ -3823,4 +3835,5 @@
       SH_MUTEX_UNLOCK(mutex_thread_nolog);
       SH_FREE(tmp2);
+      SL_RETURN((-1),_("sh_unix_getinfo"));
     }
 
@@ -3989,5 +4002,5 @@
       if (fileHash != NULL)
 	{
-	  if ((theFile->check_mask & MODI_CHK) == 0 ||
+	  if ((theFile->check_flags & MODI_CHK) == 0 ||
 	      sh_restrict_this(theFile->fullpath, (UINT64) fbuf.st_size, 
 			       (UINT64) fbuf.st_mode, rval_open))
@@ -3995,10 +4008,10 @@
 	      sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
 	    }
-	  else if ((theFile->check_mask & MODI_PREL) != 0 &&
+	  else if ((theFile->check_flags & MODI_PREL) != 0 &&
 		   S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size, 
 					      alert_timeout, theFile->fullpath))
 	    {
 	      if (0 != sh_prelink_run (theFile->fullpath, 
-				       fileHash, alert_timeout))
+				       fileHash, alert_timeout, theFile->check_flags))
 		sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
 	    }
@@ -4008,9 +4021,10 @@
 	      UINT64 length_current = TIGER_NOLIM;
 
-	      if (MODI_TXT_ENABLED(theFile->check_mask) && fbuf.st_size < (10 * SH_TXT_MAX))
+	      if (MODI_TXT_ENABLED(theFile->check_flags) && fbuf.st_size < (10 * SH_TXT_MAX))
 		{
 		  sl_init_content (rval_open, fbuf.st_size);
 		}
 
+	      if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(theFile->check_flags);
 	      sl_strlcpy(fileHash,
 			 sh_tiger_generic_hash (theFile->fullpath, 
@@ -4023,5 +4037,5 @@
 	      content = sh_string_copy(content);
 
-	      if ((theFile->check_mask & MODI_SGROW) != 0)
+	      if ((theFile->check_flags & MODI_SGROW) != 0)
 		{
 		  /* Update size so it matches the one for which the checksum
@@ -4032,5 +4046,5 @@
 		  sh_unix_checksum_size (theFile->fullpath, length_current, S_TRUE,
 					 &fileHash[KEY_LEN + 1], 
-					 alert_timeout, rval_open);
+					 alert_timeout, rval_open, theFile->check_flags);
 		}
 	    }
@@ -4046,5 +4060,5 @@
       if (fileHash != NULL)
 	{
-	  if ((theFile->check_mask & MODI_CHK) == 0 ||
+	  if ((theFile->check_flags & MODI_CHK) == 0 ||
 	      sh_restrict_this(theFile->fullpath, (UINT64) fbuf.st_size, 
 			       (UINT64) fbuf.st_mode, rval_open))
@@ -4057,5 +4071,5 @@
 	    {
 	      if (0 != sh_prelink_run (theFile->fullpath, 
-				       fileHash, alert_timeout))
+				       fileHash, alert_timeout, theFile->check_flags))
 		sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
 	    }
@@ -4065,9 +4079,10 @@
 	      UINT64 length_current = TIGER_NOLIM;
 
-	      if (MODI_TXT_ENABLED(theFile->check_mask) && fbuf.st_size < (10 * SH_TXT_MAX))
+	      if (MODI_TXT_ENABLED(theFile->check_flags) && fbuf.st_size < (10 * SH_TXT_MAX))
 		{
 		  sl_init_content (rval_open, fbuf.st_size);
 		}
 
+	      if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(theFile->check_flags);
 	      sl_strlcpy(fileHash, 
 			 sh_tiger_generic_hash (theFile->fullpath, rval_open, 
@@ -4080,5 +4095,5 @@
 	      content = sh_string_copy(content);
 
-	      if ((theFile->check_mask & MODI_SGROW) != 0) 
+	      if ((theFile->check_flags & MODI_SGROW) != 0) 
 		{
 		  /* Update size so it matches the one for which the checksum
@@ -4089,5 +4104,5 @@
 		  sh_unix_checksum_size (theFile->fullpath, length_current, S_TRUE,
 					 &fileHash[KEY_LEN + 1], 
-					 alert_timeout, rval_open);
+					 alert_timeout, rval_open, theFile->check_flags);
 		}
 	    }
@@ -4105,5 +4120,5 @@
 	sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
 
-      if ((theFile->check_mask & MODI_CHK) != 0)
+      if ((theFile->check_flags & MODI_CHK) != 0)
 	{
 	  tmp2 = sh_util_safe_name (theFile->fullpath);
@@ -4276,5 +4291,5 @@
   /* --- Output the file. ---
    */
-  if (flag_err_debug == SL_TRUE)
+  if (flag_err_debug == S_TRUE)
     {
       tmp2 = sh_util_safe_name ((filename == NULL) ? 
@@ -5294,5 +5309,5 @@
 int sh_unix_count_mlock()
 {
-  int i = 0;
+  unsigned int i = 0;
   char str[32][64];
   sh_page_l * page_list;
@@ -5325,8 +5340,8 @@
 #ifdef WITH_TPT
   {
-    int j = 0;
+    unsigned int j = 0;
     while (j < i && j < 32)
       {
-	sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, j, MSG_E_SUBGEN,
+	sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, j, MSG_E_SUBGEN,
 			str[j], _("sh_unix_count_mlock"));
 	++j;
@@ -5336,5 +5351,5 @@
 
   sl_snprintf(str[0], 64, _("%d pages locked"), i);
-  sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, i, MSG_E_SUBGEN,
+  sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, i, MSG_E_SUBGEN,
 		  str[0], _("sh_unix_count_mlock"));
   SL_RETURN((i), _("sh_unix_count_mlock"));
@@ -5515,5 +5530,5 @@
       this_line  = 0;
       c          = '\0';
-      while (c != '\n' && num > 0 && this_line < (sizeof(theline)-1))
+      while (c != '\n' && this_line < (sizeof(theline)-1))
 	{
 	  do {
Index: trunk/src/sh_utils.c
===================================================================
--- trunk/src/sh_utils.c	(revision 476)
+++ trunk/src/sh_utils.c	(revision 481)
@@ -309,9 +309,9 @@
 	  }
 	}
-	out[rem] = ','; ++rem;
-	while (p[1] == '\n') ++p; /* scan over consecutive newlines */
+	out[rem] = ','; ++rem;    /* <-- ensures (rem > 0) is true    */ 
+	while (p[1] == '\n') ++p; /* scan over consecutive newlines   */
 	state = 0;
 	if (p[1] == '\0') {
-	  if (rem > 0) out[rem-1] = '\0';
+	  out[rem-1] = '\0';      /* rem > 0 because of 4 lines above */
 	  break;
 	}
@@ -782,27 +782,18 @@
   char hashbuf[KEYBUF_SIZE];
 
-
+  int         result;
   size_t      i;
 
   SL_ENTER(_("sh_util_hmac_tiger"));
-  ASSERT((KEY_BLOCK <= (KEY_LEN/2)), _("KEY_BLOCK <= (KEY_LEN/2)"))
-
-  if (KEY_BLOCK > (KEY_LEN/2))
-    {
-      (void) sh_tiger_hash (NULL, TIGER_DATA, 0, hashbuf, sizeof(hashbuf));
-      sl_strlcpy(res, hashbuf, len);
-      SL_RETURN(res, _("sh_util_hmac_tiger"));
-    }
+
+  ASSERT((KEY_BLOCK <= (KEY_LEN/2)), _("KEY_BLOCK <= (KEY_LEN/2)"));
 
   memcpy (K, zap, KEY_BLOCK);
 
-  if (sh_util_hextobinary (K, hexkey, KEY_LEN) < 0)
-    {
-      (void) sh_tiger_hash (NULL, TIGER_DATA, 0, hashbuf, sizeof(hashbuf));
-      sl_strlcpy(res, hashbuf, len);
-      SL_RETURN(res, _("sh_util_hmac_tiger"));
-    }
-
-  if (sl_ok_adds(textlen, KEY_BLOCK))
+  result = sh_util_hextobinary (K, hexkey, KEY_LEN);
+
+  ASSERT((result >= 0), _("result >= 0"));
+
+  if ((result >= 0) && sl_ok_adds(textlen, KEY_BLOCK))
     {
       inner = (char *) SH_ALLOC (textlen + KEY_BLOCK); 
@@ -830,23 +821,15 @@
   /* now compute the hash 
    */
-  h1 = sh_tiger_hash_uint32 ( outer,
-			      TIGER_DATA,
-			      KEY_BLOCK,
+  h1 = sh_tiger_hash_uint32 ( outer, TIGER_DATA, KEY_BLOCK,
 			      kbuf, KEY_BYT/sizeof(UINT32));
   for (i = 0; i < (KEY_LEN/8); ++i)
-    {
-      /* cc[i] = h1[i]; */
-      copy_four ( (unsigned char *) &(cc[i]), h1[i]);
-    }
-
-  h2 = sh_tiger_hash_uint32 ( inner,
-			      TIGER_DATA,
+    copy_four ( (unsigned char *) &(cc[i]), h1[i]);
+
+  h2 = sh_tiger_hash_uint32 ( inner, TIGER_DATA,
 			      (unsigned long) KEY_BLOCK+textlen,
 			      kbuf, KEY_BYT/sizeof(UINT32));
   for (i = KEY_LEN/8; i < (KEY_LEN/4); ++i)
-    {
-      copy_four ( (unsigned char *) &(cc[i]), h2[i - (KEY_LEN/8)]);
-      /* cc[i] = h2[i - (KEY_LEN/8)]; */
-    }
+    copy_four ( (unsigned char *) &(cc[i]), h2[i - (KEY_LEN/8)]);
+
   SH_FREE(inner);
   
@@ -1033,5 +1016,5 @@
 
 
-/* interval [0, 4294967296]
+/* interval [0, 4294967295]
  */
 static UINT32 taus_get_long (void *vstate)
@@ -1160,5 +1143,6 @@
   char                 bufx[9 * sizeof(UINT32) + 1];
   int                  status;
-  static unsigned long seed_time = 0;
+  static unsigned long seed_time    = 0;
+  static unsigned long seed_counter = 3000;
   unsigned long        gtime;
 
@@ -1167,9 +1151,13 @@
   if (skey->rngI == GOOD)
     {
-      if ( (sh_unix_longtime () - seed_time) < 7200)
+      ++seed_counter;
+
+      if ( ((sh_unix_longtime () - seed_time) < 1800) &&
+	   ( seed_counter                     < 3000))
 	SL_RETURN( (0), _("taus_seed"));
     }
   
-  seed_time = sh_unix_longtime ();
+  seed_time    = sh_unix_longtime ();
+  seed_counter = 0;
 
   status = sh_entropy (24, bufx);
@@ -1834,5 +1822,5 @@
 int sh_util_obscurename (ShErrLevel level, const char * name_orig, int flag)
 {
-  const unsigned char * name = (unsigned char *) name_orig;
+  const unsigned char * name = (const unsigned char *) name_orig;
   char * safe;
   unsigned int i;
@@ -2308,5 +2296,5 @@
   unsigned char b;
   size_t lout = 0;
-  int    w = 0;
+  unsigned int  w = 0;
 
   if (out && in)
Index: trunk/src/sh_utmp.c
===================================================================
--- trunk/src/sh_utmp.c	(revision 476)
+++ trunk/src/sh_utmp.c	(revision 481)
@@ -848,6 +848,6 @@
  * by longjmp' warning. And no, 'volatile' proved insufficient.
  */
-static void * sh_dummy_userold = NULL;
-static void * sh_dummy_user    = NULL;
+void * sh_dummy_850_userold = NULL;
+void * sh_dummy_851_user    = NULL;
 
 
@@ -883,6 +883,6 @@
    * Avoids the 'clobbered by longjmp' warning. 
    */
-  sh_dummy_userold = (void*) &userold;
-  sh_dummy_user    = (void*) &user;
+  sh_dummy_850_userold = (void*) &userold;
+  sh_dummy_851_user    = (void*) &user;
 
   /* ------- find user -------- 
@@ -1133,6 +1133,6 @@
 
  out:
-  sh_dummy_user    = NULL;
-  sh_dummy_userold = NULL;
+  sh_dummy_851_user    = NULL;
+  sh_dummy_850_userold = NULL;
 
   SL_RET0(_("sh_utmp_addlogin"));
Index: trunk/src/sh_xfer_client.c
===================================================================
--- trunk/src/sh_xfer_client.c	(revision 481)
+++ trunk/src/sh_xfer_client.c	(revision 481)
@@ -0,0 +1,1628 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 1999, 2000, 2015 Rainer Wichmann                          */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/* Must be early on FreeBSD
+ */
+#include <sys/types.h>
+
+/* must be .le. than (1020 * 64)
+ * (see sh_tools.c -- put_header)
+ *
+ * also: must be  (N * 16), otherwise
+ * binary files cannot be transferred encrypted
+ *
+ * 65280 = (1020*64)
+ * #define TRANS_BYTES 8000  V0.8
+ */
+#ifdef  SH_ENCRYPT
+#define TRANS_BYTES 65120
+#else
+#define TRANS_BYTES 65280
+#endif
+
+/* timeout for session key
+ */
+#define TIMEOUT_KEY 7200
+
+/* max time between connection attempts
+ */
+#define TIMEOUT_CON 2048 
+
+/* #undef  SRP_DEBUG */
+/* #define SRP_DEBUG */
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef  HAVE_UNISTD_H
+#include <errno.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#endif
+
+#ifndef FD_SET
+#define NFDBITS         32
+#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#endif /* !FD_SET */
+#ifndef FD_SETSIZE
+#define FD_SETSIZE      32
+#endif
+#ifndef FD_ZERO
+#define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p)))
+#endif
+
+#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
+#include <sys/mman.h>
+#endif
+
+
+#include <netdb.h> 
+#include <sys/types.h> 
+#include <netinet/in.h> 
+#include <sys/socket.h> 
+#ifndef S_SPLINT_S
+#include <arpa/inet.h>
+#endif
+
+#include "sh_ipvx.h"
+#include "samhain.h"
+#include "sh_tiger.h"
+#include "sh_utils.h"
+#include "sh_unix.h"
+#include "sh_xfer.h"
+#include "sh_srp.h"
+#include "sh_fifo.h"
+#include "sh_tools.h"
+#include "sh_entropy.h"
+#include "sh_html.h"
+#include "sh_nmail.h"
+#include "sh_socket.h"
+#define SH_NEED_GETHOSTBYXXX
+#include "sh_static.h"
+
+#ifdef SH_ENCRYPT
+#include "rijndael-api-fst.h"
+char * sh_tools_makePack (unsigned char * header, int flag,
+			  char * payload, unsigned long payload_size,
+			  keyInstance * keyInstE);
+char * sh_tools_revertPack (unsigned char * header, int flag, char * message,
+			    keyInstance * keyInstE, 
+			    unsigned long message_size);
+#endif
+
+/* define this if you want to debug the client/server communication */
+/* #define SH_DBG_PROT 1 */
+
+#ifdef  SH_DBG_PROT
+#define SH_SHOWPROT(c,d) sh_tools_show_header((c), (d))
+#else
+#define SH_SHOWPROT(c,d) 
+#endif
+
+/* the port client will be connecting to 
+ */
+#ifndef SH_DEFAULT_PORT
+#define SH_DEFAULT_PORT 49777    
+#endif
+
+#ifndef SH_SELECT_REPEAT
+#define SH_SELECT_REPEAT 60
+#endif
+
+#ifndef SH_HEADER_SIZE
+#define SH_HEADER_SIZE 7
+#endif
+
+#ifndef SH_CHALLENGE_SIZE
+#define SH_CHALLENGE_SIZE 9
+#endif
+
+#undef  FIL__
+#define FIL__  _("sh_xfer_client.c")
+
+extern int flag_err_debug;
+extern int flag_err_info;
+
+#ifndef SH_STANDALONE
+
+#if defined(WITH_TRACE) || defined(WITH_TPT) 
+char * hu_trans(const char * ihu)
+{
+  static char ohu[17];
+  sprintf(ohu, _("%c%03o"), '\\',                   /* known to fit  */
+	  (unsigned char) ihu[0]);
+  sprintf(&(ohu[4]), _("%c%03o"), '\\',             /* known to fit  */
+	  (unsigned char) ihu[1]);
+  sprintf(&(ohu[8]), _("%c%03o"), '\\',             /* known to fit  */
+	  (unsigned char) ihu[2]);
+  sprintf(&(ohu[12]), _("%c%03o"), '\\',            /* known to fit  */
+	  (unsigned char) ihu[3]);
+  ohu[16] = '\0';
+  return ohu;
+}
+#endif
+/* #ifndef SH_STANDALONE */
+#endif
+
+#if !defined(USE_SRP_PROTOCOL)
+void sh_passwd (char * salt, char * password, char * nounce, char *hash)
+{
+
+  char           *combi;
+  size_t          len;
+  unsigned char * tmp = NULL;
+  char hashbuf[KEYBUF_SIZE];
+
+  if (password == NULL)
+    {
+      tmp = (unsigned char *) &(skey->pw[0]);
+      memcpy(skey->vernam, tmp, PW_LEN);
+      sl_strlcpy (skey->vernam,
+		  sh_tiger_hash(skey->vernam, TIGER_DATA, PW_LEN,
+				hashbuf, sizeof(hashbuf)), 
+		  KEY_LEN+1);
+    }
+  else if (sl_strlen(password) < PW_LEN)
+    {
+      fprintf(stderr, _("Password has less than %d chars !\n"),
+		   PW_LEN);
+      _exit(EXIT_FAILURE);
+    }
+  else
+    {
+      sl_strlcpy (skey->vernam, password, KEY_LEN+1);
+    }
+
+  len = sl_strlen(salt) + 1;
+  if (sl_ok_adds(len, sl_strlen(skey->vernam)))
+    len += sl_strlen(skey->vernam);
+  if (nounce != NULL && sl_ok_adds(len, sl_strlen(nounce))) 
+    len += sl_strlen(nounce);
+  
+  /* H(s,P)
+   */
+  combi = SH_ALLOC(len);
+  (void) sl_strlcpy (combi, salt, len);
+  (void) sl_strlcat (combi, skey->vernam, len);
+  if (nounce != NULL)
+    (void) sl_strlcat (combi, nounce, len);
+  (void) sl_strlcpy (hash, 
+		     sh_tiger_hash(combi, TIGER_DATA, 
+				   (unsigned long) sl_strlen(combi),
+				   hashbuf, sizeof(hashbuf)),
+		     KEY_LEN+1);
+  SH_FREE (combi);
+  hash[KEY_LEN] = '\0';
+  return;
+}
+#endif
+
+#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
+
+/* Server addresses in use
+ */
+static int count_dev_server = 0;
+
+void reset_count_dev_server(void)
+{
+  count_dev_server = 0;
+  return;
+}
+
+int sh_xfer_set_logserver (const char * address)
+{
+  SL_ENTER(_("sh_xfer_set_logserver"));
+
+  if (address != NULL && count_dev_server < 2 
+      && sl_strlen(address) < SH_PATHBUF && sl_strlen(address) > 0) 
+    {
+      if (count_dev_server == 0)
+	(void) sl_strlcpy (sh.srvexport.name, address, SH_PATHBUF);
+      else
+	(void) sl_strlcpy (sh.srvexport.alt,  address, SH_PATHBUF);
+
+      ++count_dev_server;
+      SL_RETURN (0, _("sh_xfer_set_logserver"));
+    }
+  SL_RETURN (-1, _("sh_xfer_set_logserver"));
+}
+
+static
+int xfer_send_intern (int mysocket, const int protocol, char * micro, 
+		      char * msgbuf, unsigned long length, int docrypt)
+{
+  unsigned long           numbytes, countbytes;
+  int                     flag_err = 0;
+  unsigned char           head[SH_HEADER_SIZE];
+  char                  * outbuf;
+#ifdef SH_ENCRYPT
+  char                  * msg2buf = NULL;
+#else
+  (void) docrypt;
+#endif
+
+  SL_ENTER(_("xfer_send_intern"));
+
+#ifdef SH_ENCRYPT
+  if  ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0))
+    {
+      put_header (head, protocol, &length, micro);
+      msg2buf  = sh_tools_makePack (head, 0, msgbuf, length, 
+				    &(skey->keyInstE));
+      length   = (unsigned long) (256 * (unsigned int)head[1] + 
+				  (unsigned int)head[2]);
+      outbuf   = msg2buf;
+    }
+  else
+    {
+      outbuf = msgbuf;
+      put_header (head, protocol, &length, micro);
+    }
+#else
+  outbuf = msgbuf;
+  put_header (head, protocol, &length, micro);
+#endif
+
+  SH_SHOWPROT(head,'>');
+  
+  numbytes     = SH_HEADER_SIZE;
+  countbytes   = write_port (mysocket, (char *)head, numbytes, &flag_err, 300);
+
+  if (countbytes == numbytes && outbuf != NULL)
+    {
+      numbytes     = length;
+      countbytes   = write_port (mysocket, outbuf, numbytes, &flag_err, 300);
+    }
+
+#ifdef SH_ENCRYPT
+  if (msg2buf != NULL)
+    SH_FREE(msg2buf);
+#endif
+
+  if (countbytes == numbytes)
+    SL_RETURN( 0, _("xfer_send_intern"));
+  else
+    SL_RETURN( flag_err, _("xfer_send_intern"));
+}
+
+static
+int xfer_send (int mysocket, const int protocol, char * micro, 
+		     char * msgbuf, unsigned long length)
+{
+  int i;
+  SL_ENTER(_("xfer_send"));
+  TPT(( 0, FIL__, __LINE__, _("msg=<Send.>\n")));
+  i =  xfer_send_intern (mysocket, protocol, micro, 
+			       msgbuf, length, S_FALSE);
+  SL_RETURN(i, _("xfer_send"));
+}
+static
+int xfer_send_crypt (int mysocket, const int protocol, char * micro, 
+			   char * msgbuf, unsigned long length)
+{
+  int i;
+  SL_ENTER(_("xfer_send_crypt"));
+#ifdef SH_ENCRYPT
+  TPT(( 0, FIL__, __LINE__, _("msg=<Send encrypted.>\n")));
+#else
+  TPT(( 0, FIL__, __LINE__, _("msg=<Send.>\n")));
+#endif
+  i = xfer_send_intern (mysocket, protocol, micro, 
+			      msgbuf, length, S_TRUE);
+  SL_RETURN(i, _("xfer_send_crypt"));
+}
+
+
+/* receive answer, add a trailing NULL to terminate string
+ * decrypt answer
+ */
+static
+long xfer_receive_intern (int mysocket, const int protocol, char * micro,     
+			  char *  msgbuf, unsigned long length, 
+			  int docrypt)
+{
+  unsigned long numbytes, countbytes;
+  int           flag_err = -1;
+  unsigned char head[SH_HEADER_SIZE];
+#ifndef SH_ENCRYPT
+  (void) docrypt;
+#endif
+
+  SL_ENTER(_("xfer_receive_intern"));
+
+#ifdef SH_ENCRYPT
+  /* make sure length is not multiple of B_SIZ, see below 
+   */
+  ASSERT_RET((length % B_SIZ != 0), _("length % 16 != 0"), flag_err);
+#endif
+
+  if (micro != NULL)
+    micro[4]     = '\0';
+  if (msgbuf != NULL)
+    msgbuf[0]     = '\0';
+
+  numbytes     = SH_HEADER_SIZE;
+  countbytes   = read_port (mysocket, (char *)head, numbytes, &flag_err, 300);
+
+  if (countbytes != numbytes)
+    {
+      TPT(( 0, FIL__, __LINE__, _("msg=<countbytes != numbytes>\n")));
+      SL_RETURN(flag_err, _("xfer_receive_intern"));
+    }
+  else if (msgbuf == NULL)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+		      _("msgbuf is NULL"), _("xfer_receive_intern"));
+      SL_RETURN((-1), _("xfer_receive_intern"));
+    }
+  else if (head[0] != protocol && (head[0] & SH_PROTO_SRP) == 0)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISMATCH);
+      SL_RETURN((-1), _("xfer_receive_intern"));
+    }
+  else
+    {
+      get_header (head, &numbytes, micro);
+      SH_SHOWPROT(head, '<');
+
+      if (numbytes > 0)
+	{
+	  numbytes = (numbytes > length ? length : numbytes);
+
+	  countbytes = read_port (mysocket, msgbuf, numbytes, &flag_err, 300);
+
+	  if (countbytes < length)
+	    msgbuf[countbytes] = '\0';
+	  else
+	    msgbuf[length-1] = '\0';
+
+	  if (flag_err != 0)
+	    {
+	      TPT(( 0, FIL__, __LINE__, _("msg=<read error>\n")));
+	      SL_RETURN((-1), _("xfer_receive_intern"));
+	    }
+	}
+    }
+
+#ifdef SH_ENCRYPT
+  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0))
+    {
+      unsigned long head_length;
+      char * tmp = SH_ALLOC((size_t)length);
+
+      memcpy(tmp, msgbuf, (size_t)length);
+      tmp = sh_tools_revertPack (head, 0, tmp, &(skey->keyInstD), countbytes);
+
+      head_length = (unsigned long) (256 * (unsigned int)head[1] + 
+				     (unsigned int)head[2]);
+
+      /* 
+       * revertPack returns header with length <= (original_length-16), so
+       * the following msgbuf[length] = '\0' is always safe.
+       * Nevertheless, check for proper length.
+       */
+      if (head_length <= (length-1))
+	length      = head_length;
+      else
+	--length;
+
+      memcpy(msgbuf, tmp, (size_t)length);
+      msgbuf[length] = '\0';
+      SH_FREE(tmp);
+      if (countbytes == numbytes) 
+	countbytes = length; /* to avoid error on return, see below */
+      numbytes = length;
+    }
+#endif
+
+  if (countbytes == numbytes)
+    SL_RETURN(((long)numbytes), _("xfer_receive_intern"));
+  else
+    {
+      TPT(( 0, FIL__, __LINE__, _("msg=<short read>\n")));
+      SL_RETURN(flag_err, _("xfer_receive_intern"));
+    }
+}
+
+static
+long xfer_receive (int mysocket, const int protocol, char * micro,     
+		   char * msgbuf, unsigned long length)
+{
+  long i;
+  SL_ENTER(_("xfer_receive"));
+  TPT(( 0, FIL__, __LINE__, _("msg=<Receive.>\n")));
+  i = xfer_receive_intern (mysocket, protocol, micro, 
+			   msgbuf, length, S_FALSE);
+  SL_RETURN(i, _("xfer_receive"));
+}
+
+static
+long xfer_receive_crypt (int mysocket, const int protocol, char * micro,     
+			 char * msgbuf, unsigned long length)
+{
+  long i;
+  SL_ENTER(_("xfer_receive_crypt"));
+#ifdef SH_ENCRYPT
+  TPT(( 0, FIL__, __LINE__, _("msg=<Receive encrypted.>\n")));
+#else
+  TPT(( 0, FIL__, __LINE__, _("msg=<Receive.>\n")));
+#endif
+  i = xfer_receive_intern (mysocket, protocol, micro, 
+			   msgbuf, length, S_TRUE);
+  SL_RETURN(i, _("xfer_receive_crypt"));
+}
+
+/**************************************************
+ *
+ *
+ *  C L I E N T  
+ *
+ *
+ ***************************************************/
+
+
+#include <time.h>
+
+static SH_FIFO * fifo = NULL;
+
+static long xfer_try_report (char * errmsg);
+
+unsigned int ServerPort = SH_DEFAULT_PORT;
+
+int sh_xfer_server_port (const char * str)
+{
+  unsigned long l;
+  char * endptr;
+
+  SL_ENTER(_("sh_xfer_server_port"));
+
+  l = strtoul (str, &endptr, 0);
+  if (l > 65535 || endptr == str)
+    {
+      SL_RETURN (-1, _("sh_xfer_server_port"));
+    }
+  ServerPort = (unsigned int) l;
+  SL_RETURN (0, _("sh_xfer_server_port"));
+}
+
+long sh_xfer_report (char * errmsg)
+{
+  static int have_server = S_TRUE;
+  long   status;
+  char * popmsg;
+  static int nofail = S_TRUE;
+
+  SL_ENTER(_("sh_xfer_report"));
+
+  /* --- No log server available. ---
+   */
+  if (have_server == S_TRUE && sh.srvexport.name[0] == '\0')
+    {
+      have_server = S_FALSE;
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NONAME);
+      SL_RETURN (-1, _("sh_xfer_report"));
+    }
+  else if (have_server == BAD)
+    {
+      SL_RETURN (-1, _("sh_xfer_report"));
+    }
+
+  /* --- Allocate fifo. ---
+   */
+  if (fifo == NULL)
+    {
+      fifo = SH_ALLOC(sizeof(SH_FIFO));
+      fifo_init(fifo);
+    }
+
+  /* --- Check for messages on the queue, and send them first. ---
+   */
+  while (NULL != (popmsg = pop_list(fifo)) )
+    {
+      status = xfer_try_report (popmsg);
+      if (status != 0)
+	{
+	  (void) push_tail_list (fifo, popmsg, 0, NULL); 
+	  SH_FREE(popmsg);
+	  if (SH_FIFO_MAX == push_list (fifo, errmsg, 0,NULL))
+	    SL_RETURN (-2, _("sh_xfer_report"));
+	  SL_RETURN (-1, _("sh_xfer_report"));
+	}
+      SH_FREE(popmsg);
+    }
+
+  /* --- Now send the error message. ---
+   */ 
+  status = xfer_try_report (errmsg);
+  if (status != 0)
+    {
+      if (nofail == S_TRUE)
+	sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL,
+			 _("log server"), sh.srvexport.name);
+      nofail = S_FALSE;
+      if (SH_FIFO_MAX == push_list (fifo, errmsg, 0, NULL))
+	SL_RETURN (-2, _("sh_xfer_report"));
+      SL_RETURN (-1, _("sh_xfer_report"));
+    }
+
+  nofail = S_TRUE;
+  SL_RETURN (0, _("sh_xfer_report"));  
+}
+
+static long xfer_try_report_int (char * errmsg, const int what);
+
+static long xfer_try_report (char * errmsg)
+{
+  long i;
+  SL_ENTER(_("xfer_try_report"));
+  i = xfer_try_report_int (errmsg, SH_PROTO_MSG);
+  SL_RETURN(i, _("xfer_try_report")); 
+}
+
+long sh_xfer_request_file (const char * file)
+{
+  long i;
+  char tmp_file[64];
+  SL_ENTER(_("sh_xfer_request_file"));
+  sl_strlcpy(tmp_file, file, sizeof(tmp_file));
+  i = xfer_try_report_int (tmp_file, SH_PROTO_BIG);
+  SL_RETURN(i, _("sh_xfer_request_file")); 
+}
+
+static unsigned long sh_throttle_delay = 0;
+
+int sh_xfer_set_throttle_delay (const char * c)
+{
+  long val;
+
+  SL_ENTER(_("sh_xfer_set_throttle_delay"));
+  val = strtol (c, (char **)NULL, 10);
+  if (val < 0)
+    SL_RETURN( (-1), _("sh_xfer_set_throttle_delay"));
+
+  val = (val > 1000) ? 1000 : val;
+
+  sh_throttle_delay = (unsigned long) val;
+  SL_RETURN( (0), _("sh_xfer_set_throttle_delay"));
+}
+
+static time_t xfer_timeout_val =  1;
+
+static int xfer_conn_state(int initialized, int conn_state)
+{
+  static time_t time_now  = 1200;
+  static time_t time_last =    0;
+
+  if (initialized == S_FALSE || conn_state == S_FALSE)
+    {
+      xfer_timeout_val = 
+	((xfer_timeout_val > TIMEOUT_CON) ? TIMEOUT_CON : xfer_timeout_val);
+
+      /* --- Retry bad attempt only after some time. ---
+       */
+      time_now  = time (NULL);
+      if ((time_now - time_last) < xfer_timeout_val) 
+	{
+	  TPT(( 0, FIL__, __LINE__, _("msg=<Within deadtime, no retry.>\n")));
+	  return -1;
+	}
+      TPT(( 0, FIL__, __LINE__, _("msg=<Retry.>\n")));
+    }
+  time_last  = time (NULL);
+  return 0;
+}
+
+static int xfer_connect(int * conn_state)
+{
+  char         error_msg[256];
+  char         error_call[SH_MINIBUF] = { 0 };
+  int          error_num = 0;
+
+  int sockfd = connect_port_2 (sh.srvexport.name, sh.srvexport.alt, ServerPort, 
+			       error_call, &error_num, error_msg, 256);
+
+  if (sockfd < 3)
+    {
+      *conn_state = S_FALSE;
+      xfer_timeout_val *= 2;
+      sh_error_handle ((-1), FIL__, __LINE__, error_num, 
+		       MSG_E_NET, error_msg, error_call,
+		       _("export"), sh.srvexport.name);
+      return -1;
+    }
+
+  *conn_state = S_TRUE;
+  return sockfd;
+}
+
+int xfer_greet_server(int sockfd, char * answer)
+{
+  int    flag_err;
+  char   head_u[5];
+  int    theProto = SH_PROTO_SRP;
+  
+  TPT(( 0, FIL__, __LINE__, _("msg=<c/r: entry>\n")));
+  
+  sl_strlcpy (answer, sh.host.name, 512);
+      
+  flag_err = xfer_send (sockfd, theProto, _("SALT"), 
+			answer,  (unsigned long)sl_strlen(answer));
+      
+  TPT(( 0, FIL__, __LINE__, _("msg=<c/r: sent SALT, flag_err = %d>\n"), 
+	flag_err));
+      
+  /* get nonce from server
+   */
+  if (flag_err == 0)
+    {
+      flag_err = xfer_receive (sockfd, (char)theProto, head_u, 
+				   answer,  511);
+      flag_err = (flag_err < 0) ? flag_err : 0;
+      TPT(( 0, FIL__, __LINE__, 
+	    _("msg=<c/r: rcvt nonce, flag_err = %d>\n"), 
+	    flag_err));
+    }
+  
+  if ( 0 != check_request (head_u, _("INIT")) )
+    {
+      TPT(( 0, FIL__, __LINE__, _("msg=<srp: u = %03o-%03o-%03o-%03o>\n"), head_u[0], head_u[1], head_u[2], head_u[3]));
+      flag_err = -1;
+    }
+  return flag_err;
+}
+  
+
+#if !defined(USE_SRP_PROTOCOL)
+
+static int xfer_auth(int is_reinit, int * initialized, 
+		     int sockfd, char * answer)
+{
+  /**************************************************
+   *
+   * --- challenge/response authentication ---
+   *
+   **************************************************/
+
+  int                  flag_err = 0;
+  int                  theProto = 0;
+  char   nounce[KEY_LEN+1];
+  char   temp[2*KEY_LEN+1];
+  char   nonce_u[KEY_LEN+1];
+  UINT32 ticks;
+
+  char   head_u[5];
+  char   foo_M1[KEY_LEN+1];
+  char   hashbuf[KEYBUF_SIZE];
+#ifdef SH_ENCRYPT
+  int err_num;
+  char expbuf[SH_ERRBUF_SIZE];
+#endif
+
+  SL_REQUIRE((sockfd > 2), _("sockfd > 2"));
+
+  if (is_reinit == S_FALSE)
+    flag_err = xfer_greet_server(sockfd, answer);
+  else
+    sh_tools_probe_reset();
+
+  /* entry point for jump from message forward if session key must
+   * be re-initialized
+   */	 
+
+  if ( flag_err == 0 && sl_strlen(answer) >  KEY_LEN )
+    (void) sl_strlcpy(nounce, &answer[KEY_LEN], KEY_LEN+1);
+  else
+    flag_err = (-1);
+  
+  TPT(( 0, FIL__, __LINE__, _("msg=<c/r: rcvt INIT, flag_err = %d>\n"), 
+	flag_err));
+  
+  /* verify random nonce v from server H(v, P)v
+   */
+  sh_passwd (nounce, NULL, NULL, temp);
+  if ( 0 != sl_strncmp(temp, answer, KEY_LEN))
+    flag_err = (-1);
+  
+  TPT(( 0, FIL__, __LINE__, _("msg=<c/r: vrfy nonce, flag_err = %d>\n"), 
+	flag_err));
+  
+  
+  /* --- Create own nonce. ---
+   */
+  ticks = (UINT32) taus_get ();
+  
+  (void) sl_strlcpy(nonce_u, 
+		    sh_tiger_hash((char *) &ticks, 
+				  TIGER_DATA, 
+				  (unsigned long)sizeof(UINT32), 
+				  hashbuf, sizeof(hashbuf)),
+		    KEY_LEN+1);
+  
+  /* --- Form the message H(H(u,v),P)u ---
+   */
+  (void) sl_strlcpy(temp, nonce_u, 2*KEY_LEN+1); 
+  (void) sl_strlcat(temp,  nounce, 2*KEY_LEN+1); 
+  (void) sl_strlcpy(temp, 
+		    sh_tiger_hash(temp, 
+				  TIGER_DATA, 
+				  (unsigned long)sl_strlen(temp), 
+				  hashbuf, sizeof(hashbuf)),
+		    KEY_LEN+1);
+  sh_passwd (temp, NULL, NULL, foo_M1);
+  (void) sl_strlcpy(temp, foo_M1, 2*KEY_LEN+1);
+  (void) sl_strlcat(temp, nonce_u, 2*KEY_LEN+1);
+  
+  /* --- Send it to server. ---
+   */
+  if (flag_err == 0)
+    {
+      flag_err = xfer_send (sockfd, 
+			    (theProto|SH_PROTO_SRP), 
+			    _("PASS"), temp, 
+			    (unsigned long)sl_strlen(temp));
+      TPT(( 0, FIL__, __LINE__, _("msg=<c/r: sent PASS, flag_err = %d>\n"),
+	    flag_err));
+    }
+  
+  if (flag_err == 0)
+    {
+      flag_err = xfer_receive (sockfd,
+			       (theProto|SH_PROTO_SRP), 
+			       head_u, answer,  511);  
+      sh_passwd (nounce, NULL, nonce_u, foo_M1);
+      (void) sl_strlcpy (skey->session, foo_M1, KEY_LEN+1);
+#ifdef SH_ENCRYPT
+      err_num = rijndael_makeKey(&(skey->keyInstE), 
+				 (BYTE)DIR_ENCRYPT, 192, skey->session);
+      if (err_num < 0)
+	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			errorExplain(err_num, expbuf, sizeof(expbuf)), 
+			_("xfer_try_report_int: makeKey"));
+      
+      err_num = rijndael_makeKey(&(skey->keyInstD), 
+				 (BYTE)DIR_DECRYPT, 192, skey->session);
+      if (err_num < 0)
+	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			errorExplain(err_num, expbuf, sizeof(expbuf)), 
+			_("xfer_try_report_int: make_key"));
+#endif
+      *initialized = S_TRUE;
+    }
+  
+  if (*initialized == S_FALSE)
+    {
+      xfer_timeout_val *= 2;
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH);
+      memset(answer, 0, 512);
+      MUNLOCK(answer, 512);
+      SH_FREE(answer);
+      return -1;
+    }
+  else
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AUTH);
+    }
+  return 0;
+}    
+#else
+
+static void noise()
+{
+  UINT32 n = taus_get();
+  retry_msleep(0, (n & 0x0000007F));
+  return;
+}
+  
+
+static int xfer_auth(int is_reinit, int * initialized, 
+		     int sockfd, char * answer)
+{
+  /* This is the SRP authenticated key exchange protocol.
+   * Produces a session key skey->session.
+   */
+  
+  int                  flag_err = 0;
+  int                  theProto = 0;
+
+  char   head_u[5];
+  char   u_real[SH_CHALLENGE_SIZE];
+  char * foo_A;
+  char * foo_Sc;
+  char * M;
+  char   foo_M1[KEY_LEN+1];
+  char   hashbuf[KEYBUF_SIZE];
+#ifdef SH_ENCRYPT
+  int err_num;
+  char expbuf[SH_ERRBUF_SIZE];
+#endif
+
+  SL_REQUIRE((sockfd > 2), _("sockfd > 2"));
+
+  if (is_reinit == S_FALSE)
+    flag_err = xfer_greet_server(sockfd, answer);
+  else
+    sh_tools_probe_reset();
+
+  /* Entry point for jump from message forward if session key must
+   * be re-initialized.
+   */	 
+  TPT(( 0, FIL__, __LINE__, _("msg=<srp: INIT>\n")));
+  
+  if ( flag_err == 0 )
+    {
+      if (0 != sh_srp_init())
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_EBGN);
+      else 
+	{
+	  TPT(( 0, FIL__, __LINE__, _("msg=<srp: bignum initialized>\n")));
+
+	  sh_srp_x (answer, NULL);  /* x        password      */
+	  sh_srp_make_a ();         /* a        random number */
+	  foo_A = sh_srp_A();       /* g^a                    */
+
+	  TPT(( 0, FIL__, __LINE__, _("msg=<srp: A = %s>\n"), foo_A));
+
+	  if (foo_A == NULL)
+	    flag_err = (-1);
+
+	  noise();
+
+	  if (flag_err == 0)
+	    flag_err = xfer_send (sockfd, 
+				  (theProto|SH_PROTO_SRP), 
+				  _("PC01"),
+				  foo_A, sl_strlen(foo_A)+1); 
+	  if (flag_err == 0)
+	    {
+	      flag_err = xfer_receive (sockfd, 
+				       (theProto|SH_PROTO_SRP),
+				       head_u,
+				       answer, 511);
+	      flag_err = (flag_err < 0) ? flag_err : 0;
+	      TPT(( 0, FIL__, __LINE__, _("msg=<srp: B = %s>\n"), answer));
+	      TPT(( 0, FIL__, __LINE__, _("msg=<srp: u = %03o-%03o-%03o-%03o>\n"), head_u[0], head_u[1], head_u[2], head_u[3]));
+	    }
+
+	  /*                     u        nounce        */
+	  /*                     B        answer        */
+	  /*                     S = (B-g^x)^(a+ux)     */
+	  
+    
+	  if (flag_err == 0)
+	    { 
+	      noise();
+
+	      if (0 != sh_srp_check_zero (answer))
+		sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_EZERO);
+	      else 
+		{
+		  sl_strlcpy(u_real, sh_tiger_hash(head_u, TIGER_DATA, 4, 
+						   hashbuf, sizeof(hashbuf)), 
+			     SH_CHALLENGE_SIZE);
+		  foo_Sc = sh_srp_S_c (u_real, answer);
+		  
+		  TPT(( 0, FIL__, __LINE__, _("msg=<srp: U = %s>\n"), 
+			u_real));
+		  TPT(( 0, FIL__, __LINE__, _("msg=<srp:Sc = %s>\n"), 
+			foo_Sc));
+		  
+		  /* --- Now send H(A,B,H(Sc)) and check. --- 
+		   */
+		  if (foo_Sc != NULL && 0 == sh_srp_check_zero (foo_Sc))
+		    {
+		      sh_srp_M(foo_A, 
+			       answer, 
+			       sh_tiger_hash(foo_Sc, 
+					     TIGER_DATA, 
+					     sl_strlen(foo_Sc), 
+					     hashbuf, sizeof(hashbuf)),
+			       foo_M1, KEY_LEN+1);
+		      
+		      
+		      TPT(( 0, FIL__, __LINE__, _("msg=<srp:M1 = %s>\n"), 
+			    foo_M1));
+		      
+		      flag_err = xfer_send(sockfd, 
+					   (theProto|SH_PROTO_SRP), 
+					   _("PC02"),
+					   foo_M1, KEY_LEN+1);
+		    }
+		  else
+		    flag_err = (-1);
+		  
+		  if (flag_err == 0)
+		    {
+		      flag_err = xfer_receive(sockfd, 
+					      (theProto|SH_PROTO_SRP),
+					      head_u, 
+					      answer, 511);
+		      flag_err = (flag_err < 0) ? flag_err : 0;
+		      TPT(( 0, FIL__, __LINE__, _("msg=<srp: M = %s>\n"), 
+			    answer));
+		    }
+		  
+		  if (flag_err == 0   && 0 == check_request (head_u, _("PARP")) )
+		    {
+		      /* ------  verify M2 = H(A, M1, K) --------
+		       */
+		      char M_buf[KEY_LEN+1];
+		      M = sh_srp_M (foo_A, foo_M1,
+				    sh_tiger_hash(foo_Sc,
+						  TIGER_DATA,
+						  sl_strlen(foo_Sc), 
+						  hashbuf, sizeof(hashbuf)),
+				    M_buf, sizeof(M_buf)
+				    );
+		      if (M != NULL && 
+			  0 == sl_strncmp (answer, M, KEY_LEN+1))
+			{
+			  sl_strlcpy (skey->session, 
+				      sh_tiger_hash(foo_Sc, 
+						    TIGER_DATA,
+						    sl_strlen(foo_Sc), 
+						    hashbuf, sizeof(hashbuf)),
+				      KEY_LEN+1);
+			  TPT(( 0, FIL__, __LINE__, 
+				_("msg=<srp: Key = %s>\n"), 
+				skey->session));
+
+#ifdef SH_ENCRYPT
+			  err_num = rijndael_makeKey(&(skey->keyInstE), 
+						     DIR_ENCRYPT, 
+						     192, skey->session);
+			  if (err_num < 0)
+			    sh_error_handle((-1), FIL__, __LINE__, -1, 
+					    MSG_E_SUBGEN,
+					    errorExplain(err_num, expbuf, sizeof(expbuf)), 
+					    _("xfer_try_report_int: makeKey"));
+			  err_num = rijndael_makeKey(&(skey->keyInstD), 
+						     DIR_DECRYPT, 
+						     192, skey->session);
+			  if (err_num < 0)
+			    sh_error_handle((-1), FIL__, __LINE__, -1, 
+					    MSG_E_SUBGEN,
+					    errorExplain(err_num, expbuf, sizeof(expbuf)), 
+					    _("xfer_try_report_int: makeKey"));
+#endif
+			  *initialized = S_TRUE;
+			  noise();
+			}
+		    }
+		  if (foo_Sc != NULL)
+		    SH_FREE(foo_Sc);
+		}
+	    }
+	  if (foo_A != NULL)
+	    SH_FREE(foo_A);
+	  sh_srp_exit();
+	}
+    }
+
+  if (*initialized == S_FALSE)
+    {
+      xfer_timeout_val *= 2;
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH);
+      memset(answer, '\0', 512);
+      MUNLOCK(answer, 512);
+      SH_FREE(answer);
+      return -1;
+    }
+  else
+    {
+      if (flag_err_info == S_TRUE)
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AUTH);
+    }
+  return 0;
+}
+#endif
+
+int xfer_check_server_cmd(char * answer, char * buffer)
+{
+  int    flag_err;
+  size_t pos;
+  char   sigbuf[KEYBUF_SIZE];
+
+  /* --- SERVER CMD --- */
+  if (answer[KEY_LEN] != '\0' && 
+      sl_strlen(answer) > (2*KEY_LEN))
+    {
+      pos = sl_strlen(answer) - (2*KEY_LEN);
+      /*
+       * buffer is  >= 256
+       * answer has <= 255 bytes
+       */
+      (void) sl_strlcpy(buffer, &answer[KEY_LEN], 
+			pos+1);
+      flag_err = 
+	sl_strncmp(&answer[KEY_LEN+pos],
+		   sh_util_siggen(skey->session, 
+				  buffer,
+				  pos,
+				  sigbuf, sizeof(sigbuf)),
+		   KEY_LEN);
+      
+      TPT((0, FIL__, __LINE__, 
+	   _("CONF RECV <%d> <%s>\n"),
+	   flag_err, &answer[KEY_LEN]));
+      
+      if (flag_err != 0) {
+	sh_error_handle((-1), FIL__, __LINE__, 
+			flag_err,
+			MSG_TCP_NOCONF);
+      } 
+#ifdef SH_WITH_CLIENT
+      else {
+	sh_socket_server_cmd(buffer);
+      }
+#endif
+      flag_err = 0;
+      
+    } else {
+    
+    TPT((0, FIL__, __LINE__, 
+	 _("CONF RECV <0> <[null]>\n")));
+    
+  }
+  /* --- SERVER CMD END --- */
+  return 0;
+}
+
+
+
+int xfer_send_message(char * errmsg, int sockfd, char * answer)
+{
+  char   hash[KEY_LEN+1];
+  size_t len;
+  char * buffer;
+  char   nsrv[KEY_LEN+1];
+  char   sigbuf[KEYBUF_SIZE];
+  char   head_u[5];
+  int    flag_err;
+
+  SL_REQUIRE((sockfd > 2), _("sockfd > 2"));
+
+  /* --- Save the challenge. ---  
+   */
+  (void) sl_strlcpy(nsrv, answer, KEY_LEN + 1);
+  
+  /* --- Hash(msg,challenge,sessionkey). ---  
+   */
+  len    = sl_strlen(errmsg) + sl_strlen(answer) 
+    + KEY_LEN + 1;
+  len = (size_t)((len < 256) ? 256 : len);
+  buffer = SH_ALLOC(len);
+  MLOCK(buffer, len);
+  (void) sl_strlcpy(buffer, errmsg, len);
+  (void) sl_strlcat(buffer, answer, len);
+  (void) sl_strlcpy(hash, 
+		    sh_util_siggen (skey->session, 
+				    buffer, 
+				    sl_strlen(buffer),
+				    sigbuf, sizeof(sigbuf)), 
+		    KEY_LEN+1);
+  TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
+       sh_util_siggen(skey->session, buffer, 
+		      sl_strlen(buffer), sigbuf, sizeof(sigbuf))));
+  
+  (void) sl_strlcpy(buffer, errmsg, len);
+  (void) sl_strlcat(buffer, hash,   len);
+  
+  flag_err = 
+    xfer_send_crypt (sockfd, 
+#ifdef SH_ENCRYPT
+		     (char)(SH_PROTO_MSG|SH_PROTO_ENC),
+#else
+		     (char)(SH_PROTO_MSG),
+#endif
+		     _("MESG"),
+		     buffer, 
+		     (unsigned long)(sl_strlen(buffer)+1));
+  TPT(( 0, FIL__, __LINE__, 
+	_("msg=<Sent %s, status %d.>\n"), 
+	answer, flag_err));
+
+  /* --- Get confirmation. ---
+   */
+  if (flag_err == 0)
+    {
+      flag_err = (int)
+	xfer_receive_crypt (sockfd, 
+#ifdef SH_ENCRYPT
+			    (char)(SH_PROTO_MSG|SH_PROTO_ENC|SH_PROTO_END),
+#else
+			    (char)(SH_PROTO_MSG|SH_PROTO_END),
+#endif
+			    head_u, 
+			    answer, 255);   
+      TPT(( 0, FIL__, __LINE__, 
+	    _("msg=<Rcvt %s, u %s, status %d.>\n"), 
+	    answer, hu_trans(head_u), flag_err));
+      flag_err = (flag_err < 0) ? flag_err : 0;
+    }
+
+  
+  /* --- Check confirmation. ---
+   */
+  if (flag_err == 0)
+    {
+      /*   CLIENT CONF RECV
+       * 
+       *   first KEY_LEN bytes must be
+       *   sig(skey->session (errmsg nsrv))
+       *
+       */
+      (void) sl_strlcpy(buffer, errmsg, len);
+      (void) sl_strlcat(buffer, nsrv,   len);
+      flag_err = sl_strncmp(answer,
+			    sh_util_siggen(skey->session, 
+					   buffer,
+					   sl_strlen(buffer),
+					   sigbuf, sizeof(sigbuf)),
+			    KEY_LEN);
+      TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
+	   sh_util_siggen(skey->session, buffer, 
+			  sl_strlen(buffer), sigbuf, sizeof(sigbuf))));
+      
+      if (flag_err != 0)
+	{
+#ifdef ENOMSG
+	  flag_err = ENOMSG;
+#else
+	  flag_err = EIO;
+#endif
+	  sh_error_handle((-1), FIL__, __LINE__, flag_err,
+			  MSG_TCP_NOCONF);
+	}
+      else
+	{
+#ifdef SH_ENCRYPT
+	  flag_err = xfer_check_server_cmd(answer, buffer);
+#endif
+	  if (flag_err_debug == S_TRUE)
+	    sh_error_handle((-1), FIL__, __LINE__, 0,
+			    MSG_TCP_CONF);
+	}
+    }
+  
+  memset(buffer, 0, len);
+  MUNLOCK(buffer, len);
+  SH_FREE(buffer);
+
+  if (flag_err != 0)
+    return -1;
+  return 0;
+}
+
+
+static SL_TICKET xfer_get_file(int sockfd, char * answer, 
+			       char * nclt, char * foo_M1, const int theProto)
+{
+  /* --- Open a temporary file. ---
+   */
+  int flag_err = 0;
+  SL_TICKET sfd;
+
+  SL_REQUIRE((sockfd > 2), _("sockfd > 2"));
+
+  if ( (sfd = open_tmp ()) < 0)
+    {
+      flag_err = (-1);
+      sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_EFIL);
+    }
+  else
+    {
+      /* --- Read from socket into tmp file. ---
+       */
+      int    transfercount = 0;
+      char   head_u[5];
+
+      do {
+	flag_err = (int)
+	  xfer_receive_crypt (sockfd, 
+#ifdef SH_ENCRYPT
+			      (char)(SH_PROTO_BIG|SH_PROTO_ENC),
+#else
+			      (char)(SH_PROTO_BIG),
+#endif
+			      head_u, 
+			      answer, 
+			      TRANS_BYTES + 255);
+	
+	TPT(( 0, FIL__, __LINE__, 
+	      _("msg=<Received: %d bytes, marked %s.>\n"),
+	      flag_err, hu_trans(head_u)));
+
+	if (flag_err > 0 && 0 == check_request_nerr(head_u, _("FILE")))
+	  {
+	    if (0 == hash_check (foo_M1, answer, flag_err))
+	      {
+		(void) sl_write(sfd, &answer[KEY_LEN], 
+				flag_err-KEY_LEN);
+		++transfercount;
+
+		/*  Delay for throughput throttling
+		 */
+		if (sh_throttle_delay > 0)
+		  retry_msleep(sh_throttle_delay/1000, sh_throttle_delay % 1000);
+
+		flag_err = xfer_send_crypt (sockfd, theProto, 
+					    _("RECV"),
+					    nclt, 
+					    (unsigned long)sl_strlen(nclt));
+		
+	      }
+	    else
+	      {
+		TPT(( 0, FIL__, __LINE__, 
+		      _("msg=<File transfer: Hash check failed.>\n")));
+		break;
+	      }
+	  }
+	else
+	  {
+	    TPT(( 0, FIL__, __LINE__, 
+		  _("msg=<File transfer: No more data.>\n")));
+	    break;
+	  }
+      } while (transfercount < 32000); /* 64 Mbyte */
+      
+      if (0 == check_request_nerr(head_u, _("EEOT")) &&
+	  0 <  flag_err                              &&
+	  0 == hash_check (foo_M1, answer, (int)sl_strlen(answer)))
+	{
+	  flag_err = xfer_send_crypt (sockfd, theProto, 
+				      _("EOTE"),
+				      nclt, 
+				      (unsigned int) sl_strlen(nclt));
+	  
+	  (void) rewind_tmp (sfd);
+	  (void) sl_sync(sfd);
+	  if (flag_err_info == S_TRUE)
+	    sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_FOK);
+	}
+      else
+	{
+	  (void) sl_close (sfd);
+	  sfd = (-1);
+	}
+    }
+
+  return sfd;
+}
+
+static  long xfer_try_report_int (char * errmsg, const int what)
+{
+  static int           initialized = S_FALSE;
+  static int           conn_state  = S_TRUE;
+  int                  sockfd;
+  int                  flag_err = 0;
+  char               * answer;
+  int                  theProto = 0;
+
+  UINT32 ticks;
+  char   head_u[5];
+  char * buffer;
+  char   nsrv[KEY_LEN+1];
+  char   nclt[KEY_LEN+1];
+  char   foo_M1[KEY_LEN+1];
+
+  char hashbuf[KEYBUF_SIZE];
+  char sigbuf[KEYBUF_SIZE];
+
+  SL_ENTER(_("xfer_try_report_int"));
+
+  /* --- No message to transmit. ---
+   */
+  if (errmsg == NULL && initialized == S_TRUE)
+    SL_RETURN( 0, _("xfer_try_report_int"));
+  
+  /* --- Connection in bad state. ---
+   */
+  if (xfer_conn_state(initialized, conn_state) < 0)
+    SL_RETURN( (-1), _("xfer_try_report_int"));
+
+  /* --- Try to connect to log server. ---
+   */
+  sockfd = xfer_connect(&conn_state);
+  if (sockfd < 0)
+    SL_RETURN( (-1), _("xfer_try_report_int"));
+  
+
+  /*************************
+   *
+   *  initialization
+   * 
+   */
+  flag_err = 0;
+  answer   = SH_ALLOC(512);
+  MLOCK(answer, 512);
+
+  if (initialized == S_FALSE)
+    {
+      if (xfer_auth(S_FALSE, &initialized, sockfd, answer) < 0)
+	SL_RETURN( (-1), _("xfer_try_report_int"));
+    }
+
+ retry_send:
+
+  /* no message, just session key negotiated
+   */
+  if (errmsg == NULL)
+    {
+      xfer_timeout_val = 1;
+      memset(answer, 0, 512);
+      MUNLOCK(answer, 512);
+      SH_FREE(answer);
+      TPT(( 0, FIL__, __LINE__, _("msg=<No message.>\n")));
+      SL_RETURN( (0), _("xfer_try_report_int"));
+    }
+  else if (what == SH_PROTO_BIG)
+    {
+      MUNLOCK(answer, 512);
+      SH_FREE (answer);
+      answer   = SH_ALLOC(TRANS_BYTES + 256);
+      MLOCK(answer, TRANS_BYTES + 256);
+      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer.>\n")));
+    }
+
+  sl_strlcpy (answer, 
+	      sh_util_siggen(skey->session,
+			     sh.host.name,
+			     sl_strlen(sh.host.name),
+			     sigbuf, sizeof(sigbuf)), 
+	      KEY_LEN+1);
+
+  TPT((0, FIL__, __LINE__, _("msg=<host %s>\n"), sh.host.name));
+  TPT((0, FIL__, __LINE__, _("msg=<ckey %s>\n"), skey->session));
+  TPT((0, FIL__, __LINE__, _("msg=<sign %s>\n"), answer));
+    
+  sl_strlcat (answer, sh.host.name, 512);
+
+  TPT((0, FIL__, __LINE__, _("msg=<mesg %s>\n"), answer));
+
+  /***********************************************
+   *
+   * send the message
+   *
+   */
+
+  if (what == SH_PROTO_MSG)
+    theProto = SH_PROTO_MSG;
+  else if (what == SH_PROTO_BIG)
+    theProto = SH_PROTO_BIG;
+
+  /* --- Say HELO  ---       
+   */
+  flag_err = xfer_send    (sockfd, theProto, _("HELO"),
+			   answer, sl_strlen(answer));
+  TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s, status %d.>\n"), 
+	answer, flag_err));
+
+  if (flag_err == 0)
+    { 
+      /* --- Get NSRV. ---  
+       */
+      flag_err = (int) xfer_receive (sockfd, theProto, head_u, answer, 255);
+      TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s, u %s, status %d.>\n"), 
+	    answer, hu_trans(head_u), flag_err));
+      flag_err = (flag_err < 0) ? flag_err : 0;
+    }   
+
+  if (what == SH_PROTO_MSG)
+    {
+      if (flag_err == 0)
+	{
+	  /* --- Re-negotiate key. ---
+	   */
+	  if (0 == check_request_nerr(head_u, _("INIT")))
+	    {
+	      flag_err    = 0;
+	      initialized = S_FALSE;
+	      if (xfer_auth(S_TRUE, &initialized, sockfd, answer) == 0)
+		goto retry_send;
+	    }
+	  
+	  else if (0 == check_request(head_u, _("TALK")))
+	    {
+	      flag_err = xfer_send_message(errmsg, sockfd, answer);
+	    }
+
+	  else
+	    {
+	      /* --- Unexpected reply from server. ---
+	       */
+	      sh_error_handle((-1), FIL__, __LINE__, 0,
+			      MSG_TCP_UNEXP);
+	      flag_err = (-1);
+		
+	    }
+	}
+    }
+
+
+  else if (what == SH_PROTO_BIG)
+    {
+      if (flag_err == 0)
+	{
+	  
+	  /* --- Re-negotiate key. ---
+	   */
+	  if (0 == check_request_nerr(head_u, _("INIT")))
+	    {
+	      flag_err    = 0;
+	      initialized = BAD;
+	      if (xfer_auth(S_TRUE, &initialized, sockfd, answer) == 0)
+		goto retry_send;
+	    }
+	  
+ 
+	  else if (0 == check_request(head_u, _("NSRV")))
+	    {
+	      size_t buffersize;
+#ifdef SH_ENCRYPT
+	      /* --- Set encryption flag. ---
+	       */
+	      theProto = (SH_PROTO_BIG|SH_PROTO_ENC);
+#endif
+
+	      (void) sl_strlcpy(nsrv, answer, KEY_LEN+1);
+	      
+	      /* --- Generate a nonce. ---
+	       */
+	      ticks = (UINT32) taus_get ();
+              
+	      (void) sl_strlcpy(nclt, 
+				sh_tiger_hash((char *) &ticks, 
+					      TIGER_DATA, 
+					      (unsigned long)sizeof(UINT32), 
+					      hashbuf, sizeof(hashbuf)),
+				KEY_LEN+1);
+
+	      /* --- Compute H(nsrv, nclt, skey). ---
+	       */
+	      buffer = sh_util_strconcat (nsrv, nclt, 
+					  skey->session, NULL);
+	      (void)sl_strlcpy(foo_M1, 
+			       sh_tiger_hash(buffer, TIGER_DATA,
+					     (unsigned long)sl_strlen(buffer), 
+					     hashbuf, sizeof(hashbuf)),
+			       KEY_LEN+1);
+	      memset (buffer, 0, sl_strlen(buffer));
+	      SH_FREE(buffer);
+
+	      /* --- Send (nclt, msg) ---
+	       */
+	      buffersize = strlen(nclt)+strlen(errmsg)+2;
+	      buffer = SH_ALLOC(buffersize);
+
+	      sl_strlcpy(buffer, nclt,   buffersize);
+	      sl_strlcat(buffer, errmsg, buffersize);
+
+#if !defined(SH_ENCRYPT)
+	      if (4 == sl_strlen(errmsg)) {      /* backward compatibility */
+		buffersize = sl_strlen(buffer);
+		buffer[buffersize]   = theProto; /* nctl//DATA//theProto   */
+		buffer[buffersize+1] = '\0';
+	      }
+	      sh_tools_hash_add(foo_M1, buffer, buffersize+1);
+#endif
+
+	      flag_err = 
+		xfer_send_crypt (sockfd, (char) theProto, _("NCLT"),
+				 buffer, 
+				 (unsigned long) sl_strlen(buffer));
+ 
+	      TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s, status %d.>\n"), 
+		    buffer, flag_err));
+	      SH_FREE (buffer);
+	    }   
+	}
+
+      if (flag_err == 0)
+	{
+	  /* --- Receive the file. ---
+	   */
+	  SL_TICKET sfd = xfer_get_file(sockfd, answer, nclt, foo_M1, theProto);
+	  if (!SL_ISERROR(sfd))
+	    {
+	      (void) sl_close_fd (FIL__, __LINE__, sockfd);
+	      memset(answer, 0, TRANS_BYTES + 256);
+	      MUNLOCK(answer, TRANS_BYTES + 256);
+	      SH_FREE(answer);
+	      xfer_timeout_val = 1;
+
+	      SL_RETURN( (sfd), _("xfer_try_report_int"));
+	    }
+	}
+
+      (void) sl_close_fd (FIL__, __LINE__, sockfd);
+      memset(answer, 0, TRANS_BYTES + 256);
+      MUNLOCK(answer, TRANS_BYTES + 256);
+      SH_FREE(answer);
+      xfer_timeout_val *= 2;
+
+      SL_RETURN( (-1), _("xfer_try_report_int"));
+    }
+ 
+  (void) sl_close_fd (FIL__, __LINE__, sockfd);
+  memset(answer, 0, 512);
+  MUNLOCK(answer, 512);
+  SH_FREE(answer);
+
+#ifndef EIO
+#define EIO 5
+#endif
+  
+
+#ifdef SH_ERROR_H  
+  if (flag_err != 0)
+    {
+      char errbuf[SH_ERRBUF_SIZE];
+      conn_state = S_FALSE;
+      xfer_timeout_val *= 2;
+      if (flag_err < 0 || NULL == sh_error_message(flag_err, errbuf, sizeof(errbuf)))
+	flag_err = EIO;
+      sh_error_handle((-1), FIL__, __LINE__, flag_err, MSG_TCP_ECONN,
+		      sh_error_message(flag_err, errbuf, sizeof(errbuf)));
+      SL_RETURN( (-1), _("xfer_try_report_int"));
+    }
+#endif
+  xfer_timeout_val = 1;
+
+  SL_RETURN( (0), _("xfer_try_report_int"));
+}
+
+/* #ifdef SH_WITH_CLIENT */
+#endif
+
+
+
+
Index: trunk/src/sh_xfer_server.c
===================================================================
--- trunk/src/sh_xfer_server.c	(revision 481)
+++ trunk/src/sh_xfer_server.c	(revision 481)
@@ -0,0 +1,3778 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+/* Must be early on FreeBSD
+ */
+#include <sys/types.h>
+
+/* must be .le. than (1020 * 64)
+ * (see sh_tools.c -- put_header)
+ *
+ * also: must be  (N * 16), otherwise
+ * binary files cannot be transferred encrypted
+ *
+ * 65280 = (1020*64)
+ * #define TRANS_BYTES 8000  V0.8
+ */
+#ifdef  SH_ENCRYPT
+#define TRANS_BYTES 65120
+#else
+#define TRANS_BYTES 65280
+#endif
+
+/* timeout for session key
+ */
+#define TIMEOUT_KEY 7200
+
+/* max time between connection attempts
+ */
+#define TIMEOUT_CON 2048 
+
+/* #undef  SRP_DEBUG */
+/* #define SRP_DEBUG */
+
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+/*
+#ifdef TM_IN_SYS_TIME
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+*/
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef  HAVE_UNISTD_H
+#include <errno.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#endif
+
+#ifndef FD_SET
+#define NFDBITS         32
+#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#endif /* !FD_SET */
+#ifndef FD_SETSIZE
+#define FD_SETSIZE      32
+#endif
+#ifndef FD_ZERO
+#define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p)))
+#endif
+
+#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
+#include <sys/mman.h>
+#endif
+
+
+#include <netdb.h> 
+#include <sys/types.h> 
+#include <netinet/in.h> 
+#include <sys/socket.h> 
+#ifndef S_SPLINT_S
+#include <arpa/inet.h>
+#endif
+
+#include "sh_ipvx.h"
+#include "samhain.h"
+#include "sh_tiger.h"
+#include "sh_utils.h"
+#include "sh_unix.h"
+#include "sh_xfer.h"
+#include "sh_srp.h"
+#include "sh_fifo.h"
+#include "sh_tools.h"
+#include "sh_entropy.h"
+#include "sh_html.h"
+#include "sh_nmail.h"
+#include "sh_socket.h"
+#define SH_NEED_GETHOSTBYXXX
+#include "sh_static.h"
+#include "sh_guid.h"
+
+#ifdef SH_ENCRYPT
+#include "rijndael-api-fst.h"
+char * sh_tools_makePack (unsigned char * header, int flag,
+			  char * payload, unsigned long payload_size,
+			  keyInstance * keyInstE);
+char * sh_tools_revertPack (unsigned char * header, int flag, char * message,
+			    keyInstance * keyInstE, 
+			    unsigned long message_size);
+#endif
+
+/* define this if you want to debug the client/server communication */
+/* #define SH_DBG_PROT 1 */
+
+#ifdef  SH_DBG_PROT
+#define SH_SHOWPROT(c,d) sh_tools_show_header((c), (d))
+#else
+#define SH_SHOWPROT(c,d) 
+#endif
+
+/* the port client will be connecting to 
+ */
+#ifndef SH_DEFAULT_PORT
+#define SH_DEFAULT_PORT 49777    
+#endif
+
+#ifndef SH_SELECT_REPEAT
+#define SH_SELECT_REPEAT 60
+#endif
+
+#ifndef SH_HEADER_SIZE
+#define SH_HEADER_SIZE 7
+#endif
+
+#ifndef SH_CHALLENGE_SIZE
+#define SH_CHALLENGE_SIZE 9
+#endif
+
+#undef  FIL__
+#define FIL__  _("sh_xfer_server.c")
+
+int     clt_class = (-1);
+
+extern int flag_err_debug;
+extern int flag_err_info;
+
+
+#if defined (SH_WITH_SERVER)
+
+#if defined(WITH_TRACE) || defined(WITH_TPT) 
+extern char * hu_trans(const char * ihu);
+#endif
+extern unsigned int ServerPort;
+#if !defined(USE_SRP_PROTOCOL)
+extern void sh_passwd (char * salt, char * password, char * nounce, char *hash);
+#endif
+
+static int StripDomain = S_TRUE;
+
+int sh_xfer_set_strip (const char * str)
+{
+  static int fromcl = 0;
+
+  if (fromcl == 1)
+    return 0;
+  else
+    return (sh_util_flagval(str, &StripDomain));
+}
+
+static char * sh_strip_domain (char *name)
+{
+  char * out = NULL;
+
+  SL_ENTER(_("sh_strip_domain"));
+
+  if (StripDomain == S_FALSE || strchr(name, '.') == NULL) 
+    {
+      out = sh_util_strdup(name);
+      SL_RETURN( out, _("sh_strip_domain"));
+    }
+  else
+    {
+      /* check whether it is in dotted number format
+       * --> last part must be kept
+       */
+      if (0 != sh_ipvx_is_numeric(name))
+	{
+	  out = sh_util_strdup(name);
+	  SL_RETURN( out, _("sh_strip_domain"));
+	}
+      else
+	{
+	  char * p;
+	  out = sh_util_strdup(name);
+	  p   = strchr(out, '.');
+	  if (p) *p = '\0';
+	  SL_RETURN( out, _("sh_strip_domain"));
+	}
+    }
+
+  SL_RETURN( out, _("sh_strip_domain"));
+}
+
+#ifndef USE_SRP_PROTOCOL
+
+int sh_xfer_make_client (const char * str)
+{
+  /* char *          safer; */
+  char            key[KEY_LEN+1];
+  unsigned char   in[PW_LEN+1];
+  int    i = 0, j, k, l = 0;
+  char hashbuf[KEYBUF_SIZE];
+  
+  if (sl_strlen(str) != (PW_LEN * 2)) 
+    {
+      fprintf(stderr, 
+	      _("Input must be a %d digit hexadecimal number"\
+		" (only 0-9, a-f, A-F allowed in input)\n"),
+	      (PW_LEN * 2));
+      _exit(EXIT_FAILURE);
+    }
+  
+  while (i < (PW_LEN * 2))
+    {
+      k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); 
+      if (k != -1 && j != -1) 
+        {
+          in[l] = (k * 16 + j);
+          ++l; i+= 2;
+        }
+      else
+        {
+          fprintf(stderr, _("Invalid char %c\n"), str[i]);
+          _exit(EXIT_FAILURE);
+        }
+    }
+  in[PW_LEN] = '\0';
+
+  sl_strlcpy ((char *)key, 
+	      sh_tiger_hash ((char*)in, TIGER_DATA, PW_LEN, 
+			     hashbuf, sizeof(hashbuf)), 
+	      KEY_LEN+1);
+  key[KEY_LEN] = '\0';
+  
+  fprintf(stdout, _("Client entry: Client=HOSTNAME@00000000@%s\n"), 
+	  key);
+  fflush(stdout);
+
+  _exit(EXIT_SUCCESS);
+  return 0;
+}
+
+#else
+
+int sh_xfer_make_client (const char * str)
+{
+  char * foo_v;
+
+  char   salt[17];
+  char   key[KEY_LEN+1];
+  char   in[PW_LEN];
+  int    i = 0, j, k, l = 0;
+  char hashbuf[KEYBUF_SIZE];
+  
+  if (sl_strlen(str) != (PW_LEN*2)) 
+    {
+      fprintf(stderr, 
+	      _("Input must be a %d digit hexadecimal number"\
+		" (only 0-9, a-f, A-F allowed in input)\n"),
+	      (PW_LEN*2));
+      _exit(EXIT_FAILURE);
+    }
+
+    while (i < (PW_LEN*2))
+      {
+        k = sh_util_hexchar(str[i]); j = sh_util_hexchar(str[i+1]); 
+        if (k != -1 && j != -1) 
+          {
+            in[l] = (k * 16 + j);
+            ++l; i+= 2;
+          }
+        else
+          {
+            fprintf(stderr, _("Invalid char %c\n"), str[i]);
+            _exit(EXIT_FAILURE);
+          }
+      }
+    
+  
+    if (0 == sh_srp_init())
+      {
+	sh_util_keyinit(key, KEY_LEN);
+	sl_strlcpy(salt, sh_tiger_hash(key, TIGER_DATA, KEY_LEN, 
+				       hashbuf, sizeof(hashbuf)), 
+		   17); 
+	sh_srp_x (salt, in);
+	foo_v  = sh_srp_verifier ();
+	fprintf(stdout, _("Client=HOSTNAME@%s@%s\n"), 
+		salt, foo_v);
+	fflush(stdout);
+	SH_FREE(foo_v);
+	sh_srp_exit();
+	_exit(EXIT_SUCCESS);
+      }
+    fprintf(stdout, "%s",_("ERROR initializing BigNum library.\n"));
+    fflush (stdout);
+    _exit(EXIT_FAILURE);
+    return -1;
+}
+#endif
+
+
+int sh_xfer_create_password (const char * dummy)
+{
+  UINT32   val[2]; 
+  char     output[KEY_LEN+1];
+  char hashbuf[KEYBUF_SIZE];
+
+  val[0] = taus_get ();
+  val[1] = taus_get ();
+
+  sl_strlcpy (output, 
+	      sh_tiger_hash((char *)(&val[0]), TIGER_DATA, 2*sizeof(UINT32),
+			    hashbuf, sizeof(hashbuf)),
+	      KEY_LEN);
+
+  output[16] = '\0';
+
+  fprintf(stdout, _("%s\n"), output);
+  fflush (stdout);
+
+  if (dummy)
+    _exit(EXIT_SUCCESS);
+  else
+    _exit(EXIT_SUCCESS);  
+  return (0);  /* avoid compiler warning */
+}
+
+/* #if defined (SH_WITH_SERVER) */
+#endif
+
+/**************************************************
+ *
+ *
+ *  S E R V E R   
+ *
+ *
+ ***************************************************/
+
+#ifdef SH_WITH_SERVER
+
+#include "sh_readconf.h"
+
+
+#define CONN_FREE    0
+#define CONN_READING 1
+#define CONN_SENDING 2
+#define CONN_PAUSE   3
+#define CONN_BUSY    4
+
+char * clt_stat[] = {
+  N_("Inactive"),
+  N_("Started"),
+  N_("ILLEGAL"),
+  N_("FAILED"),
+  N_("Exited"),
+  N_("PANIC"),
+  N_("POLICY"),
+  N_("File_transfer"),
+  N_("Message"),
+  N_("TIMEOUT_EXCEEDED"),
+  N_("Suspended"),
+  N_("Filecheck"),
+};
+
+#include <time.h>
+
+/* in sh_html.h:
+ *  typedef struct client_entry {
+ *  } client_t;
+ */
+
+#include "zAVLTree.h"
+
+static char * sh_tolower (char * s)
+{
+  char * ret = s;
+  if (s)
+    {
+      for (; *s; ++s)
+	{ 
+	  *s = tolower((unsigned char) *s);
+	}
+    }
+  return ret;
+}
+
+/* Function to return the key for indexing
+ * the argument 
+ */
+zAVLKey sh_avl_key (void const * arg)
+{
+  const client_t * sa = (const client_t *) arg;
+  return (zAVLKey) sa->hostname;
+}
+
+zAVLTree * all_clients = NULL;
+
+void sh_xfer_html_write()
+{
+  SL_ENTER(_("sh_xfer_html_write"));
+  sh_html_write(all_clients);
+  SL_RET0(_("sh_xfer_html_write"));
+}
+
+
+int sh_xfer_use_clt_class (const char * c)
+{
+  int i;
+  SL_ENTER(_("sh_xfer_use_clt_class"));
+  i = sh_util_flagval(c, &(sh.flag.client_class));
+  SL_RETURN(i, _("sh_xfer_use_clt_class"));
+}
+
+int sh_xfer_use_clt_sev (const char * c)
+{
+  int i;
+  SL_ENTER(_("sh_xfer_use_clt_sev"));
+  i = sh_util_flagval(c, &(sh.flag.client_severity));
+  SL_RETURN(i, _("sh_xfer_use_clt_sev"));  
+}
+
+
+/* the destructor
+ */
+void free_client(void * inptr)
+{
+  client_t * here;
+
+  SL_ENTER(_("free_client"));
+  if (inptr == NULL)
+    SL_RET0(_("free_client"));
+  else
+    here = (client_t *) inptr;
+
+  if (here->hostname != NULL)
+    SH_FREE(here->hostname);
+  if (here->salt != NULL)
+    SH_FREE(here->salt);
+  if (here->verifier != NULL)
+    SH_FREE(here->verifier);
+  SH_FREE(here);
+  SL_RET0(_("free_client"));
+}
+
+
+int sh_xfer_register_client (const char * str)
+{
+  client_t   * newclt;
+  client_t   * testclt;
+
+  const char * ptr;
+  int          sepnum = 0;
+  int          sep[2];
+  register int i = 0;
+  int          siz_str = 0;
+
+  SL_ENTER(_("sh_xfer_register_client"));
+
+  ptr = str; 
+  while (*ptr) {
+    if (*ptr == '@' && sepnum < 2 ) 
+      { 
+	sep[sepnum] = i;
+	++sepnum;
+      } 
+    ++ptr; ++i; 
+  }
+
+  if (all_clients == NULL)
+    {
+      all_clients = zAVLAllocTree (sh_avl_key, zAVL_KEY_STRING);
+      if (all_clients == NULL) 
+	{
+	  (void) safe_logger (0, 0, NULL);
+	  aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+	}
+    }
+  
+  if ((sepnum == 2) && (sep[0] > 0) && (sep[1] > sep[0]))
+    {
+      newclt = SH_ALLOC (sizeof(client_t));
+      newclt->hostname = SH_ALLOC (sep[0]+1);
+      newclt->salt     = SH_ALLOC (sep[1]-sep[0]);
+      newclt->verifier = SH_ALLOC (sl_strlen(str)-sep[1]+1);
+      newclt->exit_flag         = 0;
+      newclt->dead_flag         = 0;
+#ifdef SH_ENCRYPT
+      newclt->encf_flag         = SH_PROTO_ENC;
+      newclt->ency_flag         = SH_PROTO_ENC;
+#else
+      newclt->encf_flag         = 0;
+      newclt->ency_flag         = 0;
+#endif
+      newclt->ivst_flag         = 0;
+      newclt->session_key[0]    = '\0';
+      newclt->last_connect      = (time_t) 0;
+      newclt->session_key_timer = (time_t) 0;
+      newclt->status_now        = CLT_INACTIVE;
+      for (i = 0; i < CLT_MAX; ++i) 
+	newclt->status_arr[i] = CLT_INACTIVE;
+      (void) sh_unix_time(0, newclt->timestamp[CLT_INACTIVE], TIM_MAX);
+
+      /* truncate */
+      sl_strlcpy(newclt->hostname,  &str[0],        sep[0]+1);
+      sh_tolower(newclt->hostname);
+
+      /* truncate */
+      sl_strlcpy(newclt->salt,      &str[sep[0]+1], sep[1]-sep[0]);
+      sl_strlcpy(newclt->verifier,  &str[sep[1]+1], sl_strlen(str)-sep[1]+1);
+
+      testclt = (client_t *) zAVLSearch (all_clients, newclt->hostname);
+
+      if (testclt != NULL)
+	{
+	  SH_FREE(testclt->verifier);
+	  siz_str = strlen (newclt->verifier) + 1;
+	  testclt->verifier = SH_ALLOC (siz_str);
+	  sl_strlcpy(testclt->verifier, newclt->verifier, siz_str);
+
+	  SH_FREE(testclt->salt);
+	  siz_str = strlen (newclt->salt) + 1;
+	  testclt->salt = SH_ALLOC (siz_str);
+	  sl_strlcpy(testclt->salt, newclt->salt, siz_str);
+
+	  testclt->dead_flag = 0;
+	      
+	  free_client(newclt);
+	  SL_RETURN( 0, _("sh_xfer_register_client"));
+	}
+      else
+	{
+	  if (0 == zAVLInsert (all_clients, newclt))
+	    {
+	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CREG,
+			      newclt->hostname, 
+			      newclt->salt, newclt->verifier);
+	      SL_RETURN( 0, _("sh_xfer_register_client"));
+	    }
+	}
+    }
+  SL_RETURN (-1, _("sh_xfer_register_client"));
+}
+
+typedef struct {
+  int             state;
+  int             fd;
+  char          * buf;
+  unsigned char   head[SH_HEADER_SIZE];
+  char            challenge[SH_CHALLENGE_SIZE];
+  char            peer[SH_MINIBUF+1];
+  client_t      * client_entry;
+  char          * K;
+  char          * M1;
+  char          * A;
+  int             headcount;
+  unsigned long   bytecount;
+  unsigned long   bytes_to_send;
+  unsigned long   bytes_to_get;
+  int             pass;
+  unsigned long   timer;
+
+  char          * FileName;
+  unsigned long   FileLength;
+  unsigned long   FileSent;
+  char            FileType[5];
+
+  struct sh_sockaddr addr_peer;
+} sh_conn_t;
+
+
+static char zap_challenge[SH_CHALLENGE_SIZE] = { 0 };
+ 
+void sh_xfer_do_free (sh_conn_t * conn)
+{
+  SL_ENTER(_("sh_xfer_do_free"));
+
+  if (conn->K != NULL) 
+    {
+      SH_FREE(conn->K);
+      conn->K           = NULL;
+    }
+  if (conn->A != NULL) 
+    {
+      SH_FREE(conn->A);
+      conn->A           = NULL;
+    }
+  if (conn->M1 != NULL) 
+    {
+      SH_FREE(conn->M1);
+      conn->M1           = NULL;
+    }
+  if (conn->buf != NULL) 
+    {
+      SH_FREE(conn->buf);
+      conn->buf          = NULL;
+    }
+  if (conn->fd != (-1))
+    {
+      sl_close_fd (FIL__, __LINE__, conn->fd);
+      conn->fd            = -1;
+    }
+  memcpy(conn->challenge, zap_challenge, SH_CHALLENGE_SIZE);
+  conn->state         = CONN_FREE;
+  conn->headcount     = 0;
+  conn->bytecount     = 0;
+  conn->bytes_to_send = 0;
+  conn->bytes_to_get  = 0;
+  conn->pass          = 0;
+  conn->timer         = 0;
+  conn->client_entry  = NULL;
+
+  if (conn->FileName != NULL) 
+    {
+      SH_FREE(conn->FileName);
+      conn->FileName     = NULL;
+    }
+  conn->FileLength     = 0;
+  conn->FileSent       = 0;
+  conn->FileType[0] = '\0';
+  conn->FileType[1] = '\0';
+  conn->FileType[2] = '\0';
+  conn->FileType[3] = '\0';
+  conn->FileType[4] = '\0';
+
+  --server_status.conn_open;
+  
+  SL_RET0(_("sh_xfer_do_free"));
+}
+
+/****************************************
+ *
+ *   -- Reconfiguration. --
+ *
+ *   (1) Mark all clients as 'dead'.
+ *   (2) Reload configuration - clients
+ *       in config are non-dead now.
+ *   (3) Remove all clients still
+ *       marked as 'dead'.
+ */
+
+/* -- Mark all clients as dead.
+ */
+void sh_xfer_mark_dead (void)
+{
+  zAVLCursor avlcursor;
+  client_t * item;
+
+  SL_ENTER(_("sh_xfer_mark_dead"));
+
+  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
+       item = (client_t *) zAVLNext(&avlcursor))
+    {
+      item->dead_flag = 1;
+    }
+  SL_RET0(_("sh_xfer_mark_dead"));
+}
+
+
+/* -- Clean tree from dead clients.
+ */
+void sh_xfer_clean_tree (void)
+{
+  zAVLCursor avlcursor;
+  client_t * item;
+
+  SL_ENTER(_("sh_xfer_clean_tree"));
+
+ repeat_search:
+
+  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
+       item = (client_t *) zAVLNext(&avlcursor))
+    {
+      if (item->dead_flag == 1)
+	{
+	  zAVLDelete (all_clients, item->hostname);
+	  free_client (item);
+	  goto repeat_search;
+	}
+    }
+  SL_RET0(_("sh_xfer_clean_tree"));
+}
+
+/*
+ *
+ **********************************************/
+
+
+
+/* -- SERVER SEND FUNCTION. --
+ */
+void sh_xfer_prep_send_int (sh_conn_t * conn, 
+			    char * msg, unsigned long length,
+			    char * u, char protocol,
+			    int docrypt)
+{
+  /* register unsigned long i; */
+  unsigned long           length2;
+
+#if !defined(SH_ENCRYPT)
+  (void) docrypt;
+#endif
+
+  SL_ENTER(_("sh_xfer_prep_send_int"));
+
+  TPT((0, FIL__, __LINE__, _("msg=<%s>, docrypt=<%d>\n"), msg, docrypt ));
+
+  length2 = length;
+
+  conn->headcount     = 0;
+  conn->bytecount     = 0;
+  conn->bytes_to_send = 0;
+  conn->bytes_to_get  = 0;
+
+  if (conn->buf != NULL) 
+    {
+      SH_FREE(conn->buf);
+      conn->buf           = NULL;
+    }
+
+  put_header (conn->head, protocol, &length2, u);
+  SH_SHOWPROT(conn->head,'>');
+
+  TPT((0, FIL__, __LINE__, _("msg=<put_header done>\n") ));
+
+  if (msg == NULL) 
+    length2 = 0;
+  
+#ifdef SH_ENCRYPT
+  if      ((S_TRUE == docrypt) && ((protocol & SH_PROTO_ENC) != 0))
+    {
+      TPT((0, FIL__, __LINE__, _("encrypting (version 2)\n")));
+      
+      conn->buf = sh_tools_makePack (conn->head, conn->client_entry->ivst_flag,
+				     msg, length2,
+				     &(conn->client_entry->keyInstE));
+    }
+  else if (msg == NULL)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+		      _("msg is NULL"), 
+		      _("sh_xfer_prep_send_int: cipherInit"));
+    }
+  else
+    {
+      if ((length2 + 1) < length2) --length2;
+      conn->buf       = SH_ALLOC(length2 + 1);
+
+      memcpy(conn->buf, msg, length2);
+      conn->buf[length2] = '\0';
+      TPT((0, FIL__, __LINE__, _("msg=<no encryption done>\n") ));
+    }
+#else
+  if ((length2 + 1) < length2) --length2;
+  conn->buf       = SH_ALLOC(length2 + 1);
+
+  memcpy(conn->buf, msg, length2);
+  conn->buf[length2] = '\0';
+  TPT((0, FIL__, __LINE__, _("msg=<no encryption done>\n") ));
+#endif
+
+  conn->state     = CONN_SENDING;
+  SL_RET0(_("sh_xfer_prep_send_int"));
+}
+
+/* -- Send/Receive. --
+ */
+void sh_xfer_prep_send (sh_conn_t * conn, 
+			   char * msg, unsigned long length,
+			   char * u, char protocol)
+{
+  SL_ENTER(_("sh_xfer_prep_send"));
+  sh_xfer_prep_send_int (conn,  msg, length, u, protocol, S_FALSE);
+  SL_RET0(_("sh_xfer_prep_send"));
+}  
+
+void sh_xfer_send_crypt (sh_conn_t * conn, 
+				 char * msg, unsigned long length,
+				 char * u, char protocol)
+{
+  SL_ENTER(_("sh_xfer_send_crypt"));
+  sh_xfer_prep_send_int (conn,  msg, length, u, protocol, S_TRUE);
+  SL_RET0(_("sh_xfer_send_crypt"));
+}  
+
+/* #include <sys/times.h> */
+
+#if defined(WITH_EXTERNAL)
+#include "sh_extern.h"
+#endif
+
+/* -- Update the client status. --
+ *
+ * Update the status array for the client,
+ * and eventually call external program.
+ */
+static void status_update (client_t * conn, int status)
+{ 
+#if defined(WITH_EXTERNAL)
+  char msg[2 * SH_MINIBUF + TIM_MAX + 3];
+#endif
+
+  SL_ENTER(_("status_update"));
+
+  if (conn == NULL || 
+      status < 0   || status >= CLT_MAX)
+    SL_RET0(_("status_update"));
+
+  conn->status_now = status;
+  conn->status_arr[status] = status;
+  (void) sh_unix_time(0, conn->timestamp[status], TIM_MAX);
+
+#if defined(WITH_EXTERNAL)
+  sl_snprintf(msg, sizeof(msg), _("%s %s %s"),
+	      conn->hostname, conn->timestamp[status], _(clt_stat[status]));
+  sh_ext_execute('s', 'r', 'v', msg, 0);
+#endif
+
+  SL_RET0(_("status_update"));
+}
+
+static time_t time_client_limit = 86400;
+
+int sh_xfer_set_time_limit (const char * c)
+{
+  long val;
+
+  SL_ENTER(_("sh_xfer_set_time_limit"));
+
+  val = strtol (c, (char **)NULL, 10);
+  if (val <= 0)
+    SL_RETURN( (-1), _("sh_xfer_set_time_limit"));
+
+  time_client_limit = (time_t) val;
+  SL_RETURN( (0), _("sh_xfer_set_time_limit"));
+}
+
+
+/* -- Check for time limit exceeded. --
+ */
+static int client_time_check(void)
+{
+  zAVLCursor avlcursor;
+  client_t * item;
+
+  SL_ENTER(_("client_time_check"));
+
+  if (time_client_limit == (time_t) 0)
+    SL_RETURN( 0, _("client_time_check"));
+
+  for (item = (client_t *) zAVLFirst(&avlcursor, all_clients); item;
+       item = (client_t *) zAVLNext(&avlcursor))
+    {
+      if (item->exit_flag == 0 && item->last_connect != (time_t) 0)
+	{
+	  if ( (time(NULL) - item->last_connect) > time_client_limit)
+	    {
+	      if (item->status_now != CLT_TOOLONG)
+		{
+		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMEXC,
+				  item->hostname);
+		  status_update (item, CLT_TOOLONG);
+		}
+	    }
+	}
+    }
+  SL_RETURN( 0, _("client_time_check"));
+}
+
+static int lookup_err = SH_ERR_SEVERE;
+
+int sh_xfer_lookup_level (const char * c)
+{
+  int ci =  sh_error_convert_level (c);
+
+  SL_ENTER(_("sh_xfer_lookup_level"));
+
+  if (ci >= 0)
+    {
+      lookup_err = ci;
+      SL_RETURN( 0, _("sh_xfer_lookup_level"));
+    }
+  else
+    SL_RETURN( (-1), _("sh_xfer_lookup_level"));
+}
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN  127
+#endif
+
+int check_addr (const char * claim, struct sh_sockaddr * addr_peer)
+{
+  char               h_name[MAXHOSTNAMELEN + 1];
+  char               h_peer[MAXHOSTNAMELEN + 1];
+  char               h_peer_IP[SH_IP_BUF];
+  char               tmp_peer_IP[SH_IP_BUF];
+  char             * canonical;
+  char               numeric[SH_IP_BUF];
+
+  SL_ENTER(_("check_addr"));
+
+  if (claim == NULL)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+		      _("NULL input"), _("check_addr"));
+      SL_RETURN ((-1), _("check_addr"));
+    }
+
+  /* Make sure we have the canonical name for the client
+   */
+  canonical = sh_ipvx_canonical(claim, numeric, sizeof(numeric));
+
+  /* copy canonical name into h_name
+   */
+  if (canonical != NULL)
+    {
+      sl_strlcpy(h_name, canonical, MAXHOSTNAMELEN + 1);
+      SH_FREE(canonical);
+    }
+  else
+    {
+      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESCLT,
+		      claim);
+      SL_RETURN ((0), _("check_addr"));
+    }
+
+
+  /* get canonical name of socket peer
+   */
+  canonical = sh_ipvx_addrtoname(addr_peer);
+
+  if (canonical)
+    {
+      if (0 == sl_strcmp(canonical, _("localhost")))
+	sl_strlcpy(h_peer, sh.host.name, MAXHOSTNAMELEN + 1);
+      else
+	sl_strlcpy(h_peer, canonical, MAXHOSTNAMELEN + 1);
+      SH_FREE(canonical);
+    }
+  else
+    {
+      sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer);
+      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_RESPEER,
+		      claim, tmp_peer_IP);
+      SL_RETURN ((0), _("check_addr"));
+    }
+
+  sh_ipvx_ntoa (h_peer_IP, sizeof(h_peer_IP), addr_peer);
+
+  /* reverse lookup
+   */
+  if (0 == sh_ipvx_reverse_check_ok (h_peer, ServerPort, addr_peer))
+    {
+      sh_ipvx_ntoa (tmp_peer_IP, sizeof(tmp_peer_IP), addr_peer);
+
+      sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKERS,
+		      claim, h_peer, tmp_peer_IP);
+      SL_RETURN ((0), _("check_addr"));
+    }
+
+  /* Check whether claim and peer are identical
+   */
+  sh_tolower(h_peer); /* Canonical name of what the peer is     */
+  sh_tolower(h_name); /* Canonical name of what the peer claims */
+
+  if ((0 == sl_strcmp(h_peer, h_name)) || (0 == sl_strcmp(h_peer_IP, h_name)))
+    {
+      SL_RETURN ((0), _("check_addr"));
+    }
+#if !defined(USE_IPVX)
+  else
+    {
+      struct hostent   * he = sh_gethostbyname(h_peer);
+      int                i = 0;
+      int                flag = 0;
+
+      while (he->h_aliases[i] != NULL)
+	{
+	  if (0 == sl_strcmp(sh_tolower(he->h_aliases[i]), h_name))
+	    {
+	      flag = 1;
+	      break;
+	    }
+	  ++i;
+	}
+      if (flag == 0) 
+	sh_error_handle(lookup_err, FIL__, __LINE__, 0, MSG_TCP_LOOKUP,
+			claim, h_peer);
+    }
+#endif
+
+  SL_RETURN ((0), _("check_addr"));
+}
+
+static int UseSocketPeer = S_FALSE;
+
+int set_socket_peer (const char * c)
+{
+  return sh_util_flagval(c, &UseSocketPeer);
+}
+
+
+/* -- Search register. --
+ */
+client_t * search_register(sh_conn_t * conn, int pos)
+{
+  client_t * this_client;
+  char       peer_ip[SH_IP_BUF];
+  char       numerical[SH_IP_BUF];
+  char       peer_name[MAXHOSTNAMELEN+1];
+  char     * search_string;
+
+  struct sh_sockaddr peer_addr;
+  char             * canonical;
+
+  SL_ENTER(_("search_register"));
+
+  if (UseSocketPeer == S_TRUE)
+    {
+      memcpy(&peer_addr, &(conn->addr_peer), sizeof(struct sh_sockaddr));
+      sh_ipvx_ntoa (peer_ip, sizeof(peer_ip), &peer_addr);
+
+      /* get canonical name of socket peer
+       */
+      canonical = sh_ipvx_canonical(peer_ip, numerical, sizeof(numerical));
+
+      if (canonical != NULL)
+	{
+	  if (0 == sl_strcmp(canonical, _("localhost")))
+	    sl_strlcpy(peer_name, sh.host.name, MAXHOSTNAMELEN + 1);
+	  else
+	    sl_strlcpy(peer_name, canonical,    MAXHOSTNAMELEN + 1);
+	  SH_FREE(canonical);
+	}
+
+      if (0 == sh_ipvx_reverse_check_ok (peer_name, ServerPort, &peer_addr))
+	{
+	  sl_strlcpy(peer_name, peer_ip, MAXHOSTNAMELEN + 1);
+	}
+
+      search_string = peer_name;
+    }
+  else
+    {
+      search_string = &(conn->buf[pos]);
+
+      if (0 != check_addr (search_string, &(conn->addr_peer)))
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+			  _("Reverse lookup failed"), search_string);
+	  sh_xfer_do_free (conn);
+	  SL_RETURN( NULL, _("search_register"));
+	} 
+    }
+
+  sh_tolower(search_string);
+
+  /* ----  search the register  -----
+   */
+  this_client = zAVLSearch(all_clients, search_string);
+
+  if (this_client == NULL)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+		      _("Not in client list"), search_string);
+      sh_xfer_do_free (conn);
+      SL_RETURN( NULL, _("search_register"));
+    } 
+  if (this_client->exit_flag == 1)
+    {
+      TPT((0, FIL__, __LINE__, _("msg=<this_client->exit_flag == 1>\n")));
+      this_client->session_key_timer = (time_t) 0;
+      this_client->session_key[0]    = '\0';
+      this_client->exit_flag         = 0;    
+    }
+  TPT((0, FIL__, __LINE__, _("msg=<search_register: client %s>\n"), 
+       this_client->hostname));
+  TPT((0, FIL__, __LINE__, _("msg=<search_register: key %s>\n"), 
+       this_client->session_key));
+  SL_RETURN( this_client, _("search_register"));
+}  
+
+client_t * do_check_client(sh_conn_t * conn, int * retval)
+{
+  client_t * this_client = NULL; 
+  char sigbuf[KEYBUF_SIZE];
+  
+  *retval = 0;
+
+  TPT(( 0, FIL__, __LINE__, _("msg=<Client connect - HELO (1).>\n")));
+	  
+  if (conn->buf == NULL || sl_strlen(conn->buf) <= KEY_LEN)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
+      sh_xfer_do_free (conn);
+      return NULL;
+    } 
+	  
+  /* ----  search the register  -----
+   */
+  
+  this_client = search_register (conn, KEY_LEN);
+  if (this_client == NULL)
+    return NULL;
+  
+  /* ---- force authentication -----
+   */
+  
+  if (this_client->session_key[0] == '\0' ||
+      (time(NULL) - this_client->session_key_timer) 
+      > (time_t) TIMEOUT_KEY )
+    {
+      size_t len;
+
+      /* fake an auth request and jump there
+       */
+      conn->head[0]  = (conn->head[0] | SH_PROTO_SRP);
+      conn->head[3]  = 'S';
+      conn->head[4]  = 'A';
+      conn->head[5]  = 'L';
+      conn->head[6]  = 'T';
+      if (flag_err_info == S_TRUE)
+	sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FAUTH,
+			&(conn->buf[KEY_LEN]));
+      len = sl_strlen(&(conn->buf[KEY_LEN])) + 1;
+      /* may overlap, thus only memmove is correct */
+      memmove(conn->buf, &(conn->buf[KEY_LEN]), len); 
+      this_client->session_key[0]    = '\0';
+      this_client->session_key_timer = (time_t) 1;
+      *retval = -1;
+      return NULL;
+    }
+
+  /* --- check whether hostname is properly signed ---
+   */ 
+  if (conn->K != NULL) 
+    {
+      SH_FREE(conn->K);
+      conn->K = NULL;
+    }
+  
+  conn->K = SH_ALLOC(KEY_LEN+1);
+  
+  sl_strlcpy (conn->K, 
+	      sh_util_siggen(this_client->session_key,
+			     &(conn->buf[KEY_LEN]),
+			     sl_strlen(&(conn->buf[KEY_LEN])),
+			     sigbuf, sizeof(sigbuf)),
+	      KEY_LEN+1);
+  
+  if (0 != sl_strncmp(conn->K, conn->buf, KEY_LEN))
+    {
+      TPT((0, FIL__, __LINE__, _("msg=<clt %s>\n"), conn->buf));
+      TPT((0, FIL__, __LINE__, _("msg=<srv %s>\n"), conn->K));
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+		      _("Signature mismatch"), 
+		      &(conn->buf[KEY_LEN]));
+      
+      this_client->session_key_timer =
+	time(NULL) - (2*TIMEOUT_KEY);
+      
+      sh_xfer_do_free (conn);
+      return NULL;
+    }
+  SH_FREE(conn->K); 
+  conn->K = NULL;
+
+  return this_client;
+}
+
+/* ------------------------------------------------------
+ *
+ *  FILE TRANSFER
+ *
+ * ------------------------------------------------------ */
+
+static void do_file_send_data(sh_conn_t * conn)
+{
+  char     * read_buf = 0;
+  char     * send_buf;
+  int        bytes;
+  SL_TICKET  sfd = -1;
+#ifdef SH_ENCRYPT
+  int        blkfac;
+  int        rem;
+  int        send_bytes;
+#endif
+
+  if (conn == NULL    || conn->FileName == NULL)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, sfd, MSG_TCP_NFILE,
+                      conn->peer, 
+                      (conn->FileName == NULL) ? 
+                      _("(NULL)") : conn->FileName);
+      status_update (conn->client_entry, CLT_FAILED);
+      sh_xfer_do_free (conn);
+      return;
+    }
+
+  if (conn->FileSent == conn->FileLength)
+    {
+      send_buf = hash_me(conn->K, conn->peer, sl_strlen(conn->peer));
+#ifdef SH_ENCRYPT
+      sh_xfer_send_crypt (conn, send_buf, sl_strlen(conn->peer)+KEY_LEN, 
+				  _("EEOT"), SH_PROTO_BIG|conn->client_entry->encf_flag);
+#else
+      sh_xfer_send_crypt (conn, send_buf, sl_strlen(conn->peer)+KEY_LEN, 
+				  _("EEOT"), SH_PROTO_BIG);
+#endif
+      SH_FREE(send_buf);
+    }
+  else
+    {
+      bytes = -1;
+
+      sfd = sl_open_read(FIL__, __LINE__, conn->FileName, SL_YESPRIV);
+
+      if (!SL_ISERROR(sfd))
+	{
+	  read_buf = SH_ALLOC(TRANS_BYTES);
+	  if (conn->FileSent > 0)
+	    sl_seek (sfd, (off_t) conn->FileSent);
+	  bytes = sl_read (sfd, read_buf, TRANS_BYTES);
+	  sl_close(sfd);
+	}
+      else
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, sfd, 
+			  MSG_E_ACCESS, (long) geteuid(), conn->FileName);
+	}
+
+      if (bytes >= 0)
+	{
+#ifdef SH_ENCRYPT
+	  /* need to send N * B_SIZ bytes
+	   */ 
+	  blkfac = bytes / B_SIZ;
+	  rem    = bytes - (blkfac * B_SIZ);
+	  if (rem != 0)
+	    {
+	      memset(&read_buf[bytes], '\n', (B_SIZ-rem));
+	      ++blkfac;
+	      send_bytes = blkfac * B_SIZ;
+	    }
+	  else
+	    send_bytes = bytes;
+	  
+	  send_buf = hash_me(conn->K, read_buf,  send_bytes);
+	  
+	  sh_xfer_send_crypt (conn, send_buf, send_bytes+KEY_LEN, _("FILE"),  
+				      SH_PROTO_BIG|conn->client_entry->encf_flag);
+#else
+	  send_buf = hash_me(conn->K, read_buf, bytes);
+	  sh_xfer_send_crypt (conn, send_buf, bytes+KEY_LEN, _("FILE"),  
+				      SH_PROTO_BIG);
+#endif
+	  conn->FileSent += bytes;
+	  if (send_buf) /* hash_me() *may* return NULL */
+	    SH_FREE(send_buf);
+	  SH_FREE(read_buf);
+	}
+      else
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NFILE, conn->peer,
+			  (conn->FileName == NULL) ? _("(NULL)") : conn->FileName);
+	  status_update (conn->client_entry, CLT_FAILED);
+	  sh_xfer_do_free (conn);
+	}
+    }
+  return;
+}
+
+static void do_file_initial(sh_conn_t * conn)
+{
+  char     * ptok;
+  char       hashbuf[KEYBUF_SIZE];
+
+  /* --- get client nonce and compute hash ---
+   *
+   *  K = H(NSRV, NCLT, session_key) 
+   */ 
+  if (conn->A != NULL)
+    {
+      SH_FREE(conn->A);
+      conn->A = NULL;
+    }
+  conn->A = SH_ALLOC(3*KEY_LEN+1);
+  sl_strlcpy (conn->A, conn->K, KEY_LEN+1); 
+  sl_strlcat(conn->A, conn->buf, /* truncate */
+	     2*KEY_LEN+1);
+  sl_strlcat(conn->A, conn->client_entry->session_key, 
+	     3*KEY_LEN+1);
+  sl_strlcpy (conn->K, sh_tiger_hash(conn->A,TIGER_DATA,3*KEY_LEN,
+				     hashbuf, sizeof(hashbuf)),
+	      KEY_LEN+1);
+  SH_FREE(conn->A); 
+  conn->A = NULL;
+  
+
+  /* Warn about encryption mismatch
+   */
+#ifdef SH_ENCRYPT
+  if ((conn->client_entry->encf_flag != 0) &&  /* server */
+      ((conn->head[0] & SH_PROTO_ENC) == 0))   /* client */
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
+		      _("file download"), _("version2"), _("none"));
+    }
+
+  else if ((conn->client_entry->encf_flag != 0) && /* server */
+	   ((conn->head[0] & SH_MASK_ENC) !=       /* client */
+	    conn->client_entry->encf_flag))
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
+		      _("file download"), _("version2"),
+		      ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? 
+		      _("version2") : _("invalid"));
+      conn->client_entry->encf_flag = (conn->head[0] & SH_MASK_ENC);
+    }
+#else
+  if ((conn->head[0] & SH_PROTO_ENC) != 0) 
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
+		      _("file download"), _("none"), 
+		      ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? 
+		      _("version2") : _("invalid"));
+    }
+#endif
+  
+  
+  if (conn->FileName != NULL)
+    {
+      SH_FREE(conn->FileName);
+      conn->FileName = NULL;
+    }
+
+  /* Determine what to send
+   */
+  if (0 == sl_strncmp (_("CONF"), &(conn->buf[KEY_LEN]), 4))
+    {
+      strcpy(conn->FileType, _("CONF"));     /* known to fit  */
+      conn->FileName = get_client_conf_file(conn->peer, &(conn->FileLength));
+      conn->FileSent = 0;
+    }
+  else  if (0 == sl_strncmp (_("DATA"), &(conn->buf[KEY_LEN]), 4))
+    {
+      strcpy(conn->FileType, _("DATA"));     /* known to fit  */
+      conn->FileName = get_client_data_file(conn->peer, &(conn->FileLength));
+      conn->FileSent = 0;
+    }
+  else  if (0 == sh_uuid_check(&(conn->buf[KEY_LEN])))
+    {
+      char * uuid = &(conn->buf[KEY_LEN]);
+      strcpy(conn->FileType, _("UUID"));     /* known to fit  */
+      conn->FileName = get_client_uuid_file(conn->peer, &(conn->FileLength), uuid);
+      conn->FileSent = 0;
+    }
+  else
+    {
+      ptok = sh_util_safe_name(&(conn->buf[KEY_LEN]));
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FFILE,
+		      conn->peer, 
+		      ptok);
+      SH_FREE(ptok);
+      status_update (conn->client_entry, CLT_FAILED);
+      sh_xfer_do_free (conn);
+    }
+
+  return;
+}
+
+
+static int do_file_transfer(sh_conn_t * conn, int state)
+{
+  client_t * this_client; 
+  UINT32     ticks;
+  char       hashbuf[KEYBUF_SIZE];
+
+  SL_ENTER(_("do_file_transfer"));
+
+  if (state == SH_DO_READ)        /* finished reading */
+    {
+      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - entry.>\n")));
+      
+      /* -- Client requests challenge. --
+       */
+      if (0 == check_request_nerr ((char *) &(conn->head[3]), _("HELO")))
+	{
+	  int client_state;
+
+	  this_client = do_check_client(conn, &client_state);
+	  if (!this_client)
+	    SL_RETURN(client_state, _("do_file_transfer"));
+
+	  /* --- create and send a nonce ---
+	   */
+	  
+	  conn->client_entry = this_client;
+	  sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1);
+	  
+	  ticks = (UINT32) taus_get ();
+	  
+	  if (conn->K != NULL) 
+	    {
+	      SH_FREE(conn->K);
+	      conn->K = NULL;
+	    }
+	  conn->K = SH_ALLOC(KEY_LEN+1);
+	  sl_strlcpy (conn->K, 
+		      sh_tiger_hash ((char *) &ticks, 
+				     TIGER_DATA, sizeof(UINT32), 
+				     hashbuf, sizeof(hashbuf)), 
+		      KEY_LEN+1);
+	  
+	  TPT((0, FIL__, __LINE__, _("msg=<send nonce>\n")));
+	  sh_xfer_prep_send (conn, conn->K, KEY_LEN+1, _("NSRV"), 
+				SH_PROTO_BIG);
+	}
+
+      /* --- Client has send a message. Check state and message. ---
+       */
+      else if (0 == check_request_nerr((char *)&(conn->head[3]), _("NCLT")) &&
+	       conn->client_entry != NULL                           &&
+	       sl_strlen(conn->buf) > KEY_LEN                       &&
+	       conn->K != NULL)
+	{
+	  
+	  TPT(( 0, FIL__, __LINE__, 
+		_("msg=<File transfer - NCLT (3).>\n")));
+	  
+          do_file_initial(conn);
+	  do_file_send_data(conn);
+	}
+      
+      else if (0 == check_request_nerr((char *)&(conn->head[3]), 
+				       _("RECV"))                    &&
+	       conn->client_entry != NULL                           &&
+	       conn->K != NULL                                      &&
+	       conn->FileName != NULL)
+	{
+	  
+	  TPT(( 0, FIL__, __LINE__, 
+		_("msg=<File transfer - RCVT (5+).>\n")));
+	  
+	  do_file_send_data(conn);
+	}
+      
+      
+      else if (0 == check_request_nerr((char *)&(conn->head[3]), 
+				       _("EOTE")) &&
+	       conn->client_entry != NULL)
+	{
+	  
+	  TPT(( 0, FIL__, __LINE__, 
+		_("msg=<File transfer - EOTE (7).>\n")));
+	  
+	  if (flag_err_info == S_TRUE)
+	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKFILE,
+			    conn->peer);
+	  
+	  if ((conn->client_entry->status_now != CLT_SUSPEND) &&
+	      (conn->client_entry->status_now != CLT_TOOLONG))
+	    { status_update (conn->client_entry, CLT_FILE); }
+	  else
+	    { conn->client_entry->session_key[0]    = '\0'; }
+	  conn->client_entry->last_connect = time (NULL);
+	  sh_xfer_do_free (conn);
+	}
+      
+      
+      /* client does something unexpected
+       */
+      else  /* ---- ??? ----- */
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
+			  1, conn->pass, conn->peer,  
+			  '\\', conn->head[3], '\\',conn->head[4],
+			  '\\', conn->head[5], '\\',conn->head[6]);
+	  status_update (conn->client_entry, CLT_FAILED);
+	  sh_xfer_do_free (conn);
+	}
+    }
+  
+  else if (state == SH_DO_WRITE)  /* finished writing */
+    {
+      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - (wait).>\n")));
+      
+      /* challenge is sent, now wait for message from client
+       */
+      conn->headcount     = 0;
+      conn->bytecount     = 0;
+      conn->bytes_to_send = 0;
+      conn->bytes_to_get  = 0;
+      if (conn->buf != NULL) 
+	{
+	  SH_FREE(conn->buf);
+	  conn->buf           = NULL;
+	}
+      conn->state     = CONN_READING;
+    }
+  SL_RETURN(0, _("do_file_transfer"));
+}
+
+/* ------------------------------------------------------
+ *
+ *  MESSAGE TRANSFER
+ *
+ * ------------------------------------------------------ */
+static int do_message_transfer(sh_conn_t * conn, int state)
+{
+  client_t * this_client; 
+  char     * cmd;
+  char       hash[SH_MAXMSGLEN + KEY_LEN + KEY_LEN + 1];
+  char     * buffer;
+  int        clt_sev;
+  char     * ptok;
+  UINT32     ticks;
+  size_t     len;
+  int        i;
+  char     * test;
+  char       sigbuf[KEYBUF_SIZE];
+
+  SL_ENTER(_("do_message_transfer"));
+
+  if (state == SH_DO_READ)        /* finished reading */
+    {
+      TPT(( 0, FIL__, __LINE__, _("msg=<File transfer - entry.>\n")));
+      
+      /* -- Client requests challenge. --
+       */
+      if (0 == check_request_nerr ((char *) &(conn->head[3]), _("HELO")))
+	{
+	  int client_state;
+	  
+	  this_client = do_check_client(conn, &client_state);
+	  if (!this_client)
+	    SL_RETURN(client_state, _("do_message_transfer"));
+	  
+	  
+	  /* -- create a nonce and send it --
+	   */
+	  conn->client_entry = this_client;
+	  sl_strlcpy (conn->peer, &(conn->buf[KEY_LEN]), SH_MINIBUF+1);
+	  
+	  ticks = (UINT32) taus_get ();
+	  
+	  test = (char *) &ticks;
+	  sh_util_cpylong (conn->challenge, test, 4);
+	  conn->challenge[4] = '\0';
+	  for (i = 0; i < 4; ++i)
+	    if (conn->challenge[i] == '\0')
+	      conn->challenge[i] = 0x01;
+      
+	  sh_xfer_prep_send (conn, conn->challenge, 5, _("TALK"), 
+				SH_PROTO_MSG);
+	  TPT(( 0, FIL__, __LINE__, _("msg=<Sent %s.>\n"), 
+		hu_trans(conn->challenge)));
+	}
+      
+      /* Client has send a message. Check whether we are in proper
+       * state, and verify message.
+       */
+      else if (0 == 
+	       check_request_nerr((char *)&(conn->head[3]), _("MESG")) &&
+	       conn->client_entry != NULL                           &&
+	       conn->client_entry->session_key[0] != '\0'           &&
+	       (len = sl_strlen(conn->buf) - KEY_LEN) > 0           &&
+	       sl_strlen(conn->challenge) == 4)
+	{
+	  TPT(( 0, FIL__, __LINE__, 
+		_("msg=<Message transfer - MESG (3).>\n")));
+	  
+#ifdef SH_ENCRYPT
+	  if (conn->client_entry->encf_flag == 0) {
+	    conn->client_entry->ency_flag = 0;
+	  }
+	  if ((conn->client_entry->ency_flag != 0) && 
+	      ((conn->head[0] & SH_PROTO_ENC) == 0)) 
+	    {
+	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_MISENC,
+			      _("message transfer"), 
+			      _("version2"),
+			      _("none"));
+	    }
+	  else if ((conn->client_entry->ency_flag != 0) &&
+		   ((conn->head[0] & SH_MASK_ENC) != 
+		    conn->client_entry->ency_flag))
+	    {
+	      sh_error_handle(SH_ERR_NOTICE, FIL__, __LINE__, 0, 
+			      MSG_TCP_MISENC,
+			      _("message transfer"), 
+			      _("version2"),
+			      ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? _("version2") : _("invalid"));
+	      conn->client_entry->ency_flag = 
+		(conn->head[0] & SH_MASK_ENC); 
+	    }
+#else
+	  if ((conn->head[0] & SH_PROTO_ENC) != 0) 
+	    {
+	      sh_error_handle((-1), FIL__, __LINE__, 0, 
+			      MSG_TCP_MISENC,
+			      _("message transfer"), 
+			      _("none"), 
+			      ((conn->head[0] & SH_PROTO_ENC) == SH_PROTO_ENC) ? _("version2") : _("invalid"));
+	    }
+#endif
+	  
+	  TPT(( 0, FIL__, __LINE__, _("msg=<Rcvt %s.>\n"), conn->buf));
+	  /* get hash from message end, truncate message
+	   */
+	  sl_strlcpy(hash, &(conn->buf[len]), KEY_LEN+1);
+	  conn->buf[len] = '\0';
+	  
+	  /* verify hash
+	   */
+	  buffer = sh_util_strconcat(conn->buf, conn->challenge, NULL);
+	  i =  sl_strncmp(hash, 
+			  sh_util_siggen(conn->client_entry->session_key,
+					 buffer,
+					 sl_strlen(buffer),
+					 sigbuf, sizeof(sigbuf)),
+			  KEY_LEN);
+	  TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
+	       sh_util_siggen(conn->client_entry->session_key,
+			      buffer,
+			      sl_strlen(buffer),
+			      sigbuf, sizeof(sigbuf))));
+	  
+	  
+	  if (0 != i)
+	    {
+	      TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
+	      status_update (conn->client_entry, CLT_FAILED);
+	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+			      _("Msg signature mismatch"), conn->peer);
+	      conn->client_entry->session_key_timer = 
+		time(NULL) - (2*TIMEOUT_KEY);
+	      sh_xfer_do_free (conn);
+	      SL_RETURN(0, _("do_message_transfer"));
+	    }
+	  else
+	    {
+	      conn->client_entry->last_connect = time (NULL);
+	      
+	      if (NULL != sl_strstr(conn->buf,      _("EXIT")))
+		{
+		  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
+		  conn->client_entry->exit_flag = 1;
+		  status_update (conn->client_entry, CLT_EXITED);
+		}
+	      else if (NULL != sl_strstr(conn->buf, _("PANIC")))
+		{
+		  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
+		  status_update (conn->client_entry, CLT_PANIC);
+		}
+	      else if (NULL != sl_strstr(conn->buf, _("SUSPEND")))
+		{
+		  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
+		  status_update (conn->client_entry, CLT_SUSPEND);
+		}
+	      else if (NULL != sl_strstr(conn->buf, _("POLICY")))
+		{
+		  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
+		  status_update (conn->client_entry, CLT_POLICY);
+		}
+	      else if (NULL != sl_strstr(conn->buf, 
+					 _("File check completed")))
+		{
+		  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
+		  status_update (conn->client_entry, CLT_CHECK);
+		}
+	      else if (NULL != sl_strstr(conn->buf, _("START")))
+		{
+		  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
+		  sh_socket_add2reload (conn->client_entry->hostname);
+		  if (conn->client_entry->status_now == CLT_SUSPEND) {
+		    status_update (conn->client_entry, CLT_ILLEGAL);
+		    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL,
+				    conn->peer);
+		  }
+		  else
+		    status_update (conn->client_entry, CLT_STARTED);
+		}
+	      else
+		{
+		  TPT((0, FIL__, __LINE__, _("msg=<update status>\n")));
+		  if (NULL != sl_strstr(conn->buf, 
+					_("Runtime configuration reloaded")))
+		    {
+		      sh_socket_add2reload (conn->client_entry->hostname);
+		    }
+		  status_update (conn->client_entry, CLT_MSG);
+		}
+	      
+	      TPT((0, FIL__, __LINE__, _("msg=<status updated>\n")));
+	      clt_sev   = atoi(conn->buf);
+	      clt_class = (-1);
+	      ptok    = strchr(conn->buf, '?');
+	      if (ptok != NULL)
+		{
+		  ++ptok;
+		  if (ptok != NULL && sh.flag.client_class == S_TRUE) 
+		    clt_class = atoi(ptok);  /* is a global */
+		  ptok = strchr(ptok, '?');
+		  if (ptok != NULL) 
+		    ++ptok;
+		}
+	      if (sh.flag.client_severity == S_FALSE)
+		clt_sev = (-1);
+	      
+	      /* here we expect an xml formatted message, thus we don't
+		 escape xml special chars (flag == 0) */
+	      ptok = 
+		sh_tools_safe_name ((ptok!=NULL) ? ptok : conn->buf, 0);
+	      
+	      /* push client name to error routine
+	       */
+#if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE)
+	      {
+		char peer_ip[SH_IP_BUF];
+		sh_ipvx_ntoa(peer_ip, sizeof(peer_ip), &(conn->addr_peer)); 
+		sh_error_set_peer_ip( peer_ip );
+	      }                        
+#endif
+	      {
+		char * pstrip = sh_strip_domain (conn->peer);
+		sh_error_set_peer(pstrip);
+		sh_error_handle(clt_sev, FIL__, __LINE__, 0, MSG_TCP_MSG,
+				pstrip, 
+				ptok);
+		SH_FREE(pstrip);
+		sh_error_set_peer(NULL);
+	      }
+#if defined(SH_WITH_SERVER) && defined(HAVE_LIBPRELUDE)
+	      sh_error_set_peer_ip(NULL);
+#endif
+	      
+	      TPT((0, FIL__, __LINE__, _("msg=<%s>\n"), ptok));
+	      SH_FREE(ptok);
+	      clt_class = (-1);
+	    }
+	  memset(buffer, '\0', sl_strlen(buffer));
+	  SH_FREE(buffer);
+	  
+	  /* SERVER CONF SEND
+	   */
+	  buffer = sh_util_strconcat(conn->buf,
+				     conn->challenge,
+				     NULL);
+	  sl_strlcpy(hash, 
+		     sh_util_siggen ( conn->client_entry->session_key,
+				      buffer,
+				      sl_strlen(buffer),
+				      sigbuf, sizeof(sigbuf)),
+		     KEY_LEN+1);
+	  
+	  /* --- SERVER CMD --- */
+	  cmd = sh_socket_check (conn->peer);
+	  
+	  if (cmd != NULL)
+	    {
+	      /* max cmd size is SH_MAXMSGLEN bytes
+	       */
+	      sl_strlcpy(&hash[KEY_LEN], cmd, SH_MAXMSGLEN);
+	      sl_strlcat(&hash[KEY_LEN],
+			 sh_util_siggen ( conn->client_entry->session_key,
+					  &hash[KEY_LEN],
+					  sl_strlen(&hash[KEY_LEN]),
+					  sigbuf, sizeof(sigbuf)),
+			 SH_MAXMSGLEN+KEY_LEN+1);
+	      
+	      TPT((0, FIL__, __LINE__, _("CONF SEND <0> <%s>\n"), 
+		   &hash[KEY_LEN]));
+	      
+	    } else {
+	    
+	    TPT((0, FIL__, __LINE__, _("CONF SEND <0> <[NULL]>\n")));
+	    
+	  }
+	  /* --- SERVER CMD END --- */
+	  
+	  TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
+	       sh_util_siggen(conn->client_entry->session_key,
+			      buffer,
+			      sl_strlen(buffer),
+			      sigbuf, sizeof(sigbuf))));
+	  
+#ifdef SH_ENCRYPT
+	  sh_xfer_send_crypt (conn, hash, 
+			      sl_strlen(hash) /* KEY_LEN */, 
+			      _("CONF"), 
+			      SH_PROTO_MSG|SH_PROTO_END|conn->client_entry->ency_flag);
+#else
+	  sh_xfer_send_crypt (conn, hash, 
+			      sl_strlen(hash) /* KEY_LEN */, 
+			      _("CONF"), 
+			      SH_PROTO_MSG|SH_PROTO_END);
+#endif
+	  
+	  memset(buffer, '\0', sl_strlen(buffer));
+	  SH_FREE(buffer);
+	  
+	  /* sh_xfer_do_free (conn); */
+	}
+      
+      /* client does something unexpected
+       */
+      else  /* ---- ??? ----- */
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
+			  2, conn->pass, conn->peer,  
+			  '\\', conn->head[3], '\\',conn->head[4],
+			  '\\', conn->head[5], '\\',conn->head[6]);
+	  status_update (conn->client_entry, CLT_FAILED);
+	  conn->client_entry->session_key_timer = 
+	    time(NULL) - (2*TIMEOUT_KEY);
+	  sh_xfer_do_free (conn);
+	}
+    }
+
+  else if (state == SH_DO_WRITE)  /* finished writing */
+    {
+      if (0 != (conn->head[0] & SH_PROTO_END))
+	{
+	  if (flag_err_debug == S_TRUE)
+	    {
+	      char * pstrip = sh_strip_domain (conn->peer);
+	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_OKMSG,
+			      pstrip);
+	      SH_FREE(pstrip);
+	    }
+	  sh_xfer_do_free (conn);
+	  SL_RETURN(0, _("do_message_transfer"));
+	}
+      
+      TPT(( 0, FIL__, __LINE__, _("msg=<Msg transfer - (wait).>\n")));
+      
+      /* challenge is sent, now wait for message from client
+       */
+      conn->headcount     = 0;
+      conn->bytecount     = 0;
+      conn->bytes_to_send = 0;
+      conn->bytes_to_get  = 0;
+      if (conn->buf != NULL) 
+	{
+	  SH_FREE(conn->buf);
+	  conn->buf           = NULL;
+	}
+      conn->state     = CONN_READING;
+    }
+  TPT((0, FIL__, __LINE__, _("msg=<return>\n") ));
+  SL_RETURN(0, _("do_message_transfer"));
+}
+
+/* ------------------------------------------------------
+ *
+ *  AUTHENTICATION
+ *
+ * ------------------------------------------------------ */
+
+static void check_probe(sh_conn_t * conn)
+{
+  if (conn && conn->client_entry)
+    {
+      /* If client has sent probe, change ivst_flag and clear probe in head[0].
+       */
+      conn->head[0] = sh_tools_probe_store(conn->head[0], 
+					   &(conn->client_entry->ivst_flag));
+    }
+}
+
+client_t * do_auth_start(sh_conn_t * conn)
+{
+  client_t * this_client;
+
+  TPT((0, FIL__, __LINE__, 
+       _("msg=<Authentication - SALT (1).>\n")));
+  
+  if (conn->buf == NULL || sl_strlen(conn->buf) == 0)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOCLT);
+      sh_xfer_do_free (conn);
+      return NULL;
+    } 
+                  
+  /* search the register
+   */
+  
+  this_client = search_register (conn, 0);
+  if (NULL == this_client)
+    return NULL;
+    
+  conn->client_entry = this_client;
+  sl_strlcpy (conn->peer, conn->buf, SH_MINIBUF+1);
+  
+  if (0 != check_request_s((char *)&(conn->head[3]), 
+			   _("SALT"),conn->peer))
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+		      _("No salt requested"), conn->peer);
+      status_update (conn->client_entry, CLT_FAILED);
+      conn->client_entry->session_key_timer = 
+	time(NULL) - (2*TIMEOUT_KEY);
+      sh_xfer_do_free (conn);
+      return NULL;
+    }
+
+  check_probe(conn);
+  return this_client;
+}
+
+#if !defined(USE_SRP_PROTOCOL)
+
+int do_auth(sh_conn_t * conn)
+{
+  client_t * this_client; 
+  UINT32     ticks;
+  char       u[5] = "OOOO";
+#ifdef SH_ENCRYPT
+  int        err_num;
+  char expbuf[SH_ERRBUF_SIZE];
+#endif
+  char       hash[SH_MAXMSGLEN + KEY_LEN + KEY_LEN + 1];
+  char hashbuf[KEYBUF_SIZE];
+
+  /* first pass -- client request salt  
+   */
+  if (conn->pass    == 1) 
+    {
+      this_client = do_auth_start(conn);
+
+      if (!this_client)
+	return -1;
+
+      /* -- create server nounce v --
+       */
+      ticks = (UINT32) taus_get ();
+      
+      if (conn->A != NULL)
+	{
+	  SH_FREE(conn->A);
+	  conn->A = NULL;
+	}
+      conn->A = SH_ALLOC(KEY_LEN+1);
+      
+      sl_strlcpy(conn->A, 
+		 sh_tiger_hash((char *) &ticks, 
+			       TIGER_DATA, sizeof(UINT32), 
+			       hashbuf, sizeof(hashbuf)),
+		 KEY_LEN+1);
+      u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0';
+      
+      if (conn->M1 != NULL)
+	{
+	  SH_FREE(conn->M1);
+	  conn->M1 = NULL;
+	}
+      conn->M1 = SH_ALLOC(2*KEY_LEN+1);
+      
+      /* compute hash key H(v(server), P)v(server)
+       */
+      sh_passwd (conn->A, conn->client_entry->verifier, 
+		 NULL, conn->M1);
+      
+      sl_strlcat(conn->M1, conn->A, 2*KEY_LEN+1);
+      
+      
+      /* --- send H(v(server), P)v(server) ----
+       */
+      sh_xfer_prep_send (conn, 
+			    conn->M1, 
+			    sl_strlen(conn->M1), 
+			    u, 
+			    (conn->head[0]|SH_PROTO_SRP));
+      
+      SH_FREE(conn->M1); 
+      conn->M1 = NULL;
+    }
+  
+  /* client -- third pass
+   * Message is H(H(u,v),P)u
+   *
+   * A := v, verifier := H(password), 
+   */
+  else if (conn->pass    == 3                   && 
+	   conn->client_entry != NULL)
+    {
+      
+      TPT((0, FIL__, __LINE__, 
+	   _("msg=<Authentication - PASS (3).>\n")));
+      
+      if (0 != check_request_s((char *) &(conn->head[3]), _("PASS"), 
+			       conn->peer)                    ||
+	  sl_strlen(conn->buf) <= KEY_LEN                        ||
+	  conn->A == NULL)
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+			  _("Invalid client request"), conn->peer);
+	  status_update (conn->client_entry, CLT_FAILED);
+	  conn->client_entry->session_key_timer = 
+	    time(NULL) - (2*TIMEOUT_KEY);
+	  sh_xfer_do_free (conn);
+	  return -1;
+	} 
+
+      check_probe(conn);
+
+      /* store random nonce u from client
+       */
+      if (conn->K != NULL)
+	{
+	  SH_FREE(conn->K);
+	  conn->K = NULL;
+	}
+      conn->K = SH_ALLOC(KEY_LEN+1);
+      sl_strlcpy(conn->K, &(conn->buf[KEY_LEN]), KEY_LEN+1);
+      
+      /* verify random nonce u from client
+       */
+      if (conn->M1 != NULL)
+	{
+	  SH_FREE(conn->M1);
+	  conn->M1 = NULL;
+	}
+      conn->M1 = sh_util_strconcat(conn->K, conn->A, NULL);
+      
+      TPT((0, FIL__, __LINE__, _("msg=<c/r: K = %s>\n"), conn->K));
+      TPT((0, FIL__, __LINE__, _("msg=<c/r: A = %s>\n"), conn->A));
+      TPT((0, FIL__, __LINE__, _("msg=<c/r: M = %s>\n"), conn->M1));
+      
+      sl_strlcpy(hash, sh_tiger_hash (conn->M1, 
+				      TIGER_DATA, 
+				      sl_strlen(conn->M1),
+				      hashbuf, sizeof(hashbuf)), 
+		 KEY_LEN+1); 
+      sh_passwd (hash, conn->client_entry->verifier, NULL, conn->M1);
+      
+      TPT((0, FIL__, __LINE__, _("msg=<c/r: H = %s>\n"), hash));
+      TPT((0, FIL__, __LINE__, _("msg=<c/r: P = %s>\n"), conn->M1));
+      
+      if ( 0 != sl_strncmp(conn->M1, conn->buf, KEY_LEN))
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+			  _("Session key mismatch"), conn->peer);
+	  status_update (conn->client_entry, CLT_FAILED);
+	  conn->client_entry->session_key_timer = 
+	    time(NULL) - (2*TIMEOUT_KEY);
+	  sh_xfer_do_free (conn);
+	  return -1;
+	} 
+      
+      /* ---- compute hash key H(v, P, u) ----
+       */
+      sh_passwd (conn->A, conn->client_entry->verifier, conn->K,
+		 conn->M1);
+      
+      sl_strlcpy(conn->client_entry->session_key, 
+		 conn->M1, KEY_LEN+1);
+      TPT((0, FIL__, __LINE__, _("msg=<c/r: Key = %s>\n"), 
+	   conn->client_entry->session_key));
+      
+#ifdef SH_ENCRYPT
+      err_num = rijndael_makeKey(&(conn->client_entry->keyInstE), 
+				 DIR_ENCRYPT, 192, 
+				 conn->client_entry->session_key);
+      if (err_num < 0)
+	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			errorExplain(err_num, expbuf, sizeof(expbuf)), 
+			_("check_protocol: makeKey"));
+      err_num = rijndael_makeKey(&(conn->client_entry->keyInstD), 
+				 DIR_DECRYPT, 192, 
+				 conn->client_entry->session_key);
+      if (err_num < 0)
+	sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			errorExplain(err_num, expbuf, sizeof(expbuf)), 
+			_("check_protocol: makeKey"));
+#endif
+      
+      if (conn->K  != NULL) SH_FREE (conn->K);
+      conn->K  = NULL;
+      if (conn->A  != NULL) SH_FREE (conn->A);
+      conn->A  = NULL;
+      if (conn->M1 != NULL) SH_FREE (conn->M1);
+      conn->M1 = NULL;
+      
+      /* if (conn->client_entry->status_now == CLT_STARTED */
+      if (((conn->client_entry->status_now != CLT_INACTIVE) &&
+	   (conn->client_entry->status_now != CLT_EXITED)   &&
+	   (conn->client_entry->status_now != CLT_SUSPEND))
+	  && conn->client_entry->session_key_timer > (time_t) 1)
+	{
+	  status_update (conn->client_entry, CLT_ILLEGAL);
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_ILL,
+			  conn->peer);
+	}
+      else if (conn->client_entry->session_key_timer == (time_t) 0)
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NEW,
+			  conn->peer);
+	  if (conn->client_entry->status_now != CLT_SUSPEND)
+	    status_update (conn->client_entry, CLT_STARTED);
+	}
+      
+      conn->client_entry->session_key_timer = time (NULL);
+      conn->client_entry->last_connect = time (NULL);
+      
+      /* put in read state
+       */
+      sh_xfer_prep_send (conn, 
+			    _("AUTH"),
+			    5, 
+			    _("AUTH"), 
+			    (conn->head[0]|SH_PROTO_SRP));
+      
+    }
+  else
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
+		      3, conn->pass, conn->peer, 
+		      '\\', conn->head[3], '\\', conn->head[4],
+		      '\\', conn->head[5], '\\', conn->head[6]);
+      sh_xfer_do_free (conn);
+    }
+  return 0;
+}
+
+#else
+
+static void noise()
+{
+  UINT32 n = taus_get();
+  retry_msleep(0, (n & 0x0000007F));
+  return;
+}
+  
+/* use SRP */
+
+int do_auth(sh_conn_t * conn)
+{
+  client_t * this_client; 
+  UINT32     ticks;
+  char       u[5] = "OOOO";
+#ifdef SH_ENCRYPT
+  int        err_num;
+  char expbuf[SH_ERRBUF_SIZE];
+#endif
+  size_t     len;
+  char     * test;
+  char     * foo_B;
+  char     * foo_Ss;
+  char hashbuf[KEYBUF_SIZE];
+
+  /* use SRP                    
+   */
+  if (conn->pass == 1)
+    {
+      this_client = do_auth_start(conn);
+      if (!this_client)
+	return -1;
+
+      u[0] = 'I'; u[1] = 'N'; u[2] = 'I'; u[3] = 'T'; u[4] = '\0';
+      sh_xfer_prep_send (conn, 
+			    conn->client_entry->salt, 
+			    sl_strlen(conn->client_entry->salt), 
+			    u, 
+			    (conn->head[0]|SH_PROTO_SRP));
+    }
+
+  /* client has sent A -- third pass
+   */
+  else if (conn->pass == 3                    && 
+	   conn->client_entry != NULL)
+    {
+      
+      TPT((0, FIL__, __LINE__, 
+	   _("msg=<Authentication - PC01 (3).>\n")));
+      
+      if (0 != check_request_s((char *)&(conn->head[3]),_("PC01"),conn->peer)||
+	  conn->buf == NULL
+	  )
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+			  _("Invalid client request"), conn->peer);
+	  status_update (conn->client_entry, CLT_FAILED);
+	  conn->client_entry->session_key_timer = 
+	    time(NULL) - (2*TIMEOUT_KEY);
+	  sh_xfer_do_free (conn);
+	  return -1;
+	} 
+      
+      check_probe(conn); noise();
+
+      if (0 != sh_srp_init())
+	{
+	  status_update (conn->client_entry, CLT_FAILED);
+	  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
+			  MSG_TCP_EBGN);
+	  sh_xfer_do_free (conn);
+	  return -1;
+	}
+      
+      
+      /* check A, only send B if correct 
+       */
+      if ( sl_strlen(conn->buf) < SH_BUFSIZE && 
+	   0 == sh_srp_check_zero (conn->buf) )
+	{
+	  len = sl_strlen(conn->buf)+1;
+	  
+	  if (conn->A != NULL)
+	    {
+	      SH_FREE(conn->A);
+	      conn->A = NULL;
+	    }
+	  conn->A = SH_ALLOC(len);
+	  sl_strlcpy (conn->A, conn->buf, len);
+	  
+	  /* 
+	   * compute B 
+	   */
+	  if (0 != sh_srp_make_a ())     /* b        random number */
+	    {
+	      status_update (conn->client_entry, CLT_FAILED);
+	      
+	      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
+			      MSG_TCP_EBGN);
+	      sh_srp_exit();
+	      sh_xfer_do_free (conn);
+	      return -1;
+	    }
+	  
+	  foo_B = sh_srp_B               /* B = v + g^b            */
+	    (conn->client_entry->verifier);
+	  
+	  if (foo_B == NULL)
+	    {
+	      status_update (conn->client_entry, CLT_FAILED);
+	      
+	      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
+			      MSG_TCP_EBGN);
+	      sh_srp_exit();
+	      sh_xfer_do_free (conn);
+	      return -1;
+	    }
+	  
+	  TPT((0, FIL__, __LINE__, _("msg=<srp: A = %s>\n"), conn->A));
+	  TPT((0, FIL__, __LINE__, _("msg=<srp: B = %s>\n"), foo_B));
+	  
+	  /* 
+	   * create nonce u 
+	   */
+	  ticks = (UINT32) taus_get ();
+	  
+	  test = (char *) &ticks;
+	  sh_util_cpylong (u, test, 4);  /* u        nounce        */
+	  u[4] = '\0';
+	  sl_strlcpy(conn->challenge, 
+		     sh_tiger_hash(u, TIGER_DATA, 4, hashbuf, sizeof(hashbuf)),
+		     SH_CHALLENGE_SIZE);
+	  
+	  TPT((0, FIL__, __LINE__, _("msg=<srp: u = %03o-%03o-%03o-%03o>\n"), u[0], u[1], u[2], u[3]));
+	  TPT((0, FIL__, __LINE__, _("msg=<srp: U = %s>\n"), 
+	       conn->challenge));
+	  
+	  /* 
+	   * compute the session key K and M1 = Hash(A,B,K)
+	   */
+	  foo_Ss = sh_srp_S_s (conn->challenge, 
+			       conn->A, 
+			       conn->client_entry->verifier);
+	  
+	  if (foo_Ss == NULL || 0 != sh_srp_check_zero (foo_Ss))
+	    {
+	      status_update (conn->client_entry, CLT_FAILED);
+	      
+	      sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
+			      MSG_TCP_EBGN);
+	      sh_srp_exit();
+	      sh_xfer_do_free (conn);
+	      return -1;
+	    }
+	  
+	  if (conn->K != NULL)
+	    {
+	      SH_FREE(conn->K);
+	      conn->K = NULL;
+	    }
+	  conn->K = SH_ALLOC(KEY_LEN+1);
+	  sl_strlcpy(conn->K, 
+		     sh_tiger_hash(foo_Ss, TIGER_DATA, 
+				   sl_strlen(foo_Ss), 
+				   hashbuf, sizeof(hashbuf)),
+		     KEY_LEN+1);
+	  
+	  if (conn->M1 != NULL)
+	    {
+	      SH_FREE(conn->M1);
+	      conn->M1 = NULL;
+	    }
+	  conn->M1 = SH_ALLOC(KEY_LEN+1);
+	  sh_srp_M (conn->A, foo_B, conn->K, conn->M1, KEY_LEN+1);
+	  
+	  TPT((0, FIL__, __LINE__, _("msg=<srp:Ss = %s>\n"), foo_Ss));
+	  TPT((0, FIL__, __LINE__, _("msg=<srp: K = %s>\n"), conn->K));
+	  TPT((0, FIL__, __LINE__, _("msg=<srp:M1 = %s>\n"),conn->M1));
+	  
+	  /*
+	   * send B
+	   */
+	  sh_xfer_prep_send (conn, 
+				foo_B,
+				sl_strlen(foo_B)+1,
+				u,
+				(conn->head[0]|SH_PROTO_SRP));
+	  if (foo_Ss != NULL)
+	    {
+	      SH_FREE(foo_Ss);
+	      foo_Ss = NULL;
+	    }
+	  if (foo_B  != NULL)
+	    {
+	      SH_FREE(foo_B);
+	      foo_B = NULL;
+	    }
+	}
+      else
+	{
+	  status_update (conn->client_entry, CLT_FAILED);
+	  
+	  sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, 
+			  MSG_TCP_EZERO);
+	  sh_xfer_do_free (conn);
+	}
+      
+      sh_srp_exit();
+    }
+  
+  /* client has sent M1 -- fifth pass
+   */
+  else if (conn->pass    == 5           && 
+	   conn->client_entry != NULL) 
+    {
+      TPT((0, FIL__, __LINE__, 
+	   _("msg=<Authentication - PC02 (5).>\n")));
+      
+      /* check that the state is valid
+       */
+      if (0 != check_request_s((char *)&(conn->head[3]), _("PC02"),
+			       conn->peer)                   ||
+	  conn->A == NULL || conn->K == NULL || conn->M1 == NULL)
+	{
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+			  _("Invalid client request"), conn->peer);
+	  status_update (conn->client_entry, CLT_FAILED);
+	  conn->client_entry->session_key_timer = 
+	    time(NULL) - (2*TIMEOUT_KEY);
+	  sh_xfer_do_free (conn);
+	  return -1;
+	} 
+
+      check_probe(conn); noise();
+
+      /* ------ verify M1 = H(A,  B, K) -------
+       * -----    send M2 = H(A, M1, K) -------
+       */
+      if (conn->buf != NULL && 
+	  sl_strncmp(conn->buf, conn->M1, KEY_LEN) == 0)
+	{
+	  /*
+	   * send M2
+	   */
+	  char M_buf[KEY_LEN+1];
+	  sh_xfer_prep_send (conn, 
+				sh_srp_M (conn->A, conn->M1, conn->K,
+					  M_buf, sizeof(M_buf)),
+				KEY_LEN+1,
+				_("PARP"),
+				(conn->head[0]|SH_PROTO_SRP));
+	  
+	  if (conn->A  != NULL) SH_FREE(conn->A);  conn->A  = NULL;
+	  if (conn->M1 != NULL) SH_FREE(conn->M1); conn->M1 = NULL;
+	  sl_strlcpy(conn->client_entry->session_key, 
+		     conn->K, KEY_LEN+1);
+	  TPT((0, FIL__, __LINE__, _("msg=<key %s>\n"), 
+	       conn->client_entry->session_key));
+	  
+#ifdef SH_ENCRYPT
+	  err_num = rijndael_makeKey(&(conn->client_entry->keyInstE), 
+				     DIR_ENCRYPT, 192, 
+				     conn->client_entry->session_key);
+	  if (err_num < 0)
+	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
+			    _("sh_xfer_prep_send_int: makeKey"));
+	  err_num = rijndael_makeKey(&(conn->client_entry->keyInstD), 
+				     DIR_DECRYPT, 192, 
+				     conn->client_entry->session_key);
+	  if (err_num < 0)
+	    sh_error_handle((-1), FIL__, __LINE__, -1, MSG_E_SUBGEN,
+			    errorExplain(err_num, expbuf, sizeof(expbuf)), 
+			    _("sh_xfer_prep_send_int: makeKey"));
+#endif
+	  
+	  if (conn->K  != NULL) SH_FREE(conn->K);  conn->K  = NULL;
+	  
+	  conn->client_entry->last_connect = time (NULL);
+	  
+	  if (((conn->client_entry->status_now != CLT_INACTIVE) &&
+	       (conn->client_entry->status_now != CLT_EXITED)   &&
+	       (conn->client_entry->status_now != CLT_SUSPEND))
+	      && conn->client_entry->session_key_timer > (time_t) 1)
+	    {
+	      status_update (conn->client_entry, CLT_ILLEGAL);
+	      
+	      sh_error_handle((-1), FIL__, __LINE__, 0, 
+			      MSG_TCP_ILL,
+			      conn->peer);
+	    }
+	  else if (conn->client_entry->session_key_timer == (time_t) 0)
+	    {
+	      sh_error_handle((-1), FIL__, __LINE__, 0, 
+			      MSG_TCP_NEW,
+			      conn->peer);
+	      if (conn->client_entry->status_now != CLT_SUSPEND)
+		status_update (conn->client_entry, CLT_STARTED);
+	    }
+	  conn->client_entry->session_key_timer = time (NULL);
+	  
+	}
+      else
+	{
+	  status_update (conn->client_entry, CLT_FAILED);
+	  conn->client_entry->session_key_timer = 
+	    time(NULL) - (2*TIMEOUT_KEY);
+	  
+	  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
+			  _("Session key mismatch"), conn->peer);
+	  sh_xfer_do_free (conn);
+	} 
+    }
+  
+  else
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_FINV,
+		      4, conn->pass, conn->peer, 
+		      '\\', conn->head[3], '\\', conn->head[4],
+		      '\\', conn->head[5], '\\', conn->head[6]);
+      sh_xfer_do_free (conn);
+    }
+  return 0;
+}
+#endif
+
+/************************************************************************
+ *
+ * Here we check the message received, and decide on the answer to send
+ * (if any). The connection is in CONN_PAUSED state, thus we must:
+ * (i)   define the proper reaction
+ * (ii)  reset to CONN_READING or CONN_WRITING or CONN_FREE
+ * (iii) eventually reset the connection entry
+ *
+ *************************************************************************/
+static
+void check_protocol(sh_conn_t * conn, int state)
+{
+  SL_ENTER(_("check_protocol"));
+
+  /* seed / re-seed the PRNG if required
+   */
+  (void) taus_seed();
+
+  /* protocols: 
+   * -- (iii)    file transfer
+   * -- (ii)     authenticated message transfer
+   * -- (i)      SRP key exchange
+   */
+
+  /* --------- FILE TRANSFER  -----------
+   */
+  if ( (conn->head[0] & SH_PROTO_SRP) == 0  &&
+       (conn->head[0] & SH_PROTO_BIG) != 0  /* is set */ )
+    {
+      /* nonzero means re-authentication is required
+       */
+      if (0 == do_file_transfer(conn, state))
+	SL_RET0(_("check_protocol"));
+    }
+  /* --------- END FILE TRANSFER ----------- */
+
+
+  /* ---------  message exchange  -----------
+   */
+  else if ((conn->head[0] & SH_PROTO_SRP) == 0  && 
+	   (conn->head[0] & SH_PROTO_MSG) != 0  /* is set */ )
+    {
+      /* nonzero means re-authentication is required
+       */
+      if (0 == do_message_transfer(conn, state))
+	SL_RET0(_("check_protocol"));
+    }
+  /* ---------  END MESSAGE TRANSFER ------ */
+
+  /* ---------  authentication  -----------
+   */
+  if ( (conn->head[0] & SH_PROTO_SRP) != 0   /* is set */ )
+    {
+      if (state == SH_DO_READ)        /* finished reading */
+	{
+	  do_auth(conn);
+	}
+
+      else if (state == SH_DO_WRITE)  /* finished writing */
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Authentication -- (wait).>\n")));
+
+	  conn->headcount     = 0;
+	  conn->bytecount     = 0;
+	  conn->bytes_to_send = 0;
+	  conn->bytes_to_get  = 0;
+	  if (conn->buf != NULL) 
+	    {
+	      SH_FREE(conn->buf);
+	      conn->buf           = NULL;
+	    }
+	  conn->state     = CONN_READING;
+	}
+    }
+  SL_RET0(_("check_protocol"));
+}
+
+
+/***********************************************************
+ *
+ *    SERVER RECEIVE FUNCTION
+ *
+ ***********************************************************
+ */
+int sh_xfer_do_read (sh_conn_t * conn)
+{
+  unsigned long   byteread;     /* bytes read         */
+
+  SL_ENTER(_("sh_xfer_do_read"));
+
+  if (conn->state == CONN_SENDING)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_SYNC,
+		      conn->peer);
+      SL_RETURN( (-1), _("sh_xfer_do_read"));
+    }
+
+  if (conn->headcount < SH_HEADER_SIZE) 
+    {
+      conn->bytes_to_get = SH_HEADER_SIZE - conn->headcount;
+      byteread = read (conn->fd, &(conn->head[conn->headcount]),
+		       conn->bytes_to_get);
+      if (byteread > 0 || errno == EINTR) 
+	{
+	  if (byteread > 0) 
+	    conn->headcount += byteread;
+	  if (conn->headcount == SH_HEADER_SIZE)
+	    {
+	      conn->bytes_to_get = (256 * (unsigned int)conn->head[1] + 
+				    (unsigned int)conn->head[2]);
+	      SH_SHOWPROT(conn->head, '<');
+	      conn->bytecount = 0;
+	    }
+	}
+      else
+	goto conn_reset;
+      SL_RETURN( (0), _("sh_xfer_do_read"));
+    }
+
+  /* limit message size
+   */
+  conn->bytes_to_get = (conn->bytes_to_get > TRANS_BYTES) ? 
+    TRANS_BYTES : conn->bytes_to_get;
+
+  if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get > 0)
+    {
+      if ( conn->bytecount == 0)
+	{
+	  if (conn->buf != NULL)
+	    SH_FREE (conn->buf);
+	  conn->buf = SH_ALLOC(conn->bytes_to_get + 1); /* <= TRANS_BYTES+1 */
+	}
+
+      byteread           = read (conn->fd, &(conn->buf[conn->bytecount]),
+				 conn->bytes_to_get - conn->bytecount);
+      if (byteread > 0 || errno == EINTR) 
+	{
+	  if (byteread > 0) 
+	    conn->bytecount    += byteread;
+	  if (conn->bytecount == conn->bytes_to_get) 
+	    {
+	      ++conn->pass;
+	      /* always terminate with NULL - we might use sl_strcmp() */
+	      conn->buf[conn->bytecount] = '\0';
+	      conn->state                = CONN_PAUSE;
+
+#ifdef SH_ENCRYPT
+	      if ((conn->head[0] & SH_PROTO_ENC) != 0) 
+		{
+		  conn->buf = sh_tools_revertPack (conn->head, 
+						   conn->client_entry->ivst_flag,
+						   conn->buf,
+						   &(conn->client_entry->keyInstD),
+						   conn->bytecount);
+		}
+#endif
+	      /* ------  HERE CALL check_protocol(conn) -------  */
+	      check_protocol(conn, SH_DO_READ);
+	    }
+	}
+      else
+	  goto conn_reset;
+    }
+
+  else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_get == 0)
+    {
+      if (conn->buf != NULL)
+	SH_FREE (conn->buf);
+      conn->buf       = NULL;
+      conn->bytecount = 0;
+      ++conn->pass;
+      conn->state     = CONN_PAUSE;
+      /* ------  HERE CALL check_protocol(conn) -------  */
+      check_protocol(conn, SH_DO_READ);
+    }
+      
+  SL_RETURN( (0), _("sh_xfer_do_read"));
+
+ conn_reset:
+  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET,
+		  conn->peer);
+  sh_xfer_do_free ( conn );
+  SL_RETURN( (-1), _("sh_xfer_do_read"));
+}
+
+#if !defined(O_NONBLOCK)
+#if defined(O_NDELAY)
+#define O_NONBLOCK  O_NDELAY
+#else
+#define O_NONBLOCK  0
+#endif
+#endif
+
+/* send to the client
+ */
+int sh_xfer_do_write (sh_conn_t * conn)
+{
+  int    flags;
+  long   arg = 0;
+  long   bytesent;     /* bytes read         */
+
+  SL_ENTER(_("sh_xfer_do_write"));
+
+  /* ---- consistency check ------
+   */
+  if (conn->state == CONN_READING)
+    {
+      sh_error_handle( (-1), FIL__, __LINE__, 0, MSG_TCP_SYNC,
+		      conn->peer);
+      SL_RETURN( (-1), _("sh_xfer_do_write"));
+    }
+ 
+  flags = retry_fcntl (FIL__, __LINE__, conn->fd, F_GETFL, arg);
+  retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags|O_NONBLOCK);
+
+  /* ---- send the header ------
+   */
+  if (conn->headcount < SH_HEADER_SIZE) 
+    {
+      conn->bytes_to_send = SH_HEADER_SIZE - conn->headcount;
+      bytesent = write (conn->fd, &(conn->head[conn->headcount]), 
+			conn->bytes_to_send);
+      if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) 
+	{
+	  if (bytesent > 0) 
+	    conn->headcount += bytesent;
+	  if (conn->headcount == SH_HEADER_SIZE) 
+	    conn->bytes_to_send = 
+	      (256 * (int)conn->head[1] + (int)conn->head[2]);
+	}
+      else 
+	goto conn_reset_w;
+
+      if (conn->fd >= 0)
+	retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags);
+      SL_RETURN( (0), _("sh_xfer_do_write"));
+    }
+
+  /* ---- send the body ------
+   */
+
+  if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send > 0 &&
+      conn->buf != NULL)
+    {
+      bytesent = write (conn->fd, &(conn->buf[conn->bytecount]), 
+			conn->bytes_to_send - conn->bytecount);
+      if (bytesent >= 0 || errno == EINTR || errno == EAGAIN) 
+	{
+	  if (bytesent > 0) 
+	    conn->bytecount    += bytesent;
+	  if (conn->bytecount == conn->bytes_to_send) 
+	    {
+	      ++conn->pass;
+	      conn->state = CONN_PAUSE;
+	      /* ------  HERE CALL check_protocol(conn) -------  */
+	      check_protocol(conn, SH_DO_WRITE);
+	    }
+	}
+      else
+	goto conn_reset_w;
+    }
+      
+  else if (conn->headcount == SH_HEADER_SIZE && conn->bytes_to_send == 0)
+    {
+      ++conn->pass;
+      conn->state = CONN_PAUSE;
+      /* ------  HERE CALL check_protocol(conn) -------  */
+      check_protocol(conn, SH_DO_WRITE);
+    }
+
+  if (conn->fd >= 0)
+    retry_fcntl (FIL__, __LINE__, conn->fd, F_SETFL,  flags);
+  SL_RETURN( (0), _("sh_xfer_do_write"));
+
+ conn_reset_w:
+  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_RESET,
+		  conn->peer);
+  sh_xfer_do_free ( conn );
+  SL_RETURN( (-1), _("sh_xfer_do_write"));
+}
+
+/* accept a connection from a client
+ */ 
+#include <syslog.h>
+#ifdef SH_USE_LIBWRAP
+#include <tcpd.h>
+
+#ifndef ALLOW_SEVERITY 
+#define ALLOW_SEVERITY LOG_INFO
+#define DENY_SEVERITY  LOG_WARNING
+#endif
+
+int allow_severity;
+int deny_severity;
+#endif
+
+#ifdef SH_USE_LIBWRAP
+static int check_libwrap(int rc, sh_conn_t * newconn)
+{
+  struct request_info request;
+  char                errbuf[128];
+  char                daemon[128];
+
+  sl_strlcpy(daemon, SH_INSTALL_NAME, sizeof(daemon));
+  request_init(&request, RQ_DAEMON, daemon, RQ_FILE, rc, 0);
+  fromhost(&request);
+  if (!hosts_access(&request)) 
+    {
+      sl_strlcpy(errbuf, _("Refused connection from "), sizeof(errbuf));
+      sl_strlcat(errbuf,   eval_client(&request), sizeof(errbuf));
+      
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+		      errbuf, _("libwrap"));
+      newconn->fd    = -1;
+      newconn->state = CONN_FREE;
+      sl_close_fd(FIL__, __LINE__, rc);
+      return -1;
+    }
+  return 0;
+}
+#endif
+
+int sh_xfer_accept (int sock, sh_conn_t * newconn)
+{
+  int                errflag;
+  int                rc;
+  struct sh_sockaddr addr;
+  
+  /* handle AIX (size_t addrlen) in wrapper
+   */
+  int                addrlen = sizeof(addr);
+
+  SL_ENTER(_("sh_xfer_accept"));
+
+  rc = retry_accept(FIL__, __LINE__, sock, &addr, &addrlen);
+
+  if (rc < 0)
+    {
+      char err_buf[SH_ERRBUF_SIZE];
+      errflag = errno;
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+		      sh_error_message(errflag,err_buf, sizeof(err_buf)), _("accept"));
+      newconn->fd    = -1;
+      newconn->state = CONN_FREE;
+      SL_RETURN( (-1), _("sh_xfer_accept"));
+    }
+
+  if (addrlen == 0)
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+		      _("Connecting entity unknown"), _("accept"));
+      newconn->fd    = -1;
+      newconn->state = CONN_FREE;
+      sl_close_fd(FIL__, __LINE__, rc);
+      SL_RETURN( (-1), _("sh_xfer_accept"));
+    }
+
+#ifdef SH_USE_LIBWRAP
+  if (check_libwrap(rc) < 0)
+    SL_RETURN( (-1), _("sh_xfer_accept"));
+#endif
+
+  memcpy (&(newconn->addr_peer), &addr, sizeof(struct sh_sockaddr));
+
+  /* prepare for usage of connection
+   */
+  (void) retry_fcntl( FIL__, __LINE__, rc, F_SETFD, 1 );
+  newconn->fd           = rc;
+  newconn->state        = CONN_READING;
+  newconn->timer        = (unsigned long) time (NULL);
+  
+  if (flag_err_info == S_TRUE)
+    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_CNEW, newconn->fd);
+
+  SL_RETURN( (0), _("sh_xfer_accept"));
+}
+
+extern char sh_sig_msg[64];  /* defined in sh_unix.c */
+
+/* ------------  port and interface -------
+ */
+static unsigned int server_port = SH_DEFAULT_PORT;
+
+int sh_xfer_set_port (const char * str)
+{
+  int retval = 0;
+  unsigned long   i;
+  char * endptr;
+  
+  SL_ENTER(_("sh_xfer_set_port"));
+  i = strtoul (str, &endptr, 0);
+  if (endptr == str) {
+    retval = -1;
+  } else if (i > 65535) {
+    retval = -1;
+  } else {
+    server_port = i;
+  }
+  SL_RETURN( (retval), _("sh_xfer_set_port"));
+}
+
+static struct sh_sockaddr server_interface;
+static int            use_server_interface = 0;
+
+int sh_xfer_set_interface (const char * str)
+{
+  if (0 == strcmp(str, _("INADDR_ANY")))
+    {
+      use_server_interface = 0;
+      return 0;
+    }
+
+  if (0 == sh_ipvx_aton(str, &server_interface)) 
+    {
+      use_server_interface = 0;
+      return -1;
+    }
+
+  use_server_interface = 1;
+  return 0;
+}
+
+/* ------------  print error --------------
+ */
+struct sock_err_st {
+  char msg[128];
+  int  errnum;
+  int  port;
+  int  line;
+  int  euid;
+};
+
+static struct sock_err_st sock_err[2];
+
+void sh_xfer_printerr(char * str, int errnum, unsigned int port, int line)
+{
+  int slot = 0;
+
+  if (port != server_port)
+    slot = 1;
+  if (str == NULL)
+    sock_err[slot].msg[0] = '\0';
+  else
+    sl_strlcpy(sock_err[slot].msg, str, 128);
+  sock_err[slot].errnum = errnum;
+  sock_err[slot].port   = port;
+  sock_err[slot].line   = line;
+  sock_err[slot].euid   = (int) geteuid();
+}
+
+int sh_xfer_printerr_final(int slot)
+{
+  char errbuf[SH_ERRBUF_SIZE];
+
+  SL_ENTER(_("sh_xfer_printerr_final"));
+  if (sock_err[slot].msg[0] != '\0')
+    {
+      dlog(1, FIL__, __LINE__, 
+	   _("Could not set up the listening socket for the server because of the\nfollowing error: %s\nPossible reasons include:\n - insufficient privilege for UID %d, or\n - the port %d is already used by another program.\n"),
+	   sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)), 
+	   sock_err[slot].euid, 
+	   sock_err[slot].port);
+      sh_error_handle((-1), FIL__, sock_err[slot].line, 
+		      sock_err[slot].errnum, MSG_EXIT_ABORTS,
+		      sh_error_message(sock_err[slot].errnum, errbuf, sizeof(errbuf)),
+		      sh.prg_name,
+		      sock_err[slot].msg);
+      SL_RETURN((-1), _("sh_xfer_printerr_final"));
+    }
+  SL_RETURN(0, _("sh_xfer_printerr_final"));
+}
+
+#define  TIME_OUT_DEF 900
+static   unsigned long  time_out_val = TIME_OUT_DEF;
+
+int sh_xfer_set_timeout (const char * c)
+{
+  long val;
+
+  SL_ENTER(_("sh_xfer_set_time_out"));
+
+  val = strtol (c, (char **)NULL, 10);
+
+  if (val == 0)
+    {
+      val = TIME_OUT_DEF;
+    }
+  else if (val < 0)
+    {
+      time_out_val = TIME_OUT_DEF;
+      SL_RETURN( (-1), _("sh_xfer_set_time_out"));
+    }
+
+  time_out_val = (unsigned long) val;
+  SL_RETURN( (0), _("sh_xfer_set_time_out"));
+}
+
+
+static   sh_conn_t        * conns = NULL;
+static   int  maxconn = 0;  /* maximum number of simultaneous connections */
+
+
+#ifdef INET_SYSLOG
+#define INET_SUSPEND_TIME 180		/* equal to 3 minutes */
+#define SH_MINSOCK_DEFAULT 3
+int sh_xfer_syslog_sock[SH_SOCKMAX] = { -1 };
+extern int sh_xfer_recv_syslog_socket   (int fd);
+int sh_xfer_syslog_sock_n = 0;
+#else
+#define SH_MINSOCK_DEFAULT 2
+#endif
+
+int SH_MINSOCK = SH_MINSOCK_DEFAULT;
+
+extern int pf_unix_fd;
+
+/* the tcp socket, and the function to establish it
+ */
+static int sh_tcp_sock[SH_SOCKMAX] = { -1 };
+static int sh_tcp_sock_n = 0;
+
+static int do_socket(int domain, int type, int protocol,
+		     struct sockaddr * sa, int salen)
+{
+  int sock = -1;
+  int errnum = 0;
+  int flag   = 1; /* non-zero to enable an option */
+
+  /* create the socket, bind() it and listen()
+   */
+  if ((sock = socket(domain, type, protocol)) < 0 )
+    {
+      errnum = errno; 
+      sh_xfer_printerr (_("socket"), errnum, server_port, __LINE__);
+      return -1;
+    }
+  (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 );
+ 
+  if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+		  (void *) &flag, sizeof(flag)) < 0 )
+    {
+      errnum = errno;
+      sh_xfer_printerr (_("setsockopt"), errnum, server_port, __LINE__);
+      sl_close_fd (FIL__, __LINE__, sock);
+      return -1;
+    }
+  
+  if ( bind(sock, (struct sockaddr *) sa, salen) < 0) 
+    {
+      if (errno != EADDRINUSE)
+	{
+	  errnum = errno;
+	  sh_xfer_printerr (_("bind"), errnum, server_port, __LINE__);
+	  sl_close_fd (FIL__, __LINE__, sock);
+	  return -1;
+	}
+      else
+	{
+	  sl_close_fd (FIL__, __LINE__, sock);
+	  return -2;
+	}
+    }
+  
+  if ( retry_fcntl( FIL__, __LINE__, sock, F_SETFL, O_NONBLOCK ) < 0 )
+    {
+      errnum = errno;
+      sh_xfer_printerr (_("fcntl"), errnum, server_port, __LINE__);
+      sl_close_fd (FIL__, __LINE__, sock);
+      return -1;
+    }
+  
+  if ( listen(sock, 64) < 0)
+    {
+      errnum = errno;
+      sh_xfer_printerr (_("listen"), errnum, server_port, __LINE__);
+      sl_close_fd (FIL__, __LINE__, sock);
+      return -1;
+    }
+
+  return sock;
+}
+
+int sh_create_tcp_socket (void)
+{
+#if defined(USE_IPVX)
+  struct addrinfo *ai;
+  struct addrinfo *p;
+  struct addrinfo hints;
+  char            port[32];
+#else
+  struct sockaddr_in addr;
+  int addrlen      = sizeof(addr);
+#endif
+
+  int sock   = -1;
+
+  SL_ENTER(_("sh_create_tcp_socket"));
+
+  sh_xfer_printerr (NULL, 0, server_port, __LINE__);
+
+#if defined(USE_IPVX)
+  if (use_server_interface == 0) /* INADDR_ANY, listen on all interfaces */
+    {
+      memset (&hints, '\0', sizeof (hints));
+      hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+      hints.ai_socktype = SOCK_STREAM;
+      hints.ai_family   = AF_UNSPEC;
+      sl_snprintf(port, sizeof(port), "%d", server_port);
+
+      if (getaddrinfo (NULL, port, &hints, &ai) != 0)
+	{
+	  int errnum = errno;
+	  sh_xfer_printerr (_("getaddrinfo"), errnum, server_port, __LINE__);
+	  sl_close_fd (FIL__, __LINE__, sock);
+	  SL_RETURN((-1), _("sl_create_tcp_socket"));
+	}
+      
+      p = ai;
+      
+      while (p != NULL && sh_tcp_sock_n < SH_SOCKMAX)
+	{
+	  sock = do_socket(p->ai_family, p->ai_socktype, p->ai_protocol,
+			   p->ai_addr, p->ai_addrlen);
+	  
+	  if (sock >= 0) {
+	    if (sh_tcp_sock_n < SH_SOCKMAX) {
+	      sh_tcp_sock[sh_tcp_sock_n] = sock;
+	      ++sh_tcp_sock_n;
+	    }
+	    else {
+	      sl_close_fd (FIL__, __LINE__, sock);
+	    }    
+	  } else if (sock == -1) {
+	    freeaddrinfo (ai);
+	    goto end;
+	  }
+	  p = p->ai_next;
+	}
+      
+      freeaddrinfo (ai);
+    }
+  else
+    {
+      sh_ipvx_set_port(&server_interface, server_port);
+
+      sock = do_socket(server_interface.ss_family, SOCK_STREAM, 0, 
+		       sh_ipvx_sockaddr_cast(&server_interface), 
+		       SH_SS_LEN(server_interface));
+      
+      if (sock >= 0) {
+	sh_tcp_sock[0] = sock;
+	sh_tcp_sock_n  = 1;
+      }
+    }	       
+#else
+  if (use_server_interface == 0)
+    addr.sin_addr.s_addr = INADDR_ANY;
+  else
+    memcpy(&addr, sh_ipvx_sockaddr_cast(&server_interface), addrlen);
+  addr.sin_family      = AF_INET;
+  addr.sin_port        = htons(server_port);
+  
+  sock = do_socket(AF_INET, SOCK_STREAM, 0, (struct sockaddr *) &addr, addrlen);
+
+  if (sock >= 0) {
+      sh_tcp_sock[0] = sock;
+      sh_tcp_sock_n  = 1;
+  }
+
+#endif
+
+#if defined(USE_IPVX)
+ end:
+#endif
+  if (sh_tcp_sock_n > 1)
+    SH_MINSOCK += (sh_tcp_sock_n - 1);
+
+  SL_RETURN((sh_tcp_sock_n), _("sl_create_tcp_socket"));
+}
+
+/*****************************************
+ *
+ * This is the server main loop.
+ *
+ * The server is set up for listening, and
+ * and starts a select() loop.
+ *
+ *****************************************/
+
+void sh_xfer_start_server()
+{
+#ifdef SH_USE_XML
+  extern int  sh_log_file    (char * message, char * inet_peer);
+#endif
+
+  /* Use volatile to circumvent a gcc4 problem on RH/CentOS 4.8 (?) */
+  volatile int       sock = -1;
+  sh_conn_t        * cx;
+  fd_set             readset;
+  fd_set             writeset;
+  struct timeval     tv;
+  int                num_sel;
+  int                errnum;
+  int                nowconn;
+  int                status;
+  int                high_fd = -1;
+  register int       i;
+  long               dummy = 0;
+  unsigned long      time_now;
+  unsigned long      time_last = 0;
+  unsigned long      time_out = time_out_val;  
+  
+  time_t told;
+  time_t tcurrent;
+
+  unsigned long tchkold;
+
+  int setsize_fd;
+
+  int sock_tcp[2];
+  int sock_unix;
+#ifdef INET_SYSLOG
+  int sock_log[2];
+#endif
+  
+  SL_ENTER(_("sh_xfer_start_server"));
+
+  if ( sh_xfer_printerr_final(0) < 0)
+    {
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+
+  sock = sh_tcp_sock[0];
+
+  /* ****************************************************************
+   *
+   * This is a non-forking server. We use select() on the listen()
+   * socket to watch for new connections. For new connections, accept()
+   * will return a new socket that is put in the read/write filesets.
+   * Data about active connections are kept in the 'conns' table. 
+   *
+   ******************************************************************/
+  
+  /* The table to hold info on sockets.
+   * We reserve 6 file descriptors for misc. use.
+   * The POSIX lower limit on open files seems to be eight. 
+   */
+  maxconn    = get_open_max() - 6;
+
+  /* ugly fix for FreeBSD compiler warning; casting FD_SETSIZE in the
+   * conditional expression does not suppress the warning... */
+  setsize_fd = (int)FD_SETSIZE;
+  maxconn = (setsize_fd < maxconn) ? setsize_fd : maxconn;
+
+  if (maxconn < 0 || !sl_ok_muls(maxconn, sizeof(sh_conn_t)))
+    {
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV,
+		      0, sock);
+      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+    }
+  conns   = SH_ALLOC (sizeof(sh_conn_t) * maxconn);
+
+  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_START_SRV,
+		  (maxconn-1), sock);
+
+  /* timer
+   */
+  tcurrent                   = (unsigned long) time (NULL);
+  told                       = tcurrent;
+
+  tchkold                    = tcurrent;
+  
+  for (i = SH_MINSOCK; i < maxconn; ++i)
+    {
+      conns[i].buf         = NULL;
+      conns[i].K           = NULL;
+      conns[i].A           = NULL;
+      conns[i].M1          = NULL;
+      conns[i].FileName    = NULL;
+      conns[i].fd          = -1;
+      sh_xfer_do_free ( &conns[i]);
+    }
+  
+  /* status init
+   */
+  server_status.conn_open  = 0;
+  server_status.conn_total = 0;
+  server_status.conn_max   = maxconn-1;
+  server_status.start      = time (NULL);
+  server_status.last       = (time_t) 0;
+
+  nowconn    = 1;
+  tv.tv_sec  = 5;
+  tv.tv_usec = 0;
+  
+  /* conns[0] is the listen() socket. Always in read mode.
+   */
+  sock = 0;
+
+  sock_tcp[0] = 0;
+  while (sock < sh_tcp_sock_n)
+    {
+      conns[sock].fd    = sh_tcp_sock[sock];
+      conns[sock].state = CONN_READING;
+      /* high_fd = (sh_tcp_sock[sock] > high_fd) ? sh_tcp_sock[sock] : high_fd; */
+      ++sock;
+    }
+  sock_tcp[1] = sock;
+  
+  conns[sock].fd    = pf_unix_fd;
+  conns[sock].state = CONN_READING;
+  /* high_fd = (pf_unix_fd > high_fd) ? pf_unix_fd : high_fd; */
+
+  sock_unix = sock;
+
+  ++sock;
+
+#ifdef INET_SYSLOG
+  conns[sock].fd = -1;
+
+  if ( sh_xfer_printerr_final(1) < 0)
+    {
+      SH_FREE(conns);
+      conns = NULL;
+      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
+    }
+
+  sock_log[0] = sock;
+  sock_log[1] = sock;
+
+  if (sh_xfer_syslog_sock_n > 0)
+    {
+      int s2;
+      for (s2 = 0; s2 < sh_xfer_syslog_sock_n; ++s2)
+	{
+	  conns[sock].fd    = sh_xfer_syslog_sock[s2];
+	  conns[sock].state = CONN_READING;
+	  /* high_fd = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd; */
+	  ++sock;
+	}
+      sock_log[1] = sock;
+
+    }
+#endif
+  
+  sh_html_write(all_clients);
+  
+  /* This is the select() loop.
+   */
+  while (1 == 1)
+    {
+
+    if (sig_raised > 0)
+      {
+	TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
+
+	if (sig_termfast == 1)  /* SIGTERM */
+	  {
+	    TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
+	    strncpy (sh_sig_msg, _("SIGTERM"), 20);
+	    --sig_raised; --sig_urgent;
+	    aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+	  }
+	  
+	if (sig_config_read_again == 1)
+	  {
+	    TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")));
+	    sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
+
+
+	    /* -- Delete the name server cache. --
+	     */
+
+	    delete_cache();
+#if defined(WITH_EXTERNAL)
+	    /* -- Delete list of external tasks. --
+	     */
+	    (void) sh_ext_cleanup();
+#endif
+#if defined(SH_WITH_MAIL)
+	      sh_nmail_free();
+#endif
+	    /* - mark all clients dead
+	     * - read configuration file
+	     * - remove clients still dead
+	     */
+	    sh_xfer_mark_dead ();
+
+	    reset_count_dev_console();
+	    reset_count_dev_time();
+	    sl_trust_purge_user();
+
+	    (void) sh_readconf_read ();
+
+	    for (i = SH_MINSOCK; i < maxconn; ++i)
+	      if (conns[i].state != CONN_FREE   && 
+		  conns[i].client_entry != NULL &&
+		  conns[i].client_entry->dead_flag == 1)
+		sh_xfer_do_free ( &conns[i]);
+	    sh_xfer_clean_tree ();
+
+	    sig_config_read_again = 0;
+	    --sig_raised;
+	  }
+
+	if (sig_fresh_trail == 1) /* SIGIOT */
+	  {
+	    /* Logfile access 
+	     */
+#ifdef SH_USE_XML
+	    sh_log_file (NULL, NULL);
+#endif
+	    TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
+	    sh_error_only_stderr (S_TRUE);
+	    sh_unix_rm_lock_file(sh.srvlog.name);
+	    retry_msleep(3, 0);
+	    sh.flag.log_start = S_TRUE;
+	    sh_error_only_stderr (S_FALSE);
+	    sig_fresh_trail       = 0;
+	    --sig_raised;
+	  }
+	
+	  
+	if (sig_terminate == 1 && nowconn < 2)  /* SIGQUIT */
+	  {
+	    TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
+	    strncpy (sh_sig_msg, _("SIGQUIT"), 20);
+	    --sig_raised; --sig_urgent;
+	    aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
+	  }
+	
+	  
+	if (sig_debug_switch == 1)  /* SIGUSR1 */
+	  {
+	    TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
+	    sh_error_dbg_switch();
+	    sig_debug_switch = 0;
+	    --sig_raised;
+	  }
+	
+	if (sig_suspend_switch > 0)  /* SIGUSR2 */
+	  {
+	    TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
+	    if (sh_global_suspend_flag == 1) {
+	      sh_global_suspend_flag = 0;
+	    } else {
+	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, 
+			      sh.prg_name);
+	      sh_global_suspend_flag = 1;
+	    }
+	    --sig_suspend_switch;
+	    --sig_raised; --sig_urgent;
+	  }
+
+	sig_raised = (sig_raised < 0) ? 0 : sig_raised;
+	sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
+	TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
+      }
+      
+      if (sh_global_suspend_flag == 1)
+	{
+	  (void) retry_msleep (1, 0);
+	  continue;
+	}
+
+      /* Recompute the descriptor set. select() modifies it,
+       * thus we update it using the info from the connection table.
+       * Also recompute the number of open connections.
+       */
+      FD_ZERO( &readset );
+      FD_ZERO( &writeset );
+      high_fd = conns[0].fd;
+
+      for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock)
+	{
+	  FD_SET(conns[sock].fd, &readset );
+	  high_fd   = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd;
+	}
+
+      if (conns[sock_unix].fd > -1)
+	{
+	  FD_SET(conns[sock_unix].fd, &readset );
+	  high_fd   = (high_fd > conns[sock_unix].fd) ? high_fd : conns[sock_unix].fd;
+	}
+
+#ifdef INET_SYSLOG
+      for (sock = sock_log[0]; sock < sock_log[1]; ++sock)
+	{
+	  if (conns[sock].fd > -1)
+	    {
+	      FD_SET(conns[sock].fd, &readset );
+	      high_fd   = (high_fd > conns[sock].fd) ? high_fd : conns[sock].fd;
+	    }
+	}
+#endif
+
+      time_now  = (unsigned long) time (NULL);
+      nowconn   = 1;
+      
+      for (i = SH_MINSOCK; i < maxconn; ++i)
+	{
+	  /* eliminate timed out connections
+	   */
+	  if (conns[i].state != CONN_FREE) 
+	    {
+	      if (time_now-conns[i].timer > time_out)
+		{
+		  sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_TIMOUT,
+				  conns[i].peer);
+		  sh_xfer_do_free ( &conns[i]);
+		}
+	      else
+		++nowconn;
+	    }
+	  
+	  
+	  if       (conns[i].state   == CONN_READING)
+	    { 
+	      FD_SET(conns[i].fd, &readset);
+	      high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd);
+	    }
+	  else if  (conns[i].state   == CONN_SENDING)
+	    {
+	      FD_SET(conns[i].fd, &writeset);
+	      high_fd = (high_fd < conns[i].fd ? conns[i].fd : high_fd);
+	    }
+	}
+
+      /* -- Exponentially reduce timeout limit if more than 1/2 full. --
+       */
+      /* Eliminate this, will cause problems when too much clients are
+       * starting up. */
+#if 0
+      if (nowconn > (maxconn/2))
+	time_out = ( (time_out/2) > 1) ? (time_out/2) : 1;
+      else
+	time_out = time_out_val;
+#endif
+      
+      
+      /* -- Do the select(). --
+       */
+      num_sel = select(high_fd+1, &readset, &writeset, NULL, &tv);
+      errnum  = errno;
+      
+      /* reset timeout - modified by select() on some systems
+       */
+      tv.tv_sec  = 5;
+      tv.tv_usec = 0;
+      
+
+      if ( (time_now - time_last) > 2L)
+	{
+	  time_last = time_now;
+	  if (sh_html_write(all_clients) < 0)
+	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML);
+	}
+      
+      
+      /* Error handling.
+       */
+      if ( num_sel < 0 )        /* some error             */
+	{
+	  char errbuf[SH_ERRBUF_SIZE];
+
+	  if (sig_raised == 1)
+	    {
+	      sig_raised = 2;
+	      continue;
+	    }
+
+	  if ( errnum == EINTR)
+	    continue;	  /* try again              */
+
+	  if ( errnum == EBADF)
+	    {
+	      /* seek and destroy the bad fd
+	       */
+	      for (i = SH_MINSOCK; i < high_fd; ++i)
+		{
+		  if ((conns[i].state == CONN_READING) ||
+		      (conns[i].state == CONN_SENDING))
+		    {
+		      if (-1 == retry_fcntl(FIL__, __LINE__, 
+					    conns[i].fd, F_GETFL, dummy))
+			sh_xfer_do_free ( &conns[i]);
+		    }
+		}
+	      continue;
+	    }
+
+	  sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_EXIT_ABORTS,
+			  sh_error_message(errnum, errbuf, sizeof(errbuf)), 
+			  sh.prg_name,
+			  _("select"));
+	  aud_exit(FIL__, __LINE__,  EXIT_FAILURE );
+	}
+      
+
+      /* log the timestamp
+       */
+      if ((tcurrent - told) > sh.looptime )
+	{
+	  told = tcurrent;
+#ifdef MEM_DEBUG
+	  sh_mem_check();
+	  sh_unix_count_mlock();
+#else
+	  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_STAMP);
+#endif
+	}
+
+#if defined(SH_WITH_MAIL)
+      /* 
+       * flush the mail queue
+       */
+      if (tcurrent - sh.mailTime.alarm_last > sh.mailTime.alarm_interval) 
+	{
+	  TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
+	  (void) sh_nmail_flush ();
+	  sh.mailTime.alarm_last = tcurrent;
+	}
+#endif
+#ifdef MEM_DEBUG
+      sh_mem_dump();
+#endif
+
+      tcurrent = (unsigned long) time (NULL);
+
+      /* check for time limit exceeded
+       */
+      if ((tcurrent - tchkold) > (unsigned int) 3 )
+	{
+	  tchkold = tcurrent;
+	  client_time_check(/* all_clients */);
+	  /* reset cache */
+	  sh_userid_destroy();
+	}
+      
+      /* seed / re-seed the PRNG if required
+       */
+      (void) taus_seed();
+
+      /* select() timeout handling.
+       */
+      if ( num_sel == 0 )       /* timeout - no connection */ 
+	{
+	  if (sh_html_write(all_clients) < 0)
+	    sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HTML);
+	  continue;
+	}
+
+      /* New connection.
+       */
+      for (sock = sock_tcp[0]; sock < sock_tcp[1]; ++sock)
+	{
+	  if ( FD_ISSET(conns[sock].fd , &readset )) /* a new connection   */
+	    {
+	      --num_sel;
+	      status = 0;
+	      if (nowconn < maxconn && sig_terminate == 0 && sig_termfast == 0)
+		{
+		  /* Find a free slot to accept the connection
+		   */
+		  i = SH_MINSOCK;
+		  while (i < maxconn)
+		    {
+		      if (conns[i].state == CONN_FREE)
+			{
+			  /* Here we run the accept() and copy the peer to
+			   * the free slot. 
+			   */
+			  status = sh_xfer_accept(conns[sock].fd, &conns[i]);
+			  
+			  if (status == 0)
+			    {
+			      high_fd = 
+				(high_fd > conns[i].fd ? high_fd : conns[i].fd);
+			      ++server_status.conn_open;
+			      ++server_status.conn_total;
+			      server_status.last = time (NULL);
+			    }
+			  break;
+			}
+		      ++i;
+		    }
+		}
+	      /* This re-runs select to accept data on the new
+	       * connection, rather than first dealing with old
+	       * connections.
+	       */
+	      if (status == 0) 
+		continue;
+	    }
+	}
+      
+      /* check for commands on the socket
+       */
+      if (conns[sock_unix].fd > (-1) && FD_ISSET(conns[sock_unix].fd , &readset ))
+	{
+	  sh_socket_poll();
+	}
+
+#ifdef INET_SYSLOG
+      for (sock = sock_log[0]; sock < sock_log[1]; ++sock)
+	{
+	  if (conns[sock].fd > (-1) && FD_ISSET(conns[sock].fd , &readset ))
+	    {
+	      sh_xfer_recv_syslog_socket (conns[sock].fd);
+	    }
+	}
+#endif
+
+      /* Check for pending read/write on the rest of the sockets.
+       */
+      for ( i = SH_MINSOCK; num_sel > 0 && i < maxconn; ++i )
+	{
+	  if (sig_termfast == 1)
+	    break;
+
+	  cx = &conns[i];
+	  if ( cx->state == CONN_READING &&
+	       FD_ISSET( cx->fd, &readset ) )
+	    {
+	      --num_sel;
+	      sh_xfer_do_read ( cx );
+	    }
+	  else if ( cx->state == CONN_SENDING &&
+		    FD_ISSET( cx->fd, &writeset ) )
+	    {
+	      --num_sel;
+	      sh_xfer_do_write ( cx );
+	    }
+	}
+      /* continue */
+    }
+  /* notreached */
+}
+
+void  free_client_tree (void)
+{
+  SL_ENTER(_("free_client_tree"));
+  zAVLFreeTree (all_clients, free_client);
+  SL_RET0(_("free_client_tree"));
+}
+
+void sh_xfer_free_all ()
+{
+  register int i;
+  
+  SL_ENTER(_("sh_xfer_free_all"));
+
+  if (conns != NULL)
+    for (i = SH_MINSOCK; i < maxconn; ++i)
+      {
+	sh_xfer_do_free ( &conns[i]);
+      }
+
+
+  free_client_tree ();
+
+  if (conns != NULL)
+    SH_FREE (conns);
+
+  SL_RET0(_("sh_xfer_free_all"));
+}
+
+
+
+/* #ifdef SH_WITH_SERVER */
+#endif
+
+
+  
+
+
+
Index: trunk/src/sh_xfer_syslog.c
===================================================================
--- trunk/src/sh_xfer_syslog.c	(revision 481)
+++ trunk/src/sh_xfer_syslog.c	(revision 481)
@@ -0,0 +1,481 @@
+/* SAMHAIN file system integrity testing                                   */
+/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
+/*                                                                         */
+/*  This program is free software; you can redistribute it                 */
+/*  and/or modify                                                          */
+/*  it under the terms of the GNU General Public License as                */
+/*  published by                                                           */
+/*  the Free Software Foundation; either version 2 of the License, or      */
+/*  (at your option) any later version.                                    */
+/*                                                                         */
+/*  This program is distributed in the hope that it will be useful,        */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*  GNU General Public License for more details.                           */
+/*                                                                         */
+/*  You should have received a copy of the GNU General Public License      */
+/*  along with this program; if not, write to the Free Software            */
+/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
+
+#include "config_xor.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+/* Must be early on FreeBSD
+ */
+#include <sys/types.h>
+#include <sys/socket.h> 
+#include <netdb.h>
+#include <netinet/in.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef SH_WITH_SERVER
+
+#include "samhain.h"
+#include "sh_tools.h"
+#include "sh_utils.h"
+#include "sh_ipvx.h"
+
+#undef  FIL__
+#define FIL__  _("sh_xfer_syslog.c")
+
+#ifdef INET_SYSLOG
+
+extern void sh_xfer_printerr(char * str, int errnum, unsigned int port, int line);
+extern int sh_xfer_syslog_sock[SH_SOCKMAX];
+extern int sh_xfer_syslog_sock_n;
+extern int SH_MINSOCK;
+
+/* Unlike Linux / FreeBSD, most systems don't define the stuff below
+ * in syslog.h
+ */
+
+#ifndef LOG_FAC
+#define LOG_FAC(p)      (((p) & LOG_FACMASK) >> 3)
+#endif
+
+#ifndef LOG_PRI
+#define LOG_PRI(p)      ((p) & LOG_PRIMASK)
+#endif
+
+typedef struct sh_code {
+        char    *c_name;
+        int     c_val;
+} SH_CODE;
+
+SH_CODE sh_facilitynames[] =
+{
+#ifdef LOG_AUTH
+  { N_("auth"), LOG_AUTH },
+#endif
+#ifdef LOG_AUTHPRIV 
+  { N_("authpriv"), LOG_AUTHPRIV },
+#endif
+#ifdef LOG_CRON
+  { N_("cron"), LOG_CRON },
+#endif
+#ifdef LOG_DAEMON
+  { N_("daemon"), LOG_DAEMON },
+#endif
+#ifdef LOG_FTP
+  { N_("ftp"), LOG_FTP },
+#endif
+#ifdef LOG_KERN
+  { N_("kern"), LOG_KERN },
+#endif
+#ifdef LOG_LPR
+  { N_("lpr"), LOG_LPR },
+#endif
+#ifdef LOG_MAIL
+  { N_("mail"), LOG_MAIL },
+#endif
+#ifdef INTERNAL_MARK
+  { N_("mark"), INTERNAL_MARK },          /* INTERNAL */
+#endif
+#ifdef LOG_NEWS
+  { N_("news"), LOG_NEWS },
+#endif
+#ifdef LOG_AUTH
+  { N_("security"), LOG_AUTH },           /* DEPRECATED */
+#endif
+#ifdef LOG_SYSLOG
+  { N_("syslog"), LOG_SYSLOG },
+#endif
+#ifdef LOG_USER
+  { N_("user"), LOG_USER },
+#endif
+#ifdef LOG_UUCP
+  { N_("uucp"), LOG_UUCP },
+#endif
+#ifdef LOG_LOCAL0
+  { N_("local0"), LOG_LOCAL0 },
+#endif
+#ifdef LOG_LOCAL1
+  { N_("local1"), LOG_LOCAL1 },
+#endif
+#ifdef LOG_LOCAL2 
+  { N_("local2"), LOG_LOCAL2 },
+#endif
+#ifdef LOG_LOCAL3
+  { N_("local3"), LOG_LOCAL3 },
+#endif
+#ifdef LOG_LOCAL4
+  { N_("local4"), LOG_LOCAL4 },
+#endif
+#ifdef LOG_LOCAL5
+  { N_("local5"), LOG_LOCAL5 },
+#endif
+#ifdef LOG_LOCAL6
+  { N_("local6"), LOG_LOCAL6 },
+#endif
+#ifdef LOG_LOCAL7
+  { N_("local7"), LOG_LOCAL7 },
+#endif
+  { NULL, -1 }
+};
+ 
+
+SH_CODE sh_prioritynames[] =
+{  
+#ifdef LOG_ALERT
+  { N_("alert"), LOG_ALERT },
+#endif
+#ifdef LOG_CRIT
+  { N_("crit"), LOG_CRIT },
+#endif
+#ifdef LOG_DEBUG
+  { N_("debug"), LOG_DEBUG },
+#endif
+#ifdef LOG_EMERG
+  { N_("emerg"), LOG_EMERG },
+#endif
+#ifdef LOG_ERR
+  { N_("err"), LOG_ERR },
+#endif
+#ifdef LOG_ERR
+  { N_("error"), LOG_ERR },               /* DEPRECATED */
+#endif
+#ifdef LOG_INFO
+  { N_("info"), LOG_INFO },
+#endif
+#ifdef INTERNAL_NOPRI
+  { N_("none"), INTERNAL_NOPRI },         /* INTERNAL */
+#endif
+#ifdef LOG_NOTICE
+  { N_("notice"), LOG_NOTICE },
+#endif
+#ifdef LOG_EMERG
+  { N_("panic"), LOG_EMERG },             /* DEPRECATED */
+#endif
+#ifdef LOG_WARNING
+  { N_("warn"), LOG_WARNING },            /* DEPRECATED */
+#endif
+#ifdef LOG_WARNING
+  { N_("warning"), LOG_WARNING },
+#endif
+  { NULL, -1 }
+};
+
+static int enable_syslog_socket = S_FALSE;
+
+int sh_xfer_recv_syslog_socket (int fd)
+{
+  static time_t      return_next = 0;
+  int                priority = 0;
+  int                fac, pri;
+  int                i;
+  char             * cfac = NULL;
+  char             * cpri = NULL;
+  int                res;
+  char             * tmp;
+  char             * bptr;
+  char             * ptr = NULL;
+  char               buf[1048];
+  struct sockaddr_in from;
+  char errbuf[SH_ERRBUF_SIZE];
+
+  struct sh_sockaddr ss;
+  struct sockaddr * sa = (struct sockaddr *) &from;
+  char   namebuf[SH_BUFSIZE];
+
+  /* The 6th argument in recvfrom is *socklen_t in Linux and *BSD, 
+   * but *int everywhere else. Because socklen_t is unsigned int, there
+   * should be no problem as long as  sizeof(struct sockaddr_in) < INT_MAX ...
+   */
+  unsigned int fromlen = sizeof(from);
+
+  if (enable_syslog_socket == S_FALSE)
+    return 0;
+
+  SL_ENTER(_("sh_xfer_recv_syslog_socket"));
+
+  if (return_next > 0)
+    {
+      if ( (time(NULL) - return_next) < 2)
+	SL_RETURN( 0, _("sh_xfer_recv_syslog_socket"));
+      else
+	return_next = 0;
+    }
+
+  res = recvfrom(fd,  buf,  1047, 0, (struct sockaddr *) &from, &fromlen);
+
+  sh_ipvx_save(&ss, sa->sa_family, (struct sockaddr *) &from);
+  sh_ipvx_ntoa(namebuf, sizeof(namebuf), &ss);
+
+  if (res > 0)
+    {
+      res = (res < 1047) ? res : 1047; 
+      buf[res] = '\0';
+      if (res > 1 && buf[res-1] == '\n')
+	buf[res-1] = '\0';
+
+      /* here we expect an xml formatted message, thus we don't
+	 escape xml special chars (flag == 0) */
+      /* commented out to not escape twice    */
+      /* bptr = sh_tools_safe_name(buf, 0);   */
+      bptr = buf;
+
+      if (!bptr || !(*bptr))
+	{
+	  res = errno;
+	  TPT(( 0, FIL__, __LINE__, _("msg=<UDP error: %d>\n"), res));
+	  sh_error_handle((-1), FIL__, __LINE__, res, MSG_ERR_SYSLOG,
+			  sh_error_message(res, errbuf, sizeof(errbuf)), 
+			  namebuf);
+	  SL_RETURN( (-1), _("sh_xfer_recv_syslog_socket"));
+	}      
+
+      TPT(( 0, FIL__, __LINE__, _("msg=<UDP message from %s>\n"), namebuf ));
+
+      ptr = bptr;
+      i = 0;
+      if (*ptr == '<') 
+	{
+	  ++ptr; ++i;
+	  while (i < res &&
+		 (unsigned char) *ptr > 47 && (unsigned char) *ptr < 58)
+	    {
+	      priority = 10 * priority + (*ptr - '0');
+	      ++ptr;
+	      ++i;
+	    }
+	  if (*ptr == '>')
+	    ++ptr;
+	}
+      fac = LOG_FAC(priority);
+      i = 0; 
+      while (sh_facilitynames[i].c_name != NULL)
+	{
+	  if (sh_facilitynames[i].c_val == (fac<<3))
+	    { cfac = sh_util_strdup(_(sh_facilitynames[i].c_name)); break; }
+	  ++i;
+	}
+      pri = LOG_PRI(priority);
+      i = 0; 
+      while (sh_prioritynames[i].c_name != NULL)
+	{
+	  if (sh_prioritynames[i].c_val == pri)
+	    { cpri = sh_util_strdup(_(sh_prioritynames[i].c_name)); break; }
+	  ++i;
+	}
+
+      /* here we do not expect an xml formatted message, thus we escape
+	 xml special chars (flag == 1) */
+      tmp = sh_tools_safe_name (ptr, 1);
+      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_INET_SYSLOG,
+		      namebuf, 
+		      (cfac == NULL) ? _("none") : cfac, 
+		      (cpri == NULL) ? _("none") : cpri, 
+		      (tmp  == NULL) ? _("none") : tmp);
+      if (cfac != NULL)
+	SH_FREE(cfac);
+      if (cpri != NULL)
+	SH_FREE(cpri);
+      SH_FREE(tmp);
+      /* SH_FREE(bptr); */
+    }
+
+  else if (res < 0 && errno != EINTR)
+    {
+      res = errno;
+      TPT(( 0, FIL__, __LINE__, _("msg=<UDP error: %d>\n"), res));
+      sh_error_handle((-1), FIL__, __LINE__, res, MSG_ERR_SYSLOG,
+		      sh_error_message(res, errbuf, sizeof(errbuf)), 
+		      namebuf);
+
+      /* don't accept anything the next 2 seconds
+       */
+      return_next = time(NULL);
+      SL_RETURN( (-1), _("sh_xfer_recv_syslog_socket"));
+    }      
+  SL_RETURN( (0), _("sh_xfer_recv_syslog_socket"));
+}
+
+int set_syslog_active(const char * c)
+{
+  return sh_util_flagval(c, &enable_syslog_socket);
+}
+
+static int do_syslog_socket(int domain, int type, int protocol,
+			    struct sockaddr * sa, int salen)
+{
+  int                flag = 1;  /* non-zero to enable an option */
+  int sock;
+  int errnum;
+  int res;
+
+  /* create the socket, bind() it and listen()
+   */
+  sock = socket(domain, type, protocol);
+
+  if (sock < 0)
+    {
+      errnum = errno; 
+      sh_xfer_printerr (_("syslog socket"), errnum, 514, __LINE__);
+      return -1;
+    }
+  (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 );
+  
+  if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+		  (void *) &flag, sizeof(flag)) < 0 )
+    {
+      errnum = errno;
+      sh_xfer_printerr (_("syslog setsockopt SO_REUSEADDR"), 
+			   errnum, 514, __LINE__);
+      return -1;
+    }
+
+#if defined(SO_BSDCOMPAT)
+  if ( setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
+		  (void *) &flag, sizeof(flag)) < 0 )
+    {
+      errnum = errno;
+      sh_xfer_printerr (_("syslog setsockopt SO_BSDCOMPAT"), 
+			   errnum, 514, __LINE__);
+      return -1;
+    }
+#endif
+  
+  res = bind(sock, sa, salen);
+
+  if ( res < 0) 
+    {
+      errnum = errno;
+      sh_xfer_printerr (_("syslog bind"), errnum, 514, __LINE__);
+      sl_close_fd(FIL__, __LINE__, sock);
+      return -1;
+    }
+  return sock;
+}
+
+/* callerFlag == S_TRUE means override the enable_syslog_socket flag
+ */
+int sh_xfer_create_syslog_socket (int callerFlag)
+{
+  int sock;
+
+#if defined(USE_IPVX)
+  struct addrinfo *ai;
+  struct addrinfo *p;
+  struct addrinfo hints;
+#else
+  struct sockaddr_in addr;
+  int addrlen      = sizeof(addr);
+#endif
+
+  SL_ENTER(_("sh_xfer_create_syslog_socket"));
+
+  if (callerFlag == S_FALSE)
+    {
+      if (enable_syslog_socket == S_FALSE && sh_xfer_syslog_sock_n > 0)
+	{
+	  /* user does not wish to use this facility
+	   */
+	  TPT(( 0, FIL__, __LINE__, _("msg=<close syslog socket>\n")));
+	  for (sock = 0; sock < sh_xfer_syslog_sock_n; ++sock)
+	    {
+	      sl_close_fd(FIL__, __LINE__, sh_xfer_syslog_sock[sock]);
+	      sh_xfer_syslog_sock[0] = -1;
+	    }
+	}
+      SL_RETURN((-1), _("sh_xfer_create_syslog_socket"));
+    }
+
+  sh_xfer_printerr (NULL, 0, 514, __LINE__);
+
+#if !defined(USE_IPVX)
+
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family      = AF_INET;
+  addr.sin_port        = htons(514);
+  
+  sock = do_syslog_socket(AF_INET, SOCK_DGRAM, 0, 
+			  (struct sockaddr *) &addr, addrlen);
+
+  if (sock >= 0) {
+    sh_xfer_syslog_sock[0] = sock;
+    sh_xfer_syslog_sock_n  = 1;
+  }
+
+#else
+  memset (&hints, '\0', sizeof (hints));
+  hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
+  hints.ai_socktype = SOCK_DGRAM;
+  if (getaddrinfo (NULL, "syslog", &hints, &ai) != 0)
+    {
+      int errnum = errno;
+      sh_xfer_printerr (_("getaddrinfo"), errnum, 514, __LINE__);
+      SL_RETURN((-1), _("sh_xfer_create_syslog_socket"));
+    }
+  
+  p = ai;
+
+  while (p != NULL && sh_xfer_syslog_sock_n < SH_SOCKMAX)
+    {
+      sock = do_syslog_socket(p->ai_family, p->ai_socktype, p->ai_protocol,
+			      p->ai_addr, p->ai_addrlen);
+      
+      if (sock >= 0) {
+	if (sh_xfer_syslog_sock_n < SH_SOCKMAX) {
+	  sh_xfer_syslog_sock[sh_xfer_syslog_sock_n] = sock;
+	  ++sh_xfer_syslog_sock_n;
+	}
+	else {
+	  sl_close_fd (FIL__, __LINE__, sock);
+	}    
+      } else if (sock == -1) {
+	freeaddrinfo (ai);
+	goto end;
+      }
+      p = p->ai_next;
+    }
+  freeaddrinfo (ai);
+
+ end:
+#endif
+  if (sh_xfer_syslog_sock_n > 1)
+    SH_MINSOCK += (sh_xfer_syslog_sock_n - 1);
+
+  SL_RETURN((sh_xfer_syslog_sock_n), _("sh_xfer_create_syslog_socket"));
+}
+/* #ifdef INET_SYSLOG */
+#endif
+
+/* #ifdef SH_WITH_SERVER */
+#endif
Index: trunk/src/slib.c
===================================================================
--- trunk/src/slib.c	(revision 476)
+++ trunk/src/slib.c	(revision 481)
@@ -587,4 +587,14 @@
 
 
+#if !defined (VA_COPY)
+#if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
+#define VA_COPY(ap1, ap2)     (*(ap1) = *(ap2))
+#elif defined (VA_COPY_AS_ARRAY)
+#define VA_COPY(ap1, ap2)     memmove ((ap1), (ap2), sizeof (va_list))
+#else /* va_list is a pointer */
+#define VA_COPY(ap1, ap2)     ((ap1) = (ap2))
+#endif
+#endif 
+
 #if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF)
 static
@@ -774,5 +784,5 @@
   str[n-1] = '\0';
 #else
-  va_copy(vl2, vl);                      /* save the argument list           */
+  VA_COPY (vl2, vl);                     /* save the argument list           */
   total = sl_printf_count (format, vl);
   len = (int) total;
@@ -820,5 +830,5 @@
   str[n-1] = '\0';
 #else
-  va_copy(vl2, vl);                    /* save the argument list           */
+  VA_COPY (vl2, vl);                   /* save the argument list           */
   total = sl_printf_count (format, vl);
   if (total < n) 
@@ -1141,6 +1151,6 @@
 static   gid_t   rgid_orig;
 
-static   int     uids_are_stored = SL_FALSE;
-static   int     suid_is_set     = SL_TRUE;
+static   int     uids_are_stored = S_FALSE;
+static   int     suid_is_set     = S_TRUE;
 
 #ifdef HAVE_SETRESUID
@@ -1156,5 +1166,5 @@
 int sl_is_suid()
 {
-  if (uids_are_stored == SL_FALSE)
+  if (uids_are_stored == S_FALSE)
     {
       if (getuid() == geteuid() && getgid() == getegid())
@@ -1179,6 +1189,6 @@
 {
   SL_ENTER(_("sl_get_euid"));
-  /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
-  if (uids_are_stored == SL_TRUE)
+  /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/
+  if (uids_are_stored == S_TRUE)
     *ret = euid;
   else
@@ -1189,6 +1199,6 @@
 uid_t sl_ret_euid()
 {
-  /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
-  if (uids_are_stored == SL_TRUE)
+  /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/
+  if (uids_are_stored == S_TRUE)
     return (euid);
   else
@@ -1203,6 +1213,6 @@
 {
   SL_ENTER(_("sl_get_egid"));
-  /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
-  if (uids_are_stored == SL_TRUE)
+  /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/
+  if (uids_are_stored == S_TRUE)
     *ret = egid;
   else
@@ -1218,6 +1228,6 @@
 {
   SL_ENTER(_("sl_get_ruid"));
-  /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
-  if (uids_are_stored == SL_TRUE)
+  /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/
+  if (uids_are_stored == S_TRUE)
     *ret = ruid;
   else
@@ -1233,6 +1243,6 @@
 {
   SL_ENTER(_("sl_get_rgid"));
-  /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
-  if (uids_are_stored == SL_TRUE)
+  /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/
+  if (uids_are_stored == S_TRUE)
     *ret = rgid;
   else
@@ -1248,6 +1258,6 @@
 {
   SL_ENTER(_("sl_get_ruid_orig"));
-  /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
-  if (uids_are_stored == SL_TRUE)
+  /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/
+  if (uids_are_stored == S_TRUE)
     *ret = ruid_orig;
   else
@@ -1263,6 +1273,6 @@
 {
   SL_ENTER(_("sl_get_rgid_orig"));
-  /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
-  if (uids_are_stored == SL_TRUE)
+  /* SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));*/
+  if (uids_are_stored == S_TRUE)
     *ret = rgid_orig;
   else
@@ -1289,17 +1299,17 @@
   SL_ENTER(_("sl_set_suid"));
 
-  if (uids_are_stored == SL_FALSE)
+  if (uids_are_stored == S_FALSE)
     {
       SL_IRETURN(SL_ENONE, _("sl_set_suid"));
     }
 
-  SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));  
+  SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));  
 
   if (ruid == euid && rgid == egid) 
     {
-      suid_is_set = SL_TRUE;
+      suid_is_set = S_TRUE;
       SL_IRETURN(SL_ENONE, _("sl_set_suid"));
     }  
-  SL_REQUIRE(suid_is_set     == SL_FALSE, _("suid_is_set == SL_FALSE"));  
+  SL_REQUIRE(suid_is_set     == S_FALSE, _("suid_is_set == S_FALSE"));  
 
 #if defined(HAVE_SETRESUID)
@@ -1330,5 +1340,5 @@
 
   SL_REQUIRE(retval == 0, _("retval == 0"));
-  suid_is_set = SL_TRUE;
+  suid_is_set = S_TRUE;
   SL_IRETURN(SL_ENONE, _("sl_set_suid"));
 }
@@ -1344,17 +1354,17 @@
   SL_ENTER(_("sl_unset_suid"));
 
-  if (uids_are_stored == SL_FALSE)
+  if (uids_are_stored == S_FALSE)
     {
       SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
     }
 
-  SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));
+  SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));
 
   if (ruid == euid && rgid == egid)
     {
-      suid_is_set = SL_FALSE;
+      suid_is_set = S_FALSE;
       SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
     }  
-  SL_REQUIRE(suid_is_set     == SL_TRUE, _("suid_is_set == SL_TRUE"));  
+  SL_REQUIRE(suid_is_set     == S_TRUE, _("suid_is_set == S_TRUE"));  
 
 #if defined(HAVE_SETRESUID)
@@ -1384,5 +1394,5 @@
 
   SL_REQUIRE(retval == 0, _("retval == 0"));
-  suid_is_set = SL_FALSE;
+  suid_is_set = S_FALSE;
   SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
 }
@@ -1395,5 +1405,5 @@
 {
   SL_ENTER(_("sl_save_uids"));
-  if (uids_are_stored == SL_TRUE) 
+  if (uids_are_stored == S_TRUE) 
     SL_IRETURN(SL_EREPEAT, _("sl_save_uids"));
 
@@ -1404,5 +1414,5 @@
   ruid = ruid_orig;
   rgid = rgid_orig;
-  uids_are_stored = SL_TRUE;
+  uids_are_stored = S_TRUE;
 
   SL_IRETURN(SL_ENONE, _("sl_save_uids"));
@@ -1417,5 +1427,5 @@
 {
   SL_ENTER(_("sl_drop_privileges"));
-  SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));
+  SL_REQUIRE(uids_are_stored == S_TRUE, _("uids_are_stored == S_TRUE"));
 
   SL_REQUIRE(setgid(rgid_orig) == 0, _("setgid(rgid_orig) == 0"));
@@ -1442,5 +1452,5 @@
 {
   SL_ENTER(_("sl_policy_get_root"));
-  SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
+  SL_REQUIRE(uids_are_stored == S_FALSE, _("uids_are_stored == S_FALSE"));
 
   SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
@@ -1455,5 +1465,5 @@
       rgid = egid;
     }
-  suid_is_set = SL_TRUE;
+  suid_is_set = S_TRUE;
   if (euid == 0)
     {
@@ -1474,5 +1484,5 @@
 {
   SL_ENTER(_("sl_policy_get_real"));
-  SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
+  SL_REQUIRE(uids_are_stored == S_FALSE, _("uids_are_stored == S_FALSE"));
   SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
 
@@ -1507,5 +1517,5 @@
 	      _("sl_drop_privileges() == SL_ENONE"));
 
-  suid_is_set = SL_TRUE;
+  suid_is_set = S_TRUE;
   SL_IRETURN(SL_ENONE, _("sl_policy_get_real"));
 }
@@ -1522,5 +1532,5 @@
 
   SL_REQUIRE(user != NULL, _("user != NULL"));
-  SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
+  SL_REQUIRE(uids_are_stored == S_FALSE, _("uids_are_stored == S_FALSE"));
   SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
 
@@ -1778,5 +1788,5 @@
   ofiles[fd]->content = NULL;
   ofiles[fd]->stream  = stream;
-  ofiles[fd]->flush   = SL_FALSE;
+  ofiles[fd]->flush   = S_FALSE;
 
   sl_strlcpy(ofiles[fd]->ofile, ofile, SL_OFILE_SIZE);
@@ -2058,5 +2068,5 @@
   ofiles[fd]->content = NULL;
   ofiles[fd]->stream  = NULL;
-  ofiles[fd]->flush   = SL_FALSE;
+  ofiles[fd]->flush   = S_FALSE;
 
   sl_strlcpy(ofiles[fd]->ofile, ofile, SL_OFILE_SIZE);
@@ -2182,5 +2192,5 @@
 #endif
 
-static int sl_drop_cache = SL_FALSE;
+static int sl_drop_cache = S_FALSE;
 
 int sl_set_drop_cache(const char * str)
@@ -2203,5 +2213,5 @@
 #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_MINCORE) && defined(POSIX_FADV_DONTNEED)
 
-  if (SL_FALSE != sl_drop_cache && !SL_ISERROR(status))
+  if (S_FALSE != sl_drop_cache && !SL_ISERROR(status))
     {
       int fd = get_the_fd(status);
@@ -2209,5 +2219,5 @@
 	{
 	  if (0 == sl_check_mincore(fd))
-	    ofiles[fd]->flush = SL_TRUE;
+	    ofiles[fd]->flush = S_TRUE;
 	}
     }
@@ -2345,5 +2355,5 @@
     {
 #if defined(HAVE_POSIX_FADVISE) && defined(HAVE_MINCORE) && defined(POSIX_FADV_DONTNEED)
-      if (ofiles[fd]->flush == SL_TRUE)
+      if (ofiles[fd]->flush == S_TRUE)
 	{
 	  posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
@@ -2569,5 +2579,5 @@
   extern volatile int sig_termfast;
  
-  if (is_nonblocking == SL_FALSE)
+  if (is_nonblocking == S_FALSE)
     {
       /* set to non-blocking mode 
@@ -2620,5 +2630,5 @@
 		{
 		  error = errno;
-		  if (is_nonblocking == SL_FALSE)
+		  if (is_nonblocking == S_FALSE)
 		      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
 		  TPT(( 0, FIL__, __LINE__, _("msg=<read error>")));
@@ -2637,5 +2647,5 @@
       else if (retval == 0)
 	{
-	  if (is_nonblocking == SL_FALSE)
+	  if (is_nonblocking == S_FALSE)
 	      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
 	  TPT(( 0, FIL__, __LINE__, _("msg=<timeout>")));
@@ -2648,5 +2658,5 @@
 	{
 	  error = errno;
-	  if (is_nonblocking == SL_FALSE)
+	  if (is_nonblocking == S_FALSE)
 	      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
 	  TPT(( 0, FIL__, __LINE__, _("msg=<timeout>")));
@@ -2657,5 +2667,5 @@
       if (sig_termfast == 1) 
 	{
-	  if (is_nonblocking == SL_FALSE)
+	  if (is_nonblocking == S_FALSE)
 	      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
 	  TPT(( 0, FIL__, __LINE__, _("msg=<terminated>")));
@@ -2669,5 +2679,5 @@
       if (tdiff > timeout)
 	{
-	  if (is_nonblocking == SL_FALSE)
+	  if (is_nonblocking == S_FALSE)
 	      retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
 	  TPT(( 0, FIL__, __LINE__, _("msg=<timeout>")));
@@ -2679,5 +2689,5 @@
     }
 
-  if (is_nonblocking == SL_FALSE)
+  if (is_nonblocking == S_FALSE)
     retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags);
   return ((int) bytes);
@@ -2888,6 +2898,6 @@
 
 extern uid_t rootonly[];
-extern int   EUIDSLOT;
-extern int   ORIG_EUIDSLOT;
+extern unsigned int   EUIDSLOT;
+extern unsigned int   ORIG_EUIDSLOT;
 
 extern char  tf_path[MAXFILENAME];	/* Error path for trust function. */
@@ -2998,5 +3008,5 @@
 int  sl_trust_purge_user (void)
 {
-  int i;
+  unsigned int i;
 
   EUIDSLOT = ORIG_EUIDSLOT;
@@ -3074,6 +3084,6 @@
 {
   long          status;
-  static time_t old = 0;
-  static time_t now;
+  static size_t old = 0;
+  static size_t now;
 
   SL_ENTER(_("sl_trustfile_euid"));
@@ -3084,4 +3094,5 @@
 
   now = time(NULL);
+
   if (now < (old + 300))
     {
@@ -3119,6 +3130,6 @@
 {
   if ((b == 0) || (a >= (INT_MIN / b) && a <= (INT_MAX / b)))
-    return SL_TRUE; /* no overflow */
-  return SL_FALSE;
+    return S_TRUE; /* no overflow */
+  return S_FALSE;
 }
 
@@ -3126,6 +3137,6 @@
 {
   if ((b == 0) || (a <= (SIZE_MAX / b)))
-    return SL_TRUE; /* no overflow */
-  return SL_FALSE;
+    return S_TRUE; /* no overflow */
+  return S_FALSE;
 }
 
@@ -3134,6 +3145,6 @@
   (void) a;
   if (b != 0)
-    return SL_TRUE; /* no overflow */
-  return SL_FALSE;
+    return S_TRUE; /* no overflow */
+  return S_FALSE;
 }
 
@@ -3143,16 +3154,16 @@
     {
       if (a <= (INT_MAX - b))
-	return SL_TRUE; /* no overflow */
+	return S_TRUE; /* no overflow */
       else
-	return SL_FALSE;
+	return S_FALSE;
     }
   else if (a < 0 && b < 0)
     {
       if (a >= (INT_MIN - b))
-	return SL_TRUE; /* no overflow */
+	return S_TRUE; /* no overflow */
       else
-	return SL_FALSE;
-    }
-  return SL_TRUE;
+	return S_FALSE;
+    }
+  return S_TRUE;
 }
 
@@ -3160,7 +3171,7 @@
 {
   if (a <= (SIZE_MAX - b))
-    return SL_TRUE; /* no overflow */
+    return S_TRUE; /* no overflow */
   else
-    return SL_FALSE;
+    return S_FALSE;
 }
 
@@ -3170,15 +3181,15 @@
     {
       if (a <= (INT_MAX + b))
-	return SL_TRUE; /* no overflow */
+	return S_TRUE; /* no overflow */
       else
-	return SL_FALSE;
+	return S_FALSE;
     }
   else if (a < 0 && b >= 0)
     {
       if (a >= (INT_MIN + b))
-	return SL_TRUE; /* no overflow */
+	return S_TRUE; /* no overflow */
       else
-	return SL_FALSE;
-    }
-  return SL_TRUE;
-}
+	return S_FALSE;
+    }
+  return S_TRUE;
+}
Index: trunk/src/t-test0.c
===================================================================
--- trunk/src/t-test0.c	(revision 481)
+++ trunk/src/t-test0.c	(revision 481)
@@ -0,0 +1,482 @@
+/*
+* Copyright (c) 1996-1999, 2001-2004 Wolfram Gloger
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that (i) the above copyright notices and this permission
+notice appear in all copies of the software and related documentation,
+and (ii) the name of Wolfram Gloger may not be used in any advertising
+or publicity relating to the software.
+
+THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+IN NO EVENT SHALL WOLFRAM GLOGER BE LIABLE FOR ANY SPECIAL,
+INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
+DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY
+OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * $Id: t-test1.c,v 1.2 2004/11/04 14:58:45 wg Exp $
+ * by Wolfram Gloger 1996-1999, 2001, 2004
+ * A multi-thread test for malloc performance, maintaining one pool of
+ * allocated bins per thread.
+ */
+/*
+  t-test[12] <n-total> <n-parallel> <n-allocs> <size-max> <bins>
+
+    n-total = total number of threads executed (default 10)
+    n-parallel = number of threads running in parallel (2)
+    n-allocs = number of malloc()'s / free()'s per thread (10000)
+    size-max = max. size requested with malloc() in bytes (10000)
+    bins = number of bins to maintain
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#if (defined __STDC__ && __STDC__) || defined __cplusplus
+# include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+
+/*
+#if !USE_MALLOC
+#include <malloc.h>
+#else
+#include "malloc.h"
+#endif
+*/
+
+#ifdef USE_SYSTEM_MALLOC
+extern void *memalign(size_t boundary, size_t size);
+/* #define memalign(a,b)  malloc(b) */
+#else
+extern void *memalign(size_t boundary, size_t size);
+#endif
+
+static int verbose = 1;
+
+/* dummy for the samhain safe_fatal logger 
+ */
+void safe_fatal(const char * details, 
+				const char * file, int line)
+{
+  (void) file;
+  (void) line;
+  fputs("assert failed: ", stderr);
+  puts(details);
+  _exit(EXIT_FAILURE);
+}
+
+/* lran2.h
+ * by Wolfram Gloger 1996.
+ *
+ * A small, portable pseudo-random number generator.
+ */
+
+#ifndef _LRAN2_H
+#define _LRAN2_H
+
+#define LRAN2_MAX 714025l /* constants for portable */
+#define IA	  1366l	  /* random number generator */
+#define IC	  150889l /* (see e.g. `Numerical Recipes') */
+
+struct lran2_st {
+    long x, y, v[97];
+};
+
+static void
+lran2_init(struct lran2_st* d, long seed)
+{
+    long x;
+    int j;
+
+    x = (IC - seed) % LRAN2_MAX;
+    if(x < 0) x = -x;
+    for(j=0; j<97; j++) {
+	x = (IA*x + IC) % LRAN2_MAX;
+	d->v[j] = x;
+    }
+    d->x = (IA*x + IC) % LRAN2_MAX;
+    d->y = d->x;
+}
+
+#ifdef __GNUC__
+__inline__
+#endif
+static long
+lran2(struct lran2_st* d)
+{
+    int j = (d->y % 97);
+
+    d->y = d->v[j];
+    d->x = (IA*d->x + IC) % LRAN2_MAX;
+    d->v[j] = d->x;
+    return d->y;
+}
+
+#undef IA
+#undef IC
+
+#endif
+
+/*
+ * $Id: t-test.h,v 1.1 2004/11/04 14:32:21 wg Exp $
+ * by Wolfram Gloger 1996.
+ * Common data structures and functions for testing malloc performance.
+ */
+
+/* Testing level */
+#ifndef TEST
+#define TEST 99
+#endif
+
+/* For large allocation sizes, the time required by copying in
+   realloc() can dwarf all other execution times.  Avoid this with a
+   size threshold. */
+#ifndef REALLOC_MAX
+#define REALLOC_MAX	2000
+#endif
+
+struct bin {
+	unsigned char *ptr;
+	unsigned long size;
+};
+
+#if TEST > 0
+
+static void
+mem_init(unsigned char *ptr, unsigned long size)
+{
+	unsigned long i, j;
+
+	if(size == 0) return;
+#if TEST > 3
+	memset(ptr, '\0', size);
+#endif
+	for(i=0; i<size; i+=2047) {
+		j = (unsigned long)ptr ^ i;
+		ptr[i] = ((j ^ (j>>8)) & 0xFF);
+	}
+	j = (unsigned long)ptr ^ (size-1);
+	ptr[size-1] = ((j ^ (j>>8)) & 0xFF);
+}
+
+static int
+mem_check(unsigned char *ptr, unsigned long size)
+{
+	unsigned long i, j;
+
+	if(size == 0) return 0;
+	for(i=0; i<size; i+=2047) {
+		j = (unsigned long)ptr ^ i;
+		if(ptr[i] != ((j ^ (j>>8)) & 0xFF)) return 1;
+	}
+	j = (unsigned long)ptr ^ (size-1);
+	if(ptr[size-1] != ((j ^ (j>>8)) & 0xFF)) return 2;
+	return 0;
+}
+
+static int
+zero_check(unsigned* ptr, unsigned long size)
+{
+	unsigned char* ptr2;
+
+	while(size >= sizeof(*ptr)) {
+		if(*ptr++ != 0)
+			return -1;
+		size -= sizeof(*ptr);
+	}
+	ptr2 = (unsigned char*)ptr;
+	while(size > 0) {
+		if(*ptr2++ != 0)
+			return -1;
+		--size;
+	}
+	return 0;
+}
+
+#endif /* TEST > 0 */
+
+/* Allocate a bin with malloc(), realloc() or memalign().  r must be a
+   random number >= 1024. */
+int n_malloc=0, n_memalign=0, n_realloc=0, n_calloc=0;
+
+static void
+bin_alloc(struct bin *m, unsigned long size, int r)
+{
+#if TEST > 0
+	if(mem_check(m->ptr, m->size)) {
+	  fprintf(stderr, "memory corrupt!\n");
+	  exit(1);
+	}
+#endif
+	r %= 1024;
+	/*printf("%d ", r);*/
+	if(r < 4) { /* memalign */
+		if(m->size > 0) free(m->ptr);
+		m->ptr = (unsigned char *)memalign(sizeof(int) << r, size);
+		++n_memalign;
+	} else if(r < 20) { /* calloc */
+		if(m->size > 0) free(m->ptr);
+		m->ptr = (unsigned char *)calloc(size, 1);
+#if TEST > 0
+		if(zero_check((unsigned*)m->ptr, size)) {
+			unsigned long i;
+			for(i=0; i<size; i++)
+				if(m->ptr[i] != 0)
+					break;
+			fprintf(stderr, "calloc'ed memory non-zero (ptr=%p, i=%ld)!\n", m->ptr, i);
+			exit(1);
+		}
+#endif
+		++n_calloc;
+	} else if(r < 100 && m->size < REALLOC_MAX) { /* realloc */
+		if(m->size == 0) m->ptr = NULL;
+		m->ptr = realloc(m->ptr, size);
+		++n_realloc;
+	} else { /* plain malloc */
+		if(m->size > 0) free(m->ptr);
+		m->ptr = (unsigned char *)malloc(size);
+		++n_malloc;
+	}
+	if(!m->ptr) {
+	  fprintf(stderr, "out of memory (r=%d, size=%ld)!\n", r, (long)size);
+	  exit(1);
+	}
+	m->size = size;
+#if TEST > 0
+	mem_init(m->ptr, m->size);
+#endif
+}
+
+/* Free a bin. */
+
+static void
+bin_free(struct bin *m)
+{
+	if(m->size == 0) return;
+#if TEST > 0
+	if(mem_check(m->ptr, m->size)) {
+	  fprintf(stderr, "memory corrupt!\n");
+	  exit(1);
+	}
+#endif
+	free(m->ptr);
+	m->size = 0;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * End:
+ */
+
+
+struct user_data {
+	int bins, max;
+	unsigned long size;
+	long seed;
+};
+
+/*
+ * $Id: thread-st.h$
+ * pthread version
+ * by Wolfram Gloger 2004
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+
+pthread_cond_t finish_cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t finish_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#ifndef USE_PTHREADS_STACKS
+#define USE_PTHREADS_STACKS 0
+#endif
+
+#ifndef STACKSIZE
+#define STACKSIZE	32768
+#endif
+
+
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * End:
+ */
+
+
+#define N_TOTAL		10
+#ifndef N_THREADS
+#define N_THREADS	2
+#endif
+#ifndef N_TOTAL_PRINT
+#define N_TOTAL_PRINT 50
+#endif
+#ifndef MEMORY
+#define MEMORY		8000000l
+#endif
+#define SIZE		10000
+#define I_MAX		10000
+#define ACTIONS_MAX	30
+#ifndef TEST_FORK
+#define TEST_FORK 0
+#endif
+
+#define RANDOM(d,s)	(lran2(d) % (s))
+
+struct bin_info {
+	struct bin *m;
+	unsigned long size, bins;
+};
+
+#if TEST > 0
+
+void
+bin_test(struct bin_info *p)
+{
+	unsigned int b;
+
+	for(b=0; b<p->bins; b++) {
+		if(mem_check(p->m[b].ptr, p->m[b].size)) {
+		  fprintf(stderr, "memory corrupt!\n");
+		  abort();
+		}
+	}
+}
+
+#endif
+
+void
+malloc_test(unsigned long size, int bins, int max)
+{
+    unsigned int b;
+	int i, j, actions;
+	struct bin_info p;
+	struct lran2_st ld; /* data for random number generator */
+
+	lran2_init(&ld, ((long)max*size + getpid()) ^ bins);
+
+	p.m = (struct bin *)malloc(bins*sizeof(*p.m));
+	p.bins = bins;
+	p.size = size;
+
+	for(b=0; b<p.bins; b++) {
+		p.m[b].size = 0;
+		p.m[b].ptr = NULL;
+		if(RANDOM(&ld, 2) == 0)
+			bin_alloc(&p.m[b], RANDOM(&ld, p.size) + 1, lran2(&ld));
+	}
+	for(i=0; i<=max;) {
+#if TEST > 1
+		bin_test(&p);
+#endif
+		actions = RANDOM(&ld, ACTIONS_MAX);
+#if USE_MALLOC && MALLOC_DEBUG
+		if(actions < 2) { mallinfo(); }
+#endif
+		for(j=0; j<actions; j++) {
+			b = RANDOM(&ld, p.bins);
+			bin_free(&p.m[b]);
+		}
+		i += actions;
+		actions = RANDOM(&ld, ACTIONS_MAX);
+		for(j=0; j<actions; j++) {
+			b = RANDOM(&ld, p.bins);
+			bin_alloc(&p.m[b], RANDOM(&ld, p.size) + 1, lran2(&ld));
+#if TEST > 2
+			bin_test(&p);
+#endif
+		}
+
+		i += actions;
+	}
+	for(b=0; b<p.bins; b++)
+		bin_free(&p.m[b]);
+	free(p.m);
+	return;
+}
+
+int n_total=0, n_total_max=N_TOTAL, n_running;
+
+int
+main(int argc, char *argv[])
+{
+	int bins;
+	int n_thr=N_THREADS;
+	int i_max=I_MAX;
+	unsigned long size=SIZE;
+
+#if USE_MALLOC && USE_STARTER==2
+	ptmalloc_init();
+	printf("ptmalloc_init\n");
+#endif
+
+	if((argc > 1) && (0 == strcmp(argv[1], "-h") || 0 == strcmp(argv[1], "--help")))
+	  {
+		printf("%s <n-total> <n-parallel> <n-allocs> <size-max> <bins>\n\n", argv[0]);
+		printf(" n-total = total number of threads executed (default 10)\n");
+		printf(" UNUSED n-parallel = number of threads running in parallel (2)\n");
+		printf(" n-allocs = number of malloc()'s / free()'s per thread (10000)\n");
+		printf(" size-max = max. size requested with malloc() in bytes (10000)\n");
+		printf(" bins = number of bins to maintain\n");
+		return 0;
+	  }
+
+	if(argc > 1) n_total_max = atoi(argv[1]);
+	if(n_total_max < 1) n_thr = 1;
+	if(argc > 2) n_thr = atoi(argv[2]);
+	if(n_thr < 1) n_thr = 1;
+	if(n_thr > 100) n_thr = 100;
+	if(argc > 3) i_max = atoi(argv[3]);
+
+	if(argc > 4) size = atol(argv[4]);
+	if(size < 2) size = 2;
+
+	bins = MEMORY/(size*n_thr);
+	if(argc > 5) bins = atoi(argv[5]);
+	if(bins < 4) bins = 4;
+
+	printf("[total=%d threads=%d] i_max=%d size=%ld bins=%d\n",
+		   n_total_max, n_thr, i_max, size, bins);
+
+	do {
+	  n_total++;
+	  malloc_test(size, bins, i_max);
+	  if (verbose)
+		if(n_total%N_TOTAL_PRINT == 0)
+		  printf("n_total = %8d - malloc %12d / memalign %12d / realloc %12d / calloc %12d\n", 
+				 n_total, 
+				 n_malloc, n_memalign, n_realloc, n_calloc);
+	} while (n_total < n_total_max);
+
+
+#if USE_MALLOC
+	malloc_stats();
+#endif
+	if (verbose)
+	  printf("Done.\n");
+	return 0;
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * End:
+ */
Index: trunk/src/t-test1.c
===================================================================
--- trunk/src/t-test1.c	(revision 476)
+++ trunk/src/t-test1.c	(revision 481)
@@ -230,5 +230,4 @@
 		if(m->size > 0) free(m->ptr);
 		m->ptr = (unsigned char *)memalign(sizeof(int) << r, size);
-		/* fprintf(stderr, "FIXME memalign %p\n", m->ptr); */
 		++n_memalign;
 	} else if(r < 20) { /* calloc */
@@ -246,14 +245,11 @@
 #endif
 		++n_calloc;
-		/* fprintf(stderr, "FIXME calloc %p\n", m->ptr); */
 	} else if(r < 100 && m->size < REALLOC_MAX) { /* realloc */
 		if(m->size == 0) m->ptr = NULL;
 		m->ptr = realloc(m->ptr, size);
-		/* fprintf(stderr, "FIXME realloc %p\n", m->ptr); */
 		++n_realloc;
 	} else { /* plain malloc */
 		if(m->size > 0) free(m->ptr);
 		m->ptr = (unsigned char *)malloc(size);
-		/* fprintf(stderr, "FIXME malloc %p\n", m->ptr); */
 		++n_malloc;
 	}
Index: trunk/src/trustfile.c
===================================================================
--- trunk/src/trustfile.c	(revision 476)
+++ trunk/src/trustfile.c	(revision 481)
@@ -102,5 +102,5 @@
 
 
-#ifndef TRUST_MAIN
+#if !defined(TRUST_MAIN)
 
 #include "slib.h"
@@ -121,6 +121,6 @@
 
 #define TRUST_DEBUG
-#define SL_FALSE 0
-#define SL_TRUE  1
+#define S_FALSE 0
+#define S_TRUE  1
 #define SL_ENTER(string)
 #define SL_IRETURN(a, b)  return a
@@ -222,6 +222,6 @@
 
 uid_t tf_euid = tf_uid_neg;
-int EUIDSLOT = sizeof(test_rootonly)/sizeof(uid_t);
-int ORIG_EUIDSLOT = sizeof(test_rootonly)/sizeof(uid_t);
+unsigned int EUIDSLOT = sizeof(test_rootonly)/sizeof(uid_t);
+unsigned int ORIG_EUIDSLOT = sizeof(test_rootonly)/sizeof(uid_t);
 
 char  tf_path[MAXFILENAME];		/* error path for trust function */
@@ -381,5 +381,5 @@
   SL_ENTER(_("isin"));
   if (list == NULL)
-    SL_IRETURN(SL_FALSE, _("isin"));
+    SL_IRETURN(S_FALSE, _("isin"));
 
   while(*list != tf_uid_neg && *list != n)
@@ -400,5 +400,5 @@
 	       (UID_CAST) n);
 #endif 
-      SL_IRETURN(SL_FALSE, _("isin"));
+      SL_IRETURN(S_FALSE, _("isin"));
     }
 
@@ -408,5 +408,5 @@
 	   (UID_CAST)n, (UID_CAST)*list);
 #endif 
-  SL_IRETURN(SL_TRUE, _("isin"));
+  SL_IRETURN(S_TRUE, _("isin"));
 }
 
@@ -506,5 +506,5 @@
   if (pbuffer) free(pbuffer);
 #endif
-  SL_IRETURN(SL_FALSE, _("isingrp"));
+  SL_IRETURN(S_FALSE, _("isingrp"));
 
  end_true:
@@ -513,5 +513,5 @@
   if (pbuffer) free(pbuffer);
 #endif
-  SL_IRETURN(SL_TRUE, _("isingrp"));
+  SL_IRETURN(S_TRUE, _("isingrp"));
 }
 
@@ -537,5 +537,5 @@
 #endif
 
-  int retval = SL_FALSE;
+  int retval = S_FALSE;
 
   SL_ENTER(_("onlytrustedingrp"));
@@ -567,5 +567,5 @@
 	      (UID_CAST)grp); 
 #endif
-      retval = SL_FALSE;
+      retval = S_FALSE;
       goto end_retval;
     }
@@ -574,5 +574,5 @@
    
   if(g->gr_mem == NULL || g->gr_mem[0] == NULL )
-    SL_IRETURN(SL_TRUE, _("onlytrustedingrp") );
+    SL_IRETURN(S_TRUE, _("onlytrustedingrp") );
   */
 
@@ -640,5 +640,5 @@
 #endif 
 	  tf_baduid = w->pw_uid;
-	  retval = SL_FALSE;
+	  retval = S_FALSE;
 #if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
 	  if (pbuffer) free(pbuffer);
@@ -698,11 +698,11 @@
 #endif
 	      tf_baduid = w->pw_uid;
-	      retval = SL_FALSE;
+	      retval = S_FALSE;
 	      goto out;
-	      /* SL_IRETURN(SL_FALSE, _("onlytrustedingrp")); */
-	    }
-	}
-    }
-  retval = SL_TRUE;
+	      /* SL_IRETURN(S_FALSE, _("onlytrustedingrp")); */
+	    }
+	}
+    }
+  retval = S_TRUE;
 
  out:
@@ -720,5 +720,5 @@
 
 #ifdef TRUST_DEBUG
-  if (retval == SL_TRUE)
+  if (retval == S_TRUE)
     fprintf(stderr,
 	    "trustfile: group %ld:  all members are trusted users --> OK\n", 
@@ -849,7 +849,8 @@
 	  char * csym;	                /* contents of symlink file  */
 	  char * full;	                /* "full" name of symlink    */
-	  register char *b, *t;	        /* used to copy stuff around */
-	  register int lsym;	        /* num chars in symlink ref  */
-	  register int i;		/* trustworthy or not?       */
+	  char *b;                      /* used to copy stuff around */
+	  const char *t;	        /* used to copy stuff around */
+	  int lsym;	                /* num chars in symlink ref  */
+	  int i;		        /* trustworthy or not?       */
 	  const char * t_const;
 	  char *end;
@@ -915,5 +916,5 @@
 	      /* smack on the /../ 
 	       */
-	      t_const = "/../"; t = (char *)t_const;
+	      t_const = "/../"; t = (const char *)t_const;
 	      while(*t && b < end)
 		*b++ = *t++;
@@ -997,6 +998,6 @@
        * file regardless of permissions, so bomb
        */
-      if (((okusers != NULL && SL_FALSE == isin((uid_t)stbuf.st_uid,okusers))||
-	   (badusers != NULL && SL_TRUE == isin((uid_t)stbuf.st_uid,badusers))))
+      if (((okusers != NULL && S_FALSE == isin((uid_t)stbuf.st_uid,okusers))||
+	   (badusers != NULL && S_TRUE == isin((uid_t)stbuf.st_uid,badusers))))
 	{
 #ifdef TRUST_DEBUG
Index: trunk/src/yulectl.c
===================================================================
--- trunk/src/yulectl.c	(revision 476)
+++ trunk/src/yulectl.c	(revision 481)
@@ -24,4 +24,5 @@
 #include <stdlib.h>
 #include <string.h> 
+#include <ctype.h>
 #include <errno.h>
 
@@ -41,9 +42,12 @@
 #define SH_MAXMSG 209
 
+#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && \
+  !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && \
+  !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
+#define SH_REQ_PASSWORD 1
+#endif
+
 static int    sock     = -1;
-static char * sockname = NULL;
-
 static char   password[15] = "";
-
 static int    verbose = 0;
 
@@ -86,15 +90,8 @@
 
 
-int 
-make_named_socket (char * sockname)
+static int 
+create_unix_socket ()
 {
   int sock;
-
-#if 0
-  struct sockaddr_un name;
-  size_t size;
-#else
-  (void) sockname;
-#endif
 
   /* Create the socket. */
@@ -107,27 +104,8 @@
     }
 
-#if 0
-  /* Bind a name to the socket. */
-  name.sun_family = AF_FILE;
-  strcpy (name.sun_path, sockname);
-
-  /* The size of the address is
-     the offset of the start of the filename,
-     plus its length,
-     plus one for the terminating null byte. */
-  size = (offsetof (struct sockaddr_un, sun_path)
-          + strlen (name.sun_path) + 1);
-
-  if (bind (sock, (struct sockaddr *) &name, size) < 0)
-    {
-      perror (_("ERROR: bind"));
-      return -1;
-    }
-#endif
-
   return sock;
 }
 
-void
+static void
 termination_handler (int signum)
 {
@@ -138,17 +116,26 @@
 	fprintf(stdout, _("# Terminated on signal %d\n"), signum);
     }
-#if 0
-  if (sockname != NULL) unlink (sockname);
-#endif
-  if (sock   >= 0 ) close  (sock);
-
+  if (sock   >= 0 ) 
+    close  (sock);
   return;
 }
 
-
-int send_to_server (char * serversock, char * message)
+static char * safe_copy(char * to, const char * from, size_t size)
+{
+  if (to && from)
+    {
+      strncpy (to, from, size);
+      if (size > 0)
+	to[size-1] = '\0';
+      else 
+	*to = '\0';
+    }
+  return to;
+}
+ 
+
+static int send_to_server (char * serversock, char * message)
 {
   struct sockaddr_un name;
-  /* size_t size; */
   int size;
   int nbytes;
@@ -168,10 +155,7 @@
     }
 
-  /* Send the datagram. 
-  nbytes = sendto (sock, message, strlen (message) + 1, 0,
-                   (struct sockaddr *) & name, size);
+  /* Send the data. 
    */
   nbytes = send (sock, message, strlen (message) + 1, 0);
-
   if (nbytes < 0)
     {
@@ -205,5 +189,5 @@
 }
 
-int recv_from_server (char * message)
+static int recv_from_server (char * message)
 {
   int nbytes = 0;
@@ -211,48 +195,20 @@
   int  num = 0;
   int  good = -1;
-  int  islist = 0;
   char * p;
 
   if (password[0] == '\0')
-    {
-      if (message[0] == 'L' && message[1] == 'I' &&
-	  message[2] == 'S' && message[3] == 'T')
-	{
-	  islist = 1;
-	}
-      if (message[0] == 'P' && message[1] == 'R' &&
-	  message[2] == 'O' && message[3] == 'B' && message[4] == 'E' )
-	{
-	  islist = 1;
-	}
-    }
+    p = message;
   else
-    {
-      p = &message[strlen(password)+1];
-      if (p[0] == 'L' && p[1] == 'I' &&
-	  p[2] == 'S' && p[3] == 'T')
-	{
-	  islist = 1;
-	}
-      if (p[0] == 'P' && p[1] == 'R' &&
-	  p[2] == 'O' && p[3] == 'B' && p[4] == 'E' )
-	{
-	  islist = 1;
-	}
-    }
-
-  if (islist == 1)
+    p = &message[strlen(password)+1];
+
+  if (0 == strncmp(p, _("PROBE"), 5) ||
+      0 == strncmp(p, _("LIST"),  4))
     {
       do {
-	/*
-	nbytes = recvfrom (sock, recvmsg, SH_MAXMSG, 0, NULL, 0);
-	*/
 	nbytes = getline_from_server (sock, recvmsg, SH_MAXMSG);
 	if (nbytes < 0)
 	  {
 	    if (errno == EAGAIN)
-	      {
-		return 0;
-	      }
+	      return 0;
 	    else
 	      {
@@ -262,7 +218,6 @@
 	  }
 	else if (nbytes == 0)
-	  {
-	    return 0;
-	  }
+	  return 0;
+
 	if (recvmsg[0] == 'E' && recvmsg[1] == 'N' && recvmsg[2] == 'D')
 	  {
@@ -277,7 +232,4 @@
   else
     {
-      /*
-      nbytes = recvfrom (sock, recvmsg, SH_MAXMSG, 0, NULL, 0);
-      */
       nbytes = recv (sock, recvmsg, SH_MAXMSG, 0);
       if (nbytes < 0)
@@ -290,15 +242,19 @@
   /* Print a diagnostic message. */
   if (password[0] == '\0')
-    {
-      good = strcmp (message, recvmsg);
-    }
+    good = strcmp (message, recvmsg);
   else
-    {
-      good = strcmp (&message[strlen(password)+1], recvmsg);
-    }
+    good = strcmp (&message[strlen(password)+1], recvmsg);
 
   if (0 != good)
     {
-      fprintf (stderr, "%s", _("ERROR: Bounced message != original message (possible reason: superfluous password).\n"));
+      if (0 == strncmp(recvmsg, _("!E:"), 3))
+	{ 
+	  fputs(recvmsg, stderr); 
+	  fputc('\n', stderr); 
+	}
+      else
+	{
+	  fputs (_("ERROR: Bounced message != original message.\n"), stderr);
+	}
       return -1;
     }
@@ -312,5 +268,60 @@
 }
 
-void usage(char * name)
+static int check_uuid(const char * in)
+{
+  int 		i;
+  const char	*cp;
+
+  if (!in || strlen(in) != 36)
+    return -1;
+  for (i=0, cp = in; i <= 36; i++,cp++) {
+    if ((i == 8) || (i == 13) || (i == 18) ||
+	(i == 23)) {
+      if (*cp == '-')
+	continue;
+      else
+	return -1;
+    }
+    if (i== 36)
+      if (*cp == 0)
+	continue;
+    if (!isxdigit(*cp))
+      return -1;
+  }
+  return 0;
+}
+
+static int check_command(const char * str)
+{
+  unsigned int i = 0;
+  char * commands[] = { N_("DELTA:"), N_("RELOAD"),  N_("STOP"), N_("SCAN"),
+			N_("CANCEL"), N_("LISTALL"), N_("LIST"), N_("PROBE"), NULL };
+
+  while (commands[i])
+    {
+      size_t len = strlen(_(commands[i]));
+
+      if (0 == strncmp(_(commands[i]), str, len))
+	{
+	  if (i == 0)
+	    {
+	      char * p = strchr(str, ':'); ++p;
+	      if ( 0 == check_uuid(p) )
+		return 0;
+	    }
+	  else
+	    {
+	      if (len == strlen(str))
+		return 0;
+	    }
+	}
+      ++i;
+    }
+
+  fprintf (stderr, _("ERROR: invalid command <%s>\n\n"), str);
+  return -1;
+}
+
+static void print_usage_and_exit(char * name, int exit_status)
 {
   printf(_("\nUsage : %s [-v][-s server_socket] -c command <client_hostname>\n\n"), 
@@ -325,12 +336,13 @@
   printf("%s", _("          variable YULECTL_PASSWORD (not recommended).\n\n"));
 
-  printf("%s", _("Commands: RELOAD    <reload configuration>\n"));
-  printf("%s", _("          STOP      <terminate>\n"));
-  printf("%s", _("          SCAN      <initiate file system check\n"));
-  printf("%s", _("          CANCEL    <cancel previous command>\n"));
-  printf("%s", _("          LIST      <list queued commands>\n"));
-  printf("%s", _("          LISTALL   <list queued and last sent commands>\n"));
-  printf("%s", _("          PROBE     <probe all clients for necessity of reload>\n"));
-  return;
+  printf("%s", _("Commands: RELOAD         reload configuration\n"));
+  printf("%s", _("          DELTA:<uuid>   load delta database with given uuid\n"));
+  printf("%s", _("          STOP           terminate\n"));
+  printf("%s", _("          SCAN           initiate file system check\n"));
+  printf("%s", _("          CANCEL         cancel pending command(s)\n"));
+  printf("%s", _("          LIST           list queued commands\n"));
+  printf("%s", _("          LISTALL        list queued and last sent commands\n"));
+  printf("%s", _("          PROBE          probe all clients for necessity of reload\n"));
+  exit(exit_status);
 }
 
@@ -339,6 +351,5 @@
   size_t len;
 
-  if (!str)
-    return str;
+  if (!str) return str;
 
   len = strlen(str);
@@ -351,24 +362,11 @@
 	break;
     }
-    
   return str;
 }
 
-void fixup_message (char * message)
-{
-  char message2[SH_MAXMSG];
-  char home[4096];
-  FILE * fp;
+static int get_home(char * home, size_t size)
+{
   struct passwd * pwent;
-  char * pw;
-
-  pw = getenv(_("YULECTL_PASSWORD"));
-  if (pw && strlen(pw) < 15)
-    {
-      strcpy(password, pw);
-      strcpy(message2, password);
-      goto do_msg;
-    }
-  
+
   pwent = getpwuid(geteuid());
   if ((pwent == 0) || (pwent->pw_dir == NULL))
@@ -379,28 +377,49 @@
       if (NULL != getenv(_("HOME")))
 	{
-	  strncpy(home, getenv(_("HOME")), 4096);
-	  home[4095] = '\0';
+	  safe_copy(home, getenv(_("HOME")), size);
 	}
       else
 	{
 	  fprintf (stderr, _("ERROR: no home directory for euid %ld (tried $HOME and password database).\n"), (long) geteuid());
-	  exit(EXIT_FAILURE);
+	  return -1;
 	}
     }
   else
     {
-      strncpy(home, pwent->pw_dir, 4096);
-      home[4095] = '\0';
-    }
+      safe_copy(home, pwent->pw_dir, size);
+    }
+  return 0;
+}
+
+static int get_passwd(char * message2, size_t size)
+{
+  char home[4096];
+  FILE * fp;
+  char * pw;
+
+  /* 1) Password from environment
+   */
+  pw = getenv(_("YULECTL_PASSWORD"));
+  if (pw && strlen(pw) < 15)
+    {
+      strcpy(password, pw);
+      strcpy(message2, password);
+      return 0;
+    }
+
+  /* 2) Password from $HOME/.yule_cred
+   */
+  if (get_home(home, sizeof(home)) < 0)
+    return -1;
 
   if ( (strlen(home) + strlen(_("/.yulectl_cred")) + 1) > 4096)
     {
       fprintf (stderr, "%s", _("ERROR: path for $HOME is too long.\n"));
-      exit(EXIT_FAILURE);
+      return -1;
     }
   strcat(home, _("/.yulectl_cred"));
   fp = fopen(home, "r");
 
-#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_STRUCT_CMSGCRED) && !defined(HAVE_STRUCT_FCRED) && !(defined(HAVE_STRUCT_SOCKCRED) && defined(LOCAL_CREDS))
+#if defined(SH_REQ_PASSWORD)
   if (fp == NULL)
     {
@@ -415,17 +434,17 @@
 		 home, (long)geteuid(), (long)getuid());
       }
-      exit(EXIT_FAILURE);
+      return -1;
     }
 #else
   if (fp == NULL)
-    return;
+    return 0;
 #endif
 
-  if (NULL == fgets(message2, sizeof(message2), fp))
+  if (NULL == fgets(message2, size, fp))
     {
       fprintf (stderr,
 	       _("ERROR: empty or unreadable password file (%s).\n"),
 	       home);
-      exit(EXIT_FAILURE);
+      return -1;
     }
 
@@ -436,19 +455,73 @@
       fprintf (stderr, "%s", 
 	       _("ERROR: Password too long (max. 14 characters).\n"));
-      exit(EXIT_FAILURE);
-    }
-
+      return -1;
+    }
   strcpy(password, message2);
   fclose(fp);
 
- do_msg:
-  strcat(message2, "@");
-
-  strncat(message2, message, SH_MAXMSG - strlen(message2) -1);
-  message2[SH_MAXMSG-1] = '\0';
-  strcpy(message, message2);
+  return 0;
+}
+
+static int fixup_message (char * message)
+{
+  char message_fixed[SH_MAXMSG] = { 0 };
+
+  if (get_passwd(message_fixed, sizeof(message_fixed)) < 0)
+    return -1;
+
+  if (strlen(message_fixed) > 0)
+    {
+      strcat(message_fixed, "@");
+
+      strncat(message_fixed, message, SH_MAXMSG - strlen(message_fixed) -1);
+      message_fixed[SH_MAXMSG-1] = '\0';
+      strcpy(message, message_fixed);
+    }
+  return 0;
+}
+
+static int fill_serversock(char * serversock, size_t size)
+{
+  int status;
+
+#ifdef HAVE_VSNPRINTF
+  status = snprintf(serversock, size, _("%s/%s.sock"), 
+		    DEFAULT_PIDDIR, SH_INSTALL_NAME);
+#else
+  if ((strlen(DEFAULT_PIDDIR) + strlen(SH_INSTALL_NAME) + 1 + 6) > size)
+    status = -1;
+  else
+    status = sprintf (serversock, _("%s/%s.sock"), 
+		      DEFAULT_PIDDIR, SH_INSTALL_NAME);
+#endif
+
+  if ((status < 0) || (status > (int)(size-1)))
+    {
+      fprintf(stderr, _("ERROR: Path too long (maximum %d): %s/%s.sock\n"), 
+	      (int) (size-1), DEFAULT_PIDDIR, SH_INSTALL_NAME);
+      return -1;
+    }
+  return 0;
+}
+
+static void checklen(char * command, char * str, size_t maxlen)
+{
+  if (strlen(str) > maxlen) 
+    {
+      fprintf(stderr, _("ERROR: String too long (max %d): %s\n\n"), 
+	      (int) maxlen, str);
+      print_usage_and_exit (command, EXIT_FAILURE);
+    }
   return;
 }
 
+static void checknull(char * command, char * str)
+{
+  if (str == NULL || str[0] == '\0') {
+    fprintf(stderr, "%s", _("ERROR: option with missing argument\n\n"));
+    print_usage_and_exit(command, EXIT_FAILURE);
+  }
+  return;
+}
 
 int
@@ -457,31 +530,12 @@
 
   char   message[SH_MAXMSG] = "";
-  char   clientcd[1024];
   char   serversock[256];
-  int    status, size;
+  int    status;
   int    num = 1;
   int    flag = 0;
-  
-#ifdef HAVE_VSNPRINTF
-  status = snprintf(serversock, 256, _("%s/%s.sock"), 
-		    DEFAULT_PIDDIR, SH_INSTALL_NAME);
-#else
-  if ((strlen(DEFAULT_PIDDIR) + strlen(SH_INSTALL_NAME) + 1 + 6) > 256)
-    {
-      status = -1;
-    }
-  else
-    {
-      status = sprintf (serversock, _("%s/%s.sock"), 
-			DEFAULT_PIDDIR, SH_INSTALL_NAME);
-    }
-#endif
-
-  if ((status < 0) || (status > 255))
-    {
-      fprintf(stderr, _("ERROR: Path too long (maximum 255): %s/%s.sock\n"), 
-	      DEFAULT_PIDDIR, SH_INSTALL_NAME);
-      return (EXIT_FAILURE);
-    }
+
+  if (fill_serversock(serversock, sizeof(serversock)) < 0)
+    return (EXIT_FAILURE);
+
 
   while (argc > 1 && argv[num][0] == '-')
@@ -490,53 +544,30 @@
 	{
 	  case 'h':
-	    usage(argv[0]);
-	    return (EXIT_SUCCESS);
-
+	    print_usage_and_exit(argv[0], EXIT_SUCCESS);
+	    break;
 	  case 'v':
 	    ++verbose;
 	    break;
-
 	  case 's':
 	    --argc; ++num;
-	    if (argv[num] == NULL || argv[num][0] == '\0') {
-	      usage(argv[0]);
-	      fprintf(stderr, "%s", _("ERROR: -s: argument missing\n"));
-	      return (EXIT_FAILURE);
-	    } else {
-	      if (strlen(argv[num]) > 255) 
-		{
-		  fprintf(stderr, _("ERROR: Path too long: %s\n"), argv[num]);
-		  return (EXIT_FAILURE);
-		}
-	      strncpy (serversock, argv[num], 256);
-	      serversock[255] = '\0';
-	    }
+	    checknull(argv[0], argv[num]);
+	    checklen(argv[0], argv[num], sizeof(serversock)-1);
+	    safe_copy (serversock, argv[num], sizeof(serversock));
 	    break;
-
 	  case 'c':
 	    --argc; ++num;
-	    if (argv[num] == NULL || argv[num][0] == '\0') {
-	      usage(argv[0]);
-	      fprintf(stderr, "%s", _("ERROR: -c: argument missing\n"));
-	      return (EXIT_FAILURE);
-	    } else {
-	      if (strlen(argv[num]) >= SH_MAXMSG) 
-		{
-		  fprintf(stderr, _("ERROR: Command too long: %s\n"), 
-			  argv[num]);
-		  return (EXIT_FAILURE);
-		}
-	      strncpy (message, argv[num], SH_MAXMSG);
-	      message[SH_MAXMSG-1] = '\0';
-	      strncat(message, ":", SH_MAXMSG-strlen(message)-1);
-	      message[SH_MAXMSG-1] = '\0';
-	      flag = 1;
-	    }
+	    checknull(argv[0], argv[num]);
+	    checklen(argv[0], argv[num], SH_MAXMSG-1);
+	    if (0 != check_command(argv[num]))
+	      print_usage_and_exit(argv[0], EXIT_FAILURE);
+	    safe_copy(message, argv[num], SH_MAXMSG);
+	    strncat(message, ":", SH_MAXMSG-strlen(message)-1);
+	    message[SH_MAXMSG-1] = '\0';
+	    flag = 1;
 	    break;
-
 	  default:
-	    usage(argv[0]);
-	    fprintf(stderr, _("ERROR: unknown option -%c\n"), argv[num][1]);
-	    return (EXIT_FAILURE);
+	    fprintf(stderr, _("ERROR: unknown option -%c\n\n"), argv[num][1]);
+	    print_usage_and_exit(argv[0], EXIT_FAILURE);
+	    break;
 	}
       --argc; ++num;
@@ -544,70 +575,35 @@
 
   if (flag == 0) /* no command given */
-    {
-      usage(argv[0]);
-      return (EXIT_FAILURE);
-    }
+    print_usage_and_exit(argv[0], EXIT_FAILURE);
 
   if (argc > 1)
     {
-      if (strlen(argv[num]) > (SH_MAXMSG - strlen(message) -1)) 
-	{
-	  fprintf(stderr, _("ERROR: Hostname too long: %s\n"), argv[num]);
-	  return (EXIT_FAILURE);
-	}
-      strncat (message, argv[num], SH_MAXMSG -strlen(message) - 1);
+      checklen(argv[0], argv[num], SH_MAXMSG - strlen(message) - 1);
+      strncat (message, argv[num], SH_MAXMSG - strlen(message) - 1);
       message[SH_MAXMSG-1] = '\0';
     }
   else
     {
-      if (message[0] == 'P' && message[1] == 'R' &&
-	  message[2] == 'O' && message[3] == 'B' && message[4] == 'E' )
+      if (0 == strncmp(message, _("PROBE"), 5) ||
+	  0 == strncmp(message, _("LIST"),  4))
 	{
 	  strncat (message, _("dummy"), SH_MAXMSG -strlen(message) - 1);
 	  message[SH_MAXMSG-1] = '\0';
 	}
-      else if (message[0] == 'L' && message[1] == 'I' &&
-	       message[2] == 'S' && message[3] == 'T')
-	{
-	  strncat (message, _("dummy"), SH_MAXMSG -strlen(message) - 1);
-	  message[SH_MAXMSG-1] = '\0';
-	}
       else
 	{
 	  fprintf(stderr, "%s", _("ERROR: this command requires a hostname\n"));
-	  usage(argv[0]);
-	  return (EXIT_FAILURE);
-	}
-    }
-
-  fixup_message(message);
-
-  /* OpenBSD wants >= 1024
-   */
-  if (NULL == getcwd(clientcd, 1024))
-    {
-      perror(_("ERROR: getcwd"));
-      return (EXIT_FAILURE);
-    }
-  size = strlen(clientcd) + 1 + strlen(CLIENT) + 6;
-  sockname = calloc(1,size);
-  if (!sockname)
-    {
-      perror(_("ERROR: main: malloc"));
-      return (EXIT_FAILURE);
-    }
-#ifdef HAVE_VSNPRINTF
-  snprintf(sockname, size, _("%s/%s.sock"), clientcd, CLIENT);
-#else
-  sprintf(sockname, _("%s/%s.sock"), clientcd, CLIENT);
-#endif
+	  print_usage_and_exit(argv[0], EXIT_FAILURE);
+	}
+    }
+
+  if (fixup_message(message) < 0)
+    return (EXIT_FAILURE);
 
   /* Make the socket.
    */
-  sock = make_named_socket (sockname);
+  sock = create_unix_socket ();
   if (sock < 0)
-    {
-      return (EXIT_FAILURE);
-    }
+    return (EXIT_FAILURE);
 
   /* Set up termination handler.
@@ -630,20 +626,17 @@
   /* Wait for a reply. 
    */
-  if (message[0] == 'L' && message[1] == 'I' &&
-      message[2] == 'S' && message[3] == 'T')
-    {
-      if (verbose)
+  if (verbose)
+    {
+      if (0 == strncmp(message, "LIST", 4))
 	fprintf(stdout, "%s", _("# Waiting for listing.\n"));
-    }
-  else
-    {
-      if (verbose)
+      else
 	fprintf(stdout, "%s", _("# Waiting for confirmation.\n"));
     }
+
   status = recv_from_server (message);
 
   if (status < 0)
     {
-      fprintf(stderr, "%s", _("ERROR: receiving data from server failed.\n"));
+      fputs(_("ERROR: unexpected or no reply from server.\n"), stderr);
       (void) termination_handler(0);
       return (EXIT_FAILURE);
Index: trunk/src/zAVLTree.c
===================================================================
--- trunk/src/zAVLTree.c	(revision 476)
+++ trunk/src/zAVLTree.c	(revision 481)
@@ -40,7 +40,7 @@
 }
 
-static char * dummy_zfree_string;
+char * dummy_zfree_string;
 #ifdef __clang__
-static char * dummy_zfree_str;
+char * dummy_zfree_str;
 #endif
 
@@ -145,10 +145,10 @@
   if (tree->keytype == zAVL_KEY_STRING)
     {
-      return (strcmp((char*)a, (char *)b));
+      return (strcmp((const char*)a, (const char *)b));
     }
   else /* zAVL_KEY_INT */
     {
-      int x = *((int *)a);
-      int y = *((int *)b);
+      const int x = *((const int *)a);
+      const int y = *((const int *)b);
 
       if      (x > y) return  1;
