Index: trunk/src/sh_mail.c
===================================================================
--- trunk/src/sh_mail.c	(revision 210)
+++ trunk/src/sh_mail.c	(revision 214)
@@ -59,4 +59,6 @@
 #include "sh_tools.h"
 #include "sh_pthread.h"
+#include "sh_mail_int.h"
+#include "sh_nmail.h"
 
 #undef  FIL__
@@ -67,17 +69,4 @@
 static int failedMail = SL_FALSE;
 
-/* MX Resolver Struct
- */
-typedef struct mx_ {
-  int    pref;
-  char * address;
-} mx;
-
-typedef struct dnsrep_ {
-  int    count;
-  mx   * reply;
-} dnsrep;
-
-static int free_mx (dnsrep * answers);
 static dnsrep * return_mx (char *domain);
 
@@ -258,22 +247,31 @@
 }
 
-#define SH_FILT_NUM 32
-#define SH_FILT_OR  0
-#define SH_FILT_AND 1
-#define SH_FILT_NOT 2
-#define SH_FILT_INIT { 0, { NULL }, 0, { NULL }, 0, { NULL }}
-
-typedef struct _sh_filter_type
-{
-  int      for_c;
-  char   * for_v[SH_FILT_NUM];
-  int      fand_c;
-  char   * fand_v[SH_FILT_NUM];
-  int      fnot_c;
-  char   * fnot_v[SH_FILT_NUM];
-
-} sh_filter_type;
-
-static
+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)
@@ -375,166 +373,58 @@
 
 /*
- * -- check filters
- */
-static 
+ * -- Check filters. Returns 0 if message passes.
+ */ 
 int sh_filter_filter (const char * message, sh_filter_type * filter)
 {
   int i;
-  int j = 0;
-
-  SL_ENTER(_("sh_mail_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_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)
 	    {
-	      SL_RETURN ((-1), _("sh_filter_filter"));
+	      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)
-    {
-      j = 0;
-
-      for (i = 0; i < filter->fand_c; ++i)
-	if (NULL != sl_strstr(message, filter->fand_v[i]))
-	  ++j;
-
-      if (j != filter->fand_c)
-	{
+      
+      /* 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"));
 	}
-    }
-
-  /* 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"));
-}
-
-
-static sh_filter_type mail_filter = SH_FILT_INIT;
-
-/*
- * -- add keywords to the OR filter
- */
-int sh_mail_add_or (const char * str)
-{
-  return (sh_filter_filteradd (str, &(mail_filter), SH_FILT_OR));
-}
-
-/*
- * -- add keywords to the AND filter
- */
-int sh_mail_add_and (const char * str)
-{
-  return (sh_filter_filteradd (str, &(mail_filter), SH_FILT_AND));
-}
-
-/*
- * -- add keywords to the NOT filter
- */
-int sh_mail_add_not (const char * str)
-{
-  return (sh_filter_filteradd (str, &(mail_filter), SH_FILT_NOT));
-}
-
-
-static char * address_list[8] = { 
-  NULL, NULL, NULL, NULL, 
-  NULL, NULL, NULL, NULL 
-};
-
-static   int   address_num = 0;
-static   int   address_num_compiled = 0;
-static   int   setaddress_compiled = S_FALSE;
-
-void reset_count_dev_mail(void)
-{
-  /* if not, then we still have the compiled-in address (if any), so we
-   * don' touch them
-   */
-  if (address_num_compiled == -99)
-    address_num = 0;
-  return;
-}
-
-int sh_mail_setaddress (const char * address)
-{
-  char     *     p;
-
-  SL_ENTER(_("sh_mail_setaddress"));
-  
-  if (0 == strcmp(address, _("NULL")))
-    SL_RETURN ( (0), _("sh_mail_setaddress"));
-    
-  if (address != NULL && address_num < (2 * SH_PATHBUF / 64 )) 
-    {
-      if (address_num < (SH_PATHBUF / 64 ))
-	p = &sh.srvmail.name[address_num*64];
-      else
-	p = &sh.srvmail.alt[address_num*64];
-
-      (void) sl_strlcpy (p, address, 64);
-      
-      if ((p == NULL) || ( sl_strlen(address) != sl_strlen(p)))
-	{
-	  memset(p, (int)'\0', 64);
-	  SL_RETURN ( (-1), _("sh_mail_setaddress"));
-	}
-      address_list[address_num] = p;
-#if 0
-      if (!sl_is_suid())
-	{
-	  TPT(( 0, FIL__, __LINE__, _("msg=<address_list[%d] = %s>\n"), 
-		address_num, address_list[address_num]));
-	}
-#endif
-      if (setaddress_compiled == S_TRUE)
-	{
-	  ++address_num;
-	  ++address_num_compiled;
-	}
-      else
-	{
-	  if (address_num == address_num_compiled)
-	    {
-	      address_num = 0;
-	      address_num_compiled = -99;
-	    }
-	  ++address_num;
-	}
-      SL_RETURN ( (0), _("sh_mail_setaddress"));
-    }
-  SL_RETURN ( (-1), _("sh_mail_setaddress"));
-}
-
-int sh_mail_setaddress_int (const char * address)
-{
-  int i;
-  SL_ENTER(_("sh_mail_setaddress_int"));
-  setaddress_compiled = S_TRUE;
-  i = sh_mail_setaddress(address);
-  setaddress_compiled = S_FALSE;
-  SL_RETURN(i, _("sh_mail_setaddress_int"));
 }
 
@@ -553,5 +443,5 @@
 
 
-static int all_in_one = S_FALSE;
+int sh_mail_all_in_one = S_FALSE;
 
 int sh_mail_setFlag (const char * str)
@@ -559,5 +449,5 @@
   int i;
   SL_ENTER(_("sh_mail_setFlag"));
-  i = sh_util_flagval(str, &all_in_one);
+  i = sh_util_flagval(str, &sh_mail_all_in_one);
   SL_RETURN(i, _("sh_mail_setFlag"));
 }
@@ -584,6 +474,7 @@
 }
 
-
-static SH_FIFO * fifo_mail = NULL;
+SH_MUTEX_INIT(mutex_fifo_mail, PTHREAD_MUTEX_INITIALIZER);
+
+SH_FIFO * fifo_mail = NULL;
 
 static
@@ -598,4 +489,5 @@
     SL_RET0(_("sh_mail_emptystack"));
 
+  SH_MUTEX_LOCK(mutex_fifo_mail);
   while (NULL != (msg = pop_list(fifo_mail)))
     {
@@ -604,4 +496,5 @@
       SH_FREE(msg);
     }
+  SH_MUTEX_UNLOCK(mutex_fifo_mail);
 
   SL_RET0(_("sh_mail_emptystack"));
@@ -610,26 +503,25 @@
 /* insert "\r\n" after each 998 char
  */
-static char * split_string(char * str);
-
-int sh_mail_pushstack (/*@null@*/char * msg)
+static char * split_string(const char * str);
+
+/* fixes warning: variable âpâ might be clobbered by âlongjmpâ or âvforkâ*/
+static char ** p_dummy;
+
+int sh_mail_pushstack (int severity, const char * msg, const char * alias)
 {
   char * p;
-  int    retval = 0;
+  volatile int    retval = 0;
   int    status;
 
   SL_ENTER(_("sh_mail_pushstack"));
 
-  if (msg == NULL || failedMail == SL_TRUE || sh.srvmail.name[0] == '\0') 
+  if (msg == NULL || failedMail == SL_TRUE /* || sh.srvmail.name[0] == '\0' */) 
     SL_RETURN((0), (_("sh_mail_pushstack")));
 
-  if (0 != sh_filter_filter(msg, &mail_filter))
-    SL_RETURN((0), (_("sh_mail_pushstack")));
-
-#if 0
-  if (msg != NULL && sl_strlen(msg) > 998)  /* RFC 2822 */
-    msg[998] = '\0';
-#endif
-
   p = split_string(msg);
+  /* fixes "variable âpâ might be clobbered by âlongjmpâ or âvforkâ" */
+  p_dummy = &p;
+
+  SH_MUTEX_LOCK(mutex_fifo_mail);
 
   if (fifo_mail == NULL)
@@ -638,6 +530,7 @@
       fifo_init(fifo_mail);
     }
-
-  status = push_list (fifo_mail, p);
+  status = push_list (fifo_mail, p, severity, alias);
+  SH_MUTEX_UNLOCK(mutex_fifo_mail);
+
   if (status >= 0)
     ++sh.mailNum.alarm_last;
@@ -647,6 +540,6 @@
   if (sh.mailNum.alarm_last >= sh.mailNum.alarm_interval)
     {
-      BREAKEXIT(sh_mail_msg);
-      retval = sh_mail_msg (NULL);
+      BREAKEXIT(sh_nmail_flush);
+      retval = sh_nmail_flush ();
     }
 
@@ -660,8 +553,8 @@
  */
 static int sh_mail_end_conn (FILE * connfile, int fd);
-static FILE * sh_mail_start_conn (int aFlag, int * fd);
+static FILE * sh_mail_start_conn (struct alias * address, int * fd, int * anum);
 
 static
-void sh_mail_get_subject(char * message,
+void sh_mail_get_subject(const char * message,
 			 char * mheader, size_t len)
 {
@@ -677,4 +570,5 @@
   char * mptr;
   char   sev[8];
+  char * msg;
 
   SL_ENTER(_("sh_mail_get_subject"));
@@ -693,5 +587,7 @@
   /* fast forward to the important part
    */
-  mptr = (char*)sl_strstr(message, _("msg="));
+  msg  = sh_util_strdup(message);
+
+  mptr = sl_strstr(msg, _("msg="));
   if (mptr)
     {
@@ -700,7 +596,7 @@
     }
   else
-    rep_serv_tab[2].data_str   = message;
-
-  mptr = (char*)sl_strstr(message, _("sev="));
+    rep_serv_tab[2].data_str   = msg;
+
+  mptr = sl_strstr(msg, _("sev="));
   if (mptr)
     {
@@ -714,5 +610,5 @@
   else
     {
-      mptr = message;
+      mptr = msg;
       sev[0] = *mptr; ++mptr;
       sev[1] = *mptr; ++mptr;
@@ -737,59 +633,80 @@
   (void) sl_strlcat(mheader, p, len);
   SH_FREE(p);
+  SH_FREE(msg);
   SL_RET0(_("sh_mail_get_subject"));
 }
 
-
-#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
-#include <sys/mman.h>
-#endif
-
-static char * sh_mail_realloc (char * inbuf, size_t * insize, size_t increase)
-{
-  size_t newsize;
-  char * outbuf = inbuf;
-
-  SL_ENTER(_("sh_mail_realloc"));
-
-  if (sl_ok_adds((*insize), 1))
-    {
-      newsize = (*insize) + 1;
-
-      if (sl_ok_adds(newsize, increase))
-	{
-	  newsize += increase;
-
-	  outbuf = SH_ALLOC(newsize);
-	  MLOCK(outbuf, newsize);
-	  (void) sl_strlcpy(outbuf, inbuf, newsize);
-
-	  memset (inbuf, 0, (*insize));
-	  MUNLOCK(inbuf, (*insize));
-	  SH_FREE(inbuf);
-
-	  *insize = newsize;
-	}
-    }
-
-  SL_RETURN( (outbuf), _("sh_mail_realloc"));
-}
-
-int sh_mail_msg (/*@null@*/char * message)
+void sh_mail_signature_block (sh_string  * sigMsg, char * recipient,
+			      char * bufcompress)
+{
+  time_t         id_audit;
+  char         * theSig;
+  char ibuf[80];
+  unsigned int count;
+
+  /* ------ signature block ------------------------------------ */
+  
+  sigMsg = sh_string_add_from_char(sigMsg, 
+				   _("-----BEGIN SIGNATURE-----\r\n"));
+  
+  count  = sh_nmail_get_mailkey (recipient, skey->mailkey_new, KEY_LEN+1,
+				 &id_audit);
+  
+  if (count != 0)
+    {
+      char sigbuf[KEYBUF_SIZE];
+      
+      /* Sign the message with the signature key.
+       */
+      theSig = sh_util_siggen (skey->mailkey_new, 
+			       bufcompress, sl_strlen(bufcompress),
+			       sigbuf, sizeof(sigbuf));
+      sigMsg = sh_string_add_from_char(sigMsg, theSig);
+    }
+  else
+    {
+       /* reveal first signature key
+       */
+      /* flawfinder: ignore */
+      (void) sl_strlcpy(skey->crypt, skey->mailkey_new, KEY_LEN+1); 
+      
+      BREAKEXIT(sh_util_encode);
+      /* flawfinder: ignore */
+      sh_util_encode(skey->crypt, bufcompress, 0, 'A');
+      
+      /* flawfinder: ignore */
+      sigMsg     = sh_string_add_from_char(sigMsg, skey->crypt);
+      
+      /* flawfinder: ignore */
+      memset (skey->crypt, 0, KEY_LEN);
+    }
+
+    sigMsg     = sh_string_add_from_char(sigMsg, "\r\n");
+
+    sl_snprintf(ibuf, sizeof(ibuf), _("%06u %010lu::%s\r\n"),
+		count, (unsigned long) id_audit, sh.host.name);
+
+    sigMsg     = sh_string_add_from_char(sigMsg, ibuf);
+    sigMsg     = sh_string_add_from_char(sigMsg, _("-----END MESSAGE-----"));
+
+    return;
+}
+
+int sh_mail_msg (const char * message)
 {
     char         subject[32+32+SH_MINIBUF+2+3+SH_PATHBUF];
     char         mheader[32+32+SH_MINIBUF+2+3];
 
-    char       * mailMsg;
-    char       * popMsg;
-    int          status = 0, errcount;
+    sh_string  * mailMsg;
+    sh_string  * compMsg;
+    int          status = 0;
+    volatile int errcount;
     size_t       wrlen;
-    int          i;
-    int          num_popped = 0;
-    int          retval = -1;  
+    volatile int retval = -1;  
 
     char       * bufcompress;
+    size_t       compressed;
+
     static int   failcount = 0;
-    static int   isfirst   = 1;
-    static int   mailcount = 0;
     FILE       * connfile  = NULL;
 
@@ -797,50 +714,34 @@
     struct  sigaction  new_act;
 
-    static  time_t id_audit  = 0;
     static  time_t fail_time = 0;
     static  time_t success_time = 0;
 
-    static  int ma_block = 0;
-
     int       ma_socket = -1;
 
-    SH_FIFO * fifo_temp = NULL;
-
-    char    * theSig;
-    char    * theMsg = NULL;
+    int            address_num = 0;
+    sh_string    * theMsg = NULL;
 
     /* #define SH_MAILBUF (256)    */
-#define SH_MAILBUF (8*4096) 
-
-    size_t    msgbufsize = SH_MAILBUF;
-    size_t    combufsize = SH_MAILBUF;
+#define SH_MAILBUF 4096 
+
     char      timebuf[81];
-    char hashbuf[KEYBUF_SIZE];
 
     SL_ENTER(_("sh_mail_msg"));
 
-    if (ma_block == 1)
-      SL_RETURN( (0), _("sh_mail_msg"));
-
-    /* Return if we cannot mail.
+    /* 
+     * Return if we cannot mail.
      */
     if (failedMail == SL_TRUE) 
       SL_RETURN((-1), _("sh_mail_msg"));
 
-    if (failedMail == SL_FALSE && address_list[0] == NULL)
-      {
-	TPT((0, FIL__, __LINE__, 
-	     _("msg=<Mail error: no recipient address.>\n")));
-	failedMail = SL_TRUE;
-	SL_RETURN((-1), _("sh_mail_msg"));
-      }
-
+    /*
+     * Final failure, can't mail for SH_MAX_FAIL hours.
+     */
     if ( (success_time > 0) && (fail_time > 0) &&
 	 (time(NULL) - success_time) > 3600*SH_MAX_FAIL)
       {
-	ma_block = 1;
 	sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL,
-			 _("mail"), address_list[0]);
-	ma_block = 0;
+			 _("mail"), 
+			 sh_string_str(all_recipients->recipient));
 	sh_mail_emptystack();
 	sh.mailNum.alarm_last = 0;
@@ -849,5 +750,6 @@
       }
 
-    /* Try at most each hour.
+    /*
+     * Try at most every three seconds to mail if there was a failure.
      */
     if ((fail_time > 0) && (time(NULL) - fail_time) < 3/*600*/)
@@ -855,7 +757,7 @@
 	if (failcount > 3)
 	  {
-	    /* -- Save for later. -- 
+	    /* -- Save for later. Changed: done by caller. -- 
+	     *	    sh_nmail_pushstack (severity, message, alias);
 	     */
-	    sh_mail_pushstack (message);
 	    ++failcount;
 	    
@@ -873,19 +775,11 @@
     fail_time = 0;
 
-    /* -- Polling, empty queue. --
-     */
-    if (message == NULL && sh.mailNum.alarm_last == 0)
-      SL_RETURN((-1), _("sh_mail_msg"));
-
-    /* -- Filtered. --
-     */
-    if (message != NULL && 0 != sh_filter_filter(message, &mail_filter))
-      SL_RETURN((-1), (_("sh_mail_msg")));
-
-
 
     /* ---------  Build complete message. ------------------------ */
 
-    theMsg = split_string(message);
+    /* Don't flush the queue here, because tag_list doesn't know
+     * how to filter messages. */
+
+    theMsg = sh_string_new_from_lchar(message, strlen(message));
 
     /* ---------- Header  ---------------------------------------- */
@@ -894,5 +788,6 @@
       {
 	(void) sl_strlcpy(mheader, _("Subject: "),       sizeof(mheader)-5);
-	(void) sl_strlcat(mheader, sh_unix_time (0, timebuf, sizeof(timebuf)),
+	(void) sl_strlcat(mheader, 
+			  sh_unix_time (0, timebuf, sizeof(timebuf)),
 			  sizeof(mheader)-5);
 	(void) sl_strlcat(mheader, " ",                  sizeof(mheader)-5);
@@ -901,12 +796,4 @@
     else
       {
-	
-	if (message == NULL)
-	  {
-	    theMsg  = pop_list(fifo_mail);
-	    message = theMsg;
-	    if (message)
-	      --sh.mailNum.alarm_last;
-	  }
 	
 	if (message)
@@ -917,5 +804,6 @@
 	  {
 	    (void) sl_strlcpy(mheader, _("Subject: "),     sizeof(mheader)-5);
-	    (void) sl_strlcat(mheader, sh_unix_time (0, timebuf, sizeof(timebuf)),
+	    (void) sl_strlcat(mheader, 
+			      sh_unix_time (0, timebuf, sizeof(timebuf)),
 			      sizeof(mheader)-5);
 	    (void) sl_strlcat(mheader, " ",                sizeof(mheader)-5);
@@ -937,132 +825,29 @@
 
 
-    mailMsg     = (char *) SH_ALLOC (msgbufsize);
-    bufcompress = (char *) SH_ALLOC (combufsize);
-
-    MLOCK(mailMsg     , msgbufsize);
-    MLOCK(bufcompress , combufsize);
-
-    (void) sl_strlcpy(mailMsg, mheader, msgbufsize);
+    mailMsg     = sh_string_new (SH_MAILBUF);
+    compMsg     = sh_string_new (SH_MAILBUF);
+
+    mailMsg     = sh_string_add_from_char(mailMsg, mheader);
+    mailMsg     = sh_string_add_from_char(mailMsg, 
+					  _("-----BEGIN MESSAGE-----\r\n"));
+
+    mailMsg     = sh_string_add_from_char(mailMsg, subject);
+    mailMsg     = sh_string_add          (mailMsg, theMsg);
+    mailMsg     = sh_string_add_from_char(mailMsg, "\r\n");
+
+    /* ---------- Compressed Message  ---------------------------- */
+
+    compMsg     = sh_string_add_from_char(compMsg, subject);
+    compMsg     = sh_string_add          (compMsg, theMsg);
+    compMsg     = sh_string_add_from_char(compMsg, "\r\n");
+
+    bufcompress = SH_ALLOC(sh_string_len(compMsg) + KEY_LEN + 1);
     bufcompress[0] = '\0';
 
-    (void) sl_strlcat(mailMsg, _("-----BEGIN MESSAGE-----\r\n"), msgbufsize);
-    (void) sl_strlcat(mailMsg, subject, msgbufsize);
-    (void) sh_util_compress (bufcompress, subject, 
-			     (combufsize - KEY_LEN - 1));
-    if (message != NULL)
-      {
-	if ((sl_strlen(theMsg) + sl_strlen(mailMsg) + 1) > 
-	    (msgbufsize-(4*KEY_LEN)))
-	  {
-	    mailMsg     = sh_mail_realloc(mailMsg,     
-					  &msgbufsize, sl_strlen(theMsg)+2);
-	    bufcompress = sh_mail_realloc(bufcompress, 
-					  &combufsize, sl_strlen(theMsg));
-	  }
-	(void) sl_strlcat(mailMsg,  theMsg, msgbufsize-(4*KEY_LEN));
-	(void) sl_strlcat(mailMsg,  "\r\n", msgbufsize-(4*KEY_LEN));
-
-	(void) sh_util_compress (bufcompress,  theMsg, combufsize-KEY_LEN-1);
-      }
-
-    if (sh.mailNum.alarm_last > 0)
-      {
-	fifo_temp = SH_ALLOC (sizeof(SH_FIFO));
-	fifo_init (fifo_temp);
-
-	while ( NULL != (popMsg = pop_list(fifo_mail)) )
-	  {
-	    (void) push_list (fifo_temp, popMsg);
-
-	    if ((sl_strlen(popMsg) + sl_strlen(mailMsg) + 1) > 
-		(msgbufsize-(4*KEY_LEN)))
-	      {
-		mailMsg     = sh_mail_realloc(mailMsg,     
-					      &msgbufsize, 
-					      sl_strlen(popMsg)+2);
-		bufcompress = sh_mail_realloc(bufcompress, 
-					      &combufsize, 
-					      sl_strlen(popMsg));
-	      }
-
-	    (void) sl_strlcat(mailMsg, popMsg, msgbufsize-(4*KEY_LEN));
-	    (void) sl_strlcat(mailMsg, "\r\n", msgbufsize-(4*KEY_LEN));
-	    (void) sh_util_compress(bufcompress, popMsg, combufsize-KEY_LEN-1);
-	    SH_FREE(popMsg);
-	    --sh.mailNum.alarm_last;
-	    ++num_popped;
-	  }
-      }
-
-    /* ------ signature block ------------------------------------ */
-    
-    (void) sl_strlcat(mailMsg, _("-----BEGIN SIGNATURE-----\r\n"), msgbufsize);
-
-    /* Generate new signature key.
-     */
-    if (isfirst == 1)
-      {
-	BREAKEXIT(sh_util_keyinit);
-	(void) sh_util_keyinit (skey->mailkey_old, KEY_LEN+1);
-      }
-
-    /* iterate the key
-     */
-    (void) sl_strlcpy(skey->mailkey_new,
-		      sh_tiger_hash (skey->mailkey_old, TIGER_DATA, KEY_LEN,
-				     hashbuf, sizeof(hashbuf)),
-		      KEY_LEN+1);
-
-    if (isfirst == 0)
-      {
-	char sigbuf[KEYBUF_SIZE];
-
-        /* Sign the message with the signature key.
-         */
-	theSig = sh_util_siggen (skey->mailkey_new, 
-				 bufcompress, sl_strlen(bufcompress),
-				 sigbuf, sizeof(sigbuf));
-	(void) sl_strlcat (mailMsg, 
-			   theSig,
-			   msgbufsize);
-      }
-    else
-      {
-        id_audit = time (NULL);
-
-        /* reveal first signature key
-         */
-	/* flawfinder: ignore */
-        (void) sl_strlcpy(skey->crypt, skey->mailkey_new, KEY_LEN+1); 
-
-	BREAKEXIT(sh_util_encode);
-	/* flawfinder: ignore */
-        sh_util_encode(skey->crypt, bufcompress, 0, 'A');
-
-	/* flawfinder: ignore */
-        (void) sl_strlcat (mailMsg, skey->crypt, msgbufsize);
-	/* flawfinder: ignore */
-        memset (skey->crypt, 0, KEY_LEN);
-        isfirst = 0;
-      }
-    (void) sl_strlcat (mailMsg, "\r\n", msgbufsize);
-
-    /* X(n) -> X(n-1)
-     */
-    (void) sl_strlcpy (skey->mailkey_old, skey->mailkey_new, KEY_LEN+1);
-
-    sl_snprintf(subject, sizeof(subject), _("%06d %010ld::%s\r\n"),
-		mailcount, (long) id_audit, sh.host.name);
-
-    (void) sl_strlcat (mailMsg, subject, msgbufsize);
-    ++mailcount;
-
-    (void) sl_strlcat (mailMsg, _("-----END MESSAGE-----"), msgbufsize);
-
-
+    compressed = sh_util_compress (bufcompress, 
+				   sh_string_str(compMsg), 
+				   sh_string_len(compMsg) + 1);
 
     /* ---------- Connect ---------------------------------------- */
-
-
 
     /* -- Catch (ignore) 'broken pipe'.
@@ -1074,53 +859,92 @@
     (void) sigaction (SIGPIPE, &new_act, &old_act);
 
-    i        = 0;
     errcount = 0;
 
-    if (all_in_one == S_FALSE)
+    if (sh_mail_all_in_one == S_FALSE)
       {
-	while (address_list[i] != NULL && i < address_num)
+	struct alias * address_list;
+
+	address_list = all_recipients;
+
+	while (address_list)
 	  {
-	    connfile = sh_mail_start_conn (i, &ma_socket);
+	    if (address_list->send_mail == 1)
+	      {
+		connfile = sh_mail_start_conn (address_list, 
+					       &ma_socket, &address_num);
 	    
-	    if (NULL != connfile)
-	      {
-		wrlen = fwrite (mailMsg, 1, sl_strlen(mailMsg), 
-				 connfile);
-		wrlen -= sl_strlen(mailMsg);
-		if (wrlen == 0) 
-		  status = sh_mail_end_conn (connfile, ma_socket);
+		if (NULL != connfile)
+		  {
+		    wrlen = fwrite (sh_string_str(mailMsg), 1, 
+				    sh_string_len(mailMsg), connfile);
+		    wrlen -= sh_string_len(mailMsg);
+
+		    if (wrlen == 0)
+		      {
+			sh_string  * sigMsg  = sh_string_new (0);
+
+			sh_mail_signature_block (sigMsg, 
+						 sh_string_str(address_list->recipient),
+						 bufcompress);
+
+			wrlen = fwrite (sh_string_str(sigMsg), 1, 
+					sh_string_len(sigMsg), connfile);
+			wrlen -= sh_string_len(sigMsg);
+
+			sh_string_destroy(&sigMsg);
+		      }
+
+		    if (wrlen == 0) 
+		      status = sh_mail_end_conn (connfile, ma_socket);
+		    else
+		      status = -1;
+		  }
+		if (NULL == connfile ||  status != 0)
+		  {
+		    sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL,
+				     _("mail"), 
+				     sh_string_str(address_list->recipient));
+		    ++errcount;
+		    ++sh.statistics.mail_failed;
+		  }
 		else
-		  status = -1;
+		  {
+		    ++sh.statistics.mail_success;
+		  }
+		
+		if (connfile != NULL)
+		  {
+		    (void) fclose (connfile);
+		    connfile = NULL;
+		  }
 	      }
-	    if (NULL == connfile ||  status != 0)
-	      {
-		ma_block = 1;
-		sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL,
-				 _("mail"), address_list[i]);
-		ma_block = 0;
-		++errcount;
-		++sh.statistics.mail_failed;
-	      }
-	    else
-	      {
-		++sh.statistics.mail_success;
-	      }
-
-	    if (connfile != NULL)
-	      {
-		(void) fclose (connfile);
-		connfile = NULL;
-	      }
-	    ++i;
+	    address_list = address_list->all_next;
 	  }
       }
     else
       {
-	connfile = sh_mail_start_conn ( -9 , &ma_socket);
-	
+	connfile = sh_mail_start_conn (NULL, &ma_socket, &address_num);
+
 	if (NULL != connfile)
 	  {
-	    wrlen = fwrite (mailMsg, 1, sl_strlen(mailMsg), connfile);
-	    wrlen -= sl_strlen(mailMsg);
+	    wrlen = fwrite (sh_string_str(mailMsg), 1, 
+			    sh_string_len(mailMsg), connfile);
+	    wrlen -= sh_string_len(mailMsg);
+
+	    if (wrlen == 0)
+	      {
+		sh_string  * sigMsg  = sh_string_new (0);
+		
+		sh_mail_signature_block (sigMsg, 
+					 NULL,
+					 bufcompress);
+		
+		wrlen = fwrite (sh_string_str(sigMsg), 1, 
+				sh_string_len(sigMsg), connfile);
+		wrlen -= sh_string_len(sigMsg);
+		
+		sh_string_destroy(&sigMsg);
+	      }
+
 	    if (wrlen == 0)
 	      status = sh_mail_end_conn (connfile, ma_socket);
@@ -1128,10 +952,18 @@
 	      status = -1;
 	  }
-	if (NULL == connfile ||  status != 0)
+
+	if (NULL == connfile || status != 0)
 	  {
-	    ma_block = 1;
+	    struct alias* ma_address = all_recipients;
+
+	    while (ma_address)
+	      {
+		if (ma_address->send_mail == 1)
+		  break;
+		ma_address = ma_address->all_next;
+	      }
+
 	    sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_SRV_FAIL,
-			     _("mail"), address_list[0]);
-	    ma_block = 0;
+			     _("mail"), sh_string_str(ma_address->recipient));
 	    errcount = address_num;
 	    ++sh.statistics.mail_failed;
@@ -1148,57 +980,27 @@
 	  }
       }
-
     
-    memset (bufcompress, 0, combufsize);
-    MUNLOCK(bufcompress , combufsize);
+    memset (bufcompress, 0, compressed);
     SH_FREE(bufcompress);
 
-    memset (mailMsg, 0, msgbufsize);
-    MUNLOCK(mailMsg , msgbufsize);
-    SH_FREE(mailMsg);
+    memset (sh_string_str(mailMsg), 0, sh_string_len(mailMsg));
+    memset (sh_string_str(compMsg), 0, sh_string_len(compMsg));
+    memset (sh_string_str(theMsg),  0, sh_string_len(theMsg));
+
+    sh_string_destroy(&mailMsg);
+    sh_string_destroy(&compMsg);
+    sh_string_destroy(&theMsg);
 
     /* --- Stay responsible for delivery in case of failure --- */
 
-    if (errcount == address_num && fifo_temp != NULL)
+    if (errcount == address_num)
       {
-        while ( (NULL != (popMsg = pop_list(fifo_temp))) )
-          {
-            if (push_list (fifo_mail, popMsg) >= 0)
-	      ++sh.mailNum.alarm_last;
-            SH_FREE(popMsg);
-          }
-	if (message != NULL)
-	  {
-	    if (fifo_mail == NULL)
-	      {
-		fifo_mail = SH_ALLOC(sizeof(SH_FIFO));
-		fifo_init(fifo_mail);
-	      }
-	    retval = push_list (fifo_mail,  theMsg);
-	    if (retval >= 0) 
-	      ++sh.mailNum.alarm_last;
-	    if (retval == SH_FIFO_MAX)
-	      retval = -2;
-	    else
-	      retval = -1;
-	  }
+	rollback_list(fifo_mail);
+	retval = -1;
       }
-    else if (fifo_temp != NULL)
+    else
       {
-        while ( (NULL != (popMsg = pop_list(fifo_temp))) )
-          {
-            SH_FREE(popMsg);
-          }
+	mark_list(fifo_mail);
       }
-    if (fifo_temp != NULL)
-      SH_FREE(fifo_temp);
-
-    /*
-    if (connfile != NULL) 
-      fclose (connfile);
-    */
-
-    if (theMsg != NULL)
-      SH_FREE(theMsg);
 
     /* --- Reset signal. ---
@@ -1211,4 +1013,5 @@
 	SL_RETURN((retval), _("sh_mail_msg"));
       }
+
     success_time = time(NULL);
     failcount = 0;
@@ -1298,12 +1101,17 @@
  *
  * start connection
- * for details on SMTP, see RFC 821 
+ * for details on SMTP, see RFC 821
+ *
+ * If ma_address == NULL, will send to all marked with
+ * send_mail=1 in recipient list, else to ma_address.   
  */
 
 static time_t time_wait = 300;
 
-static FILE * sh_mail_start_conn (int aFlag, int * ma_socket)
+static FILE * sh_mail_start_conn (struct alias * ma_address, 
+				  int * ma_socket, int * anum)
 {
   char       * address;
+  int          aFlag = 0;
 
   int          ecount;
@@ -1334,19 +1142,29 @@
   time_wait  = 300;
 
-  if (aFlag >= 0)
-    address = address_list[aFlag];
-  else
-    address = address_list[0];
-
-  TPT(( 0, FIL__, __LINE__, _("msg=<aFlag %d address %s>\n"), 
-	aFlag, address)); 
-
-  /* -------   split adress ------------------  */
-
-  if (0 == strcmp(address, _("NULL")))
+  if (ma_address == NULL)
+    {
+      aFlag = 1;
+      ma_address = all_recipients;
+
+      while (ma_address)
+	{
+	  if (ma_address->send_mail == 1)
+	    break;
+	  ma_address = ma_address->all_next;
+	}
+    }
+
+  if (!ma_address)
     {
       SL_RETURN( NULL, _("sh_mail_start_conn"));
     } 
-    
+
+  address = sh_string_str(ma_address->recipient);
+
+  TPT(( 0, FIL__, __LINE__, _("msg=<address %s>\n"), 
+	address)); 
+
+  /* -------   split adress ------------------  */
+
   if (strchr (address, '@') == NULL) {
     (void) sl_strlcpy(ma_user,    address,     256);
@@ -1358,5 +1176,5 @@
       ++i;
     }
-
+    
     /* adress[i] = '@' 
      */
@@ -1385,5 +1203,11 @@
   else
     {
-      answers = return_mx (ma_machine);
+      answers = ma_address->mx_list;
+      if (!answers)
+	{
+	  answers = return_mx (ma_machine);
+	  ma_address->mx_list = answers;
+	}
+
       if (answers)
 	{
@@ -1402,5 +1226,4 @@
 		break;
 	    }
-	  (void) free_mx(answers);
 	}
       else
@@ -1511,5 +1334,5 @@
   /* tell them who to send mail to
    */
-  if (aFlag >= 0)
+  if (aFlag == 0)
     {
       TPT(( 0, FIL__, __LINE__,  _("msg=<RCPT TO:<%s>>%c%c"), 
@@ -1529,17 +1352,29 @@
 	  SL_RETURN( NULL, _("sh_mail_start_conn"));
 	}
+      *anum = 1;
     }
   else
     {
-      ecount = 0;
-      for (i = 0; i < address_num; ++i)
-	{
-	  if (address_list[i] == NULL)  /* paranoia */
-	    break;
+      int address_num = 0;
+      ecount      = 0;
+
+      ma_address = all_recipients;
+
+      while (ma_address)
+	{
+	  if (ma_address->send_mail != 1)
+	    {
+	      ma_address = ma_address->next;
+	      continue;
+	    }
+
+	  ++address_num;
+
 	  TPT(( 0, FIL__, __LINE__,  _("msg=<RCPT TO:<%s>>%c%c"), 
-		address_list[i], 13, 10)); 
+		sh_string_str(ma_address->recipient), 13, 10)); 
 	  
 	  (void) fflush(connFile);
-	  fprintf(connFile, _("RCPT TO:<%s>%c%c"), address_list[i], 13, 10); 
+	  fprintf(connFile, _("RCPT TO:<%s>%c%c"), 
+		  sh_string_str(ma_address->recipient), 13, 10); 
 	  (void) fflush(connFile);
 	  
@@ -1548,10 +1383,14 @@
 	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_NET, 
 			      _("RCPT TO failed"), _("sh_mail_start_conn"), 
-			      _("mail"), address_list[i]);
+			      _("mail"), sh_string_str(ma_address->recipient));
 
 	      TPT(( 0, FIL__, __LINE__, _("msg=<Timeout.>\n")));
 	      ++ecount;
 	    }
-	}
+	  ma_address = ma_address->next;
+	}
+
+      *anum += address_num;
+
       if (ecount == address_num)
 	{
@@ -1771,5 +1610,5 @@
 #define SPLIT_AT 998
 
-static char * split_string(char * str)
+static char * split_string(const char * str)
 {
   size_t size;
@@ -1778,5 +1617,5 @@
 
   char * p, * p0;
-  char * q;
+  const char * q;
 
   if (!str)
@@ -2205,5 +2044,5 @@
 }
 
-static int free_mx (dnsrep * answers)
+int free_mx (dnsrep * answers)
 {
   mx     * result;
