Index: trunk/src/samhain.c
===================================================================
--- trunk/src/samhain.c	(revision 214)
+++ trunk/src/samhain.c	(revision 215)
@@ -746,4 +746,7 @@
 #if defined(SH_WITH_SERVER)
   sh_forward_free_all ();
+#endif
+#if defined(SH_WITH_MAIL)
+  sh_nmail_free();
 #endif
   delete_cache();
@@ -1749,4 +1752,8 @@
 	      (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)
Index: trunk/src/sh_extern.c
===================================================================
--- trunk/src/sh_extern.c	(revision 214)
+++ trunk/src/sh_extern.c	(revision 215)
@@ -92,4 +92,5 @@
 #include "sh_extern.h"
 #include "sh_calls.h"
+#include "sh_filter.h"
 #define SH_NEED_PWD_GRP 1
 #include "sh_static.h"
@@ -867,10 +868,6 @@
   char     type[4];
 
-  int      for_c;
-  char   * for_v[32];
-  int      fand_c;
-  char   * fand_v[32];
-  int      fnot_c;
-  char   * fnot_v[32];
+  sh_filter_type * filter;
+
   time_t   deadtime;
   time_t   last_run;
@@ -900,5 +897,4 @@
 sh_com_t * command_init(void)
 {
-  int         i;
   uid_t       ff_euid;
   sh_com_t  * ext_com = NULL;
@@ -924,16 +920,8 @@
 
   set3(ext_com->type, 'l', 'o', 'g');
-  ext_com->for_c        = 0;
-  ext_com->fand_c       = 0;
-  ext_com->fnot_c       = 0;
+  ext_com->filter       = NULL;
   ext_com->deadtime     = 0;
   ext_com->last_run     = 0;
 
-  for (i = 0; i < 32; ++i)
-    {
-      ext_com->for_v[i]         = NULL;
-      ext_com->fand_v[i]        = NULL;
-      ext_com->fnot_v[i]        = NULL;
-    }
   ext_com->next             = NULL;
 
@@ -1128,5 +1116,4 @@
 int sh_ext_cleanup(void)
 {
-  int i;
   sh_com_t * retval;
 
@@ -1140,10 +1127,6 @@
       sh_ext_tas_free (&(retval->tas));
 
-      for (i = 0; i < 32; ++i)
-	{
-	  if (NULL != retval->for_v[i])  SH_FREE(retval->for_v[i]);
-	  if (NULL != retval->fand_v[i]) SH_FREE(retval->fand_v[i]);
-	  if (NULL != retval->fnot_v[i]) SH_FREE(retval->fnot_v[i]);
-	}
+      if (retval->filter)
+	sh_filter_free (retval->filter);
 
       SH_FREE(retval);
@@ -1173,5 +1156,7 @@
   if (ext_coms == NULL || ext_failed == (-1))
     return (-1);
-  return (sh_ext_add (str, &(ext_coms->for_c), ext_coms->for_v));
+  if (ext_coms->filter == NULL)
+    ext_coms->filter = sh_filter_alloc();
+  return (sh_filter_add(str, ext_coms->filter, SH_FILT_OR));
 }
 
@@ -1183,5 +1168,7 @@
   if (ext_coms == NULL || ext_failed == (-1))
     return (-1);
-  return (sh_ext_add (str, &(ext_coms->fand_c), ext_coms->fand_v));
+  if (ext_coms->filter == NULL)
+    ext_coms->filter = sh_filter_alloc();
+  return (sh_filter_add(str, ext_coms->filter, SH_FILT_AND));
 }
 
@@ -1193,5 +1180,7 @@
   if (ext_coms == NULL || ext_failed == (-1))
     return (-1);
-  return (sh_ext_add (str, &(ext_coms->fnot_c), ext_coms->fnot_v));
+  if (ext_coms->filter == NULL)
+    ext_coms->filter = sh_filter_alloc();
+  return (sh_filter_add(str, ext_coms->filter, SH_FILT_NOT));
 }
 
@@ -1354,55 +1343,19 @@
 static int sh_ext_filter (char * message, sh_com_t * task)
 {
-  int i;
-  int j = 0;
   time_t now_time;
 
   SL_ENTER(_("sh_ext_filter"));
 
-  /* Presence of any of these keywords prevents execution.
-   */
-  if (task->fnot_c > 0)
-    {
-      for (i = 0; i < task->fnot_c; ++i)
+  if (task->filter)
+    {
+      if (0 != sh_filter_filter (message, task->filter))
 	{
-	  if (NULL != sl_strstr(message, task->fnot_v[i]))
-	    {
-	      SL_RETURN ((-1), _("sh_ext_filter"));
-	    }
+	  SL_RETURN ((-1), _("sh_ext_filter"));
 	}
     }
 
-  /* Presence of all of these keywords is required for execution.
-   */
-  if (task->fand_c > 0)
-    {
-      j = 0;
-
-      for (i = 0; i < task->fand_c; ++i)
-	{
-	  if (NULL == sl_strstr(message, task->fand_v[i]))
-	    {
-	      SL_RETURN ((-1), _("sh_ext_filter"));
-	    }
-	}
-
-    }
-
-  /* Presence of at least one of these keywords is required for execution.
-   */
-  if (task->for_c > 0)
-    {
-      for (i = 0; i < task->for_c; ++i)
-	{
-	  if (NULL != sl_strstr(message, task->for_v[i]))
-	    {
-	      goto checkdeadtime;
-	    }
-	}
-      SL_RETURN ((-1), _("sh_ext_filter"));
-    }
-
- checkdeadtime:
-  if (task->deadtime != (time_t) 0)   /* deadtime */
+  /* Filter passed, check deadtime */
+
+  if (task->deadtime != (time_t) 0)
     {
       now_time = time (NULL);
Index: trunk/src/sh_forward.c
===================================================================
--- trunk/src/sh_forward.c	(revision 214)
+++ trunk/src/sh_forward.c	(revision 215)
@@ -5056,4 +5056,7 @@
 	    (void) sh_ext_cleanup();
 #endif
+#if defined(SH_WITH_MAIL)
+	      sh_nmail_free();
+#endif
 	    /* - mark all clients dead
 	     * - read configuration file
Index: trunk/src/sh_mail.c
===================================================================
--- trunk/src/sh_mail.c	(revision 214)
+++ trunk/src/sh_mail.c	(revision 215)
@@ -59,4 +59,5 @@
 #include "sh_tools.h"
 #include "sh_pthread.h"
+#include "sh_filter.h"
 #include "sh_mail_int.h"
 #include "sh_nmail.h"
@@ -245,186 +246,4 @@
 
   /*@notreached@*/
-}
-
-void sh_filter_filterfree (sh_filter_type * filter)
-{
-  int i;
-
-  if (filter)
-    {
-      for (i = 0; i < filter->for_c; ++i) {
-	if (filter->for_v[i])
-	  SH_FREE(filter->for_v[i]);
-	filter->for_v[i] = NULL; 
-      }
-      filter->for_c = 0;
-      for (i = 0; i < filter->fand_c; ++i) {
-	if (filter->fand_v[i])
-	  SH_FREE(filter->fand_v[i]);
-	filter->fand_v[i] = NULL; 
-      }
-      filter->fand_c = 0;
-      for (i = 0; i < filter->fnot_c; ++i) {
-	if (filter->fnot_v[i])
-	  SH_FREE(filter->fnot_v[i]);
-	filter->fnot_v[i] = NULL; 
-      }
-      filter->fnot_c = 0;
-    }
-}
-
-int sh_filter_filteradd (const char * argstring, 
-			 sh_filter_type * filter, int ftype)
-{
-  int     i = 0;
-  int     flag = 0;
-  size_t  s;
-
-  char  * dupp;
-  char  * p;
-  char  * end;
-  int   * ntok;
-  char ** stok;
-
-  SL_ENTER(_("sh_filter_filteradd"));
-
-  if (NULL == argstring)
-    {
-      SL_RETURN((-1), _("sh_filter_filteradd")); 
-    }
-
-  if (ftype == SH_FILT_OR) {
-    ntok = &(filter->for_c);
-    stok = filter->for_v;
-  }
-  else if (ftype == SH_FILT_AND) {
-    ntok = &(filter->fand_c);
-    stok = filter->fand_v;
-  }
-  else if (ftype == SH_FILT_NOT) {
-    ntok = &(filter->fnot_c);
-    stok = filter->fnot_v;
-  }
-  else {
-    SL_RETURN((-1), _("sh_filter_filteradd")); 
-  }
-
-  *ntok = 0;
-
-  dupp = sh_util_strdup(argstring);
-  p   = dupp;
-
-  do
-    {
-      while (*p == ',' || *p == ' ' || *p == '\t')
-	++p;
-      if (*p == '\0')
-	break;
-
-      end = p; ++end;
-      if (*end == '\0')
-	break;
-
-      if (*p == '\'')
-	{
-	  ++p; end = p; ++end;
-	  if (*p == '\0' || *end == '\0')
-	    break;
-	  while (*end != '\0' && *end != '\'')
-	    ++end;
-	}
-      else if (*p == '"')
-	{
-	  ++p; end = p; ++end;
-	  if (*p == '\0' || *end == '\0')
-	    break;
-	  while (*end != '\0' && *end != '"')
-	    ++end;
-	}
-      else
-	{
-	  while (*end != '\0' && *end != ',' && *end != ' ' && *end != '\t')
-	    ++end;
-	}
-      if (*end == '\0')
-	flag = 1;
-      else
-	*end = '\0';
-
-      s = strlen(p) + 1;
-      if (stok[i] != NULL)
-	SH_FREE(stok[i]);
-      stok[i] = SH_ALLOC(s);
-      (void) sl_strlcpy(stok[i], p, s);
-
-      p = end; ++p;
-
-      ++i;
-      if (i == SH_FILT_NUM)
-	break;
-    }
-  while (p != NULL && *p != '\0' && flag == 0);
-
-  *ntok = i;
-  SH_FREE(dupp);
-
-  SL_RETURN (0, _("sh_filter_filteradd"));
-}
-
-/*
- * -- Check filters. Returns 0 if message passes.
- */ 
-int sh_filter_filter (const char * message, sh_filter_type * filter)
-{
-  int i;
-
-  SL_ENTER(_("sh_filter_filter"));
-
-  if (filter)
-    {
-
-      /* Presence of any of these keywords prevents execution.
-       */
-      if (filter->fnot_c > 0)
-	{
-	  for (i = 0; i < filter->fnot_c; ++i)
-	    {
-	      if (NULL != sl_strstr(message, filter->fnot_v[i]))
-		{
-		  SL_RETURN ((-1), _("sh_filter_filter"));
-		}
-	    }
-	}
-      
-      /* Presence of all of these keywords is required for execution.
-       */
-      if (filter->fand_c > 0)
-	{
-	  for (i = 0; i < filter->fand_c; ++i)
-	    {
-	      if (NULL == sl_strstr(message, filter->fand_v[i]))
-		{
-		  SL_RETURN ((-1), _("sh_filter_filter"));
-		}
-	    }
-	}
-      
-      /* Presence of at least one of these keywords is required for execution.
-       */
-      if (filter->for_c > 0)
-	{
-	  for (i = 0; i < filter->for_c; ++i)
-	    {
-	      if (NULL != sl_strstr(message, filter->for_v[i]))
-		{
-		  goto isok;
-		}
-	    }
-	  SL_RETURN ((-1), _("sh_filter_filter"));
-	}
-    }
-
- isok:
-  SL_RETURN ((0), _("sh_filter_filter"));
 }
 
Index: trunk/src/sh_readconf.c
===================================================================
--- trunk/src/sh_readconf.c	(revision 214)
+++ trunk/src/sh_readconf.c	(revision 215)
@@ -1107,4 +1107,6 @@
   { N_("setmailsender"),     SH_SECTION_MAIL,  SH_SECTION_MISC, 
     sh_mail_set_sender },
+  { N_("setmailalias"),       SH_SECTION_MAIL,  SH_SECTION_MISC, 
+    sh_nmail_add_alias },
   { N_("setmailaddress"),    SH_SECTION_MAIL,  SH_SECTION_MISC, 
     sh_nmail_add_recipient },
Index: trunk/src/sh_string.c
===================================================================
--- trunk/src/sh_string.c	(revision 214)
+++ trunk/src/sh_string.c	(revision 215)
@@ -127,5 +127,11 @@
  * If nfields < actual fields, last string will be remainder.
  */
-char ** split_array_ws(char *line, unsigned int * nfields, size_t * lengths)
+
+#define SH_SPLIT_LIST 0
+#define SH_SPLIT_WS   1
+
+char ** split_array_ws_int (char *line, 
+			    unsigned int * nfields, size_t * lengths,
+			    int isList)
 {
   char *a, *e, *s;
@@ -144,10 +150,22 @@
       /* skip leading WS 
        */
-      if ( *s && isspace((int)*s) )
-        {
-          do {
-            ++s;
-          } while ( *s && isspace((int)*s) );
-        }
+      if (isList == SH_SPLIT_WS)
+	{
+	  if ( *s && isspace((int)*s) )
+	    {
+	      do {
+		++s;
+	      } while ( *s && isspace((int)*s) );
+	    }
+	}
+      else
+	{
+	  if ( *s && (*s == ' ' || *s == '\t' || *s == ','))
+	    {
+	      do {
+		++s;
+	      } while ( *s && (*s == ' ' || *s == '\t' || *s == ','));
+	    }
+	}
 
       if (*s)
@@ -157,7 +175,16 @@
            */
           a = s;
-          do {
-            a++;
-          } while ( *a && (!isspace((int)*a)) );
+	  if (isList == SH_SPLIT_WS)
+	    {
+	      do {
+		a++;
+	      } while ( *a && (!isspace((int)*a)) );
+	    }
+	  else
+	    {
+	      do {
+		a++;
+	      } while ( *a && (*a != ' ' && *a != '\t' && *a != ','));
+	    }
 
           /* next token, *a is either ws or '\0' 
@@ -201,4 +228,15 @@
 }
 
+char ** split_array_ws (char *line, 
+			unsigned int * nfields, size_t * lengths)
+{
+  return split_array_ws_int (line, nfields, lengths, SH_SPLIT_WS);
+}
+
+char ** split_array_list (char *line, 
+			  unsigned int * nfields, size_t * lengths)
+{
+  return split_array_ws_int (line, nfields, lengths, SH_SPLIT_LIST);
+}
 
 #define SH_STRING_PARCEL 120
