[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
patch as per pevious discussion on -b -B -r switches
From: |
Joe Maimon |
Subject: |
patch as per pevious discussion on -b -B -r switches |
Date: |
Thu, 11 Nov 2004 17:18:18 -0500 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040616 Mnenhy/0.6.0.101 |
Attached patch is an extemely rough recent draft of a patch (filled with
noob code ime sure) that supports most of what was discussed previously
about the -b -B -r switches
(I have been working on this because.....because.... I dont actualy have
a good reason)
I have been thinking of using this to feed high scoring emails for
auto-DSBL blocklisting while simultanesouly sending them to a another
address for review and potential whitelisting (again a DNS-WL) and similar.
Here is some of the embedded comments
/*
* This supports syntaxes like these:
* -b"<=20>=10,address@hidden"
* -b">10,address@hidden"
* -b">=10,address@hidden"
* -b">=10<=20,address@hidden"
* -b"<20>10,address@hidden"
* -b"<20>10,address@hidden;<30>40,address@hidden"
* -b"\<address@hidden>"
* -b"\<address@hidden> \<address@hidden>"
* -r"20,Depart from here spammer trash"
* -r
* -r '-1'
* -r20
* -r"20Go away\, now please"
* -r"disappear"
*
* -b and -B are interchangeable except -B means remove all
* real recipients.
*
* The argument value can ne concatenated with a ';' and will
* be interpreted as if two of the same options were given.
*
* The charachter [<>,;] should be escaped with \ unless they
* mean score is less than, score is greater than or start of
* rejection message or bucket destination or additional argument
* , repsectively.
*/
Even though it appears to work for the simpler syntaxes I have thrown at
it undoubtedtly it is far from finished and there is a whole lot more
cleanup,commenting and debugging I need to do on this and also a discard
message switch I would like to add.
I will probably keep at this until I lose interest anyways so....
Any and all feedback welcome,
Joe
diff -urN spamass-milt.orig/Makefile.am spamass-milt.bBranges/Makefile.am
--- spamass-milt.orig/Makefile.am 2004-11-11 16:19:27.000000000 -0500
+++ spamass-milt.bBranges/Makefile.am 2004-11-07 15:35:54.000000000 -0500
@@ -44,7 +44,7 @@
contrib/spamass-milter.spec.in
FBSD_CONTRIB = contrib/spamass-milter.sh
MISC_CONTRIB = contrib/README.gnus
-spamass_milter_SOURCES = spamass-milter.cpp spamass-milter.h
+spamass_milter_SOURCES = spamass-milter.cpp spamass-milter.h llist.c llist.h
spamass_milter_LDADD = @LIBOBJS@
EXTRA_DIST = $(DEB_CONTRIB) \
$(RH_CONTRIB) \
@@ -54,3 +54,4 @@
subst_poll.h
spamass-milter.cpp: spamass-milter.h
+llist.c: llist.h
diff -urN spamass-milt.orig/configure.in spamass-milt.bBranges/configure.in
--- spamass-milt.orig/configure.in 2004-11-11 16:19:27.000000000 -0500
+++ spamass-milt.bBranges/configure.in 2004-11-08 23:43:40.000000000 -0500
@@ -100,8 +100,8 @@
DN_WITH_DMALLOC
# Checks for library functions.
-AC_CHECK_FUNCS([vsyslog vasprintf vsnprintf])
-AC_CHECK_FUNCS([asprintf snprintf])
+AC_CHECK_FUNCS([vsyslog])
+AC_CHECK_FUNCS([snprintf vsnprintf],have_vsnprintf="yes")
AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(connect, socket)
AC_SEARCH_LIBS(inet_aton, resolv)
@@ -112,6 +112,11 @@
AC_LANG_PUSH(C)
AC_REPLACE_FUNCS(strsep daemon)
AC_CHECK_DECLS([strsep, daemon])
+AC_CHECK_FUNCS([vasprintf],AC_DEFINE(HAVE_VASPRINTF,[1]),AC_DEFINE(HAVE_VASPRINTF,[0]))
+AC_CHECK_FUNCS([asprintf],AC_DEFINE(HAVE_ASPRINTF,[1]),AC_DEFINE(HAVE_ASPRINTF,[0]))
+if test x$have_vsnprintf = xyes; then
+ AC_LIBOBJ([vsnprintf_alloc])
+fi
AC_LANG_POP(C)
# Check for libmilter and its header files in the usual locations
diff -urN spamass-milt.orig/llist.c spamass-milt.bBranges/llist.c
--- spamass-milt.orig/llist.c 1969-12-31 19:00:00.000000000 -0500
+++ spamass-milt.bBranges/llist.c 2004-11-08 23:35:36.000000000 -0500
@@ -0,0 +1,406 @@
+/*
+ llist A linked list and manipulation "library"
+
+ Copyright 2002, Joe Maimon, New York USA
+
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "llist.h"
+
+#ifdef _LLIST_ERROR_
+#include "llist_error.h"
+#endif /* _LLIST_ERROR_ */
+
+struct linked_list *
+add_linked_list_item(struct linked_list *list,char *data)
+{
+ list = push_linked_list_item(list,(void *)data,strlen(data)+1);
+ return(list);
+}
+
+struct linked_list *
+push_linked_list_item(struct linked_list * list,void * data,size_t size)
+{
+ struct linked_list * newlist = NULL;
+
+
+ if (!(size && data))
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(EINVAL,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(list);
+ }
+
+ newlist = (struct linked_list *) malloc ( sizeof(struct linked_list));
+ if (!newlist)
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(ENOMEM,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(list);
+ }
+
+ newlist->data = NULL;
+ newlist->next = NULL;
+ newlist->prev = NULL;
+ newlist->size = size;
+
+
+ newlist->data = (void *) malloc ( newlist->size );
+ if (!newlist->data)
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(ENOMEM,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ free(newlist);
+ return(list);
+ }
+
+ memcpy(newlist->data,data,newlist->size);
+
+ if (list)
+ {
+ list->next = newlist;
+ newlist->prev = list;
+ }
+
+ return(newlist);
+}
+
+struct linked_list *
+del_linked_list_item(struct linked_list *list)
+{
+ struct linked_list *newlist = NULL;
+ struct linked_list *nlistp = NULL;
+
+ if (!list)
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(EINVAL,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(NULL);
+ }
+
+ /* First the data */
+ /* If you have use of the data, set list->data=NULL before calling this
*/
+ if (list->data)
+ free(list->data);
+
+ if (list->next == NULL && list->prev != NULL)
+ {
+ /* We are at the end, more behind us and nothing in front */
+ newlist = list->prev;
+ newlist->next = NULL;
+ free(list);
+ return(newlist);
+ }
+ if (list->next != NULL && list->prev == NULL)
+ {
+ /* We are at the begining, more to come and nothing behind */
+ newlist = list->next;
+ newlist->prev = NULL;
+ free(list);
+ return(newlist);
+ }
+ if (list->next != NULL && list->prev != NULL)
+ {
+ /* We are in the middle of it now */
+ /* We choose to advance the pointer 'forward' */
+ newlist = list->next;
+ nlistp = list->prev;
+ nlistp->next = newlist;
+ newlist->prev = nlistp;
+ free(list);
+ return(newlist);
+ }
+ if (list->next == NULL && list->prev == NULL)
+ {
+ /* Last remaining Item */
+ free(list);
+ return(NULL);
+ }
+ /*
+ * We should never get here.
+ * At this point we are looking at a big bug
+ */
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(LLIST_ERROR_EDELE,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(list);
+
+}
+
+struct linked_list *
+del_linked_list(struct linked_list *list)
+{
+ while (list)
+ list = del_linked_list_item(list);
+
+ return(list);
+}
+
+struct linked_list *
+popdel_linked_list_item(struct linked_list * list,void ** data,size_t * len)
+{
+ if(!(data && list && list->data))
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(EINVAL,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(list);
+ }
+ *data = linked_list_data(list, len);
+ list->data = NULL; /* So that the list forgets about this item */
+ list = del_linked_list_item(list);
+ return (list);
+}
+
+struct linked_list *
+pop_linked_list_item(struct linked_list * list,void ** data,size_t * len)
+{
+ if(!(data && list && list->data))
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(EINVAL,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(list);
+ }
+ *data = linked_list_data(list, len);
+ return(list);
+
+}
+
+struct linked_list *
+getanddel_linked_list_item(struct linked_list * list,void ** data,size_t * len)
+{
+ return(popdel_linked_list_item(list,data,len));
+
+}
+
+struct linked_list *
+popnext_linked_list_item(struct linked_list * list,void ** data,size_t * len)
+{
+ struct linked_list * nlistp = NULL;
+ *data = linked_list_data(list, len);
+ if( (nlistp = next_linked_list_item(list)) )
+ return(nlistp);
+ else
+ if( (nlistp = prev_linked_list_item(list)) )
+ return(nlistp);
+ else
+ return(list);
+
+}
+
+void *
+linked_list_data(struct linked_list * list, size_t * len)
+{
+ if(!list)
+ return(NULL);
+
+ if(len)
+ *len = list->size;
+ return(list->data);
+}
+
+char *
+linked_list_item(struct linked_list * list)
+{
+ return((char *) linked_list_data(list,0));
+}
+
+
+struct linked_list *
+next_linked_list_item(struct linked_list * list)
+{
+ list = step_linked_list(list,1);
+ return(list);
+}
+
+struct linked_list *
+prev_linked_list_item(struct linked_list * list)
+{
+ list = step_linked_list(list,0);
+ return(list);
+}
+
+struct linked_list *
+step_linked_list(struct linked_list * list,const int dir)
+{
+ /* 0 == FIFO, 0< == LIFO */
+
+ if (!list)
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(EINVAL,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(list);
+ }
+
+ if (!dir)
+ {
+ list = list->prev;
+ }
+ else
+ {
+ list = list->next;
+ }
+ return(list);
+
+}
+
+
+struct linked_list *
+orient_linked_list(struct linked_list * list,const int dir)
+{
+ if (!list)
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(EINVAL,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(list);
+ }
+
+ if (!dir)
+ {
+ while (list->prev)
+ list = list->prev;
+ }
+ else
+ {
+ while (list->next)
+ list = list->next;
+ }
+ return(list);
+}
+
+struct linked_list *
+rewind_linked_list(struct linked_list * list)
+{
+ return(orient_linked_list(list,0));
+}
+
+struct linked_list *
+ffrwrd_linked_list(struct linked_list * list)
+{
+ return(orient_linked_list(list,1));
+}
+
+
+
+size_t
+count_linked_list_data(struct linked_list * list)
+{
+ size_t size = 0;
+
+ if(!list)
+ {
+ return(size);
+ }
+
+ list = orient_linked_list(list,0);
+
+ if(!list)
+ {
+#ifdef _LLIST_ERROR_
+
LLIST_ERROR_THROW(LLIST_ERROR_EORIENT,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(size);
+ }
+ return(count_linked_list_data_dir(list, 1));
+}
+
+size_t
+count_linked_list_data_dir(struct linked_list * list, int direction)
+{
+ size_t size = 0;
+
+ if(!list)
+ return(size);
+
+ while(list)
+ {
+ size += list->size;
+ list = step_linked_list(list, direction);
+ }
+ return(size);
+}
+
+unsigned int
+count_linked_list_items(struct linked_list * list)
+{
+ int count = 0;
+
+ if(!list)
+ {
+ return(0);
+ }
+
+ list = orient_linked_list(list,0);
+
+ if(!list)
+ return(0);
+
+ while(list)
+ {
+ count++;
+ list = next_linked_list_item(list);
+ }
+ return(count);
+}
+
+unsigned int
+count_linked_list(struct linked_list * list,const int dir)
+{
+ int count = 0;
+
+ if(!list)
+ {
+ return(0);
+ }
+
+ while(list)
+ {
+ count++;
+ list = step_linked_list(list,dir);
+ }
+ return(count);
+}
+
+struct linked_list *
+search_linked_list(struct linked_list * list, int (*cmp_func)(void *, void *),
void * needle, int direction)
+{
+
+ if(!list || !cmp_func)
+ {
+#ifdef _LLIST_ERROR_
+ LLIST_ERROR_THROW(EINVAL,__FILE__,__LINE__,__func__);
+#endif /* _LLIST_ERROR_ */
+ return(NULL);
+ }
+
+ while(list)
+ {
+ if((*cmp_func)(linked_list_data(list, NULL), needle) == 0)
+ return list;
+
+ list = step_linked_list(list, direction);
+ }
+ return(NULL);
+}
diff -urN spamass-milt.orig/llist.h spamass-milt.bBranges/llist.h
--- spamass-milt.orig/llist.h 1969-12-31 19:00:00.000000000 -0500
+++ spamass-milt.bBranges/llist.h 2004-11-08 23:34:54.000000000 -0500
@@ -0,0 +1,252 @@
+/*
+ llist.h, llist.c
+ Routines to implement linked lists.
+
+ Copyright 2002, Joe Maimon, New York USA
+
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef INCLUDED_LINK_LIST
+ #define INCLUDED_LINK_LIST 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/* A bi-directional list originaly designed for char strings
+* Can theoreticaly be used for anything.
+*
+* DO NOT define space for the structure, just a pointer.
+* When handed a NULL for the first time add_linked_list_item ||
push_linked_list_item
+* will allocate all neccessary and initialize.
+*
+* If handed garbage, you will get a segfault. SO initialize your pointer to
NULL.
+* To use:
+* struct linked_list * list = NULL;
+*/
+
+struct linked_list
+{
+ void * data;
+ struct linked_list *next;
+ struct linked_list *prev;
+ size_t size;
+};
+
+
+/* takes a list pointer and char string pointer, stores it and returns list
address
+* If the list does not currently exist, ensure the pointer *list == NULL and a
new chain will be malloced.
+* Returns *list (arg 1) on error (No mem)
+* This is safe to use with primary list handle as it will not lose a valid
list pointer.
+*
+* TO detect whether value was stored correctly, compare return poiinter with
input pointer.
+* If they match, no storage was done.
+*
+* This is a wrapper arounf push_linked_list_item for char strings.
+* TO Use:
+* list = add_linked_list_item(list, string);
+*/
+
+struct linked_list *
+add_linked_list_item(struct linked_list *list,char *data);
+
+/*See add_linked_list_item()
+ *
+ * This is the general case of the above, it takes a (void *) to an opaque
data structure.
+ * You must supply the size.
+ *
+ * TO Use:
+ * list = push_linked_list_item(list,(void *)data,(int) data_size);
+ */
+struct linked_list *
+push_linked_list_item(struct linked_list * list,void * data, size_t size);
+
+/* takes list pointer. Free char string and list item. Direction is default to
LIFO
+* returns a new list pointer or NULL if the list is done for.
+*
+* This is safe to use on primary list handle because when you get NULL back,
+* there is nothing left to lose.
+*/
+
+struct linked_list *
+del_linked_list_item(struct linked_list *list);
+
+/* Takes list pointer. recursively calls del_linked_list_item until list is no
more
+* Returns NULL.
+*
+* Use this on the primary list handle because it should be NULL after you call
this.
+*
+*/
+
+struct linked_list *
+del_linked_list(struct linked_list *list);
+
+/* These two pop the data pointer and unlink/free the current list entry.
+ * There is NO mallocing here, the data pointer is copied.
+ *
+ * Refer to pop_linked_list_item and del_linked_list_item
+ */
+
+struct linked_list *
+getanddel_linked_list_item(struct linked_list *list,void ** data,size_t * len);
+
+struct linked_list *
+popdel_linked_list_item(struct linked_list * list,void ** data,size_t * len);
+
+/* Takes a list pointer, a pointer to a pointer of proper type, and a pointer
to a size_t variable.
+ * If data pointer is NULL nothing is stored there. If length pointer is NULL,
length information is NOT stored there.
+ * You need to make sure you can detect the end of the data refereneced by the
pointer in that case.
+ *
+ * Does not delete the list item.
+ * Does not move the list position.
+ * Will not alter list value.
+ *
+ * You must use this in conjunction with {step|next|prev}_linked_list_item
which may return a NULL
+ * Test for NULL before assigning it your list handle because otherwise you
risk a memory leak.
+ *
+ * Call count_linked_list_items to obtain a loop countdown.
+ *
+ * If there is an error data will remain NULL and so will len.
+ *
+ * Advice: use linked_list_data() instead.
+ */
+
+struct linked_list *
+pop_linked_list_item(struct linked_list * list,void ** data,size_t * len);
+
+/* The only difference in this one is that the list posistion is moved.
+ * If not possible (because the end of the list is here) it will return list
verbatim.
+ * It is a good idea to orient the list while using this.
+ *
+ * DO NOT test for NULL to terminate while loops while using this. Instead
call count_linked_list_items.
+ * No deleting
+ *
+ * Advice: If possible use linked_list_data() followed by step_linked_list()
instead.
+ */
+
+struct linked_list *
+popnext_linked_list_item(struct linked_list * list,void ** data,size_t * len);
+
+/*
+ * Returns a pointer to the linked lists data. Does not free.
+ * Sets size value.
+ */
+
+void *
+linked_list_data(struct linked_list * list, size_t * len);
+
+/* Calls above but assumes char *
+ */
+
+char *
+linked_list_item(struct linked_list * list);
+
+
+/* Takes list pointer and moves forward */
+struct linked_list *
+next_linked_list_item(struct linked_list * list);
+
+/* Takes list pointer and moves backwards */
+struct linked_list *
+prev_linked_list_item(struct linked_list * list);
+
+/* Steps one link in any direction of list
+ * (DIR) ? LIFO : FIFO
+ */
+struct linked_list *
+step_linked_list(struct linked_list * list,int dir);
+
+/* Takes list pointer and flag for which direction to orient list
+* (DIR) ? LIFO : FIFO
+*/
+
+struct linked_list *
+orient_linked_list(struct linked_list *list,const int dir);
+
+/*
+ * Convenience functions for above
+ */
+struct linked_list *
+rewind_linked_list(struct linked_list *list);
+
+struct linked_list *
+ffrwrd_linked_list(struct linked_list *list);
+
+/*
+* Takes pointer to list; returns total byte count of all data pointed to
list->data_ptr
+* On error will return 0, same as no data.
+*/
+
+size_t count_linked_list_data(struct linked_list * list);
+
+/*
+ * Same as ABove but only counts data in direction indicated (1 forward 0
reverse) until
+ * end of list
+*/
+
+size_t count_linked_list_data_dir(struct linked_list * list, int direction);
+
+/*
+* Takes pointer to list; return count of ALL linked_list structures pointed to.
+*
+* Return 0 on error (passing a null or bad list in)
+*/
+
+unsigned int
+count_linked_list_items(struct linked_list * list);
+
+/*
+* Takes pointer to list; return count of linked_list structures.
+* This will only count till the end of the list in the direction you specify.
+* Return 0 on error (passing a null or bad list in)
+*/
+
+unsigned int
+count_linked_list(struct linked_list * list,const int dir);
+
+/*
+ * Takes pointer to list, address of function that return an int and takes two
+ * arguments of pointer to void, a pointer to void and a direction to search
+ * the list till end.
+ *
+ * Returns NULL or pointer to list if passed in function returns 0
+ *
+ * The passed in function will be called with a pointer to the data in the
+ * list item and the third argument. If it return 0 than, this function will
return
+ * the pointer to the list which contained that piece of data.
+ *
+ * If no items in the list produce the return value of 0 from the passed in
function
+ * or if the passed in arguments are invalid, NULL will be returned.
+ *
+ * Side effects: None except any caused by passed in function.
+ *
+ * Advice: You should consider rewind_linked_list() or ffrwrd_linked_list
before calling this.
+ */
+struct linked_list *
+search_linked_list(struct linked_list * list, int(*cmp_func)(void * data, void
* needle), void * needle, const int dir);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* INCLUDED_LINK_LIST */
diff -urN spamass-milt.orig/llist_error.c spamass-milt.bBranges/llist_error.c
--- spamass-milt.orig/llist_error.c 1969-12-31 19:00:00.000000000 -0500
+++ spamass-milt.bBranges/llist_error.c 2004-11-08 21:28:03.000000000 -0500
@@ -0,0 +1,139 @@
+#include "llist.h"
+#include "llist_error.h"
+
+struct llist_error_FLAGS llist_error_flags = { 0,0,0,0 };
+
+static unsigned int
+llist_error_index(unsigned int);
+
+static void
+llist_error_action(unsigned int,const char *);
+
+static void
+llist_error_perror_arg(unsigned int, const char *);
+
+static unsigned int
+llist_error_get(void);
+
+static struct llist_error llist_error_table [] =
+{
+ { LLIST_ERROR_EGIGO , "garbage in, garbage out" , 0 },
+ { LLIST_ERROR_EDELE , "deletion routine reaached impossible code
branch", 1},
+ { LLIST_ERROR_EORIENT, "a call to orient_linked_list returned NULL", 0}
+
+};
+
+static unsigned int llist_errno = 0;
+
+static unsigned int
+llist_error_index(unsigned int ui)
+{
+ int i = 0;
+
+ while(i < sizeof(llist_error_table)/sizeof(llist_error_table[0]) )
+ {
+ if(llist_error_table[i].llist_errno == ui)
+ return(i);
+
+ i++;
+ }
+ return(0);
+}
+
+static void
+llist_error_action(unsigned int ui,const char *s)
+{
+ if(llist_error_flags.print)
+ llist_error_perror_arg(ui,s);
+
+
+ if(ui > LLIST_ERROR_FIRST)
+ {
+
+ if( (llist_error_table[llist_error_index(ui)].severity)
+ &&(llist_error_flags.llist_abort) )
+ exit(EX_FAIL);
+ }
+ if(ui < LLIST_ERROR_FIRST)
+ {
+ if(llist_error_flags.sys_abort)
+ exit( (ui <= sys_nerr) ? ui : EX_FAIL);
+ }
+ return;
+
+}
+
+static void
+llist_error_perror_arg(unsigned int ui,const char *s)
+{
+ char * s2 = NULL;
+
+ if(ui < LLIST_ERROR_FIRST)
+ {
+ s2 = strerror((int)ui);
+ fprintf(stderr,"%s : %s\n",s,s2);
+ }
+
+ if(llist_errno > LLIST_ERROR_FIRST)
+ fprintf(stderr,"%s :
%s\n",s,llist_error_table[llist_error_index(ui)].llist_error_string);
+
+ if(ui == LLIST_ERROR_FIRST)
+ fprintf(stderr,"%s : %s\n",s,"Not an error");
+
+ return;
+}
+
+
+void llist_error_throw(unsigned int ui,const char * s)
+{
+ llist_errno = ui;
+
+ llist_error_action(ui,s);
+
+ return;
+}
+
+unsigned int llist_error_catch(const char * s)
+{
+ unsigned int ui = llist_error_get();
+
+ if(s)
+ llist_error_action(ui,s);
+ if(llist_error_flags.clear)
+ llist_error_clear();
+ return(ui);
+}
+
+void llist_error_clear(void)
+{
+ llist_errno = 0;
+}
+
+static unsigned int llist_error_get(void)
+{
+ return(llist_errno);
+}
+
+unsigned int llist_error_errno(void)
+{
+ return(llist_error_get());
+}
+
+char *
+llist_error_strerror(unsigned int ui)
+{
+ if(ui < LLIST_ERROR_FIRST)
+ return(strerror((int) ui));
+
+ if(ui > LLIST_ERROR_FIRST)
+
return(llist_error_table[llist_error_index(ui)].llist_error_string);
+
+ return("");
+}
+
+void llist_error_perror(const char * s)
+{
+ (void) llist_error_perror_arg(llist_error_errno(),s);
+
+ return;
+}
diff -urN spamass-milt.orig/llist_error.h spamass-milt.bBranges/llist_error.h
--- spamass-milt.orig/llist_error.h 1969-12-31 19:00:00.000000000 -0500
+++ spamass-milt.bBranges/llist_error.h 2004-11-08 21:28:58.000000000 -0500
@@ -0,0 +1,62 @@
+#ifndef HAVE_LLIST_ERROR_INCLUDE
+ #define HAVE_LLIST_ERROR_INCLUDE
+#include <errno.h>
+#include <sys/errno.h>
+#include <sysexits.h>
+
+#ifndef EX_FAIL
+ #define EX_FAIL 63
+#endif /* EX_FAIL */
+
+struct llist_error
+{
+ unsigned int llist_errno;
+ char * llist_error_string;
+ unsigned int severity;
+};
+
+enum
+{
+ LLIST_ERROR_FIRST = 1000,
+ LLIST_ERROR_EGIGO,
+ LLIST_ERROR_EDELE,
+ LLIST_ERROR_EORIENT,
+
+
+
+ LLIST_ERROR_LAST
+} llist_errors;
+
+struct llist_error_FLAGS
+{
+ char llist_abort; /* bail on severe errors */
+ char sys_abort; /* bail on system errors */
+ char print; /* library prints errors or not? */
+ char clear; /* clear error from llist_error_catch */
+
+} llist_error_flags ;
+
+
+
+void llist_error_throw(unsigned int,const char *);
+
+void llist_error_clear(void);
+
+unsigned int llist_error_errno(void);
+
+char * llist_error_strerror(unsigned int);
+
+void llist_error_perror(const char *);
+
+#ifndef MAX_BUF
+ #define MAX_BUF 1024
+#endif /* MAX_BUF */
+
+#define LLIST_ERROR_THROW(w,x,y,z) \
+{\
+ char buf[MAX_BUF];\
+ snprintf(buf,sizeof(buf),"%s:%d %s()",x,y,z);\
+ llist_error_throw(w,buf);\
+}
+
+#endif /* HAVE_LLIST_ERROR_INCLUDE */
diff -urN spamass-milt.orig/spamass-milter.cpp
spamass-milt.bBranges/spamass-milter.cpp
--- spamass-milt.orig/spamass-milter.cpp 2004-11-11 16:19:27.000000000
-0500
+++ spamass-milt.bBranges/spamass-milter.cpp 2004-11-11 13:11:40.000000000
-0500
@@ -102,6 +102,8 @@
#include "libmilter/mfapi.h"
//#include "libmilter/mfdef.h"
+#include "vsnprintf_alloc.h"
+#include "llist.h"
#if !HAVE_DECL_STRSEP
char *strsep(char **stringp, const char *delim);
@@ -127,6 +129,9 @@
// }}}
+struct linked_list * bBra_list = NULL;
+int bBra_search_dir = 0; /* search list in reverse order of entry*/
+
static const char Id[] = "$Id: spamass-milter.cpp,v 1.85 2004/09/24 04:42:16
dnelson Exp $";
struct smfiDesc smfilter =
@@ -165,7 +170,6 @@
int spamc_argc;
char **spamc_argv;
bool flag_bucket = false;
-bool flag_bucket_only = false;
char *spambucket;
bool flag_full_email = false; /* pass full email address to spamc */
bool flag_expand = false; /* alias/virtusertable expansion */
@@ -180,11 +184,17 @@
main(int argc, char* argv[])
{
int c, err = 0;
+#if defined(_GNU_SOURCE)
+ const char *args = "fd:mMp:P:r::u:D:i:b:B:e:x";
+#else
const char *args = "fd:mMp:P:r:u:D:i:b:B:e:x";
+#endif
char *sock = NULL;
bool dofork = false;
char *pidfilename = NULL;
FILE *pidfile = NULL;
+ struct bBrAction bbra;
+ char *p;
#ifdef HAVE_VERBOSE_TERMINATE_HANDLER
std::set_terminate (__gnu_cxx::__verbose_terminate_handler);
@@ -229,7 +239,12 @@
break;
case 'r':
flag_reject = true;
- reject_score = atoi(optarg);
+ p = optarg;
+ do {
+ bbra = parse_bBr_arg(c, p, &p);
+ bBra_list =
push_linked_list_item(bBra_list, (void*) &bbra,
+ sizeof(struct bBrAction));
+ } while (p);
break;
case 'u':
flag_sniffuser = true;
@@ -237,24 +252,24 @@
break;
case 'b':
case 'B':
- if (flag_bucket)
- {
- fprintf(stderr, "Can only have one -b
or -B flag\n");
- err = 1;
- break;
- }
flag_bucket = true;
if (c == 'b')
{
- flag_bucket_only = true;
smfilter.xxfi_flags |= SMFIF_DELRCPT;
// May delete recipients
}
- // we will modify the recipient list; if spamc
returns
- // indicating that this mail is spam, the
message will be
- // sent to <optarg>@localhost
- smfilter.xxfi_flags |= SMFIF_ADDRCPT; // May
add recipients
- // XXX we should probably verify that optarg is
vaguely sane
- spambucket = strdup( optarg );
+ smfilter.xxfi_flags |= SMFIF_ADDRCPT;
+ p = optarg;
+ do {
+ bbra = parse_bBr_arg(c, p, &p);
+ if (!bbra.bucket)
+ {
+ fprintf(stderr, "-%c arg
requires a bucket address\n", c);
+ err = 1;
+ }
+ else
+ bBra_list =
push_linked_list_item(bBra_list, (void*) &bbra,
+ sizeof(struct
bBrAction));
+ } while (p);
break;
case 'x':
flag_expand = true;
@@ -414,6 +429,16 @@
string::size_type eoh2 = assassin->d().find("\n\r\n");
string::size_type eoh = (eoh1 < eoh2) ? eoh1 : eoh2;
string::size_type bob = assassin->d().find_first_not_of("\r\n", eoh);
+ struct bBrAction bbra;
+ struct bBrAction * bbra_p = NULL;
+ int score = 0;
+ bool flag_score = false;
+ struct linked_list * rcpt_list = NULL;
+ struct linked_list * bbra_list;
+ bool flag_bucket_only = false;
+
+ bBra_list = orient_linked_list(bBra_list, (bBra_search_dir) ? 0 : 1);
+ memset(&bbra, '\0', sizeof(bbra));
if (bob == string::npos)
bob = assassin->d().size();
@@ -421,64 +446,140 @@
update_or_insert(assassin, ctx, assassin->spam_flag(),
&SpamAssassin::set_spam_flag, "X-Spam-Flag");
update_or_insert(assassin, ctx, assassin->spam_status(),
&SpamAssassin::set_spam_status, "X-Spam-Status");
- /* Summarily reject the message if SA tagged it, or if we have a minimum
- score, reject if it exceeds that score. */
+ if (flag_reject || flag_bucket)
+ {
+ /* we need the score now */
+ int rv;
+ const char *spam_status = assassin->spam_status().c_str();
+ /* SA 3.0 uses the keyword "score" */
+ rv = sscanf(spam_status,"%*s score=%d", &score);
+ if (rv != 1)
+ {
+ /* SA 2.x uses the keyword "hits" */
+ rv = sscanf(spam_status,"%*s hits=%d", &score);
+ }
+ if (rv != 1)
+ debug(D_ALWAYS, "Could not extract score from <%s>",
spam_status);
+ else
+ {
+ bbra.score = score;
+ bbra.score_flag = true;
+ debug(D_MISC, "SA score: %d", score);
+ }
+ }
+
+ /* Summarily reject the message if SA tagged it and we have a reject action
+ * that matches this scores. Otherwise reject it if there is a matching
reject action
+ * for this score.
+ */
if (flag_reject)
{
bool do_reject = false;
- if (reject_score == -1 && !assassin->spam_flag().empty())
- do_reject = true;
- if (reject_score != -1)
- {
- int score, rv;
- const char *spam_status = assassin->spam_status().c_str();
- /* SA 3.0 uses the keyword "score" */
- rv = sscanf(spam_status,"%*s score=%d", &score);
- if (rv != 1)
- {
- /* SA 2.x uses the keyword "hits" */
- rv = sscanf(spam_status,"%*s hits=%d", &score);
- }
- if (rv != 1)
- debug(D_ALWAYS, "Could not extract score from <%s>",
spam_status);
- else
- {
- debug(D_MISC, "SA score: %d", score);
- if (score >= reject_score)
- do_reject = true;
- }
- }
+ bbra_list = bBra_list;
+ bbra.bBr[0] = 'r';
+ do
+ {
+ bbra_list = search_linked_list(bbra_list, bBr_cmp,(void *)
&bbra, bBra_search_dir);
+ if (!bbra_list)
+ break;
+
+ bbra_p = (struct bBrAction *) linked_list_data(bbra_list, NULL);
+ bbra_list = step_linked_list(bbra_list, bBra_search_dir);
+ if (!bbra_p)
+ continue;
+
+ if (bbra_p->min_flag || bbra_p->max_flag)
+ do_reject = true;
+ else if (!assassin->spam_flag().empty())
+ do_reject = true;
+
+ } while(!do_reject);
+
if (do_reject)
{
+ char * p = (bbra_p && bbra_p->bucket && *bbra_p->bucket) ?
+ bbra_p->bucket : (char *)"Blocked by SpamAssassin";
debug(D_MISC, "Rejecting");
- smfi_setreply(ctx, "550", "5.7.1", "Blocked by SpamAssassin");
-
+ smfi_setreply(ctx, "550", "5.7.1", p);
+ //(bbra_p && bbra_p->bucket) ? bbra_p->bucket : (char
*)"Blocked by SpamAssassin");
if (flag_bucket)
{
+ bbra.bBr[0] = 'B';
+ bbra.bBr[1] = 'b';
+ bbra.bBr[2] = '\0';
+ bbra_list = bBra_list;
+ do
+ {
+ bbra_list = search_linked_list(bbra_list,
bBr_cmp, (void*) &bbra, bBra_search_dir);
+ if(bbra_list)
+ {
+ bbra_p = (struct bBrAction
*)linked_list_data(bbra_list, NULL);
+ bbra_list = step_linked_list(bbra_list,
bBra_search_dir);
+ rcpt_list =
add_linked_list_item(rcpt_list, bbra_p->bucket);
+ }
+ } while (bbra_list);
+ }
+
+ if (rcpt_list)
+ {
/* If we also want a copy of the spam, shell out to
sendmail and
send another copy. The milter API will not let you
send the
message AND return a failure code to the sender, so
this is
the only way to do it. */
+#if defined(__FreeBSD__)
int rv;
-
-#if defined(HAVE_ASPRINTF)
+#endif
+#if defined(HAVE_SNPRINTF)
char *buf;
+ char *buf2;
#else
- char buf[1024];
+ char buf[4096];
+ char buf2[4096];
+ char bp1 = buf;
+ char bp2 = buf2;
#endif
char *fmt="%s \"%s\"";
FILE *p;
-#if defined(HAVE_ASPRINTF)
- asprintf(&buf, fmt, SENDMAIL, spambucket);
-#else
+
#if defined(HAVE_SNPRINTF)
- snprintf(buf, sizeof(buf)-1, fmt, SENDMAIL, spambucket);
+ asprintf(&buf,"%s --", SENDMAIL);
+ while (buf && rcpt_list)
+ {
+ char * rcpt = NULL;
+ rcpt_list =
popdel_linked_list_item(rcpt_list,(void **) &rcpt, NULL);
+ asprintf(&buf2, fmt, buf, (rcpt) ? rcpt : "" );
+ if (buf2)
+ {
+ free(buf);
+ buf = buf2;
+ }
+ if (rcpt)
+ {
+ free(rcpt);
+ rcpt = NULL;
+ }
+ }
#else
/* XXX possible buffer overflow here */
- sprintf(buf, fmt, SENDMAIL, spambucket);
-#endif
+ sprintf(buf, "%s --", SENDMAIL);
+ while (rcpt_list)
+ {
+ char * rcpt = NULL;
+ char * bp3;
+
+ rcpt_list = popdel_linked_list_item(rcpt_list,
&rcpt, NULL);
+ sprintf(bp2, fmt, bp1, (rcpt) ? rcpt : "");
+ bp3 = bp2;
+ bp2 = bp1;
+ bp1 = bp3;
+ if (rcpt)
+ {
+ free(rcpt);
+ rcpt = NULL;
+ }
+ }
#endif
debug(D_COPY, "calling %s", buf);
@@ -508,7 +609,7 @@
abort();
}
#endif
-#if defined(HAVE_ASPRINTF)
+#if defined(HAVE_SNPRINTF)
free(buf);
#endif
}
@@ -516,16 +617,56 @@
}
}
- /* Drop the message into the spam bucket if it's spam */
- if ( flag_bucket ) {
- if (!assassin->spam_flag().empty()) {
- // first, add the spambucket address
- if ( smfi_addrcpt( ctx, spambucket ) != MI_SUCCESS ) {
- throw string( "Failed to add spambucket to recipients" );
- }
- if (flag_bucket_only) {
- // Move recipients to a non-active header, one at a
- // time. Note, this may generate multiple X-Spam-Orig-To
+ /* Drop the message into the spam bucket if it's score matches an -bB action
or
+ * if the message is tagged as spam and there is a scoreless -bB action */
+ if (flag_bucket && flag_score)
+ {
+
+ bbra.bBr[0] = 'B';
+ bbra.bBr[1] = '\0';
+ bbra_list = bBra_list;
+ do
+ {
+ bbra_list = search_linked_list(bbra_list, bBr_cmp,(void *)
&bbra, bBra_search_dir);
+ if (bbra_list)
+ {
+ bbra_p = (struct bBrAction
*)linked_list_data(bbra_list, NULL);
+ bbra_list = step_linked_list(bbra_list,
bBra_search_dir);
+ if (!bbra_p)
+ continue; /* should never happen */
+ if (!bbra_p->min_flag && !bbra_p->max_flag &&
assassin->spam_flag().empty())
+ {
+ /* caught scoreless && not tagged as spam,
throw it back */
+ continue;
+ }
+
+ if (bbra.bBr[0] == 'B')
+ flag_bucket_only = true;
+ rcpt_list = add_linked_list_item(rcpt_list,
bbra_p->bucket);
+ }
+ else if (bbra.bBr[0] == 'B')
+ {
+ bbra.bBr[0] = 'b';
+ bbra_list = bBra_list; /* start from end of list again
*/
+ }
+
+ } while (bbra_list);
+ }
+
+ if (rcpt_list) {
+
+ do {
+ char * rcpt;
+
+ rcpt_list = popdel_linked_list_item(rcpt_list,(void **) &rcpt,
NULL);
+ if (smfi_addrcpt(ctx, rcpt) != MI_SUCCESS ) {
+ throw string( "Failed to add spambucket to recipients");
+ }
+ } while (rcpt_list);
+
+ if (flag_bucket_only) {
+ // Move recipients to a non-active header, one at a
+ // time. Note, this may generate multiple X-Spam-Orig-To
// headers, but that's okay.
while( !assassin->recipients.empty()) {
if ( smfi_addheader( ctx, "X-Spam-Orig-To", (char
*)assassin->recipients.front().c_str()) != MI_SUCCESS ) {
@@ -539,10 +680,9 @@
}
assassin->recipients.pop_front();
}
- }
}
}
-
+
update_or_insert(assassin, ctx, assassin->spam_report(),
&SpamAssassin::set_spam_report, "X-Spam-Report");
update_or_insert(assassin, ctx, assassin->spam_prev_content_type(),
&SpamAssassin::set_spam_prev_content_type, "X-Spam-Prev-Content-Type");
update_or_insert(assassin, ctx, assassin->spam_level(),
&SpamAssassin::set_spam_level, "X-Spam-Level");
@@ -804,7 +944,9 @@
struct context *sctx = (struct context*)smfi_getpriv(ctx);
SpamAssassin* assassin = sctx->assassin;
FILE *p;
+#if defined(__FreeBSD__) /* popen bug - see PR bin/50770 */
int rv;
+#endif
debug(D_FUNC, "mlfi_envrcpt: enter");
@@ -1900,26 +2042,22 @@
vsyslog(LOG_ERR, fmt, vl);
va_end(vl);
#else
-#if defined(HAVE_VASPRINTF)
+#if defined(HAVE_VSNPRINTF)
char *buf;
#else
char buf[1024];
#endif
va_list vl;
va_start(vl, fmt);
-#if defined(HAVE_VASPRINTF)
- vasprintf(&buf, fmt, vl);
-#else
#if defined(HAVE_VSNPRINTF)
- vsnprintf(buf, sizeof(buf)-1, fmt, vl);
+ vasprintf(&buf, fmt, vl);
#else
/* XXX possible buffer overflow here; be careful what you pass
to debug() */
vsprintf(buf, fmt, vl);
#endif
-#endif
va_end(vl);
syslog(LOG_ERR, "%s", buf);
-#if defined(HAVE_VASPRINTF)
+#if defined(HAVE_VSNPRINTF)
free(buf);
#endif
#endif /* vsyslog */
@@ -1976,6 +2114,239 @@
}
+/*
+ * This supports syntaxes like these:
+ * -b"<=20>=10,address@hidden"
+ * -b">10,address@hidden"
+ * -b">=10,address@hidden"
+ * -b">=10<=20,address@hidden"
+ * -b"<20>10,address@hidden"
+ * -b"<20>10,address@hidden;<30>40,address@hidden"
+ * -b"\<address@hidden>"
+ * -b"\<address@hidden> \<address@hidden>"
+ * -r"20,Depart from here spammer trash"
+ * -r
+ * -r '-1'
+ * -r20
+ * -r"20Go away\, now please"
+ * -r"disappear"
+ *
+ * -b and -B are interchangeable except -B means remove all
+ * real recipients.
+ *
+ * The argument value can ne concatenated with a ';' and will
+ * be interpreted as if two of the same options were given.
+ *
+ * The charachter [<>,;] should be escaped with \ unless they
+ * mean score is less than, score is greater than or start of
+ * rejection message or bucket destination or additional argument
+ * , repsectively.
+ */
+struct bBrAction parse_bBr_arg(char opt, char * optarg, char **end_p)
+{
+ struct bBrAction bbra;
+ char * gt_str = NULL;
+ char * lt_str = NULL;
+ char * bucket_str = NULL;
+ int i;
+ int in_escape = 0;
+ char *p, *q;
+ char end_p_sav = '\0';
+
+ memset(&bbra, '\0', sizeof(bbra));
+ bbra.bBr[0] = opt;
+ bbra.bBr[1] = '\0';
+
+ p = optarg;
+ i = 0;
+ /* find first unescaped <>,*/
+ while (p && *p)
+ {
+ int in_escape = 0;
+
+ if(*p == '>' && !gt_str && !in_escape)
+ gt_str = p + 1;
+ else if (*p == '<' && !lt_str && !in_escape)
+ lt_str = p + 1;
+ else if (*p == ',' && !bucket_str && !in_escape)
+ bucket_str = p + 1;
+ else if (*p == ';' && end_p && !in_escape)
+ {
+ *end_p = p + 1;
+ end_p_sav = *p;
+ *p = '\0';
+ break;
+ }
+ else if (*p == '\\' && !in_escape)
+ in_escape = 1;
+ else
+ in_escape = 0;
+ p++;
+ }
+
+ if (end_p && !end_p_sav)
+ *end_p = NULL;
+
+ if (gt_str)
+ {
+ int str_off = 0;
+
+ if (*(gt_str) == '=')
+ str_off = 1;
+ bbra.min_score = strtol(gt_str+str_off, &p, 0);
+ bbra.min_score += (str_off) ? 1 : 0;
+ if (p != (gt_str + str_off))
+ bbra.min_flag = 1;
+ }
+
+ if (lt_str)
+ {
+ int str_off = 0;
+
+ if (*(lt_str) == '=')
+ str_off = 1;
+ bbra.max_score = strtol(lt_str+str_off, &p, 0);
+ bbra.max_score -= (str_off) ? 0 : 1;
+ if (p != (lt_str + str_off))
+ bbra.max_flag = 1;
+ }
+
+
+ if (!gt_str && !lt_str && optarg)
+ {
+ /* score may be there without <=>*/
+ p = optarg;
+#if BBR_REQUIRE_COMMA
+ /* no score if no ',' unless option is -r*/
+ if (opt == 'r' || bucket_str)
+#endif
+ bbra.min_score = strtol(optarg, &p, 0);
+ /*only -r supports legacy -1 argument*/
+ if (p != optarg && (opt != 'r' || bbra.min_score != -1))
+ bbra.min_flag = 1;
+#if !BBR_REQUIRE_COMMA
+ /* XXX no requirement for comma to seperate score,bucket*/
+ if (!bucket_str)
+ bucket_str = p;
+ }
+ else if (!bucket_str && optarg)
+ {
+ /* no unescaped ',' in optarg */
+ /* advance pointer past all numeric stuff */
+ p = (gt_str > lt_str) ? gt_str : lt_str;
+ p++;
+ if (*(p+1) == '=')
+ p++;
+ (void) strtol(p, &q, 0);
+ if (q)
+ bucket_str = q;
+#endif
+ }
+
+ /* strip escaping */
+ p = q = bucket_str;
+ i = 0;
+ while (p && p[i])
+ {
+ in_escape = 0;
+ if ((p[i]) == '\\' && !in_escape)
+ in_escape = 1;
+ else
+ {
+ in_escape = 0;
+ *q = *(p + i);
+ q++;
+ }
+ i++;
+ }
+ bbra.bucket = p;
+
+ if (end_p_sav && end_p && *end_p)
+ *(*end_p - 1) = end_p_sav;
+
+ return(bbra);
+}
+
+static void
+bBr_print_list (struct linked_list * bbra_list)
+{
+ struct bBrAction bbra;
+
+ bbra_list = rewind_linked_list(bbra_list);
+
+ while (bbra_list)
+ {
+ memcpy(&bbra, linked_list_data(bbra_list,NULL), sizeof(bbra));
+ bbra_list = next_linked_list_item(bbra_list);
+ }
+}
+
+int bBr_cmp(void * p1, void * p2)
+{
+ struct bBrAction * bbra1 = (struct bBrAction *)p1;
+ struct bBrAction * bbra2 = (struct bBrAction *)p2;
+
+ char * s1 = bbra1->bucket;
+ char * s2 = bbra2->bucket;
+ int max1 = bbra1->max_score;
+ int max2 = bbra2->max_score;
+ int min1 = bbra1->min_score;
+ int min2 = bbra2->min_score;
+ int min1_f = bbra1->min_flag;
+ int min2_f = bbra2->min_flag;
+ int max1_f = bbra1->max_flag;
+ int max2_f = bbra2->max_flag;
+ int score2 = bbra2->score;
+ int score1 = bbra1->score;
+ int score1_f = bbra1->score_flag;
+ int score2_f = bbra2->score_flag;
+ char * bBr1 = bbra1->bBr;
+ char * bBr2 = bbra2->bBr;
+ int result_flag = 0;
+ int i, j;
+
+ for (i = 0; bBr2[i]; i++)
+ {
+ /* see if any of the actions match */
+ for (j = 0; bBr1[j]; j++)
+ {
+ if (bBr1[j] == bBr2[i])
+ {
+ result_flag = 1;
+ break;
+ }
+ }
+ if (result_flag)
+ break;
+ }
+
+ if (result_flag)
+ {
+ if (s2) /* compare bucket strings */
+ return (strcasecmp(s1,s2));
+
+ if (score2 || score2_f) /* comparing score */
+ {
+ if ((score2 <= max1 && max1_f == score2_f) || max1_f <
score2_f)
+ {
+ if ((score2 >= min1 && min1_f == score2_f) ||
min1_f < score2_f)
+ return 0; /* match */
+ }
+ if (score2 == score1 && score1_f == score2_f)
+ return 0; /* match */
+ return 1;
+ }
+ /* comparing minmin maxmax pairs */
+ if (!((max1 <= max2) && (max1_f == max2_f)) || !(max1_f <
max2_f))
+ return 1;
+ if (!((min1 >= min2) && (min1_f == min2_f)) || !(min1_f <
min2_f))
+ return 1;
+
+ return 0; /* match */
+ }
+ return 1;
+
+}
/* closeall() - close all FDs >= a specified value */
void closeall(int fd)
{
diff -urN spamass-milt.orig/spamass-milter.h
spamass-milt.bBranges/spamass-milter.h
--- spamass-milt.orig/spamass-milter.h 2004-11-11 16:19:27.000000000 -0500
+++ spamass-milt.bBranges/spamass-milter.h 2004-11-10 22:09:22.000000000
-0500
@@ -70,6 +70,19 @@
};
+struct bBrAction
+{
+ char * bucket;
+ int max_score;
+ int max_flag;
+ int min_score;
+ int min_flag;
+ int score;
+ int score_flag;
+ char bBr[4];
+};
+
+
// Debug tokens.
enum debuglevel
{
@@ -185,5 +198,7 @@
int ip_in_networklist(struct in_addr ip, struct networklist *list);
void parse_debuglevel(char* string);
char *strlwr(char *str);
+int bBr_cmp(void *, void *);
+struct bBrAction parse_bBr_arg(char opt, char * optarg, char **end_p);
#endif
diff -urN spamass-milt.orig/vsnprintf_alloc.c
spamass-milt.bBranges/vsnprintf_alloc.c
--- spamass-milt.orig/vsnprintf_alloc.c 1969-12-31 19:00:00.000000000 -0500
+++ spamass-milt.bBranges/vsnprintf_alloc.c 2004-11-07 15:58:34.000000000
-0500
@@ -0,0 +1,191 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "vsnprintf_alloc.h"
+
+
+
+int
+vsnprintf_alloc(char **p, size_t len, const char * fmt, va_list argp)
+{
+ char *buf = NULL;
+ char *bufp = NULL;
+ short we_malloced = 0;
+ int retlen = 0;
+ size_t print_len = (len) ? len : strlen(fmt) + BUFSIZ;
+
+ if(!fmt || !p || len < 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(*p)
+ {
+ buf = realloc(*p, print_len + 1);
+ if(!buf)
+ return -1;
+ *p = buf;
+ }
+ else
+ {
+ if((buf = malloc(print_len + 1)))
+ we_malloced = 1;
+ else
+ return -1;
+ }
+
+ while(1)
+ {
+ retlen = vsnprintf(buf, print_len + 1, fmt, argp);
+
+ buf[print_len] = '\0';
+
+ if(retlen == -1)
+ {
+ if(errno == EINVAL)
+ {
+ if(we_malloced)
+ free(buf);
+ else
+ *p = buf;
+ errno = EINVAL;
+ return -1;
+ }
+ /* For optimization, switch this to doubling? */
+ print_len += BUFSIZ;
+ }
+ else if(retlen > print_len)
+ {
+ /* C99 */
+ print_len = retlen;
+ }
+ else
+ {
+ /* Sucess */
+ break;
+ }
+
+ if(len && print_len > len)
+ print_len = len;
+
+ bufp = realloc(buf, print_len + 1);
+ if(!bufp)
+ {
+ if(we_malloced)
+ free(buf);
+ else
+ *p = buf;
+ return -1;
+ }
+ else
+ buf = bufp;
+ }
+
+
+ *p = buf;
+ return(retlen);
+}
+
+int
+vsprintf_alloc(char **p, const char * fmt, va_list argp)
+{
+ if(!fmt || !p)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ return(vsnprintf_alloc(p, 0, fmt, argp));
+}
+
+int
+snprintf_alloc(char **p, size_t len, const char * fmt, ...)
+{
+ int retlen = 0;
+ va_list argp;
+
+ if(!fmt || !p || len < 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ va_start(argp, fmt);
+ retlen = vsnprintf_alloc(p, len, fmt, argp);
+ va_end(argp);
+
+ return(retlen);
+}
+
+int
+sprintf_alloc(char **p, const char * fmt, ...)
+{
+ int retlen = 0;
+ va_list argp;
+
+ if(!fmt || !p)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ va_start(argp, fmt);
+ retlen = vsprintf_alloc(p, fmt, argp);
+ va_end(argp);
+
+ return(retlen);
+}
+
+struct vsnprintf_alloc_cfg *
+vsnprintf_alloc_configure(struct vsnprintf_alloc_cfg * cfg)
+{
+
+}
+
+#if !HAVE_ASPRINTF
+int
+asprintf(char **p, const char * fmt, ...)
+{
+ int retlen = 0;
+ char * buf = NULL;
+ va_list argp;
+
+ if(!fmt || !p)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ va_start(argp, fmt);
+ retlen = vsprintf_alloc(&buf, fmt, argp);
+ if(retlen >= 0)
+ *p = buf;
+ va_end(argp);
+
+ return(retlen);
+}
+#endif /* !HAVE_ASPRINTF */
+
+#if !HAVE_VASPRINTF
+int
+vasprintf(char **p, const char * fmt, va_list argp)
+{
+ char * buf = NULL;
+ int retlen = 0;
+
+ if(!fmt || !p)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ retlen = vsnprintf_alloc(&buf, 0, fmt, argp);
+ if(retlen >= 0)
+ *p = buf;
+ return(retlen);
+}
+#endif /* !HAVE_VASPRINTF */
+#ifdef __cplusplus
+}
+#endif
diff -urN spamass-milt.orig/vsnprintf_alloc.h
spamass-milt.bBranges/vsnprintf_alloc.h
--- spamass-milt.orig/vsnprintf_alloc.h 1969-12-31 19:00:00.000000000 -0500
+++ spamass-milt.bBranges/vsnprintf_alloc.h 2004-11-07 16:14:09.000000000
-0500
@@ -0,0 +1,96 @@
+#ifndef VSNPRINTF_ALLOC_H
+ #define VSNPRINTF_ALLOC_H
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#ifndef HAVE_VASPRINTF
+ #include "config.h"
+#endif
+
+#ifndef BUFSIZ
+ #define BUFSIZ 4096
+#endif
+
+/*
+ * Takes: address of pointer to char, optional maximum length, printf(3)
format string, and a variable list of arguments
+ * Returns: -1 for error or number of bytes (that would have been) printed
into string.
+ *
+ * The address of pointer to char MUST not be null.
+ *
+ * If the pointer to char is NOT null, it MUST be a valid malloc'd memory
string.
+ *
+ * if pointer to char is null, malloc will be called and the address stored
back in the passed in addressed pointer
+ * otherwise realloc will be used as needed on the passed in pointer address
with the result stored back in.
+ *
+ *
+ * Passing in a NULL address or a negative length or a NULL format string
+ * OR
+ * Running out of memory will return -1.
+ *
+ * Doing the former will result in errno == EINVAL.
+ * Presumably the latter will result in errno == ENOMEM.
+ *
+ * On error the pointer to char will be valid if it was originaly supplied by
you and you must free it.
+ *
+ * Passing in a length of zero will allow the function to allocate memory
until the entire string is printed.
+ * Otherwise it will only allocate and print into the string up to the size
specified, including terminating '\0'.
+ *
+ *
+ */
+int
+snprintf_alloc(char **p, size_t len, const char *fmt, ...);
+
+/*
+ * Same as above except 0 is assumed for length
+ */
+int
+sprintf_alloc(char **p, const char *fmt, ...);
+
+/*
+ * same as snprintf_alloc except you pass it argp instead of variable list of
arguments
+ */
+int
+vsnprintf_alloc(char **p, size_t len, const char *fmt, va_list argp);
+
+/*
+ * same as above except 0 is assumed for length
+ */
+int
+vsprintf_alloc(char **p, const char *fmt, va_list argp);
+
+#if !HAVE_ASPRINTF
+/*
+ * like sprintf_alloc except does not support privately allocated memory. Also
does not require *p to be NULL/
+ * On error *p should NOT be used and will probably be NULL.
+ *
+ * WARNING: Passing in address of valid pointer for p will lead to memory
leaks!
+ */
+int
+asprintf(char **p, const char *fmt, ...);
+#endif /* !HAVE_ASPRINF */
+
+#if !HAVE_VASPRINTF
+/*
+ * like vsprintf_alloc except does not support privately allocated memory.
Also does not require *p to be NULL/
+ * On error *p should NOT be used and will probably be NULL.
+ *
+ * WARNING: Passing in address of valid pointer for p will lead to memory
leaks!
+ */
+int
+vasprintf(char **p, const char *fmt, va_list argp);
+#endif /* !HAVE_VASPRINF */
+
+
+struct vsnprintf_alloc_cfg
+{
+ void (*malloc) (size_t);
+ void (*free) (void *, size_t);
+ short multiply;
+ short assertive;
+ size_t internal_limit;
+ short free_on_error;
+};
+
+#endif /* VSNPRINTF_ALLOC_H */
Binary files spamass-milt.orig/vsnprintf_alloc.o and
spamass-milt.bBranges/vsnprintf_alloc.o differ
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- patch as per pevious discussion on -b -B -r switches,
Joe Maimon <=