diff -urN mailutils-052905/GNUmakefile mailutils-052905-jm/GNUmakefile
--- mailutils-052905/GNUmakefile	Thu Feb 26 14:11:27 2004
+++ mailutils-052905-jm/GNUmakefile	Sun May 29 10:14:22 2005
@@ -41,22 +41,22 @@
 
 
 halve-duplicatedb:	halve-duplicatedb.c
-	cc -s -O2 -o halve-duplicatedb halve-duplicatedb.c
+	cc -s -O2 $(CFLAGS) -o halve-duplicatedb halve-duplicatedb.c
 
 
 unquote-printables:	unquote-printables.c
-	cc -s -o unquote-printables -O2 unquote-printables.c
+	cc -s $(CFLAGS) -o unquote-printables -O2 unquote-printables.c
 
 milter-size:		milter-size.c
-	cc -s -o milter-size milter-size.c -O2 -D_REENTRANT \
+	cc -s $(CFLAGS) -o milter-size milter-size.c -O2 -D_REENTRANT \
 	$(LDMILTER)
 
 milter-dnsrbl:		milter-dnsrbl.c
-	cc -s -o milter-dnsrbl milter-dnsrbl.c -O2 -D_REENTRANT \
+	cc -s $(CFLAGS) -o milter-dnsrbl milter-dnsrbl.c -O2 -D_REENTRANT \
 	$(LDDNS) $(LDMILTER)
 
 milter-regexp:		milter-regexp.c
-	cc -s -o milter-regexp milter-regexp.c -O2 -D_REENTRANT \
+	cc -s  $(CFLAGS) -o  milter-regexp milter-regexp.c -O2 -D_REENTRANT \
 	$(LDDNS) $(LDMILTER)
 
 kemail-size-logd:	kemail-size-logd.o
@@ -67,7 +67,7 @@
 
 
 clean:
-	-rm -f *~ *.o
+	-rm -f core *~ *.o
 
 
 distclean:	clean
diff -urN mailutils-052905/halve-duplicatedb.c mailutils-052905-jm/halve-duplicatedb.c
--- mailutils-052905/halve-duplicatedb.c	Thu Feb 26 02:25:03 2004
+++ mailutils-052905-jm/halve-duplicatedb.c	Sun May 29 10:14:22 2005
@@ -40,6 +40,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <errno.h>
 
 #define TIMEOUT 10  /*  Seconds  */
 #define ERRSTRING strerror (errno)
diff -urN mailutils-052905/milter-regexp.8 mailutils-052905-jm/milter-regexp.8
--- mailutils-052905/milter-regexp.8	Mon Sep 20 22:08:23 2004
+++ mailutils-052905-jm/milter-regexp.8	Sun May 29 11:03:33 2005
@@ -55,6 +55,8 @@
 
 redirect the message to a different destination
 
+copy the message to an additional destination
+
 accept the message with no changes (this is the default if no recipe
 matches)
 
@@ -225,6 +227,10 @@
 Redirect message to the address given by \fI<optional
 address>\fP. This is an exclusive action
 .TP
+.B COPY 
+Copies message to the address given by \fI<optional
+address>\fP. This is a non-exclusive action
+.TP
 .B ACCEPT
 Accept the message without changes. This is an exclusive action. This
 is the default behaviour
@@ -255,6 +261,12 @@
 h ^X-Spam-Status: (HIGH|MEDIUM)
 PERMFAIL,STALL
 MESSAGE Likely spam content detected: rejected
+
+# copy all email addressed to user X from user Y to email address Z
+r userx@example.com 
+s & usery@example.org 
+COPY
+DESTINATION userz@example.net
 .fi
 
 .SH FORMAT OF TAGS (HEADER LINES)
diff -urN mailutils-052905/milter-regexp.c mailutils-052905-jm/milter-regexp.c
--- mailutils-052905/milter-regexp.c	Sun Nov 14 01:28:49 2004
+++ mailutils-052905-jm/milter-regexp.c	Sun May 29 10:37:18 2005
@@ -124,6 +124,7 @@
 #define ACTION_DISCARD            4
 #define ACTION_REDIRECT           5
 #define ACTION_ACCEPT             6
+#define ACTION_COPY               7
 #define ACTION_OPTION_MASK     0xf0
 #define ACTION_OPT_STALL       0x10
 
@@ -211,6 +212,8 @@
     unsigned int body_overrun;    /*  Number bytes in oversized body line    */
     struct envrcpt *first;        /*  The first envelope recipient           */
     struct envrcpt *last;         /*  The last envelope recipient            */
+    char * sender;                /*  The envelope sender                    */
+    char * envid;                 /*  The envelope ID                        */
     unsigned int wpos;            /*  Position to start writing to buffer    */
     u_char buffer[BUFLEN];        /*  The header/body overrun buffer         */
 };
@@ -221,6 +224,7 @@
 static flag debug = FALSE;
 static flag full_recipient = FALSE;
 
+static void process_line (SMFICTX *ctx, const char *line, char where);
 
 static void put_config (struct config *config, flag grab_lock)
 {
@@ -270,6 +274,7 @@
 */
 {
     char *ptr;
+    char where = 0;
 
     while ( isspace (*line) ) ++line;  /*  Skip leading whitespace  */
     if (*line == '#') return (TRUE);
@@ -280,7 +285,30 @@
 	else break;
     }
     if (ptr <= line) return (TRUE);
-    if ( (*line == 's') || (*line == 'r') || (*line == 'h') || (*line == 'b') )
+    
+    switch (*line)
+    {
+	case 's':
+	case 'S':
+	  	where = CHECK_SENDER;
+		break;
+	case 'r':
+	case 'R':
+		where = CHECK_RECIPIENT;
+		break;
+	case 'h':
+	case 'H':
+		where = CHECK_HEADER;
+		break;
+	case 'b':
+	case 'B':
+		where = CHECK_BODY;
+		break;
+	default:
+		where = FALSE;
+	break;
+    } 
+    if (where)
     {
 	int errcode;
 	struct regexp tmp, *regexp;
@@ -288,21 +316,8 @@
 
 	memset (&tmp, 0, sizeof tmp);
 	tmp.and_logic = TRUE;
-	switch (*line)
-	{
-	  case 's':
-	    tmp.where = CHECK_SENDER;
-	    break;
-	  case 'r':
-	    tmp.where = CHECK_RECIPIENT;
-	    break;
-	  case 'h':
-	    tmp.where = CHECK_HEADER;
-	    break;
-	  case 'b':
-	    tmp.where = CHECK_BODY;
-	    break;
-	}
+	tmp.where = where;
+
 	if ( ( line = skip_to_next (line) ) == NULL ) return (FALSE);
 	if (*line == '&')
 	{
@@ -410,6 +425,11 @@
 	    *action = (*action & ACTION_OPTION_MASK) + ACTION_REDIRECT;
 	    ptr += 8;
 	}
+	else if (strncasecmp (ptr, "COPY", 4) == 0)
+	{
+	    *action = (*action & ACTION_OPTION_MASK) + ACTION_COPY;
+	    ptr += 4;
+	}
 	else if (strncasecmp (ptr, "ACCEPT", 6) == 0)
 	{
 	    *action = (*action & ACTION_OPTION_MASK) + ACTION_ACCEPT;
@@ -605,8 +625,13 @@
 static sfsistat mlfi_envfrom (SMFICTX *ctx, char **argv)
 {
     struct message *message;
+    char * envid = NULL;
+
+    if(! (envid = smfi_getsymval(ctx, "i")) )
+	    envid = "NOQUEUE";
+
+    if (debug) fprintf (stderr, "%s: mlfi_envfrom: \"%s\"\n", message->envid, argv[0]);
 
-    if (debug) fprintf (stderr, "mlfi_envfrom: \"%s\"\n", argv[0]);
     /*  Set default message for resource problems for each message  */
     smfi_setreply (ctx, "441", NULL, "milter-regexp: allocation failure");
     if ( ( message = calloc (1, sizeof *message) ) == NULL )
@@ -622,8 +647,11 @@
 	free (message);
 	return (SMFIS_TEMPFAIL);
     }
+    message->sender = strdup (argv[0]);
+    message->envid = envid; 
     message->last = message->first;
     smfi_setpriv (ctx, message);
+
     return (SMFIS_CONTINUE);
 }   /*  End Function mlfi_envfrom  */
 
@@ -632,10 +660,13 @@
     struct message *message = smfi_getpriv (ctx);
     struct envrcpt *envrcpt;
 
-    if (debug) fprintf (stderr, "mlfi_envrcpt: \"%s\"\n", argv[0]);
+    if (debug) fprintf (stderr, "%s: mlfi_envrcpt: \"%s\"\n", message->envid, argv[0]);
     if ( ( envrcpt = get_envrcpt (argv[0]) ) == NULL ) return (SMFIS_TEMPFAIL);
     message->last->next = envrcpt;
     message->last = envrcpt;
+
+    process_line (ctx, argv[0], CHECK_RECIPIENT);
+    
     return (SMFIS_CONTINUE);
 }   /*  End Function mlfi_envrcpt  */
 
@@ -697,6 +728,18 @@
 	message->long_header = TRUE;
 	return (SMFIS_CONTINUE);
     }
+ 
+    if (strncasecmp (headerf,"From:",5) == 0)
+    {
+        process_line (ctx, headerv, CHECK_SENDER); 
+    } 
+    if ( (strncasecmp (headerf,"To:",3) == 0) ||
+         (strncasecmp (headerf,"CC:",3) == 0)
+        )
+    {
+        process_line (ctx, headerv, CHECK_RECIPIENTS);
+    }
+    
     sprintf (message->buffer, "%s: ", headerf);
     outptr = (char *) message->buffer + len + 2;
     stop = (char *) message->buffer + BUFLEN;
@@ -783,6 +826,10 @@
 	    smfi_delrcpt (ctx, (char *) envrcpt->name);
 	smfi_addrcpt (ctx, matched_sys_recipe->string);
 	break;
+      case ACTION_COPY:
+        if (header_only) return (SMFIS_CONTINUE);  /*  Wait until mlfi_eom() */
+	smfi_addrcpt (ctx, matched_sys_recipe->string);
+	break;
       case ACTION_ACCEPT:
 	break;
       default:
@@ -798,7 +845,10 @@
     sfsistat retval;
     struct message *message = smfi_getpriv (ctx);
 
-    if (debug) fprintf (stderr, "mlfi_eoh\n");
+
+    if (debug) fprintf (stderr, "%s: mlfi_eoh\n", message->envid);
+    
+    process_line (ctx, message->sender, CHECK_SENDER); 
     if (message->long_header) return (SMFIS_CONTINUE);
     retval = test_all (ctx, TRUE);
     if (retval != SMFIS_CONTINUE) mlfi_abort (ctx);
@@ -873,7 +923,7 @@
     static char *err_header = "X-Milter-regexp-error";
     static char *tag_header = "X-Milter-regexp";
 
-    if (debug) fprintf (stderr, "mlfi_eom\n");
+    if (debug) fprintf (stderr, "%s: mlfi_eom\n", message->envid);
     if (message->long_header) smfi_addheader (ctx, err_header, "long header");
     if (message->body_overrun)
     {
@@ -1008,7 +1058,7 @@
     struct message *message = smfi_getpriv (ctx);
     struct envrcpt *envrcpt, *envrcpt_next;
 
-    if (debug) fprintf (stderr, "mlfi_abort\n");
+    if (debug) fprintf (stderr, "%s: mlfi_abort\n", message->envid);
     smfi_setpriv (ctx, NULL);
     for (envrcpt = message->first; envrcpt; envrcpt = envrcpt_next)
     {
@@ -1016,6 +1066,8 @@
 	free_envrcpt (envrcpt);
     }
     if (message->envfrom) free ( (void *) message->envfrom );
+    if (message->sender)
+    	free (message->sender);
     free (message);
     return (SMFIS_CONTINUE);
 }   /*  End Function mlfi_abort  */
