aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/exim/Makefile177
-rw-r--r--mail/exim/Makefile.options149
-rw-r--r--mail/exim/files/extra-patch-kas886
-rw-r--r--mail/exim/options361
4 files changed, 1096 insertions, 477 deletions
diff --git a/mail/exim/Makefile b/mail/exim/Makefile
index c7ede9e4ec45..63b5e1591398 100644
--- a/mail/exim/Makefile
+++ b/mail/exim/Makefile
@@ -19,7 +19,11 @@ EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX}
MAINTAINER= krion@FreeBSD.org
COMMENT?= High performance MTA for Unix systems on the Internet
-.include "options"
+.include "Makefile.options"
+
+USE_BZIP2= yes
+
+.include <bsd.port.pre.mk>
.if defined(WITH_SA_EXIM)
MASTER_SITES+= http://marc.merlins.org/linux/exim/files/:sa_exim \
@@ -51,8 +55,6 @@ WITH_EXIMON= yes
USE_XORG= x11 xaw xt
.endif
-USE_BZIP2= yes
-
.if !defined(EXIMON_ONLY)
MAN8= exim.8
.else
@@ -102,158 +104,25 @@ PLIST_SUB= EXIM_VERSION="${EXIM_VERSION}-${PORTREVISION}" \
EXIM_GROUP=${EXIM_GROUP} \
LOGDIR="${LOGDIR}"
-# Define it to enabale malware and spam scanning in the DATA ACL,
-# and the MIME ACL.
-#WITH_CONTENT_SCAN= yes
-
-# Enable old, deprecated "demime" ACL condition, in addition
-# to all the other content-scanning features.
-#WITHOUT_OLD_DEMIME= yes
-
-# If WITH_EXIMON is defined, the eximon monitor, which requires X,
-# will be made a dependency. Note that using WITH_EXIMON will cause
-# XFree86 to be installed if it is not present.
-#WITH_EXIMON= yes
-
-# If WITH_SA_EXIM is defined, exim will be built with the SA-Exim
-# local_scan function (<http://marc.merlins.org/linux/exim/sa.html>)
-#WITH_SA_EXIM= yes
-
# Exim refuses to run local deliveries as root by default. You can
# add other users to this colon-separated list that cannot be
# overridden at runtime below, but are advised not to remove "root".
#WITH_FIXED_NEVER_USERS= root:daemon:bin
-# Define WITH_TCP_WRAPPERS, WITH_MYSQL, WITH_SQLITE and WITH_PGSQL
-# to link against libwrap, libmysqlclient, sqlite and libpq
-# respectively. Define WITH_SASLAUTHD to enable use of the Cyrus
-# SASL authentication daemon. Define WITH_SQLITE to enable use of
-# the SQLite support. Define WITH_MYSQL_VER to specify a particular
-# version of MySQL to use. Valid values are currently 323, 40 and
-# 41. Defining WITH_MYSQL_VER implies WITH_MYSQL.
-#WITH_TCP_WRAPPERS= yes
-#WITH_MYSQL= yes
-#WITH_MYSQL_VER= 40
-#WITH_PGSQL= yes
-#WITH_SQLITE= yes
-#WITH_SASLAUTHD= yes
-
-# As an alternative to WITH_SASLAUTHD, you can define WITH_PWCHECK to
-# link against libsasl for SMTP AUTH authentication via the Cyrus SASL
-# pwcheck daemon.
-################################
-# THIS MECHANISM IS DEPRECATED #
-################################
-#WITH_PWCHECK= yes
-
-# Define WITHOUT_IPV6 to exclude IPv6 support from the compiled exim
-# binary. Exim compiled with IPv6 support will still operate on
-# systems that do not have IPv6 kernel support, so this should not
-# be necessary.
-#WITHOUT_IPV6= yes
-
-# Define WITH_OPENLDAP or WITH_OPENLDAP_VER to link against libldap.
-# Define WITH_OPENLDAP_VER to specify a particular version of
-# OpenLDAP to use. Valid values are currently 21, 22 and 23.
-# Defining WITH_OPENLDAP_VER implies WITH_OPENLDAP.
-# Exim also supports NETSCAPE and SOLARIS7 lookup types, but no
-# client libraries exist for these in the ports tree.
-#WITH_OPENLDAP= yes
-#WITH_OPENLDAP_VER= 23
-
-# Define WITH_BDB or WITH_BDB_VER to link against the Berkeley DB library.
-# Define WITH_BDB_VER to specify a particular version of Berkeley DB to use.
-# Values may be 1, which corresponds to version 1.85 in the base system, 4,
-# 41, 42, 43, ... which depends on the databases/db4* ports.
-#WITH_BDB= yes
-#WITH_BDB_VER?= 1
-
# When Exim is decoding MIME "words" in header lines it converts any foreign
# character sets to the one that is set in the headers_charset option.
# The default setting is defined by this setting:
WITH_DEFAULT_CHARSET?= ISO-8859-1
-# The following options may be defined to turn off support for various
-# features that this port enables by default.
-#
-# Do not link against OpenSSL; disables STARTTLS.
-#WITHOUT_TLS= yes
-#
-# Disable the embedded Perl interpreter, which allows Perl subroutines to
-# be called during string expansion.
-#WITHOUT_PERL= yes
-#
-# Disable built-in Exim support for the PAM, RFC 2195, RFC 2595 and
-# Microsoft "Secure Password Authentication" authentication mechanisms,
-# used for SMTP AUTH.
-#WITHOUT_PAM= yes
-#WITHOUT_AUTH_CRAM_MD5= yes
-#WITHOUT_AUTH_PLAINTEXT= yes
-#WITHOUT_AUTH_DOVECOT= yes
-#WITHOUT_AUTH_SPA= yes
-#
-# Enable support for authenticating via the Cyrus SASL library
-#WITH_AUTH_SASL= yes
-#
-# Enable built-in Exim support for radius (RFC 2865) authentication
-# RADIUS_TYPE can either be RADLIB (to use the radius library supplied
-# with FreeBSD) or RADIUSCLIENT (to use port net/radiusclient)
-#WITH_AUTH_RADIUS= yes
-#WITH_RADIUS_TYPE= RADLIB
-#
-# Disable built-in Exim support for additional mailbox formats.
-#WITHOUT_MAILDIR= yes
-#WITHOUT_MAILSTORE= yes
-#WITHOUT_MBX= yes
-#
-# Define WITHOUT_CDB, WITHOUT_DNSDB, WITHOUT_DSEARCH, WITHOUT_LSEARCH,
-# WITHOUT_NIS and WITHOUT_PASSWD to disable support for CDB-style, DNS-style,
-# directory-list, wildcarded-file, NIS and /etc/passwd lookups respectively.
-#WITHOUT_CDB= yes
-#WITHOUT_DNSDB= yes
-#WITHOUT_DSEARCH= yes
-#WITHOUT_LSEARCH= yes
-#WITHOUT_NIS= yes
-#WITHOUT_PASSWD= yes
-#
-# Disable support for the LMTP (RFC 2033 "SMTP over command pipe")
-# transport.
-#WITHOUT_LMTP= yes
-#
-# Allow alternate configuration files not only in ${PREFIX}/etc/exim
-#WITHOUT_ALT_CONFIG_PREFIX= yes
-#
-# Include the unsupported patches in ${PATCHDIR}/wishlist-*.patch
-#WITH_WISHLIST= yes
-#
-# Enable Sender Policy Framework (SPF) checking in exiscan-acl
-#WITH_SPF= yes
-#
-# Enable DomainKeys support
-#WITH_DOMAINKEYS= yes
-#
-# Enable DKIM (DomainKeys Identified Mail) support
-#WITH_DKIM= yes
-#
-# Enable Sender Rewriting Scheme (SRS)
-#WITH_SRS= yes
-#
-# Enable Sender Rewriting Scheme alternative library (SRS_ALT)
-#WITH_SRS_ALT= yes
-#
-# Use the readline(3) library for the test expansion option
-#WITH_READLINE= yes
-#
-# Don't install the exim binary suid root
-#WITHOUT_SUID= yes
-#
-# Don't install scripts to run exim as a daemon
-# (for example when using option mua_wrapper)
-#WITHOUT_DAEMON= yes
-#
-# Enable XCLIENT command in exim
-#WITH_XCLIENT= yes
-#
+.if defined(WITH_XCLIENT)
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-xclient
+.endif
+
+.if defined(WITH_KAS)
+BUILD_DEPENDS+= libspamtest>=0:${PORTSDIR}/mail/libspamtest
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-kas
+.endif
+
# You should not need to fiddle with anything below this point.
.if defined(WITH_WISHLIST)
@@ -280,13 +149,13 @@ PLIST_SUB+= EXIMON="@comment "
.endif
.if !defined(WITHOUT_TLS)
-USE_OPENSSL= yes
+.include "${PORTSDIR}/Mk/bsd.openssl.mk"
SEDLIST+= -e 's,^\# (SUPPORT_TLS=),\1,'
.else
SEDLIST+= -e 's,^(TLS_LIBS=),\# \1,'
.endif
-.if !defined(WITHOUT_PERL)
+.if !defined(WITHOUT_EMBEDDED_PERL)
USE_PERL5= yes
SEDLIST+= -e 's,^\# (EXIM_PERL=),\1,'
.endif
@@ -372,12 +241,6 @@ SASLAUTHD_SOCKET?= /var/run/saslauthd/mux
SEDLIST+= -e 's,^\# (CYRUS_SASLAUTHD_SOCKET=).*,\1${SASLAUTHD_SOCKET},'
.endif
-.if defined(WITH_PWCHECK)
-RUN_DEPENDS+= ${LOCALBASE}/sbin/pwcheck:${PORTSDIR}/security/cyrus-sasl
-SEDLIST+= -e 's,^\# (SUPPORT_CYRUS_PWCHECK=),\1,' \
- -e 's,^\# (CYRUS_PWCHECK_SOCKET=),\1,'
-.endif
-
.if !defined(WITHOUT_PAM)
SEDLIST+= -e 's,XX_PAM_LIBS_XX,-lpam,' \
-e 's,^\# (SUPPORT_PAM=),\1,'
@@ -514,7 +377,7 @@ SEDLIST+= -e 's,XX_DOMAINKEYS_LIBS_XX,,'
.endif
.if defined(WITH_DKIM)
-USE_OPENSSL= yes
+.include "${PORTSDIR}/Mk/bsd.openssl.mk"
LIB_DEPENDS+= dkim.1:${PORTSDIR}/mail/libdkim
SEDLIST+= -e 's,XX_DKIM_LIBS_XX,-ldkim -lstdc++ -lssl,' \
-e 's,^\# (EXPERIMENTAL_DKIM=),\1,'
@@ -562,12 +425,6 @@ SUB_LIST+= LOGDIR="${LOGDIR}"
PLIST_SUB+= DAEMON="@comment "
.endif
-.if defined(WITH_XCLIENT)
-EXTRA_PATCHES+= ${FILESDIR}/extra-patch-xclient
-.endif
-
-.include <bsd.port.pre.mk>
-
.if defined(EXIMON_ONLY) && ${MASTERDIR} == ${PKGDIR}
.error EXIMON_ONLY is not user settable
.endif
diff --git a/mail/exim/Makefile.options b/mail/exim/Makefile.options
new file mode 100644
index 000000000000..0e51d82139ed
--- /dev/null
+++ b/mail/exim/Makefile.options
@@ -0,0 +1,149 @@
+#
+# Makefile helper for options handling.
+#
+# Targets and their behaviors:
+#
+# show-variables-list - shows WITH_*, WITHOUT_ variables set by default.
+#
+# show-options-list - generates OPTIONS string compatible with ports
+# format. Can by safely used by maintainer to
+# re-generate sorted options list to cut-and-paste them
+# into `options' file.
+#
+# $FreeBSD$
+
+AUTH_CRAM_MD5 = "Enable CRAM-MD5 authentication mechanisms"
+AUTH_DOVECOT = "Enable Dovecot authentication mechanisms"
+AUTH_PLAINTEXT = "Enalbe plaintext authentication"
+AUTH_SPA = "Enable Secure Password Authentication"
+CDB = "Enable CDB-style lookups"
+DAEMON = "Don't install scripts to run as a daemon"
+DNSDB = "Enable DNS-style lookups"
+DSEARCH = "Enable directory-list lookups"
+EMBEDDED_PERL = "Enable embedded Perl interpreter"
+ICONV = "Enable header charset conversion"
+IPV6 = "Enable IPv6 support"
+LMTP = "RFC2033 SMTP over command pipe transport"
+LSEARCH = "Enable wildcarded-file lookups"
+MAILDIR = "Enable Maildir mailbox format"
+MAILSTORE = "Enable Mailstore mailbox format"
+MBX = "Enable MBX mailbox format"
+NIS = "Enable NIS-style lookups"
+OLD_DEMIME = "Enable old, deprecated \"demime\" ACL"
+PAM = "Enable PAM authentication mechanisms"
+PASSWD = "Enable /etc/passwd lookups"
+SUID = "Install the exim binary suid root"
+TLS = "Link against OpenSSL"
+
+ALT_CONFIG_PREFIX = "Allow alternate configuration files"
+AUTH_RADIUS = "Enable radius (RFC 2865) authentication"
+AUTH_SASL = "Enable use of Cyrus SASL auth library"
+CONTENT_SCAN = "Enable exiscan email content scanner"
+DKIM = "Enable DKIM (DomainKeys Identified Mail)"
+DOMAINKEYS = "Enable Yahoo DomainKeys support"
+EXIMON = "Build eximon monitor (require XFree86!)"
+KAS = "Build with Kaspersky AntiSpam local scan"
+MYSQL = "Link against libmysqlclient library"
+OPENLDAP = "Link against libldap"
+PGSQL = "Link against libpq"
+READLINE = "Enable readline(3) library"
+SASLAUTHD = "Enable use of Cyrus SASL auth daemon"
+SA_EXIM = "SA-Exim support"
+SPF = "Enable Sender Policy Framework checking"
+SQLITE = "Enable SQLite lookups"
+SRS = "Enable Sender Rewriting Scheme"
+SRS_ALT = "Enable alternative SRS library"
+TCP_WRAPPERS = "Enable /etc/hosts.allow access control"
+WISHLIST = "Include the unsupported patches"
+XCLIENT = "Enable XCLIENT command in exim"
+
+ENABLED_OPTIONS+= \
+ AUTH_CRAM_MD5 \
+ AUTH_DOVECOT \
+ AUTH_PLAINTEXT \
+ AUTH_SPA \
+ CDB \
+ DAEMON \
+ DNSDB \
+ DSEARCH \
+ ICONV \
+ IPV6 \
+ LMTP \
+ LSEARCH \
+ MAILDIR \
+ MAILSTORE \
+ MBX \
+ NIS \
+ OLD_DEMIME \
+ PAM \
+ PASSWD \
+ EMBEDDED_PERL \
+ SUID \
+ TLS
+
+DISABLED_OPTIONS+= \
+ ALT_CONFIG_PREFIX \
+ AUTH_RADIUS \
+ AUTH_SASL \
+ CONTENT_SCAN \
+ DKIM \
+ DOMAINKEYS \
+ EXIMON \
+ KAS \
+ MYSQL \
+ OPENLDAP \
+ PGSQL \
+ READLINE \
+ SASLAUTHD \
+ SA_EXIM \
+ SPF \
+ SQLITE \
+ SRS \
+ SRS_ALT \
+ TCP_WRAPPERS \
+ WISHLIST \
+ XCLIENT
+
+ALL_OPTIONS= ${ENABLED_OPTIONS} \
+ ${DISABLED_OPTIONS}
+
+.if !target(show-options-list)
+
+_SELECTED_OPTIONS_ENV=
+.for option in ${ENABLED_OPTIONS} ${DISABLED_OPTIONS}
+.if !defined($(option))
+_SELECTED_OPTIONS_ENV+= $(option)=$(option)
+.else
+_SELECTED_OPTIONS_ENV+= $(option)=$($(option))
+.endif
+.endfor
+
+show-options-list:
+ @${ECHO_CMD} OPTIONS+= \\
+ @for option in ${ALL_OPTIONS:O:u}; do \
+ _txt=$$(${_SELECTED_OPTIONS_ENV} && \
+ eval ${ECHO_CMD} $$\{$${option}\}); \
+ if ${ECHO_CMD} ${ENABLED_OPTIONS} |${GREP} -wq $${option}; \
+ then \
+ _flag=on; \
+ else \
+ _flag=off; \
+ fi; \
+ ${PRINTF} "\t $${option} \"$${_txt}\" $${_flag} \\"; \
+ ${ECHO_CMD}; \
+ done
+.endif
+
+.if !target(show-variables-list)
+show-variables-list:
+ @for option in ${ALL_OPTIONS}; do \
+ if ${ECHO_CMD} ${ENABLED_OPTIONS} |${GREP} -wq $${option}; \
+ then \
+ ${ECHO_CMD} "WITH_$${option}=yes"; \
+ else \
+ ${ECHO_CMD} "WITHOUT_$${option}=yes"; \
+ fi; \
+ done
+.endif
+
+.include "options"
diff --git a/mail/exim/files/extra-patch-kas b/mail/exim/files/extra-patch-kas
new file mode 100644
index 000000000000..19048398e5a1
--- /dev/null
+++ b/mail/exim/files/extra-patch-kas
@@ -0,0 +1,886 @@
+--- src/EDITME 2007-01-22 16:29:54.000000000 +0000
++++ src/EDITME 2009-07-24 13:46:01.000000000 +0000
+@@ -1133,4 +1133,9 @@
+
+ # ENABLE_DISABLE_FSYNC=yes
+
++CFLAGS= -I/usr/local/ap-mailfilter3/include
++EXTRALIBS_EXIM=-L/usr/local/ap-mailfilter3/lib -lspamtest
++LOCAL_SCAN_SOURCE=Local/kas_exim.c
++LOCAL_SCAN_HAS_OPTIONS=yes
++
+ # End of EDITME for Exim 4.
+--- /dev/null 2009-07-24 13:44:23.000000000 +0000
++++ Local/kas_exim.c 2009-07-24 13:42:28.000000000 +0000
+@@ -0,0 +1,871 @@
++
++#include "local_scan.h"
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <fcntl.h>
++#include <sys/types.h>
++#include <syslog.h>
++#include <sys/stat.h>
++#include <errno.h>
++#include "spamtest.h"
++#include "msgstore.h"
++
++//#define SPAMTEST_USE_SYSLOG
++
++/* Default values for configuration options */
++#define KAS_CONNECT_TIMEOUT 60000
++#define KAS_DEFAULT_DOMAIN ""
++#define KAS_LOG_LEVEL 0
++#define KAS_ON_ERROR "tempfail"
++#define KAS_DATA_TIMEOUT 60000
++#define KAS_CONNECT_TO "tcp:127.0.0.1:2277"
++#define KAS_FILTERING_SIZE_LIMIT 512
++
++/* Result variables for configuration options */
++static uschar *result_default_domain;
++static uschar *result_connect_to;
++static uschar *result_on_error_str;
++static int result_on_error;
++
++/* Configuration options */
++//old
++static int st_connect_timeout = 0;
++static int debug_level = 0;
++static int st_rw_timeout = 0;
++static int filtering_size_limit=0;
++static uschar *st_mail_domain;
++static uschar *st_on_error;
++static uschar *st_address;
++//new
++static int kas_connect_timeout = 0;
++static int kas_log_level = 0;
++static int kas_data_timeout = 0;
++static int kas_filtering_size_limit = 0;
++static uschar *kas_default_domain;
++static uschar *kas_on_error;
++static uschar *kas_connect_to;
++
++optionlist local_scan_options[] =
++{/* The entries must appear in alphabetical order */
++ { "connect_timeout", opt_int, &st_connect_timeout },
++ { "kas_connect_timeout", opt_int, &kas_connect_timeout },
++ { "kas_connect_to", opt_stringptr, &kas_connect_to },
++ { "kas_data_timeout", opt_int, &kas_data_timeout },
++ { "kas_default_domain", opt_stringptr, &kas_default_domain },
++ { "kas_filtering_size_limit", opt_int, &kas_filtering_size_limit },
++ { "kas_log_level",opt_int,&kas_log_level},
++ { "kas_on_error",opt_stringptr,&kas_on_error},
++ { "local_mail_domain", opt_stringptr, &st_mail_domain },
++ { "log_level",opt_int,&debug_level},
++ { "on_spamtest_error",opt_stringptr,&st_on_error},
++ { "rw_timeout", opt_int, &st_rw_timeout },
++ { "spamtest_address", opt_stringptr, &st_address },
++ { "spamtest_filtering_size_limit", opt_int, &filtering_size_limit },
++};
++
++int local_scan_options_count = sizeof(local_scan_options)/sizeof(optionlist);
++
++
++int check_results(spamtest_session_t *s,spamtest_status_t *status,int *res,int fd,uschar **return_text);
++int proceed_accept(spamtest_status_t *status,int fd);
++void logger(const int log_level,const char *fmt,...);
++void prepare_config_parameters();
++void free_conf();
++
++
++int local_scan(int fd, uschar **return_text)
++{
++ int myfd;
++ char buf[4096];
++ int cnt = 0;
++ int totalcnt = 0;
++ int i;
++ header_line * tmp;
++ spamtest_session_t s;
++ int errorcode = STS_ERR_NO_ERR;
++ spamtest_status_t *status = NULL;
++ int rcpt_sent = 0;
++ int res = 0;
++ int rest = 0;
++ char *ctmp;
++
++ /* Initialize spamtest session */
++
++ prepare_config_parameters();
++
++ if(filtering_size_limit > 0)
++ {
++ struct stat sb;
++ fstat(fd,&sb);
++ if(sb.st_size > filtering_size_limit * 1024)
++ {
++ logger(LOG_DEBUG," Message larger than filtering_size_limit, accepting");
++ free_conf();
++ return LOCAL_SCAN_ACCEPT;
++ }
++ }
++
++ bzero(&s,sizeof(s));
++ s.access_address = result_connect_to;
++ s.rw_timeout = st_rw_timeout;
++ s.connect_timeout = st_connect_timeout;
++ s.mail_domain = result_default_domain;
++
++ if ( s.access_address == NULL || s.access_address[0] == '\0' )
++ {
++ logger(LOG_ERR," Spamtest access address not defined, cannot process mail by spam filtering");
++ free_conf();
++ return LOCAL_SCAN_ACCEPT;
++ }
++
++ logger(LOG_DEBUG," Spam test session: %s %s %d %d",s.access_address,s.mail_domain,s.connect_timeout,s.rw_timeout);
++
++ if ( (errorcode = sts_init(&s)) < 0 )
++ {
++ logger(LOG_ERR," Unable to connect to %s (%s)",s.access_address,sts_strerror(errorcode));
++ free_conf();
++ return result_on_error;
++ };
++
++ if ( ! s.should_store_message )
++ {
++ /* SMTP mode, blackholing message because filter will send message */
++ logger(LOG_ERR," Filter in SMTP mode, Incorrect situation.");
++ //recipients_count = 0;
++ sts_close(&s);
++ free_conf();
++ return result_on_error;
++ }
++
++ if ( sender_address != NULL && sender_address[0] != '\0' )
++ {
++ if ( (errorcode = sts_set_sender(&s,sender_address)) != STS_ERR_NO_ERR )
++ {
++ logger(LOG_ERR," Unable to pass sender address %s(%d)",sender_address,errorcode);
++ free_conf();
++ return result_on_error;
++ }
++ }
++
++ if ( sender_host_address != NULL && sender_host_address[0] != '\0' )
++ {
++ if ( ( errorcode = sts_set_relay(&s,sender_host_address) ) != STS_ERR_NO_ERR )
++ {
++ logger(LOG_ERR," Unable to pass relay IP");
++ if(errorcode == STS_ERR_OUT_OF_MEMORY){
++ free_conf();
++ return result_on_error;
++ }
++ }
++ }
++
++ rcpt_sent = 0;
++ for ( i = 0;i<recipients_count;i++)
++ {
++ if ( recipients_list[i].address != NULL && recipients_list[i].address[0] != '\0' )
++ {
++ if ( ( errorcode = sts_add_recipient(&s,recipients_list[i].address) ) != STS_ERR_NO_ERR )
++ {
++ logger(LOG_ERR," Unable to pass recipient '%s' to filter",recipients_list[i].address);
++ }
++ else
++ {
++ rcpt_sent++;
++ }
++ }
++ }
++ if ( rcpt_sent == 0 )
++ {
++ logger(LOG_DEBUG," Recipients not sent to filter. Continue.");
++ }
++
++ tmp = header_list;
++ while ( tmp != NULL )
++ {
++ if(tmp->type != '*')
++ {
++ logger(LOG_DEBUG,"Iterating a , %c %d %s|%d",tmp->type,tmp->slen,tmp->text,tmp->text[tmp->slen-1]);
++ if ( ( status = sts_send_body(&s,tmp->text,tmp->slen,STS_REINIT_TIMEOUT) ) == NULL )
++ {
++ /* failure. finish proceed */
++ logger(LOG_ERR," NULL status after sending header %s",tmp->text);
++ sts_close(&s);
++ }
++ else
++ { /* check status and finish if need */
++ logger(LOG_DEBUG," header %s sent to filter",tmp->text);
++ if ( check_results(&s,status,&res,fd,return_text) > 0 ){
++ free_conf();
++ return res;
++ }
++ }
++ }
++ if(tmp==header_last)
++ break;
++ tmp = tmp->next;
++ }
++
++ logger(LOG_DEBUG," Headers sent");
++
++ if ( ( status = sts_send_body(&s,"\n",1,STS_REINIT_TIMEOUT) ) == NULL )
++ {
++ /* failure. finish proceed */
++ logger(LOG_ERR," NULL status after sending empty string(end of headers)");
++ sts_close(&s);
++ }
++ else
++ { /* check status and finish if need */
++ logger(LOG_DEBUG," empty string (end of headers) sent to filter");
++ if ( check_results(&s,status,&res,fd,return_text) > 0 ){
++ free_conf();
++ return res;
++ }
++ }
++
++ logger(LOG_DEBUG," Enter sent");
++
++ i = 0;
++ ctmp = buf;
++ while ( (cnt = read(fd,ctmp,buf + sizeof(buf) - ctmp)) > 0 )
++ {
++ logger(LOG_DEBUG,"sending %d bytes to filter",cnt);
++ status = sts_send_body(&s,buf,cnt,STS_REINIT_TIMEOUT);
++ logger(LOG_DEBUG,"send");
++ if ( status == NULL )
++ {
++ // failure. finish proceed
++ logger(LOG_ERR," NULL status after sending part of body");
++ sts_close(&s);
++ }
++ else
++ { // check status and finish if need
++ logger(LOG_DEBUG," part of body sent to filter");
++ if ( check_results(&s,status,&res,fd,return_text) > 0 ){
++ free_conf();
++ return res;
++ }
++ }
++ };
++
++ logger(LOG_DEBUG," Total sent %d bytes of message",totalcnt);
++
++ status = sts_body_end(&s,STS_FLUSH_DATA);
++ logger(LOG_DEBUG," Body sent");
++
++
++ if ( check_results(&s,status,&res,fd,return_text) > 0 ){
++ free_conf();
++ return res;
++ }
++ else
++ sts_close(&s);
++
++ logger(LOG_DEBUG," EOF");
++
++ free_conf();
++ return LOCAL_SCAN_ACCEPT;
++
++}
++
++
++int check_results(spamtest_session_t *s,spamtest_status_t *status,int *res,int fd,uschar **return_text)
++{
++ logger(LOG_DEBUG," Check results started.");
++ switch ( status->status )
++ {
++ case STS_SMTP_ACCEPT:
++ case STS_BLACKHOLE:
++ logger(LOG_DEBUG," SMTP_ACCEPT or BLACK_HOLE.");
++ recipients_count = 0;
++ sts_close(s);
++ *res = LOCAL_SCAN_ACCEPT;
++ return 1;
++ case STS_REJECT:
++ logger(LOG_DEBUG," REJECT");
++ *return_text=(uschar *)status->reason;
++ sts_close(s);
++ *res = LOCAL_SCAN_REJECT;
++ return 1;
++ case STS_FILTER_ERROR:
++ logger(LOG_DEBUG," FILTER_ERROR");
++ sts_close(s);
++ *res = result_on_error;
++ return 1;
++ case STS_ACCEPT:
++ logger(LOG_DEBUG," ACCEPT");
++ if ( proceed_accept(status,fd) != 0 )
++ *res = result_on_error;
++ else
++ *res = LOCAL_SCAN_ACCEPT;
++ sts_close(s);
++ return 1;
++ case STS_CONTINUE:
++ logger(LOG_DEBUG," CONTINUE");
++ return 0;
++ }
++
++}
++
++extern int recipients_list_max;
++int proceed_accept(spamtest_status_t *status,int fd)
++{
++ spamtest_status_t *st;
++ message_status_t *mst;
++ int i;
++ int rcptn;
++ int good_rcpt_cnt = 0,k;
++ int found = 0;
++
++ logger(LOG_DEBUG," accept_message started.");
++
++ st = glue_actions(status);
++
++ if (st==NULL) {
++ logger(LOG_ERR," glue_actions return NULL" );
++ return -1;
++ }
++
++ mst = &st->ms_array[0] ;
++
++ rcptn = rcptlist_count(mst->rcpts);
++ for( k=0; k<rcptn; k++)
++ if(strlen(rcptlist_getn(mst->rcpts, k))>0)
++ good_rcpt_cnt++;
++ if(good_rcpt_cnt <1)
++ {
++ logger(LOG_INFO," Empty recipient list");
++ recipients_count = 0;
++ return 0;
++ }
++
++ if ( (mst != NULL) && (mst->action == STS_ACTION_CHANGE) )
++ {
++ logger(LOG_DEBUG," spamtest status returned STS_ACTION_CHANGE for message.");
++
++ // cleanup old rcpts list
++ recipients_count = 0;
++ recipients_list = NULL;
++ recipients_list_max = 0;
++ for (i = 0; i<rcptlist_count(mst->rcpts);i++)
++ {
++ char *rcpt = rcptlist_getn(mst->rcpts,i);
++ if(rcpt)
++ {
++ logger(LOG_DEBUG,"Adding recipient: %s",rcpt);
++ receive_add_recipient(string_copy(US rcpt),-1);
++ }
++ }
++
++ logger(LOG_DEBUG," new recipients_count=%d",recipients_count);
++
++ if ( sender_address[0] != '\0' )
++ {
++ if (strcasecmp(mst->mailfrom,sender_address) != 0 )
++ { /* changing sender address */
++ logger(LOG_DEBUG," senders different");
++ sender_address = string_copy( US mst->mailfrom );
++ }
++ else
++ {
++ logger(LOG_DEBUG," senders equivalented");
++ }
++ }
++ logger(LOG_DEBUG," Actions count = %d",mst->action_count);
++ for (i=0;i<mst->action_count;i++)
++ {
++ header_line * tmp;
++ header_line * matched;
++ header_line * last;
++ int deleted_count = 0;
++ int matched_count = 0;
++ int hdrlen = strlen(mst->act_array[i].header);
++
++ switch ( mst->act_array[i].type )
++ {
++ case STS_HEADER_DEL:
++ logger(LOG_DEBUG," Delete header %s",mst->act_array[i].header);
++ tmp = header_list;
++ while ( tmp != NULL )
++ {
++ if ( (tmp->type != '*') &&
++ (tmp->slen > 0) &&
++ (strncasecmp(tmp->text,
++ mst->act_array[i].header,
++ hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 )
++ )
++ {
++ deleted_count++;
++ tmp->type = '*';
++ }
++ tmp = tmp->next;
++ }
++ logger(LOG_DEBUG," deleted %d headers",deleted_count);
++ break;
++ case STS_HEADER_ADD:
++ logger(LOG_DEBUG," Add value to header %s %s",mst->act_array[i].header,mst->act_array[i].value);
++ tmp = header_list;
++ matched = NULL;
++ while ( tmp != NULL )
++ {
++ logger(LOG_DEBUG,"Iterating, %c %d %s",tmp->type,tmp->slen,tmp->text);
++ if ( (tmp->slen > 0) &&
++ (strncasecmp(tmp->text,
++ mst->act_array[i].header,
++ hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 )
++ )
++ {
++ if ( matched != NULL )
++ {
++ if ( (tmp->type != '*') || ( matched->type == '*' ) )
++ matched = tmp;
++ }
++ else
++ {
++ matched = tmp;
++ }
++ }
++ tmp = tmp->next;
++ if(matched)
++ break;
++ }
++ if ( matched != NULL )
++ { /* adding value to exits header */
++ logger(LOG_DEBUG,"Found matched header, %c %d %s",matched->type,matched->slen,matched->text);
++ if ( matched->type == '*' )
++ {
++ matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ matched->slen = strlen(matched->text);
++ matched->type = ' ';
++ matched->type = header_checkname(matched,0);
++ }
++ else
++ {
++ logger(LOG_DEBUG,"Appending value to existing header value");
++ matched->text = string_sprintf("%s %s\n",matched->text,mst->act_array[i].value);
++ matched->slen += (strlen(mst->act_array[i].value) + 2);
++ }
++ }
++ else
++ { /* add new header in case when this header not found */
++ logger(LOG_DEBUG," We must add value to header %s but this header not found.",mst->act_array[i].header);
++ header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ }
++ logger(LOG_DEBUG," Add header %s %s",mst->act_array[i].header,mst->act_array[i].value);
++ break;
++
++
++ case STS_HEADER_PREPEND:
++ logger(LOG_DEBUG," Prepend value to header %s %s",mst->act_array[i].header,mst->act_array[i].value);
++ tmp = header_list;
++ matched = NULL;
++ while ( tmp != NULL )
++ {
++ logger(LOG_DEBUG,"Iterating, %c %d %s",tmp->type,tmp->slen,tmp->text);
++ if ( (tmp->slen > 0) &&
++ (strncasecmp(tmp->text,
++ mst->act_array[i].header,
++ hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 )
++ )
++ {
++ if ( matched != NULL )
++ {
++ if ( (tmp->type != '*') || ( matched->type == '*' ) )
++ matched = tmp;
++ }
++ else
++ {
++ matched = tmp;
++ }
++ }
++ tmp = tmp->next;
++ if(matched)
++ break;
++ }
++ if ( matched != NULL )
++ { /* adding value to exits header */
++ logger(LOG_DEBUG,"Found matched header, %c %d %s",matched->type,matched->slen,matched->text);
++ if ( matched->type == '*' )
++ {
++ matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ matched->slen = strlen(matched->text);
++ matched->type = ' ';
++ matched->type = header_checkname(matched,0);
++ }
++ else
++ {
++ int l = strlen(mst->act_array[i].header);
++ char *p = matched->text+l+2;
++ matched->text[l]=0;
++ matched->text = string_sprintf("%s: %s %s",matched->text,
++ mst->act_array[i].value,p);
++ matched->slen += (strlen(mst->act_array[i].value) + 1);
++ logger(LOG_DEBUG,"Prepending value %s to existing header value %s|",
++ mst->act_array[i].value, matched->text);
++
++ }
++ }
++ else
++ { /* add new header in case when this header not found */
++ logger(LOG_DEBUG," We must add value to header %s but this header not found.",mst->act_array[i].header);
++ header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ }
++ logger(LOG_DEBUG," Prepend header %s %s",mst->act_array[i].header,mst->act_array[i].value);
++ break;
++
++ case STS_HEADER_CHG:
++ logger(LOG_DEBUG," Change header %s %s",mst->act_array[i].header,mst->act_array[i].value);
++ tmp = header_list;
++ matched = NULL;
++ matched_count = 0;
++ while ( tmp != NULL )
++ {
++ int hdrlen = strlen(mst->act_array[i].header);
++ if ( (tmp->type != '*') &&
++ (tmp->slen > 0) &&
++ (strncasecmp(tmp->text,
++ mst->act_array[i].header,
++ hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 )
++ )
++ {
++ matched = tmp;
++ matched_count++;
++ }
++ tmp = tmp->next;
++ }
++ if ( matched != NULL )
++ {
++ matched->text = string_sprintf("%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ matched->slen += (strlen(mst->act_array[i].value) + strlen(mst->act_array[i].header) + 3);
++ if ( matched_count > 1 )
++ {
++ tmp = header_list;
++ while ( (tmp != NULL) && matched_count > 1 )
++ {
++ if ( (tmp->type != '*') &&
++ (tmp->slen > 0) &&
++ (strncasecmp(tmp->text,
++ mst->act_array[i].header,
++ hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 ) &&
++ (tmp != matched)
++ )
++ {
++ tmp->type = '*';
++ matched_count--;
++ }
++ tmp = tmp->next;
++ }
++ }
++
++ }
++ else
++ {
++ logger(LOG_DEBUG," We must change value for header %s but this header not found.Adding new",mst->act_array[i].header);
++ header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ }
++ break;
++ case STS_HEADER_NEW:
++ logger(LOG_DEBUG," New header %s: %s",mst->act_array[i].header,mst->act_array[i].value);
++
++ tmp = header_list;
++ matched = NULL;
++ while ( tmp != NULL )
++ {
++ if ( (tmp->type != '*') &&
++ (tmp->slen > 0) &&
++ (strncasecmp(tmp->text,
++ mst->act_array[i].header,
++ hdrlen < tmp->slen ? hdrlen:tmp->slen) == 0 )
++ )
++ {
++ matched = tmp;
++ }
++ tmp = tmp->next;
++ }
++ if ( matched != NULL && matched != header_last )
++ {
++ if(matched == header_last)
++ {
++ logger(LOG_DEBUG,"Header %s is last in message, adding below",
++ mst->act_array[i].header);
++ header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ }
++ else
++ { /* adding value after last header with this name */
++ logger(LOG_DEBUG,"Some headers %s found",mst->act_array[i].header);
++ tmp = header_last;
++ header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ tmp->next->next = matched->next;
++ matched->next = tmp->next;
++ tmp->next = NULL;
++ header_last = tmp;
++ }
++ }
++ else
++ { /* add new header at the end of headers list */
++ logger(LOG_DEBUG,"Headers %s not found",mst->act_array[i].header);
++ header_add(' ',"%s: %s\n",mst->act_array[i].header,mst->act_array[i].value);
++ }
++
++ break;
++ default:
++ logger(LOG_INFO," Invalid action type %d",mst->act_array[i].type);
++ }
++ }
++ }
++ else if ( (mst != NULL) && (mst->action == STS_ACTION_BOUNCE) )
++ { /* bounce message */
++ header_line *tmp;
++ message_t *bounced_mess;
++
++ logger(LOG_DEBUG," bouncing message.");
++
++ /* preparing bounced message */
++ bounced_mess = message_init();
++ if ( bounced_mess == NULL )
++ {
++ logger(LOG_ERR," Unable to allocate memory for bounced message");
++ return -1;
++ }
++ logger(LOG_DEBUG," new message allocated.");
++
++ /* copying data from filter to prepared message (for automatically creating headers list ) */
++ for (i=0;i<msgtext_count_chunks(mst->bouncemsg);i++ )
++ {
++ if ( message_put_body(bounced_mess,msgtext_get_chunk(mst->bouncemsg,i),msgtext_chunk_len(mst->bouncemsg,i)) == -1 )
++ {
++ logger(LOG_ERR," unable to copy data from filter to bounced message");
++ message_free(bounced_mess);
++ return -1;
++ }
++ else
++ {
++ logger(LOG_DEBUG," message_put_body - ok.");
++ }
++ }
++
++ /* deleting exim old headers */
++ tmp = header_list;
++ while ( tmp != NULL )
++ {
++ tmp->type = '*';
++ tmp = tmp->next;
++ };
++ logger(LOG_DEBUG," headers deleted.");
++
++ /* adding new headers */
++ for ( i = 0;i < bounced_mess->headers->used; i++ )
++ {
++ header_add(' ',"%s: %s",bounced_mess->headers->array[i].header.hptr,bounced_mess->headers->array[i].value.hptr);
++ logger(LOG_DEBUG," added header: %s: %s",bounced_mess->headers->array[i].header.hptr,bounced_mess->headers->array[i].value.hptr);
++ }
++
++ /* replacing rcpts */
++ recipients_count = 0;
++ recipients_list = NULL;
++ recipients_list_max = 0;
++
++ if ( rcptlist_count(bounced_mess->recipients) > 0 )
++ {
++ for (i = 0; i<rcptlist_count(bounced_mess->recipients);i++)
++ {
++ char *rcpt = rcptlist_getn(bounced_mess->recipients,i);
++ if ( rcpt == NULL )
++ {
++ logger(LOG_ERR," unable to get recipient %d",i);
++ message_free(bounced_mess);
++ return -1;
++ }
++ logger(LOG_DEBUG," rcpt = %s",rcpt);
++ receive_add_recipient(string_copy(US rcpt),-1);
++ }
++ }
++ else
++ {
++ if ( sender_address[0] != '\0' )
++ receive_add_recipient(string_copy(US sender_address),-1);
++ else
++ {
++ logger(LOG_ERR," Unable to get sender address to bounce, failed");
++ return -1;
++ }
++ }
++ /* cleaning sender ( must be empty string ) */
++ logger(LOG_DEBUG," sender address emptied");
++ sender_address = "";
++
++ /* writing new message body */
++ lseek(fd,SPOOL_DATA_START_OFFSET,SEEK_SET);
++
++ if ( get_message_bodychunks_count(bounced_mess) > 0 )
++ {
++ for (i=0;i<get_message_bodychunks_count(bounced_mess);i++ )
++ {
++ if ( write(fd,get_message_bodychunk_ptr(bounced_mess,i),get_message_bodychunk_len(bounced_mess,i)) == -1 )
++ {
++ logger(LOG_ERR," unable to write bounced message body.");
++ message_free(bounced_mess);
++ return -1;
++ }
++ else
++ {
++ logger(LOG_DEBUG," written part of body to file");
++ }
++ }
++ }
++ else
++ {
++ char *autogenmsg = "Autogenerated message for bouncing\n\n\n";
++ if ( write(fd,autogenmsg,strlen(autogenmsg)) == -1 )
++ {
++ logger(LOG_ERR," unable to write bounced message body.");
++ message_free(bounced_mess);
++ return -1;
++ }
++ else
++ {
++ logger(LOG_DEBUG," written autogenerated message to file");
++ }
++ }
++
++ message_free(bounced_mess);
++ logger(LOG_DEBUG," bouncing finished");
++
++
++ }
++ else
++ {
++ if ( mst != NULL )
++ logger(LOG_ERR," Invalid action %d",mst->action);
++ else
++ logger(LOG_ERR," mst is NULL");
++ }
++
++ logger(LOG_DEBUG," Message accepted.");
++ return 0;
++
++}
++
++
++void logger(const int log_level,const char *fmt,...)
++{
++ va_list params;
++ char buf[512];
++ /* LOG_ERR == 3 is minimum level for us */
++ if (log_level <= (debug_level+3))
++ {
++ va_start(params,fmt);
++ vsnprintf(buf,(size_t)512,fmt,params);
++ debug_printf("-ls- %s\n",buf);
++#ifdef SPAMTEST_USE_SYSLOG
++ va_start(params,fmt);
++ vsyslog(log_level>LOG_DEBUG?LOG_DEBUG:log_level,fmt,params);
++#else
++ log_write(0,LOG_MAIN,"spamtest: %s",buf);
++#endif
++ va_end(params);
++ }
++}
++
++void prepare_config_parameters()
++{
++ int len;
++ /*
++ * Firstly we are looking for new parameter,
++ * then - for old parameter, else - we use
++ * default value.
++ */
++ if (kas_log_level != 0)
++ debug_level = kas_log_level;
++ if (debug_level == 0)
++ debug_level = KAS_LOG_LEVEL;
++
++ if (kas_connect_timeout != 0)
++ st_connect_timeout = kas_connect_timeout*1000;
++ if (st_connect_timeout == 0)
++ st_connect_timeout = KAS_CONNECT_TIMEOUT;
++
++ if (kas_data_timeout != 0)
++ st_rw_timeout = kas_data_timeout*1000;
++ if (st_rw_timeout == 0)
++ st_rw_timeout = KAS_DATA_TIMEOUT;
++
++ if (kas_filtering_size_limit != 0)
++ filtering_size_limit = kas_filtering_size_limit;
++ if (filtering_size_limit == 0)
++ filtering_size_limit = KAS_FILTERING_SIZE_LIMIT;
++
++
++ if (kas_default_domain != NULL){
++ len = strlen(kas_default_domain);
++ result_default_domain = malloc(len+1);
++ strncpy(result_default_domain,kas_default_domain,len);
++ result_default_domain[len]='\0';
++ }
++ else if (st_mail_domain != NULL){
++ len = strlen(st_mail_domain);
++ result_default_domain = malloc(len+1);
++ strncpy(result_default_domain,st_mail_domain,len);
++ result_default_domain[len]='\0';
++ }
++ else{
++ len = strlen(KAS_DEFAULT_DOMAIN);
++ result_default_domain = malloc(len+1);
++ strncpy(result_default_domain,KAS_DEFAULT_DOMAIN,len);
++ result_default_domain[len]='\0';
++ }
++
++ if (kas_connect_to != NULL){
++ len = strlen(kas_connect_to);
++ result_connect_to = malloc(len+1);
++ strncpy(result_connect_to,kas_connect_to,len);
++ result_connect_to[len]='\0';
++ }
++ else if (st_address != NULL){
++ len = strlen(st_address);
++ result_connect_to = malloc(len+1);
++ strncpy(result_connect_to,st_address,len);
++ result_connect_to[len]='\0';
++ }/* one parameter have no default,
++ * because else we can't disable kas-exim in config file*/
++
++ if (kas_on_error != NULL){
++ len = strlen(kas_on_error);
++ result_on_error_str = malloc(len+1);
++ strncpy(result_on_error_str,kas_on_error,len);
++ result_on_error_str[len]='\0';
++ }
++ else if (st_on_error != NULL){
++ len = strlen(st_on_error);
++ result_on_error_str = malloc(len+1);
++ strncpy(result_on_error_str,st_on_error,len);
++ result_on_error_str[len]='\0';
++ }
++ else{
++ len = strlen(KAS_ON_ERROR);
++ result_on_error_str = malloc(len+1);
++ strncpy(result_on_error_str,KAS_ON_ERROR,len);
++ result_on_error_str[len]='\0';
++ }
++
++ if ( strcasecmp(result_on_error_str,"accept") == 0 ){
++ result_on_error = LOCAL_SCAN_ACCEPT;
++ }
++ else if ( strcasecmp(result_on_error_str,"reject") == 0 ){
++ result_on_error = LOCAL_SCAN_REJECT;
++ }
++ else if ( strcasecmp(result_on_error_str,"tempfail") == 0 ){
++ result_on_error = LOCAL_SCAN_TEMPREJECT;
++ }
++ else{
++ logger(LOG_ERR,"Invalid value for parameter on_spamtest_error. Will use 'accept'");
++ result_on_error = LOCAL_SCAN_ACCEPT;
++ }
++}
++
++void free_conf(){
++ free(result_default_domain);
++ free(result_connect_to);
++ free(result_on_error_str);
++}
++
diff --git a/mail/exim/options b/mail/exim/options
index 5c3a01a613ae..9688c3852cfd 100644
--- a/mail/exim/options
+++ b/mail/exim/options
@@ -1,317 +1,44 @@
-# $FreeBSD$
-#
-# Configurable options for mail/exim. Note that the options listed
-# here are the defaults, so if you want to change them you have to
-# specify the opposite version in the command line, e.g.
-# `make WITH_CONTENT_SCAN=yes WITH_SASLAUTHD=yes install'
-#
-# `make WITHOUT_CONTENT_SCAN=yes WITHOUT_SASLAUTHD=no' will not give the expected results.
-
-#WITHOUT_CONTENT_SCAN
-# Exim will be built without exiscan email content scanner support.
-
-#WITH_OLD_DEMIME
-# Enable old, deprecated "demime" ACL condition, in addition
-# to all the other content-scanning features.
-
-#WITHOUT_SA_EXIM
-# SA-Exim support (<http://marc.merlins.org/linux/exim/sa.html>)
-
-#WITH_BDB_VER= 1, 4, 41, 42, 43
-# BDB_VER is the version of the Berkeley DB library to use, and
-# may be 1, which corresponds to version 1.85 in the base system, 4,
-# 41, 42 or 43 which depends on the databases/db4[123] ports.
-
-#WITH_DEFAULT_CHARSET= ISO-8859-1, *
-# When Exim is decoding MIME "words" in header lines it converts any foreign
-# character sets to the one that is set in the headers_charset option.
-# The default setting is defined by this setting
-
-#WITH_PERL
-# Embedded Perl interpreter, which allows Perl subroutines to
-# be called during string expansion.
-
-#! lookup types
-
-#WITHOUT_OPENLDAP
-#WITH_OPENLDAP_VER= auto, 21, 22, 23
-# Link against libldap.
-# Define OPENLDAP_VER to specify a particular version of
-# OpenLDAP to use. Valid values are currently auto, 21, 22 and 23.
-# The use of `auto' is recommended to avoid conflicting with
-# other ports that use the OpenLDAP client libraries.
-# Exim also supports NETSCAPE and SOLARIS7 lookup types, but no
-# client libraries exist for these in the ports tree.
-
-#WITHOUT_MYSQL
-#WITH_MYSQL_VER= auto, 323, 40, 41, 50
-#WITHOUT_PGSQL
-#WITH_POSTGRESQL_PORT= auto, databases/postgresql7, databases/postgresql73, databases/postgresql-devel, databases/pgcluster, *
-# Link against libmysqlclient and libpq respectively.
-# Define MYSQL_VER to specify a particular version of MySQL to
-# use. Valid values are auto, 323, 40, 41 and 50.
-# The use of `auto' is recommended to avoid conflicting with
-# other ports linking against MySQL client libraries.
-
-#WITHOUT_SQLITE
-# Link against libsqlite3 to support sqlite lookups.
-
-#WITH_CDB
-#WITH_DNSDB
-#WITH_DSEARCH
-#WITH_LSEARCH
-#WITH_NIS
-#WITH_PASSWD
-# Support for CDB-style, DNS-style, directory-list, wildcarded-file, NIS
-# and /etc/passwd lookups respectively.
-
-#! authentication mechanisms
-
-#WITH_PAM
-#WITH_AUTH_CRAM_MD5
-#WITH_AUTH_PLAINTEXT
-#WITH_AUTH_DOVECOT
-#WITH_AUTH_SPA
-# Built-in support for the PAM, RFC 2195, RFC 2595 and
-# Microsoft "Secure Password Authentication" authentication mechanisms,
-# used for SMTP AUTH.
-
-#WITHOUT_AUTH_SASL
-# Enable the use of the Cyrus SASL authentication library.
-
-#WITHOUT_SASLAUTHD
-# Enable the use of the Cyrus SASL authentication daemon.
-
-#WITHOUT_PWCHECK
-# As an alternative to SASLAUTHD, you can define PWCHECK to link
-# against libsasl for SMTP AUTH authentication via the Cyrus SASL
-# pwcheck daemon.
-# THIS MECHANISM IS DEPRECATED!
-
-#WITHOUT_AUTH_RADIUS
-# Link against a radius library o support radius (RFC 2865) authentication.
-#WITH_RADIUS_TYPE= RADLIB, RADIUSCLIENT
-# Choose between the system library (RADLIB) or port net/freeradius (RADIUSCLIENT).
-
-#! optional features
-
-#WITH_TLS
-# Link against OpenSSL; required for STARTTLS.
-
-#WITH_IPV6
-# Enable IPv6 support in the compiled exim binary. Exim compiled
-# with IPv6 support will still operate on systems that do not have
-# IPv6 kernel support, so this should not be necessary.
-
-#WITH_MAILDIR
-#WITH_MAILSTORE
-#WITH_MBX
-# Built-in support for additional mailbox formats.
-
-#WITH_LMTP
-# Support for the LMTP (RFC 2033 "SMTP over command pipe") transport.
-
-#WITHOUT_SPF
-# Enable Sender Policy Framework (SPF) checking in exiscan-acl
-
-#WITHOUT_SRS
-# Enable Sender Rewriting Scheme (SRS), a part of the SPF/SRS protocol pair.
-# SRS support depends on exiscan.
-# .
-# Additional options:
-# srs_alwaysrewrite (boolean) Rewrite for all domains
-# srs_hashlength (integer) Hash length to generate
-# srs_hashmin (integer) Hash length to check
-# srs_maxage (integer) Max age for SRS address
-# srs_secrets (string list) List of SRS secrets
-# srs_separator (string*) Separator for SRS addresses
-#
-# Additional expansion variables:
-# srs_orig_recipient (string*) SRS original recipient
-# srs_orig_sender (string*) SRS original sender
-# srs_recipient (string*) SRS recipient
-# srs_status (string*) SRS status
-
-#WITHOUT_SRS_ALT
-# Enable Sender Rewriting Scheme (SRS)
-
-#WITHOUT_DOMAINKEYS
-# Enable Yahoo DomainKeys support.
-# DomainKeys support depends on exiscan.
-
-#WITHOUT_DKIM
-# Enable DKIM (DomainKeys Identified Mail) support.
-
-#WITHOUT_TCP_WRAPPERS
-# Link against libwrap to support /etc/hosts.allow access control.
-
-#WITHOUT_EXIMON
-# The eximon monitor, which requires X, will be made a dependency.
-# Note that using EXIMON will cause XFree86 to be installed
-# if it is not present.
-
-#WITHOUT_ALT_CONFIG_PREFIX
-# Allow alternate configuration files not only in ${PREFIX}/etc/exim
-
-#WITHOUT_WISHLIST
-# Include the unsupported patches in ${PATCHDIR}/wishlist-*.patch
-
-#WITHOUT_RCORDER
-# FreeBSD 5.x only: Install the rc.subr(8) script to /etc/rc.d to participate
-# in rcorder(8).
-
-#WITHOUT_READLINE
-# readline(3) library for the test expansion option.
-
-#WITH_SUID
-# Install the exim binary suid root (usually required)
-
-#WITH_DAEMON
-# Don't install scripts to run exim as a daemon
-
-#WITH_ICONV
-# Link with libiconv to enable header charset conversion
-
-#WITH_XCLIENT
-# Enable XCLIENT command in exim: http://www.postfix.org/XCLIENT_README.html
-
-## AUTOMATICALLY GENERATED FILE - DO NOT CHANGE ANYTHING BELOW THIS LINE ##
-# use `make config' to edit the local configuration
-# use `make makeconfig' to edit the defaults (MAINTAINER only)
-
-_OPTIONSNG_READ?=default
-.ifndef WITH_CONTENT_SCAN
-WITHOUT_CONTENT_SCAN?=yes
-.endif
-.ifndef WITHOUT_OLD_DEMIME
-WITH_OLD_DEMIME?=yes
-.endif
-.ifndef WITH_SA_EXIM
-WITHOUT_SA_EXIM?=yes
-.endif
-WITH_BDB_VER?=1
-WITH_DEFAULT_CHARSET?=ISO-8859-1
-.ifndef WITHOUT_PERL
-WITH_PERL?=yes
-.endif
-.ifndef WITH_OPENLDAP
-WITHOUT_OPENLDAP?=yes
-.endif
-WITH_OPENLDAP_VER?=auto
-.ifndef WITH_MYSQL
-WITHOUT_MYSQL?=yes
-.endif
-WITH_MYSQL_VER?=auto
-.ifndef WITH_PGSQL
-WITHOUT_PGSQL?=yes
-.endif
-WITH_POSTGRESQL_PORT?=auto
-.ifndef WITHOUT_CDB
-WITH_CDB?=yes
-.endif
-.ifndef WITH_SQLITE
-WITHOUT_SQLITE?=yes
-.endif
-.ifndef WITHOUT_DNSDB
-WITH_DNSDB?=yes
-.endif
-.ifndef WITHOUT_DSEARCH
-WITH_DSEARCH?=yes
-.endif
-.ifndef WITHOUT_LSEARCH
-WITH_LSEARCH?=yes
-.endif
-.ifndef WITHOUT_NIS
-WITH_NIS?=yes
-.endif
-.ifndef WITHOUT_PASSWD
-WITH_PASSWD?=yes
-.endif
-.ifndef WITHOUT_PAM
-WITH_PAM?=yes
-.endif
-.ifndef WITHOUT_AUTH_CRAM_MD5
-WITH_AUTH_CRAM_MD5?=yes
-.endif
-.ifndef WITHOUT_AUTH_PLAINTEXT
-WITH_AUTH_PLAINTEXT?=yes
-.endif
-.ifndef WITHOUT_AUTH_DOVECOT
-WITH_AUTH_DOVECOT?=yes
-.endif
-.ifndef WITHOUT_AUTH_SPA
-WITH_AUTH_SPA?=yes
-.endif
-.ifndef WITH_AUTH_SASL
-WITHOUT_AUTH_SASL?=yes
-.endif
-.ifndef WITH_SASLAUTHD
-WITHOUT_SASLAUTHD?=yes
-.endif
-.ifndef WITH_PWCHECK
-WITHOUT_PWCHECK?=yes
-.endif
-.ifndef WITH_AUTH_RADIUS
-WITHOUT_AUTH_RADIUS?=yes
-.endif
-WITH_RADIUS_TYPE?=RADLIB
-.ifndef WITHOUT_TLS
-WITH_TLS?=yes
-.endif
-.ifndef WITHOUT_IPV6
-WITH_IPV6?=yes
-.endif
-.ifndef WITHOUT_MAILDIR
-WITH_MAILDIR?=yes
-.endif
-.ifndef WITHOUT_MAILSTORE
-WITH_MAILSTORE?=yes
-.endif
-.ifndef WITHOUT_MBX
-WITH_MBX?=yes
-.endif
-.ifndef WITHOUT_LMTP
-WITH_LMTP?=yes
-.endif
-.ifndef WITH_SPF
-WITHOUT_SPF?=yes
-.endif
-.ifndef WITH_SRS
-WITHOUT_SRS?=yes
-.endif
-.ifndef WITH_SRS_ALT
-WITHOUT_SRS_ALT?=yes
-.endif
-.ifndef WITH_DOMAINKEYS
-WITHOUT_DOMAINKEYS?=yes
-.endif
-.ifndef WITH_DKIM
-WITHOUT_DKIM?=yes
-.endif
-.ifndef WITH_TCP_WRAPPERS
-WITHOUT_TCP_WRAPPERS?=yes
-.endif
-.ifndef WITH_EXIMON
-WITHOUT_EXIMON?=yes
-.endif
-.ifndef WITH_ALT_CONFIG_PREFIX
-WITHOUT_ALT_CONFIG_PREFIX?=yes
-.endif
-.ifndef WITH_WISHLIST
-WITHOUT_WISHLIST?=yes
-.endif
-.ifndef WITH_RCORDER
-WITHOUT_RCORDER?=yes
-.endif
-.ifndef WITH_READLINE
-WITHOUT_READLINE?=yes
-.endif
-.ifndef WITHOUT_SUID
-WITH_SUID?=yes
-.endif
-.ifndef WITHOUT_DAEMON
-WITH_DAEMON?=yes
-.endif
-.ifndef WITHOUT_ICONV
-WITH_ICONV?=yes
-.endif
+OPTIONS+= \
+ ALT_CONFIG_PREFIX "Allow alternate configuration files" off \
+ AUTH_CRAM_MD5 "Enable CRAM-MD5 authentication mechanisms" on \
+ AUTH_DOVECOT "Enable Dovecot authentication mechanisms" on \
+ AUTH_PLAINTEXT "Enalbe plaintext authentication" on \
+ AUTH_RADIUS "Enable radius (RFC 2865) authentication" off \
+ AUTH_SASL "Enable use of Cyrus SASL auth library" off \
+ AUTH_SPA "Enable Secure Password Authentication" on \
+ CDB "Enable CDB-style lookups" on \
+ CONTENT_SCAN "Enable exiscan email content scanner" off \
+ DAEMON "Don't install scripts to run as a daemon" on \
+ DKIM "Enable DKIM (DomainKeys Identified Mail)" off \
+ DNSDB "Enable DNS-style lookups" on \
+ DOMAINKEYS "Enable Yahoo DomainKeys support" off \
+ DSEARCH "Enable directory-list lookups" on \
+ EMBEDDED_PERL "Enable embedded Perl interpreter" on \
+ EXIMON "Build eximon monitor (require XFree86!)" off \
+ ICONV "Enable header charset conversion" on \
+ IPV6 "Enable IPv6 support" on \
+ KAS "Build with Kaspersky AntiSpam local scan" off \
+ LMTP "RFC2033 SMTP over command pipe transport" on \
+ LSEARCH "Enable wildcarded-file lookups" on \
+ MAILDIR "Enable Maildir mailbox format" on \
+ MAILSTORE "Enable Mailstore mailbox format" on \
+ MBX "Enable MBX mailbox format" on \
+ MYSQL "Link against libmysqlclient library" off \
+ NIS "Enable NIS-style lookups" on \
+ OLD_DEMIME "Enable old, deprecated "demime" ACL" on \
+ OPENLDAP "Link against libldap" off \
+ PAM "Enable PAM authentication mechanisms" on \
+ PASSWD "Enable /etc/passwd lookups" on \
+ PGSQL "Link against libpq" off \
+ READLINE "Enable readline(3) library" off \
+ SASLAUTHD "Enable use of Cyrus SASL auth daemon" off \
+ SA_EXIM "SA-Exim support" off \
+ SPF "Enable Sender Policy Framework checking" off \
+ SQLITE "Enable SQLite lookups" off \
+ SRS "Enable Sender Rewriting Scheme" off \
+ SRS_ALT "Enable alternative SRS library" off \
+ SUID "Install the exim binary suid root" on \
+ TCP_WRAPPERS "Enable /etc/hosts.allow access control" off \
+ TLS "Link against OpenSSL" on \
+ WISHLIST "Include the unsupported patches" off \
+ XCLIENT "Enable XCLIENT command in exim" off \