diff -ru milter-greylist-3.0a5.orig/acl.c milter-greylist-3.0a5.fix/acl.c
--- milter-greylist-3.0a5.orig/acl.c	2006-08-27 20:54:40.000000000 +0000
+++ milter-greylist-3.0a5.fix/acl.c	2006-08-31 11:43:50.000000000 +0000
@@ -514,7 +514,8 @@
 }
 
 int 
-acl_filter(priv, rcpt)
+acl_filter(ctx, priv, rcpt)
+	SMFICTX *ctx;
 	struct mlfi_priv *priv;
 	char *rcpt;
 {
@@ -665,6 +666,20 @@
 			}
 		}
 #endif
+		if (acl->a_macrolist != NULL) {
+			if (list_macro_filter(acl->a_macrolist, ctx)) {
+				retval |= EXF_MACRO;
+			} else {
+				continue;
+			}
+		}
+		if (acl->a_macro != NULL) {
+			if (macro_check(ctx, acl->a_macro) == 0) {
+				retval |= EXF_MACRO;
+			} else {
+				continue;
+			}
+		}
 		/*
 		 * We found an entry that matches, exit the evaluation
 		 * loop
@@ -774,6 +789,11 @@
 			     "recipient %s is whitelisted", rcpt);
 			ADD_REASON(whystr, tmpstr);
 		}
+		if (retval & EXF_MACRO) {
+			snprintf(tmpstr, sizeof(tmpstr),
+			     "macro rule is satisfied");
+			ADD_REASON(whystr, tmpstr);
+		}
 		if (retval & EXF_DEFAULT) {
 			ADD_REASON(whystr, "this is the default action");
 		}
diff -ru milter-greylist-3.0a5.orig/acl.h milter-greylist-3.0a5.fix/acl.h
--- milter-greylist-3.0a5.orig/acl.h	2006-08-27 16:02:25.000000000 +0000
+++ milter-greylist-3.0a5.fix/acl.h	2006-08-31 11:36:04.000000000 +0000
@@ -131,7 +131,7 @@
 void acl_add_macro(char *);
 struct acl_entry *acl_register_entry_first (acl_type_t);
 struct acl_entry *acl_register_entry_last (acl_type_t);
-int acl_filter(struct mlfi_priv *, char *);
+int acl_filter(SMFICTX *, struct mlfi_priv *, char *);
 char *acl_entry(struct acl_entry  *);
 void acl_dump(void);
 int emailcmp(char *, char *);        
@@ -157,4 +157,5 @@
 #define EXF_DRAC	(1 << 14)
 #define EXF_DNSRBL	(1 << 15)
 #define EXF_BLACKLIST	(1 << 16)
+#define EXF_MACRO	(1 << 17)
 #endif /* _ACL_H_ */
diff -ru milter-greylist-3.0a5.orig/dump.c milter-greylist-3.0a5.fix/dump.c
--- milter-greylist-3.0a5.orig/dump.c	2006-08-30 20:50:42.000000000 +0000
+++ milter-greylist-3.0a5.fix/dump.c	2006-08-31 14:44:49.000000000 +0000
@@ -136,20 +136,11 @@
 		       (confp->c_dumpfreq != 0 &&
 			dump_todo == DUMP_TODO_FLUSH)) {
 			if (confp->c_dumpfreq > 0) {
-				struct timeval now;
 				struct timespec timeout;
 
-				gettimeofday(&now, NULL);
-				timeout.tv_sec = now.tv_sec +
-					confp->c_dumpfreq - start.tv_sec;
-				timeout.tv_nsec =
-					(now.tv_usec - start.tv_usec) * 1000;
-				if (timeout.tv_nsec < 0) {
-					--timeout.tv_sec;
-					timeout.tv_nsec += 1000000000;
-				}
-				if (timeout.tv_sec < 0)
-					break;
+				timeout.tv_sec = start.tv_sec +
+					confp->c_dumpfreq;
+				timeout.tv_nsec = start.tv_usec * 1000;
 				error = pthread_cond_timedwait(&dump_sleepflag,
 							       &dump_todo_lock,
 							       &timeout);
@@ -182,9 +173,11 @@
 				conf_retain();
 				confp = GET_CONF();
 				break;
+#ifndef WORKAROUND_LIBMILTER_RACE_CONDITION
 			case DUMP_TODO_FLUSH | DUMP_TODO_TERMINATE:
 				dump_perform(1);
 				break;
+#endif
 			case DUMP_TODO_FLUSH:
 				dump_perform(0);
 				gettimeofday(&start, NULL);
diff -ru milter-greylist-3.0a5.orig/list.c milter-greylist-3.0a5.fix/list.c
--- milter-greylist-3.0a5.orig/list.c	2006-08-27 20:54:41.000000000 +0000
+++ milter-greylist-3.0a5.fix/list.c	2006-08-31 11:37:33.000000000 +0000
@@ -455,7 +455,7 @@
 	struct list_entry *le;
 
 	LIST_FOREACH(le, &list->al_head, l_list) {
-		if (macro_check(ctx, le->l_data.macro) == 1)
+		if (macro_check(ctx, le->l_data.macro) == 0)
 			break;
 	}
 
diff -ru milter-greylist-3.0a5.orig/milter-greylist.c milter-greylist-3.0a5.fix/milter-greylist.c
--- milter-greylist-3.0a5.orig/milter-greylist.c	2006-08-30 20:50:42.000000000 +0000
+++ milter-greylist-3.0a5.fix/milter-greylist.c	2006-08-31 14:55:44.000000000 +0000
@@ -51,6 +51,7 @@
 #include <grp.h>
 #include <unistd.h>
 #include <stdarg.h>
+#include <signal.h>
 
 /* On IRIX, <unistd.h> defines a EX_OK that clashes with <sysexits.h> */
 #ifdef EX_OK
@@ -412,6 +413,7 @@
 	    (priv->priv_whitelist & EXF_NONIP) ||
 	    (priv->priv_whitelist & EXF_DRAC) ||
 	    (priv->priv_whitelist & EXF_ACCESSDB) ||
+	    (priv->priv_whitelist & EXF_MACRO) ||
 	    (priv->priv_whitelist & EXF_STARTTLS))
 		return SMFIS_CONTINUE;
 
@@ -457,7 +459,7 @@
 	 * Check the ACL
 	 */
 	reset_acl_values(priv);
-	if ((priv->priv_whitelist = acl_filter(priv, rcpt)) & EXF_WHITELIST) {
+	if ((priv->priv_whitelist = acl_filter(ctx, priv, rcpt)) & EXF_WHITELIST) {
 		priv->priv_elapsed = 0;
 		return SMFIS_CONTINUE;
 	}
@@ -741,6 +743,7 @@
 	int ch;
 	int checkonly = 0;
 	int exitval;
+	sigset_t set;
 
 	openlog("milter-greylist", LOG_PERROR, LOG_MAIL);
 
@@ -1081,6 +1084,16 @@
 	}
 
 	/*
+	 * Block signals before all other threads start.
+	 * The libmilter watches them and returns from smfi_main() if got.
+	 */
+	sigemptyset(&set);
+	sigaddset(&set, SIGHUP);
+	sigaddset(&set, SIGTERM);
+	sigaddset(&set, SIGINT);
+	pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+	/*
 	 * Start the dumper thread
 	 */
 	dumper_start();
@@ -1098,7 +1111,16 @@
 	exitval = smfi_main();
 	mg_log(LOG_ERR, "smfi_main() returned %d", exitval);
 	
+#ifdef WORKAROUND_LIBMILTER_RACE_CONDITION
+	signal(SIGSEGV, SIG_IGN);
+	signal(SIGBUS, SIG_IGN);
+	signal(SIGABRT, SIG_IGN);
+	conf_retain();
+	dump_perform(1);
+	conf_release();
+#else
 	dumper_stop();
+#endif
 	return exitval;
 }
 
diff -ru milter-greylist-3.0a5.orig/milter-greylist.h milter-greylist-3.0a5.fix/milter-greylist.h
--- milter-greylist-3.0a5.orig/milter-greylist.h	2006-08-30 04:57:58.000000000 +0000
+++ milter-greylist-3.0a5.fix/milter-greylist.h	2006-08-31 15:00:12.000000000 +0000
@@ -268,5 +268,17 @@
 		mystrlcat(whystr, reason, sizeof(whystr));		\
 	}
 
+/*
+ * Due to race conditions in the libmilter shipped with sendmail <= 8.13.8,
+ * the whole process may die after receiving a signal.
+ * It makes impossible the final dump. Apply the following patch ASAP:
+ * http://www.j10n.org/files/libmilter-8.13.8-signal.patch
+ *
+ * If you don't want to apply it, the following knob enables an uncertain
+ * effort to workaround the bug. Do not ask me about this.
+ * 
+ */
+/* #define WORKAROUND_LIBMILTER_RACE_CONDITION */
+
 #endif /* _MILTER_GREYLIST_H_ */
 
