summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/libmilter
diff options
context:
space:
mode:
authorgshapiro <gshapiro@FreeBSD.org>2002-02-17 21:56:45 +0000
committergshapiro <gshapiro@FreeBSD.org>2002-02-17 21:56:45 +0000
commit8449595fe97f4474b9b9a7e4edee1ef35dcff393 (patch)
treee7a33b132264d449a512ddf4a8685df097669c1d /contrib/sendmail/libmilter
parent289b381b31415647269c7520d881017e2dcb27f1 (diff)
downloadFreeBSD-src-8449595fe97f4474b9b9a7e4edee1ef35dcff393.zip
FreeBSD-src-8449595fe97f4474b9b9a7e4edee1ef35dcff393.tar.gz
Import sendmail 8.12.2
Diffstat (limited to 'contrib/sendmail/libmilter')
-rw-r--r--contrib/sendmail/libmilter/Makefile.m422
-rw-r--r--contrib/sendmail/libmilter/README85
-rw-r--r--contrib/sendmail/libmilter/comm.c47
-rw-r--r--contrib/sendmail/libmilter/docs/api.html194
-rw-r--r--contrib/sendmail/libmilter/docs/design.html144
-rw-r--r--contrib/sendmail/libmilter/docs/figure1.fig56
-rw-r--r--contrib/sendmail/libmilter/docs/figure1.jpgbin0 -> 21406 bytes
-rw-r--r--contrib/sendmail/libmilter/docs/figure1.ps173
-rw-r--r--contrib/sendmail/libmilter/docs/figure2.fig67
-rw-r--r--contrib/sendmail/libmilter/docs/figure2.jpgbin0 -> 47947 bytes
-rw-r--r--contrib/sendmail/libmilter/docs/figure2.ps242
-rw-r--r--contrib/sendmail/libmilter/docs/index.html92
-rw-r--r--contrib/sendmail/libmilter/docs/installation.html169
-rw-r--r--contrib/sendmail/libmilter/docs/other.html15
-rw-r--r--contrib/sendmail/libmilter/docs/overview.html194
-rw-r--r--contrib/sendmail/libmilter/docs/sample.html426
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_addheader.html94
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_addrcpt.html80
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_chgheader.html96
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_delrcpt.html79
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_getpriv.html59
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_getsymval.html92
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_main.html48
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_register.html160
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_replacebody.html90
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_setconn.html77
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_setpriv.html77
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_setreply.html92
-rw-r--r--contrib/sendmail/libmilter/docs/smfi_settimeout.html60
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_abort.html80
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_body.html80
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_close.html66
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_connect.html90
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_envfrom.html92
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_envrcpt.html94
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_eoh.html53
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_eom.html58
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_header.html74
-rw-r--r--contrib/sendmail/libmilter/docs/xxfi_helo.html59
-rw-r--r--contrib/sendmail/libmilter/engine.c153
-rw-r--r--contrib/sendmail/libmilter/handler.c9
-rw-r--r--contrib/sendmail/libmilter/libmilter.h36
-rw-r--r--contrib/sendmail/libmilter/listener.c216
-rw-r--r--contrib/sendmail/libmilter/main.c80
-rw-r--r--contrib/sendmail/libmilter/signal.c41
-rw-r--r--contrib/sendmail/libmilter/sm_gethost.c45
-rw-r--r--contrib/sendmail/libmilter/smfi.c232
47 files changed, 4319 insertions, 269 deletions
diff --git a/contrib/sendmail/libmilter/Makefile.m4 b/contrib/sendmail/libmilter/Makefile.m4
index 19381a4..f767441 100644
--- a/contrib/sendmail/libmilter/Makefile.m4
+++ b/contrib/sendmail/libmilter/Makefile.m4
@@ -1,5 +1,7 @@
include(confBUILDTOOLSDIR`/M4/switch.m4')
+dnl only required for compilation of EXTRAS
+define(`confREQUIRE_LIBSM', `true')
define(`confMT', `true')
# sendmail dir
@@ -8,17 +10,29 @@ PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ')
bldPRODUCT_START(`library', `libmilter')
define(`bldINSTALLABLE', `true')
-define(`bldSOURCES', `main.c engine.c listener.c handler.c comm.c smfi.c signal.c sm_gethost.c ')
-bldPUSH_SMLIB(`smutil')
+define(`LIBMILTER_EXTRAS', `errstring.c strl.c')
+APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL -Dsm_snprintf=snprintf')
+define(`bldSOURCES', `main.c engine.c listener.c handler.c comm.c smfi.c signal.c sm_gethost.c LIBMILTER_EXTRAS ')
+define(`confBEFORE', `LIBMILTER_EXTRAS')
bldPUSH_INSTALL_TARGET(`install-mfapi')
bldPRODUCT_END
-APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL')
+
+PUSHDIVERT(3)
+errstring.c:
+ ${LN} ${LNOPTS} ${SRCDIR}/libsm/errstring.c .
+
+strl.c:
+ ${LN} ${LNOPTS} ${SRCDIR}/libsm/strl.c .
+POPDIVERT
+
divert(bldTARGETS_SECTION)
-# Install the API header file
+# Install the API header files
MFAPI= ${SRCDIR}/inc`'lude/libmilter/mfapi.h
+MFDEF= ${SRCDIR}/inc`'lude/libmilter/mfdef.h
install-mfapi: ${MFAPI}
${INSTALL} -c -o ${INCOWN} -g ${INCGRP} -m ${INCMODE} ${MFAPI} ${DESTDIR}${INCLUDEDIR}
+ ${INSTALL} -c -o ${INCOWN} -g ${INCGRP} -m ${INCMODE} ${MFDEF} ${DESTDIR}${INCLUDEDIR}
divert(0)
bldFINISH
diff --git a/contrib/sendmail/libmilter/README b/contrib/sendmail/libmilter/README
index 3eae861..f38f68a 100644
--- a/contrib/sendmail/libmilter/README
+++ b/contrib/sendmail/libmilter/README
@@ -9,17 +9,27 @@ through reference to a sample filter which is attached at the end of this
file. It is necessary to first build libmilter.a, which can be done by
issuing the './Build' command in SRCDIR/libmilter .
-NOTE: Both libmilter and the callouts in sendmail are marked as an FFR (For
-Future Release). If you intend to use them in 8.11.X, you must compiled
-both libmilter and sendmail with -D_FFR_MILTER defined. You can do this by
-adding the following to your devtools/Site/site.config.m4 file:
+NOTE: If you intend to use filters in sendmail, you must compile sendmail
+with -DMILTER defined. You can do this by adding the following to
+your devtools/Site/site.config.m4 file:
- dnl Milter
- APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_MILTER=1')
- APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER=1')
+ APPENDDEF(`conf_sendmail_ENVDEF', `-DMILTER')
+
++----------------+
+| SECURITY HINTS |
++----------------+
+
+Note: we strongly recommend not to run any milter as root. Libmilter
+does not need root access to communicate with sendmail. It is a
+good security practice to run a program only with root privileges
+if really necessary. A milter should probably check first whether
+it runs as root and refuse to start in that case. There is a
+compile time option _FFR_MILTER_ROOT_UNSAFE which keeps libmilter
+from unlinking a socket when running as root. It is recommended
+to turn on this option:
+
+ APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER_ROOT_UNSAFE ')
-You will also need to define _FFR_MILTER when building your .cf file using
-m4.
+-------------------+
| BUILDING A FILTER |
@@ -29,14 +39,14 @@ The following command presumes that the sample code from the end of this
README is saved to a file named 'sample.c' and built in the local platform-
specific build subdirectory (SRCDIR/obj.*/libmilter).
- cc -I../../sendmail -I../../include -o sample sample.c libmilter.a ../libsmutil/libsmutil.a -pthread
+ cc -I../../sendmail -I../../include -o sample sample.c libmilter.a ../libsm/libsm.a -pthread
It is recommended that you build your filters in a location outside of
the sendmail source tree. Modify the compiler include references (-I)
and the library locations accordingly. Also, some operating systems may
require additional libraries. For example, SunOS 5.X requires '-lresolv
--lsocket -lnsl'. Depending on your OS you may need a library instead
-of the option -pthread, e.g., -lpthread.
+-lsocket -lnsl'. Depending on your operating system you may need a library
+instead of the option -pthread, e.g., -lpthread.
Filters must be thread-safe! Many operating systems now provide support for
POSIX threads in the standard C libraries. The compiler flag to link with
@@ -77,13 +87,13 @@ IPv4 socket on port 3333 of localhost. The current flags (F=) are:
T Temporary fail connection if filter unavailable
If neither F=R nor F=T is specified, the message is passed through sendmail
-as if the filter were not present.
+in case of filter errors as if the failing filters were not present.
Finally, you can override the default timeouts used by sendmail when
talking to the filters using the T= equate. There are four fields inside
of the T= equate:
-Letter Meaning
+Letter Meaning
C Timeout for connecting to a filter (if 0, use system timeout)
S Timeout for sending information from the MTA to a filter
R Timeout for reading reply from the filter
@@ -94,7 +104,7 @@ Note the separator between each is a ';' as a ',' already separates equates
and therefore can't separate timeouts. The default values (if not set in
the config) are:
-T=C:0m;S:10s;R:10s;E:5m
+T=C:5m;S:10s;R:10s;E:5m
where 's' is seconds and 'm' is minutes.
@@ -182,6 +192,30 @@ the logging level of sendmail can be raised with the LogLevel option.
See the sendmail(8) manual page for more information.
++--------------+
+| REQUIREMENTS |
++--------------+
+
+libmilter requires pthread support in the operating system. Moreover, it
+requires that the library functions it uses are thread safe; which is true
+for the operating systems libmilter has been developed and tested on. On
+some operating systems this requires special compile time options (e.g.,
+not just -pthread). libmilter is currently known to work on (modulo problems
+in the pthread support of some specific versions):
+
+FreeBSD 3.x, 4.x
+SunOS 5.x (x >= 5)
+AIX 4.3.x
+HP UX 11.x
+Linux (recent versions/distributions)
+
+libmilter is currently not supported on:
+
+IRIX 6.x
+Ultrix
+
+Feedback about problems (and possible fixes) is welcome.
+
+--------------------------+
| SOURCE FOR SAMPLE FILTER |
+--------------------------+
@@ -201,14 +235,11 @@ below to verify the functions are thread safe.
#include "libmilter/mfapi.h"
+#ifndef true
typedef int bool;
-
-#ifndef FALSE
-# define FALSE 0
-#endif /* ! FALSE*/
-#ifndef TRUE
-# define TRUE 1
-#endif /* ! TRUE*/
+# define false 0
+# define true 1
+#endif /* ! true */
struct mlfiPriv
{
@@ -295,7 +326,7 @@ mlfi_body(ctx, bodyp, bodylen)
if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0)
{
/* write failed */
- (void) mlfi_cleanup(ctx, FALSE);
+ (void) mlfi_cleanup(ctx, false);
return SMFIS_TEMPFAIL;
}
@@ -307,7 +338,7 @@ sfsistat
mlfi_eom(ctx)
SMFICTX *ctx;
{
- return mlfi_cleanup(ctx, TRUE);
+ return mlfi_cleanup(ctx, true);
}
sfsistat
@@ -321,7 +352,7 @@ sfsistat
mlfi_abort(ctx)
SMFICTX *ctx;
{
- return mlfi_cleanup(ctx, FALSE);
+ return mlfi_cleanup(ctx, false);
}
sfsistat
@@ -349,7 +380,7 @@ mlfi_cleanup(ctx, ok)
{
/* add a header to the message announcing our presence */
if (gethostname(host, sizeof host) < 0)
- strlcpy(host, "localhost", sizeof host);
+ snprintf(host, sizeof host, "localhost");
p = strrchr(priv->mlfi_fname, '/');
if (p == NULL)
p = priv->mlfi_fname;
@@ -426,4 +457,4 @@ main(argc, argv)
/* eof */
-$Revision: 8.9.2.1.2.19 $, Last updated $Date: 2001/06/28 22:25:14 $
+$Revision: 8.35 $, Last updated $Date: 2002/01/07 21:29:20 $
diff --git a/contrib/sendmail/libmilter/comm.c b/contrib/sendmail/libmilter/comm.c
index af1ee6d..3347808 100644
--- a/contrib/sendmail/libmilter/comm.c
+++ b/contrib/sendmail/libmilter/comm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -8,17 +8,16 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: comm.c,v 8.30.4.6 2000/10/05 22:44:01 gshapiro Exp $";
-#endif /* ! lint */
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: comm.c,v 8.48 2001/11/07 17:43:04 ca Exp $")
-#if _FFR_MILTER
#include "libmilter.h"
+#include <sm/errstring.h>
-#define FD_Z FD_ZERO(&readset); \
- FD_SET((u_int) sd, &readset); \
- FD_ZERO(&excset); \
- FD_SET((u_int) sd, &excset)
+#define FD_Z FD_ZERO(&readset); \
+ FD_SET((unsigned int) sd, &readset); \
+ FD_ZERO(&excset); \
+ FD_SET((unsigned int) sd, &excset)
/*
** MI_RD_CMD -- read a command
@@ -73,11 +72,13 @@ mi_rd_cmd(sd, timeout, cmd, rlen, name)
*cmd = SMFIC_SELECT;
return NULL;
}
- if ((len = MI_SOCK_READ(sd, data + i, sizeof data - i)) < 0)
+
+ len = MI_SOCK_READ(sd, data + i, sizeof data - i);
+ if (MI_SOCK_READ_FAIL(len))
{
smi_log(SMI_LOG_ERR,
"%s, mi_rd_cmd: read returned %d: %s",
- name, len, strerror(errno));
+ name, len, sm_errstring(errno));
*cmd = SMFIC_RECVERR;
return NULL;
}
@@ -100,7 +101,7 @@ mi_rd_cmd(sd, timeout, cmd, rlen, name)
{
smi_log(SMI_LOG_ERR,
"%s: mi_rd_cmd: select returned %d: %s",
- name, ret, strerror(errno));
+ name, ret, sm_errstring(errno));
*cmd = SMFIC_RECVERR;
return NULL;
}
@@ -116,7 +117,11 @@ mi_rd_cmd(sd, timeout, cmd, rlen, name)
*cmd = SMFIC_TOOBIG;
return NULL;
}
+#if _FFR_ADD_NULL
+ buf = malloc(expl + 1);
+#else /* _FFR_ADD_NULL */
buf = malloc(expl);
+#endif /* _FFR_ADD_NULL */
if (buf == NULL)
{
*cmd = SMFIC_MALLOC;
@@ -133,11 +138,12 @@ mi_rd_cmd(sd, timeout, cmd, rlen, name)
free(buf);
return NULL;
}
- if ((len = MI_SOCK_READ(sd, buf + i, expl - i)) < 0)
+ len = MI_SOCK_READ(sd, buf + i, expl - i);
+ if (MI_SOCK_READ_FAIL(len))
{
smi_log(SMI_LOG_ERR,
"%s: mi_rd_cmd: read returned %d: %s",
- name, len, strerror(errno));
+ name, len, sm_errstring(errno));
ret = -1;
break;
}
@@ -156,6 +162,10 @@ mi_rd_cmd(sd, timeout, cmd, rlen, name)
if (len >= expl - i)
{
*rlen = expl;
+#if _FFR_ADD_NULL
+ /* makes life simpler for common string routines */
+ buf[expl] = '\0';
+#endif /* _FFR_ADD_NULL */
return buf;
}
i += len;
@@ -175,14 +185,14 @@ mi_rd_cmd(sd, timeout, cmd, rlen, name)
{
smi_log(SMI_LOG_ERR,
"%s: mi_rd_cmd: select returned %d: %s",
- name, ret, strerror(save_errno));
+ name, ret, sm_errstring(save_errno));
*cmd = SMFIC_RECVERR;
return NULL;
}
*cmd = SMFIC_UNKNERR;
return NULL;
}
- /*
+/*
** MI_WR_CMD -- write a cmd to sd
**
** Parameters:
@@ -222,7 +232,7 @@ mi_wr_cmd(sd, timeout, cmd, buf, len)
do
{
FD_ZERO(&wrtset);
- FD_SET((u_int) sd, &wrtset);
+ FD_SET((unsigned int) sd, &wrtset);
if ((ret = select(sd + 1, NULL, &wrtset, NULL, timeout)) == 0)
return MI_FAILURE;
} while (ret < 0 && errno == EINTR);
@@ -248,7 +258,7 @@ mi_wr_cmd(sd, timeout, cmd, buf, len)
do
{
FD_ZERO(&wrtset);
- FD_SET((u_int) sd, &wrtset);
+ FD_SET((unsigned int) sd, &wrtset);
if ((ret = select(sd + 1, NULL, &wrtset, NULL, timeout)) == 0)
return MI_FAILURE;
} while (ret < 0 && errno == EINTR);
@@ -264,4 +274,3 @@ mi_wr_cmd(sd, timeout, cmd, buf, len)
}
return MI_SUCCESS;
}
-#endif /* _FFR_MILTER */
diff --git a/contrib/sendmail/libmilter/docs/api.html b/contrib/sendmail/libmilter/docs/api.html
new file mode 100644
index 0000000..af714ef
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/api.html
@@ -0,0 +1,194 @@
+<html>
+<head><title>Milter API</title></head>
+<body>
+<h1>Milter API</h1>
+
+<h2>Contents</h2>
+<ul>
+ <li>Library Control Functions
+ <li>Data Access Functions
+ <li>Message Modification Functions
+ <li>Callbacks
+</ul>
+
+<h2>Library Control Functions</h2>
+
+Before handing control to libmilter (by calling <a
+href="smfi_main.html">smfi_main</a>), a filter may call the following
+functions to set libmilter parameters. In particular, the filter must
+call <a href="smfi_register.html">smfi_register</a> to register its
+callbacks. Each function will return either MI_SUCCESS or MI_FAILURE to
+indicate the status of the operation.
+<p>
+None of these functions communicate with the MTA. All alter the
+library's state, some of which is communicated to the MTA inside <a
+href="smfi_main.html">smfi_main</a>.
+<p>
+<table border="1" cellspacing=0 cellpadding=2><tr bgcolor="#dddddd"><th>Function</th><th>Description</th></tr>
+
+<tr><td><a href="smfi_register.html">smfi_register</a></td><td>Register a filter.</td></tr>
+
+<tr><td><a href="smfi_setconn.html">smfi_setconn</a></td><td>Specify socket to use.</td></tr>
+
+<tr><td><a href="smfi_settimeout.html">smfi_settimeout</a></td><td>Set timeout.</td></tr>
+
+<tr><td><a href="smfi_main.html">smfi_main</a></td><td>Hand control to libmilter.</td></tr>
+
+</table>
+
+<h2>Data Access Functions</h2>
+
+The following functions may be called from within the filter-defined callbacks
+to access information about the current connection or message.
+<p>
+<table border="1" cellspacing=0 cellpadding=2><tr bgcolor="#dddddd"><th>Function</th><th>Description</th></tr>
+<tr><td><a href="smfi_getsymval.html">smfi_getsymval</a></td><td>Return the value
+of a symbol.</td></tr>
+
+<tr><td><a href="smfi_getpriv.html">smfi_getpriv</a></td><td>Get the private data
+pointer.</td></tr>
+
+<tr><td><a href="smfi_setpriv.html">smfi_setpriv</a></td><td>Set the private data
+pointer.</td></tr>
+
+<tr><td><a href="smfi_setreply.html">smfi_setreply</a></td><td>Set the specific
+reply code to be used.</td></tr>
+
+</table>
+
+<h2>Message Modification Functions</h2>
+
+The following functions change a message's contents and attributes.
+<b>They may only be called in <a href="xxfi_eom.html">xxfi_eom</a></b>.
+All of these functions may invoke additional communication with the MTA.
+They will return either MI_SUCCESS or MI_FAILURE to indicate the status of
+the operation.
+
+<p>
+A filter must have set the appropriate flag (listed below) in the
+description passed to <a href="smfi_register.html">smfi_register</a>
+to call any message modification function. Failure to do so will
+cause the MTA to treat a call to the function as a failure of the
+filter, terminating its connection.
+
+<p>
+Note that the status returned indicates only whether or not the
+filter's message was successfully sent to the MTA, not whether or not
+the MTA performed the requested operation. For example, <a
+href="smfi_addheader.html">smfi_addheader</a>, when called with an
+illegal header name, will return MI_SUCCESS even though the MTA may
+later refuse to add the illegal header.
+<p>
+<table border="1" cellspacing=0 cellpadding=2><tr bgcolor="#dddddd"><th>Function</th><th>Description</th><th>SMFIF_* flag</tr>
+<tr><td><a href="smfi_addheader.html">smfi_addheader</a></td><td>Add a header to
+the message.</td><td>SMFIF_ADDHDRS</td></tr>
+
+<tr><td><a href="smfi_chgheader.html">smfi_chgheader</a></td><td>Change or delete a header.</td><td>SMFIF_CHGHDRS</td></tr>
+
+<tr><td><a href="smfi_addrcpt.html">smfi_addrcpt</a></td><td>Add a recipient to
+the envelope.</td><td>SMFIF_ADDRCPT</td></tr>
+
+<tr><td><a href="smfi_delrcpt.html">smfi_delrcpt</a></td><td>Delete a recipient
+from the envelope.</td><td>SMFIF_DELRCPT</td></tr>
+
+<tr><td><a href="smfi_replacebody.html">smfi_replacebody</a></td><td>Replace the
+body of the message.</td><td>SMFIF_CHGBODY</td></tr>
+
+</table>
+
+<h2>Callbacks</h2>
+
+The filter should implement one or more of the following callbacks,
+which are registered via <a href="smfi_register.html">smfi_register</a>:
+<p>
+<table border="1" cellspacing=0 cellpadding=2><tr bgcolor="#dddddd"><th>Function</th><th>Description</th></tr>
+
+<tr><td><a href="xxfi_connect.html">xxfi_connect</a></td><td>connection info</td></tr>
+
+<tr><td><a href="xxfi_helo.html">xxfi_helo</a></td><td>SMTP HELO/EHLO command</td></tr>
+
+<tr><td><a href="xxfi_envfrom.html">xxfi_envfrom</a></td><td>envelope sender</td></tr>
+
+<tr><td><a href="xxfi_envrcpt.html">xxfi_envrcpt</a></td><td>envelope recipient</td></tr>
+
+<tr><td><a href="xxfi_header.html">xxfi_header</a></td><td>header</td></tr>
+
+<tr><td><a href="xxfi_eoh.html">xxfi_eoh</a></td><td>end of header</td></tr>
+
+<tr><td><a href="xxfi_body.html">xxfi_body</a></td><td>body block</td></tr>
+
+<tr><td><a href="xxfi_eom.html">xxfi_eom</a></td><td>end of message</td></tr>
+
+<tr><td><a href="xxfi_abort.html">xxfi_abort</a></td><td>message aborted</td></tr>
+
+<tr><td><a href="xxfi_close.html">xxfi_close</a></td><td>connection cleanup</td></tr>
+
+</table>
+
+<p>
+The above callbacks should all return one of the following return values,
+having the indicated meanings. Any return other than one of the below
+values constitutes an error, and will cause sendmail to terminate its
+connection to the offending filter.
+
+<p><a name="conn-spec"></a>Milter distinguishes between recipient-,
+message-, and connection-oriented routines. Recipient-oriented
+callbacks may affect the processing of a single message recipient;
+message-oriented callbacks, a single message; connection-oriented
+callbacks, an entire connection (during which multiple messages may be
+delivered to multiple sets of recipients).
+<a href="xxfi_envrcpt.html">xxfi_envrcpt</a> is recipient-oriented.
+<a href="xxfi_connect.html">xxfi_connect</a>,
+<a href="xxfi_helo.html">xxfi_helo</a> and
+<a href="xxfi_close.html">xxfi_close</a> are connection-oriented. All
+other callbacks are message-oriented.
+
+<p>
+<table border="1" cellspacing=0 cellpadding=2>
+ <tr bgcolor="#dddddd"><th>Return value</th><th>Description</th></tr>
+ <tr valign="top">
+ <td>SMFIS_CONTINUE</td>
+ <td>Continue processing the current connection, message, or recipient.
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_REJECT</td>
+ <td>For a connection-oriented routine, reject this connection; call <a href="xxfi_close.html">xxfi_close</a>.<br>
+ For a message-oriented routine (except
+ <a href="xxfi_eom.html">xxfi_eom</a> or
+ <a href="xxfi_abort.html">xxfi_abort</a>), reject this message.<br>
+ For a recipient-oriented routine, reject the current recipient (but continue processing the current message).
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_DISCARD</td>
+ <td>For a message- or recipient-oriented routine, accept this message, but silently discard it.<br>
+ SMFIS_DISCARD should not be returned by a connection-oriented routine.
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_ACCEPT</td>
+ <td>For a connection-oriented routine, accept this connection without further filter processing; call <a href="xxfi_close.html">xxfi_close</a>.<br>
+ For a message- or recipient-oriented routine, accept this message without further filtering.<br>
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_TEMPFAIL</td>
+ <td>Return a temporary failure, i.e., the corresponding SMTP command will return an appropriate 4xx status code.
+ For a message-oriented routine (except <a href="xxfi_envfrom.html">xxfi_envfrom</a>), fail for this message. <br>
+ For a connection-oriented routine, fail for this connection; call <a href="xxfi_close.html">xxfi_close</a>. <br>
+ For a recipient-oriented routine, only fail for the current recipient; continue message processing.
+ </td>
+ </tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/design.html b/contrib/sendmail/libmilter/docs/design.html
new file mode 100644
index 0000000..fbc74e6
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/design.html
@@ -0,0 +1,144 @@
+<html>
+<head>
+<title>Architecture</title>
+</head>
+<body>
+
+<h1>Architecture</h1>
+
+<h2>Contents</h2>
+
+<ul>
+ <li>Design Goals
+ <li>Implementing Filtering Policies
+ <li>MTA - Filter Communication
+</ul>
+
+<h2>Goals</h2>
+
+The Sendmail Content Management API (Milter) provides an interface for
+third-party software to validate and modify messages as they pass
+through the mail transport system. Filters can process messages'
+connection (IP) information, envelope protocol elements, message
+headers, and/or message body contents, and modify a message's
+recipients, headers, and body. The MTA configuration file specifies
+which filters are to be applied, and in what order, allowing an
+administrator to combine multiple independently-developed filters.
+
+<p>
+We expect to see both vendor-supplied, configurable mail filtering
+applications and a multiplicity of script-like filters designed by and
+for MTA administrators. A certain degree of coding sophistication and
+domain knowledge on the part of the filter provider is assumed. This
+allows filters to exercise fine-grained control at the SMTP level.
+However, as will be seen in the example, many filtering applications
+can be written with relatively little protocol knowledge.
+
+<p>
+Given these expectations, the API is designed to achieve the following
+goals:
+
+<OL>
+ <LI>Safety/security.
+ Filter processes should not need to run as root
+ (of course, they can if required, but that is a local issue);
+ this will simplify coding
+ and limit the impact of security flaws in the filter program.
+<p>
+ <LI>Reliability.
+ Coding failures in a Milter process that cause that process
+ to hang or core-dump
+ should not stop mail delivery.
+ Faced with such a failure,
+ sendmail should use a default mechanism,
+ either behaving as if the filter were not present
+ or as if a required resource were unavailable.
+ The latter failure mode will generally have sendmail return
+ a 4xx SMTP code (although in later phases of the SMTP protocol
+ it may cause the mail to be queued for later processing).
+<p>
+ <LI>Simplicity.
+ The API should make implementation of a new filter
+ no more difficult than absolutely necessary.
+ Subgoals include:
+ <UL>
+ <LI>Encourage good thread practice
+ by defining thread-clean interfaces including local data hooks.
+ <LI>Provide all interfaces required
+ while avoiding unnecessary pedanticism.
+ </UL>
+<p>
+ <LI>Performance.
+ Simple filters should not seriously impact overall MTA performance.
+</OL>
+
+<h2>Implementing Filtering Policies</h2>
+
+Milter is designed to allow a server administrator to combine
+third-party filters to implement a desired mail filtering policy. For
+example, if a site wished to scan incoming mail for viruses on several
+platforms, eliminate unsolicited commercial email, and append a mandated
+footer to selected incoming messages, the administrator could configure
+the MTA to filter messages first through a server based anti-virus
+engine, then via a large-scale spam-catching service, and finally
+append the desired footer if the message still met requisite criteria.
+Any of these filters could be added or changed independently.
+
+<p>
+Thus the site administrator, not the filter writer, controls the
+overall mail filtering environment. In particular, he/she must decide
+which filters are run, in what order they are run, and how they
+communicate with the MTA. These parameters, as well as the
+actions to be taken if a filter becomes unavailable, are selectable
+during MTA configuration. <a href="installation.html">Further
+details</a> are available later in this document.
+
+<h2>MTA - Filter communication</h2>
+
+Filters run as separate processes, outside of the sendmail address
+space. The benefits of this are threefold:
+
+<OL>
+ <LI>The filter need not run with "root" permissions, thereby
+ avoiding a large family of potential security problems.</LI>
+
+ <LI>Failures in a particular filter will not affect the MTA or
+ other filters.</LI>
+
+ <LI>The filter can potentially have higher performance because of
+ the parallelism inherent in multiple processes.</LI>
+</OL>
+
+<p>
+Each filter may communicate with multiple MTAs at the same time over
+local or remote connections, using multiple threads of execution. <a
+href="#figure-1">Figure 1</a> illustrates a possible network of
+communication channels between a site's filters, its MTAs, and other
+MTAs on the network:
+</p>
+<div align="center">
+<a name="figure-1"><img src="figure1.jpg" ALT=""></A><br>
+<b>Figure 1: A set of MTA's interacting with a set of filters.</b>
+</div>
+<p>
+The Milter library (libmilter) implements the communication protocol.
+It accepts connections from various MTAs, passes the relevant data to
+the filter through callbacks, then makes appropriate responses based
+on return codes. A filter may also send data to the MTA as a result
+of library calls. <a href="#figure-2">Figure 2</a> shows a single
+filter process processing messages from two MTAs:
+</p>
+<div align="center">
+<img src="figure2.jpg" ALT=""><br>
+<b>Figure 2: A filter handling simultaneous requests from two MTA's.</b>
+</div>
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/figure1.fig b/contrib/sendmail/libmilter/docs/figure1.fig
new file mode 100644
index 0000000..e0cbdc8
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/figure1.fig
@@ -0,0 +1,56 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+6 975 225 5025 3375
+6 1500 1275 2700 2025
+2 2 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 5
+ 1650 1425 2550 1425 2550 1875 1650 1875 1650 1425
+4 0 1 50 0 0 20 0.0000 4 195 645 1800 1725 MTA\001
+-6
+6 1950 2625 3150 3375
+2 2 0 2 4 7 50 0 -1 0.000 0 0 7 0 0 5
+ 2100 2775 3000 2775 3000 3225 2100 3225 2100 2775
+4 0 4 50 0 0 20 0.0000 4 195 645 2250 3075 MTA\001
+-6
+6 1050 225 2250 975
+2 2 0 2 14 7 50 0 -1 0.000 0 0 7 0 0 5
+ 1200 375 2100 375 2100 825 1200 825 1200 375
+4 0 14 50 0 0 20 0.0000 4 195 645 1350 675 MTA\001
+-6
+2 1 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 2
+ 2550 1575 3750 2625
+2 1 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 2
+ 2550 1575 3750 1575
+2 1 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 2
+ 2550 1575 3750 825
+2 1 0 2 4 7 50 0 -1 0.000 0 0 7 0 0 2
+ 3000 2925 3750 2625
+2 1 0 2 14 7 50 0 -1 0.000 0 0 7 0 0 2
+ 2100 525 3750 825
+2 1 0 2 14 7 50 0 -1 0.000 0 0 7 0 0 2
+ 2100 525 3750 2625
+2 1 0 4 0 7 50 0 -1 0.000 0 0 7 0 0 2
+ 1050 3075 2100 3075
+2 1 0 4 0 7 50 0 -1 0.000 0 0 7 0 0 2
+ 1050 1725 1650 1725
+2 1 0 4 0 7 50 0 -1 0.000 0 0 7 0 0 2
+ 1050 675 1200 675
+2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3750 2475 4950 2475 4950 2925 3750 2925 3750 2475
+2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3750 1425 4950 1425 4950 1875 3750 1875 3750 1425
+2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 3750 525 4950 525 4950 975 3750 975 3750 525
+4 0 0 50 0 1 20 0.0000 4 210 795 3900 2775 Filter 3\001
+4 0 0 50 0 1 20 0.0000 4 210 795 3900 1725 Filter 2\001
+4 0 0 50 0 1 20 0.0000 4 210 795 3900 825 Filter 1\001
+-6
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 300 525 1050 525 1050 3225 300 3225 300 525
+4 0 0 50 0 2 24 1.5708 4 255 1950 825 2850 INTERNET\001
diff --git a/contrib/sendmail/libmilter/docs/figure1.jpg b/contrib/sendmail/libmilter/docs/figure1.jpg
new file mode 100644
index 0000000..1a5f1de
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/figure1.jpg
Binary files differ
diff --git a/contrib/sendmail/libmilter/docs/figure1.ps b/contrib/sendmail/libmilter/docs/figure1.ps
new file mode 100644
index 0000000..ae31760
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/figure1.ps
@@ -0,0 +1,173 @@
+%!PS-Adobe-2.0
+%%Title: figure1.fig
+%%Creator: fig2dev Version 3.2.3 Patchlevel
+%%CreationDate: Tue Jun 6 14:00:04 2000
+%%For: sean@host232.Sendmail.COM (Sean O'rourke,5400)
+%%Orientation: Landscape
+%%Pages: 1
+%%BoundingBox: 0 0 612 792
+%%BeginSetup
+%%IncludeFeature: *PageSize Letter
+%%EndSetup
+%%Magnification: 1.0000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 792 moveto 0 0 lineto 612 0 lineto 612 792 lineto closepath clip newpath
+198.0 238.0 translate
+ 90 rotate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+%%Page: 1 1
+10 setmiterlimit
+ 0.06000 0.06000 sc
+%%Page: 1 1
+/Times-Bold ff 360.00 scf sf
+825 2850 m
+gs 1 -1 sc 90.0 rot (INTERNET) col0 sh gr
+/Times-Roman ff 300.00 scf sf
+1800 1725 m
+gs 1 -1 sc (MTA) col1 sh gr
+% Polyline
+15.000 slw
+n 2100 2775 m 3000 2775 l 3000 3225 l 2100 3225 l
+ cp gs col4 s gr
+/Times-Roman ff 300.00 scf sf
+2250 3075 m
+gs 1 -1 sc (MTA) col4 sh gr
+% Polyline
+n 1200 375 m 2100 375 l 2100 825 l 1200 825 l
+ cp gs col14 s gr
+/Times-Roman ff 300.00 scf sf
+1350 675 m
+gs 1 -1 sc (MTA) col14 sh gr
+% Polyline
+n 2550 1575 m
+ 3750 2625 l gs col1 s gr
+% Polyline
+n 2550 1575 m
+ 3750 1575 l gs col1 s gr
+% Polyline
+n 2550 1575 m
+ 3750 825 l gs col1 s gr
+% Polyline
+n 3000 2925 m
+ 3750 2625 l gs col4 s gr
+% Polyline
+n 2100 525 m
+ 3750 825 l gs col14 s gr
+% Polyline
+n 2100 525 m
+ 3750 2625 l gs col14 s gr
+% Polyline
+45.000 slw
+n 1050 3075 m
+ 2100 3075 l gs col0 s gr
+% Polyline
+n 1050 1725 m
+ 1650 1725 l gs col0 s gr
+% Polyline
+n 1050 675 m
+ 1200 675 l gs col0 s gr
+% Polyline
+15.000 slw
+n 3750 2475 m 4950 2475 l 4950 2925 l 3750 2925 l
+ cp gs col0 s gr
+% Polyline
+n 3750 1425 m 4950 1425 l 4950 1875 l 3750 1875 l
+ cp gs col0 s gr
+% Polyline
+n 3750 525 m 4950 525 l 4950 975 l 3750 975 l
+ cp gs col0 s gr
+/Times-Italic ff 300.00 scf sf
+3900 2775 m
+gs 1 -1 sc (Filter 3) col0 sh gr
+/Times-Italic ff 300.00 scf sf
+3900 1725 m
+gs 1 -1 sc (Filter 2) col0 sh gr
+/Times-Italic ff 300.00 scf sf
+3900 825 m
+gs 1 -1 sc (Filter 1) col0 sh gr
+% Polyline
+7.500 slw
+n 300 525 m 1050 525 l 1050 3225 l 300 3225 l
+ cp gs col0 s gr
+% Polyline
+15.000 slw
+n 1650 1425 m 2550 1425 l 2550 1875 l 1650 1875 l
+ cp gs col1 s gr
+$F2psEnd
+rs
+showpage
diff --git a/contrib/sendmail/libmilter/docs/figure2.fig b/contrib/sendmail/libmilter/docs/figure2.fig
new file mode 100644
index 0000000..c93bfe3
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/figure2.fig
@@ -0,0 +1,67 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter
+100.00
+Single
+-2
+1200 2
+5 1 0 1 0 7 50 0 -1 0.000 0 0 1 0 2981.250 1200.000 2700 1050 3300 1200 2700 1350
+ 1 1 1.00 60.00 120.00
+6 4200 900 6450 1350
+2 2 0 1 1 7 50 0 -1 0.000 0 0 7 0 0 5
+ 4200 900 6450 900 6450 1350 4200 1350 4200 900
+4 0 1 50 0 0 16 0.0000 4 195 2040 4350 1200 xxfi_header callback\001
+-6
+6 4200 2250 6450 2700
+2 2 0 1 4 7 50 0 -1 0.000 0 0 7 0 0 5
+ 4200 2250 6450 2250 6450 2700 4200 2700 4200 2250
+4 0 4 50 0 0 16 0.0000 4 195 2040 4350 2550 xxfi_header callback\001
+-6
+6 600 2100 1800 2850
+2 2 0 2 4 7 50 0 -1 0.000 0 0 7 0 0 5
+ 750 2250 1650 2250 1650 2700 750 2700 750 2250
+4 0 4 50 0 0 20 0.0000 4 195 645 900 2550 MTA\001
+-6
+6 600 750 1800 1500
+2 2 0 2 1 7 50 0 -1 0.000 0 0 7 0 0 5
+ 750 900 1650 900 1650 1350 750 1350 750 900
+4 0 1 50 0 0 20 0.0000 4 195 645 900 1200 MTA\001
+-6
+2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 120.00 240.00
+ 4200 1200 3600 1200
+2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 120.00 240.00
+ 3450 900 4050 900
+2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2400 300 6600 300 6600 3300 2400 3300 2400 300
+2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
+ 2550 750 3450 750 3450 2700 2550 2700 2550 750
+2 1 0 2 4 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 120.00 240.00
+ 3450 2700 4050 2700
+2 1 0 2 4 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 120.00 240.00
+ 4200 2400 3600 2400
+2 1 0 2 4 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 120.00 240.00
+ 1650 2700 2250 2700
+2 1 0 2 4 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 120.00 240.00
+ 2400 2400 1800 2400
+2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 120.00 240.00
+ 1650 900 2250 900
+2 1 0 2 1 7 50 0 -1 0.000 0 0 -1 1 0 2
+ 1 1 2.00 120.00 240.00
+ 2400 1200 1800 1200
+4 0 0 50 0 0 20 0.0000 4 195 630 3900 600 Filter\001
+4 0 4 50 0 0 12 0.0000 4 180 1620 3450 3000 callback (arguments)\001
+4 0 4 50 0 0 12 0.0000 4 180 1575 3900 1950 optional library calls,\001
+4 0 4 50 0 0 12 0.0000 4 135 855 3900 2175 return code\001
+4 0 4 50 0 0 12 0.0000 4 135 780 1500 2100 responses\001
+4 0 0 50 0 0 16 0.0000 4 165 645 2700 2085 Milter\001
+4 0 0 50 0 0 16 0.0000 4 225 675 2700 2400 library\001
+4 0 4 50 0 0 12 0.0000 4 135 510 1500 3000 header\001
diff --git a/contrib/sendmail/libmilter/docs/figure2.jpg b/contrib/sendmail/libmilter/docs/figure2.jpg
new file mode 100644
index 0000000..8b11485
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/figure2.jpg
Binary files differ
diff --git a/contrib/sendmail/libmilter/docs/figure2.ps b/contrib/sendmail/libmilter/docs/figure2.ps
new file mode 100644
index 0000000..861a193
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/figure2.ps
@@ -0,0 +1,242 @@
+%!PS-Adobe-2.0
+%%Title: figure2.fig
+%%Creator: fig2dev Version 3.2.3 Patchlevel
+%%CreationDate: Tue Jun 6 13:57:47 2000
+%%For: sean@host232.Sendmail.COM (Sean O'rourke,5400)
+%%Orientation: Landscape
+%%Pages: 1
+%%BoundingBox: 0 0 612 792
+%%BeginSetup
+%%IncludeFeature: *PageSize Letter
+%%EndSetup
+%%Magnification: 1.5000
+%%EndComments
+/$F2psDict 200 dict def
+$F2psDict begin
+$F2psDict /mtrx matrix put
+/col-1 {0 setgray} bind def
+/col0 {0.000 0.000 0.000 srgb} bind def
+/col1 {0.000 0.000 1.000 srgb} bind def
+/col2 {0.000 1.000 0.000 srgb} bind def
+/col3 {0.000 1.000 1.000 srgb} bind def
+/col4 {1.000 0.000 0.000 srgb} bind def
+/col5 {1.000 0.000 1.000 srgb} bind def
+/col6 {1.000 1.000 0.000 srgb} bind def
+/col7 {1.000 1.000 1.000 srgb} bind def
+/col8 {0.000 0.000 0.560 srgb} bind def
+/col9 {0.000 0.000 0.690 srgb} bind def
+/col10 {0.000 0.000 0.820 srgb} bind def
+/col11 {0.530 0.810 1.000 srgb} bind def
+/col12 {0.000 0.560 0.000 srgb} bind def
+/col13 {0.000 0.690 0.000 srgb} bind def
+/col14 {0.000 0.820 0.000 srgb} bind def
+/col15 {0.000 0.560 0.560 srgb} bind def
+/col16 {0.000 0.690 0.690 srgb} bind def
+/col17 {0.000 0.820 0.820 srgb} bind def
+/col18 {0.560 0.000 0.000 srgb} bind def
+/col19 {0.690 0.000 0.000 srgb} bind def
+/col20 {0.820 0.000 0.000 srgb} bind def
+/col21 {0.560 0.000 0.560 srgb} bind def
+/col22 {0.690 0.000 0.690 srgb} bind def
+/col23 {0.820 0.000 0.820 srgb} bind def
+/col24 {0.500 0.190 0.000 srgb} bind def
+/col25 {0.630 0.250 0.000 srgb} bind def
+/col26 {0.750 0.380 0.000 srgb} bind def
+/col27 {1.000 0.500 0.500 srgb} bind def
+/col28 {1.000 0.630 0.630 srgb} bind def
+/col29 {1.000 0.750 0.750 srgb} bind def
+/col30 {1.000 0.880 0.880 srgb} bind def
+/col31 {1.000 0.840 0.000 srgb} bind def
+
+end
+save
+newpath 0 792 moveto 0 0 lineto 612 0 lineto 612 792 lineto closepath clip newpath
+144.0 65.5 translate
+ 90 rotate
+1 -1 scale
+
+/cp {closepath} bind def
+/ef {eofill} bind def
+/gr {grestore} bind def
+/gs {gsave} bind def
+/sa {save} bind def
+/rs {restore} bind def
+/l {lineto} bind def
+/m {moveto} bind def
+/rm {rmoveto} bind def
+/n {newpath} bind def
+/s {stroke} bind def
+/sh {show} bind def
+/slc {setlinecap} bind def
+/slj {setlinejoin} bind def
+/slw {setlinewidth} bind def
+/srgb {setrgbcolor} bind def
+/rot {rotate} bind def
+/sc {scale} bind def
+/sd {setdash} bind def
+/ff {findfont} bind def
+/sf {setfont} bind def
+/scf {scalefont} bind def
+/sw {stringwidth} bind def
+/tr {translate} bind def
+/tnt {dup dup currentrgbcolor
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add
+ 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
+ bind def
+/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
+ 4 -2 roll mul srgb} bind def
+/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
+/$F2psEnd {$F2psEnteredState restore end} def
+
+$F2psBegin
+%%Page: 1 1
+10 setmiterlimit
+ 0.09000 0.09000 sc
+%%Page: 1 1
+/Times-Roman ff 180.00 scf sf
+1500 3000 m
+gs 1 -1 sc (header) col4 sh gr
+/Times-Roman ff 240.00 scf sf
+4350 1200 m
+gs 1 -1 sc (xxfi_header callback) col1 sh gr
+% Polyline
+7.500 slw
+n 4200 2250 m 6450 2250 l 6450 2700 l 4200 2700 l
+ cp gs col4 s gr
+/Times-Roman ff 240.00 scf sf
+4350 2550 m
+gs 1 -1 sc (xxfi_header callback) col4 sh gr
+% Polyline
+15.000 slw
+n 750 2250 m 1650 2250 l 1650 2700 l 750 2700 l
+ cp gs col4 s gr
+/Times-Roman ff 300.00 scf sf
+900 2550 m
+gs 1 -1 sc (MTA) col4 sh gr
+% Polyline
+n 750 900 m 1650 900 l 1650 1350 l 750 1350 l
+ cp gs col1 s gr
+/Times-Roman ff 300.00 scf sf
+900 1200 m
+gs 1 -1 sc (MTA) col1 sh gr
+% Arc
+7.500 slw
+gs clippath
+2713 1319 m 2667 1357 l 2761 1475 l 2710 1363 l 2808 1437 l cp
+eoclip
+n 2981.2 1200.0 318.8 -151.9 151.9 arc
+gs col0 s gr
+ gr
+
+% arrowhead
+n 2808 1437 m 2710 1363 l 2761 1475 l 2808 1437 l cp gs 0.00 setgray ef gr col0 s
+% Polyline
+15.000 slw
+gs clippath
+3585 1140 m 3585 1260 l 3872 1260 l 3632 1200 l 3872 1140 l cp
+eoclip
+n 4200 1200 m
+ 3600 1200 l gs col1 s gr gr
+
+% arrowhead
+n 3872 1140 m 3632 1200 l 3872 1260 l 3872 1140 l cp gs col1 1.00 shd ef gr col1 s
+% Polyline
+gs clippath
+4065 960 m 4065 840 l 3778 840 l 4018 900 l 3778 960 l cp
+eoclip
+n 3450 900 m
+ 4050 900 l gs col1 s gr gr
+
+% arrowhead
+n 3778 960 m 4018 900 l 3778 840 l 3778 960 l cp gs col1 1.00 shd ef gr col1 s
+% Polyline
+n 2400 300 m 6600 300 l 6600 3300 l 2400 3300 l
+ cp gs col0 s gr
+% Polyline
+7.500 slw
+n 2550 750 m 3450 750 l 3450 2700 l 2550 2700 l
+ cp gs col0 s gr
+% Polyline
+15.000 slw
+gs clippath
+4065 2760 m 4065 2640 l 3778 2640 l 4018 2700 l 3778 2760 l cp
+eoclip
+n 3450 2700 m
+ 4050 2700 l gs col4 s gr gr
+
+% arrowhead
+n 3778 2760 m 4018 2700 l 3778 2640 l 3778 2760 l cp gs col4 1.00 shd ef gr col4 s
+% Polyline
+gs clippath
+3585 2340 m 3585 2460 l 3872 2460 l 3632 2400 l 3872 2340 l cp
+eoclip
+n 4200 2400 m
+ 3600 2400 l gs col4 s gr gr
+
+% arrowhead
+n 3872 2340 m 3632 2400 l 3872 2460 l 3872 2340 l cp gs col4 1.00 shd ef gr col4 s
+% Polyline
+gs clippath
+2265 2760 m 2265 2640 l 1978 2640 l 2218 2700 l 1978 2760 l cp
+eoclip
+n 1650 2700 m
+ 2250 2700 l gs col4 s gr gr
+
+% arrowhead
+n 1978 2760 m 2218 2700 l 1978 2640 l 1978 2760 l cp gs col4 1.00 shd ef gr col4 s
+% Polyline
+gs clippath
+1785 2340 m 1785 2460 l 2072 2460 l 1832 2400 l 2072 2340 l cp
+eoclip
+n 2400 2400 m
+ 1800 2400 l gs col4 s gr gr
+
+% arrowhead
+n 2072 2340 m 1832 2400 l 2072 2460 l 2072 2340 l cp gs col4 1.00 shd ef gr col4 s
+% Polyline
+gs clippath
+2265 960 m 2265 840 l 1978 840 l 2218 900 l 1978 960 l cp
+eoclip
+n 1650 900 m
+ 2250 900 l gs col1 s gr gr
+
+% arrowhead
+n 1978 960 m 2218 900 l 1978 840 l 1978 960 l cp gs col1 1.00 shd ef gr col1 s
+% Polyline
+gs clippath
+1785 1140 m 1785 1260 l 2072 1260 l 1832 1200 l 2072 1140 l cp
+eoclip
+n 2400 1200 m
+ 1800 1200 l gs col1 s gr gr
+
+% arrowhead
+n 2072 1140 m 1832 1200 l 2072 1260 l 2072 1140 l cp gs col1 1.00 shd ef gr col1 s
+/Times-Roman ff 300.00 scf sf
+3900 600 m
+gs 1 -1 sc (Filter) col0 sh gr
+/Times-Roman ff 180.00 scf sf
+3450 3000 m
+gs 1 -1 sc (callback \(arguments\)) col4 sh gr
+/Times-Roman ff 180.00 scf sf
+3900 1950 m
+gs 1 -1 sc (optional library calls,) col4 sh gr
+/Times-Roman ff 180.00 scf sf
+3900 2175 m
+gs 1 -1 sc (return code) col4 sh gr
+/Times-Roman ff 180.00 scf sf
+1500 2100 m
+gs 1 -1 sc (responses) col4 sh gr
+/Times-Roman ff 240.00 scf sf
+2700 2085 m
+gs 1 -1 sc (Milter) col0 sh gr
+/Times-Roman ff 240.00 scf sf
+2700 2400 m
+gs 1 -1 sc (library) col0 sh gr
+% Polyline
+7.500 slw
+n 4200 900 m 6450 900 l 6450 1350 l 4200 1350 l
+ cp gs col1 s gr
+$F2psEnd
+rs
+showpage
diff --git a/contrib/sendmail/libmilter/docs/index.html b/contrib/sendmail/libmilter/docs/index.html
new file mode 100644
index 0000000..44c5f90
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/index.html
@@ -0,0 +1,92 @@
+<html>
+<head>
+<title>Filtering Mail with Sendmail</title>
+</head>
+<body>
+<!--
+$Id: index.html,v 1.10 2001/06/01 00:05:03 ca Exp $
+-->
+
+<h1>Filtering Mail with Sendmail</h1>
+
+<!--
+<P><b>Disclaimer</b>:
+This preliminary API description is provided for review only. This
+specification may change based on feedback from reviewers, and does
+not bind Sendmail to offer this functionality in any release.
+-->
+
+<h2>Introduction</h2>
+
+<P>
+Sendmail's Content Management API (milter) provides third-party
+programs to access mail messages as they are being processed by the
+Mail Transfer Agent (MTA), allowing them to examine and modify message
+content and meta-information. Filtering policies implemented by
+Milter-conformant filters may then be centrally configured and
+composed in an end-user's MTA configuration file.
+
+<p>
+Possible uses for filters include spam rejection, virus
+filtering, and content control. In general, Milter seeks to address
+site-wide filtering concerns in a scalable way. Individual users' mail
+filtering needs (e.g. sorting messages by subject) are left to
+client-level programs such as <a href="http://www.procmail.org">Procmail</a>.
+
+<P>
+This document is a technical introduction intended for those
+interested in developing Milter filters. It includes:
+<ul>
+<li>A description of Milter's design goals.
+
+<li>An explanation of Milter application architecture, including
+interactions between the support library and user code, and between
+filters and the MTA.
+
+<li>A specification of the C application programming interface.
+<li>An example of a simple Milter filter.
+</ul>
+
+<h2>Contents</h2>
+
+<ul>
+<li><a href="design.html">Architecture</a>
+<ul>
+ <li>Design Goals
+ <li>Implementing Filtering Policies
+ <li>MTA - Filter communication
+</ul>
+<li><a href="overview.html">Technical Overview</a>
+<ul>
+ <li>Initialization
+ <li>Control flow
+ <li>Multithreading
+ <li>Resource Management
+ <li>Signal Handling
+</ul>
+<li><a href="api.html">API Documentation</a>
+<ul>
+ <li>Library Control Functions
+ <li>Data Access Functions
+ <li>Message Modification Functions
+ <li>Callbacks
+</ul>
+<li><a href="installation.html">Installation and Configuration</a>
+<ul>
+ <li>Compiling and Installing Your Filter
+ <li>Configuring Sendmail
+</ul>
+<li><a href="sample.html">A Sample Filter</a>
+<!-- <li><a href="other.html">Other Sources of Information</a> -->
+</ul>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000, 2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/installation.html b/contrib/sendmail/libmilter/docs/installation.html
new file mode 100644
index 0000000..8ebe4ee
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/installation.html
@@ -0,0 +1,169 @@
+<html>
+<head><title>Installation and Configuration</title>
+</head>
+<body>
+<h1>Installation</h1>
+<h2>Contents</h2>
+<ul>
+ <li><a href="#compile">Compiling and Installing Your Filter</a>
+ <li><a href="#config">Configuring Sendmail</a>
+</ul>
+
+<h2><a name="compile">Compiling and Installing Your Filter</A></h2>
+
+To compile a filter, modify the Makefile provided with the sample program, or:
+<ul>
+ <li>Put the include and Sendmail directories in your include path
+ (e.g. -I/path/to/include -I/path/to/sendmail).
+
+ <li>Make sure libmilter.so is in your library path, and link your
+ application with it (e.g. "-lmilter").
+
+ <li>Compile with pthreads, either by using -pthread for gcc, or
+ linking with a pthreads support library (-lpthread).
+</ul>
+Your compile command line will look like
+<pre>
+cc -I/path/to/include -I/path/to/sendmail -c myfile.c
+</pre>
+and your linking command line will look something like
+<pre>
+cc -o myfilter [object-files] -L[library-location] -lmilter -pthread
+</pre>
+
+<p>
+To run the filter, the Milter shared library must be available to the
+run-time linker.
+
+<H2><a name="config">Configuring Sendmail</A></H2>
+
+First, you must compile sendmail versions before 8.12 with _FFR_MILTER
+defined. To do this, add the following lines to your build
+configuration file (devtools/Site/config.site.m4)
+<pre>
+APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_MILTER=1')
+APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER=1')
+</pre>
+
+then type <code>./Build -c</code> in your sendmail directory.
+
+<P>
+Next, you must add the desired filters to your sendmail configuration
+(.mc) file. With versions before 8.12, the file must then be
+processed with _FFR_MILTER defined. Mail filters have three equates:
+The required <code>S=</code> equate specifies the socket where
+sendmail should look for the filter; The optional <code>F=</code> and
+<code>T=</code> equates specify flags and timeouts, respectively. All
+equates names, equate field names, and flag values are case sensitive.
+
+<P>
+The current flags (<code>F=</code>) are:
+<p>
+<table cellspacing="1" cellpadding=4 border=1>
+<tr bgcolor="#dddddd" align=left valign=top>
+<th>Flag</TH> <th align="center">Meaning</TH>
+</TR>
+<tr align="left" valign=top>
+<TD>R</TD> <TD>Reject connection if filter unavailable</TD>
+</TR>
+<tr align="left" valign=top>
+<TD>T</TD> <TD>Temporary fail connection if filter unavailable</TD>
+</TR>
+</TABLE>
+
+If a filter is unavailable or unresponsive and no flags have been
+specified, the MTA will continue normal handling of the current
+connection. The MTA will try to contact the filter again on each new
+connection.
+
+<P>
+There are three fields inside of the <code>T=</code> equate: S, R, and
+E. Note the separator between each is a ";" (semicolon), as ","
+(comma) already separates equates. The value of each field is a
+decimal number followed by a single letter designating the units ("s"
+for seconds, "m" for minutes). The fields have the following
+meanings:
+<p>
+<TABLE cellspacing="1" cellpadding=4 border=1>
+<TR bgcolor="#dddddd" align=left valign=top>
+<TH>Flag</TH> <TH align="center">Meaning</TH>
+</TR>
+<TR align="left" valign=top>
+<TD>C</TD> <TD>Timeout for connecting to a filter. If set to 0, the
+ system's <CODE>connect()</CODE> timeout will be used.
+ Default: 5m</TD>
+</TR>
+<TR align="left" valign=top>
+<TD>S</TD> <TD>Timeout for sending information from the MTA to a
+ filter. Default: 10s</TD>
+</TR>
+<TR align="left" valign=top>
+<TD>R</TD> <TD>Timeout for reading reply from the filter. Default: 10s</TD>
+</TR>
+<TR align="left" valign=top>
+<TD>E</TD> <TD>Overall timeout between sending end-of-message to
+ filter and waiting for the final acknowledgment. Default: 5m</TD>
+</TR>
+</TABLE>
+
+<p>
+The following sendmail.mc example specifies three filters. The first
+two rendezvous on Unix-domain sockets in the /var/run directory; the
+third uses an IP socket on port 999.
+<pre>
+ INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/f1.sock, F=R')
+ INPUT_MAIL_FILTER(`filter2', `S=unix:/var/run/f2.sock, F=T, T=S:1s;R:1s;E:5m')
+ INPUT_MAIL_FILTER(`filter3', `S=inet:999@localhost, T=C:2m')
+
+ define(`confINPUT_MAIL_FILTERS', `filter2,filter1,filter3')
+<hr width="30%">
+ m4 <b>-D_FFR_MILTER</b> ../m4/cf.m4 myconfig.mc &gt; myconfig.cf
+</pre>
+By default, the filters would be run in the order declared,
+i.e. "filter1, filter2, filter3"; however, since
+<code>confINPUT_MAIL_FILTERS</code> is defined, the filters will be
+run "filter2, filter1, filter3". Also note that a filter can be
+defined without adding it to the input filter list by using
+MAIL_FILTER() instead of INPUT_MAIL_FILTER().
+
+<p>
+The above macros will result in the following lines being added to
+your .cf file:
+<PRE>
+ Xfilter1, S=unix:/var/run/f1.sock, F=R
+ Xfilter2, S=unix:/var/run/f2.sock, F=T, T=S:1s;R:1s;E:5m
+ Xfilter3, S=inet:999@localhost, T=C:2m
+
+ O InputMailFilters=filter2,filter1,filter3
+</PRE>
+<p>
+Finally, the sendmail macros accessible via <a
+href="smfi_getsymval.html">smfi_getsymval</a> can be configured by
+defining the following m4 variables (or cf options):
+<table cellspacing="1" cellpadding=4 border=1>
+<tr bgcolor="#dddddd" align=left valign=top>
+<th align="center">In .mc file</th> <th align="center">In .cf file</TH>
+<th align="center">Default Value</th>
+</tr>
+<tr><td>confMILTER_MACROS_CONNECT</td><td>Milter.macros.connect</td>
+<td><code>j, _, {daemon_name}, {if_name}, {if_addr}</code></td></tr>
+<tr><td>confMILTER_MACROS_HELO</td><td>Milter.macros.helo</td>
+<td><code>{tls_version}, {cipher}, {cipher_bits}, {cert_subject},
+{cert_issuer}</code></td></tr>
+<tr><td>confMILTER_MACROS_ENVFROM</td><td>Milter.macros.envfrom</td>
+<td><code>i, {auth_type}, {auth_authen}, {auth_ssf}, {auth_author},
+{mail_mailer}, {mail_host}, {mail_addr}</code></td></tr>
+<tr><td>confMILTER_MACROS_ENVRCPT</td><td>Milter.macros.envrcpt</td>
+<td><code>{rcpt_mailer}, {rcpt_host}, {rcpt_addr}</code></td></tr>
+</table>
+For information about available macros and their meanings, please
+consult the sendmail documentation.
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body> </html>
diff --git a/contrib/sendmail/libmilter/docs/other.html b/contrib/sendmail/libmilter/docs/other.html
new file mode 100644
index 0000000..8ec9ffd
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/other.html
@@ -0,0 +1,15 @@
+<html>
+<head><title>Other Resources</title>
+</head>
+<body>
+FAQ? Mailing list? More sample filters?
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/overview.html b/contrib/sendmail/libmilter/docs/overview.html
new file mode 100644
index 0000000..7f1c036
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/overview.html
@@ -0,0 +1,194 @@
+<html>
+<head>
+<title>Technical Overview</title>
+</head>
+<body>
+<!--
+$Id: overview.html,v 1.12 2001/06/01 00:05:03 ca Exp $
+-->
+
+<h1>Technical Overview</h1>
+
+<h2>Contents</h2>
+
+<ul>
+ <li>Initialization
+ <li>Control flow
+ <li>Multithreading
+ <li>Resource Management
+ <li>Signal Handling
+</ul>
+
+<h2>Initialization</h2>
+
+In addition to its own initialization, libmilter expects a filter to initialize several parameters before calling <a href="smfi_main.html">smfi_main</a>:
+<ul>
+ <li>The callbacks the filter wishes to be called, and the types of
+ message modification it intends to perform (required, see <a
+ href="smfi_register.html">smfi_register</a>).
+
+ <li>The socket address to be used when communicating with the MTA
+ (required, see <a href="smfi_setconn.html">smfi_setconn</a>).
+
+ <li>The number of seconds to wait for MTA connections before
+ timing out (optional, see <a
+ href="smfi_settimeout.html">smfi_settimeout</a>).
+</ul>
+<p>
+If the filter fails to initialize libmilter, or if one or more of the
+parameters it has passed are invalid, a subsequent call to smfi_main
+will fail.
+
+<h2>Control flow</h2>
+
+<p>
+The following pseudocode describes the filtering process from the
+perspective of a set of <code>N</code> MTA's, each corresponding to a
+connection. Callbacks are shown beside the processing stages in which
+they are invoked; if no callbacks are defined for a particular stage,
+that stage may be bypassed. Though it is not shown, processing may be
+aborted at any time during a message, in which case the <a
+href="xxfi_abort.html">xxfi_abort</a> callback is invoked and control
+returns to <code>MESSAGE</code>.
+<p>
+<pre>
+For each of N connections
+{
+ For each filter
+ process connection/helo (<a href="xxfi_connect.html">xxfi_connect</a>, <a href="xxfi_helo.html">xxfi_helo</a>)
+MESSAGE:For each message in this connection (sequentially)
+ {
+ For each filter
+ process sender (<a href="xxfi_envfrom.html">xxfi_envfrom</a>)
+ For each recipient
+ {
+ For each filter
+ process recipient (<a href="xxfi_envrcpt.html">xxfi_envrcpt</a>)
+ }
+ For each filter
+ {
+ For each header
+ process header (<a href="xxfi_header.html">xxfi_header</a>)
+ process end of headers (<a href="xxfi_eoh.html">xxfi_eoh</a>)
+ For each body block
+ process this body block (<a href="xxfi_body.html">xxfi_body</a>)
+ process end of message (<a href="xxfi_eom.html">xxfi_eom</a>)
+ }
+ }
+ For each filter
+ process end of connection (<a href="xxfi_close.html">xxfi_close</a>)
+}
+</pre>
+
+<P>Note: Filters are contacted in order defined in config file.</P>
+
+<P>
+To write a filter, a vendor supplies callbacks to process relevant
+parts of a message transaction. The library then controls all
+sequencing, threading, and protocol exchange with the MTA. <a
+href="#figure-3">Figure 3</a> outlines control flow for a filter
+process, showing where different callbacks are invoked.
+</p>
+<div align="center"><a name="figure-3"></a>
+<table border=1 cellspacing=0 cellpadding=2 width="70%">
+<tr bgcolor="#dddddd"><th>SMTP Commands</th><th>Milter Callbacks</th></tr>
+<tr><td>(open SMTP connection)</td><td>xxfi_connect</td></tr>
+<tr><td>HELO ...</td><td>xxfi_helo</td></tr>
+<tr><td>MAIL From: ...</td><td>xxfi_envfrom</td></tr>
+<tr><td>RCPT To: ...</td><td>xxfi_envrcpt</td></tr>
+<tr><td>[more RCPTs]</td><td>[xxfi_envrcpt]</td></tr>
+<tr><td>DATA</td><td>&nbsp;</td></tr>
+<tr><td>Header: ...</td><td>xxfi_header</td></tr>
+<tr><td>[more headers]</td><td>[xxfi_header]</td></tr>
+<tr><td>&nbsp;</td><td>xxfi_eoh</td></tr>
+<tr><td>body... </td><td>xxfi_body</td></tr>
+<tr><td>[more body...]</td><td>[xxfi_body]</td></tr>
+<tr><td>.</td><td>xxfi_eom</td></tr>
+<tr><td>QUIT</td><td>xxfi_close</td></tr>
+<tr><td>(close SMTP connection)</td><td>&nbsp;</td></tr>
+</table>
+<b>Figure 3: Milter callbacks related to an SMTP transaction.</b>
+</div>
+<p>
+Note that although only a single message is shown above, multiple
+messages may be sent in a single connection. Note also that a message
+and/or connection may be aborted by either the remote host or the MTA
+at any point during the SMTP transaction. If this occurs during a
+message (between the MAIL command and the final "."), the filter's <a
+href="xxfi_abort.html">xxfi_abort</a> routine will be called. <a
+href="xxfi_close.html">xxfi_close</a> is called any time the
+connection closes.
+
+<h2>Multithreading</h2>
+
+<p>
+A single filter process may handle any number of connections
+simultaneously. All filtering callbacks must therefore be reentrant,
+and use some appropriate external synchronization methods to access
+global data. Furthermore, since there is not a one-to-one
+correspondence between threads and connections (N connections mapped
+onto M threads, M &lt;= N), connection-specific data must be accessed
+through the handles provided by the Milter library. The programmer
+cannot rely on library-supplied thread-specific data blocks
+(e.g. pthread_getspecific()) to store connection-specific data. See
+the API documentation for <a
+href="smfi_setpriv.html">smfi_setpriv</a> and <a
+href="smfi_getpriv.html">smfi_getpriv</a> for details.
+
+<h2>Resource management</h2>
+
+Since filters are likely to be long-lived, and to handle many
+connections, proper deallocation of per-connection resources is
+important. The lifetime of a connection is bracketed by calls to the
+callbacks <a href="xxfi_connect.html">xxfi_connect</a> and <a
+href="xxfi_close.html">xxfi_close</a>. Therefore connection-specific
+resources (accessed via <a href="smfi_getpriv.html">smfi_getpriv</a>
+and <a href="smfi_setpriv.html">smfi_setpriv</a>) may be allocated in
+<a href="xxfi_connect.html">xxfi_connect</a>, and should be freed in
+<a href="xxfi_close.html">xxfi_close</a>. For further information see
+the <a href="api.html#conn-msg">discussion</a> of message- versus
+connection-oriented routines. In particular, note that there is only
+one connection-specific data pointer per connection.
+<p>
+
+Each message is bracketed by calls to <a
+href="xxfi_envfrom.html">xxfi_envfrom</a> and <a
+href="xxfi_eom.html">xxfi_eom</a> (or <a
+href="xxfi_abort.html">xxfi_abort</a>), implying that message-specific
+resources can be allocated and reclaimed in these routines. Since the
+messages in a connection are processed sequentially by each filter,
+there will be only one active message associated with a given
+connection and filter (and connection-private data block). These
+resources must still be accessed through <a
+href="smfi_getpriv.html">smfi_getpriv</a> and <a
+href="smfi_setpriv.html">smfi_setpriv</a>, and must be reclaimed
+in <a href="xxfi_abort.html">xxfi_abort</a>.
+
+<h2>Signal Handling</h2>
+
+libmilter takes care of signal handling, the filters are
+not influenced directly by signals.
+There are basically two types of signal handlers:
+
+<ol>
+<li><TT>Stop</TT>: no new connections from the MTA will be accepted,
+but existing connections are allowed to continue.
+<li><TT>Abort</TT>: all filters will be stopped as soon as the next
+communication with the MTA happens.
+</ol>
+
+Filters are not terminated asynchronously (except by
+signals that can't be caught).
+In the case of <TT>Abort</TT> the
+<a href="xxfi_abort.html">xxfi_abort</a> callback is invoked.
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000, 2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/sample.html b/contrib/sendmail/libmilter/docs/sample.html
new file mode 100644
index 0000000..7e99704
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/sample.html
@@ -0,0 +1,426 @@
+<html>
+<head><title>A Sample Filter</title></head>
+<body>
+<h1>A Sample Filter</h1>
+
+The following sample logs each message to a separate temporary file,
+adds a recipient given with the -a flag, and rejects a disallowed
+recipient address given with the -r flag. It recognizes the following
+options:
+<p>
+<center>
+<table border="1" cellpadding=2 cellspacing=1>
+<tr><td><code>-p port</code></td><td>The port through which the MTA will connect to the filter.</td></tr>
+<tr><td><code>-t sec</code></td><td>The timeout value.</td></tr>
+<tr><td><code>-r addr</code></td><td>A recipient to reject.</td></tr>
+<tr><td><code>-a addr</code></td><td>A recipient to add.</td></tr>
+</table>
+</center>
+<hr>
+<pre>
+#include "mfapi.h"
+
+#include &lt;stdio.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;string.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;sys/stat.h&gt;
+#include &lt;sysexits.h&gt;
+#include &lt;unistd.h&gt;
+#ifndef bool
+#define bool char
+#define TRUE 1
+#define FALSE 0
+#endif
+
+extern int errno;
+
+
+struct mlfiPriv
+{
+ char *mlfi_fname;
+ char *mlfi_connectfrom;
+ char *mlfi_helofrom;
+ FILE *mlfi_fp;
+};
+
+#define MLFIPRIV ((struct mlfiPriv *) <a href="smfi_getpriv.html">smfi_getpriv</a>(ctx))
+
+extern sfsistat mlfi_cleanup(SMFICTX *, bool);
+/* recipients to add and reject (set with -a and -r options) */
+char *add, *reject;
+
+sfsistat
+<a href="xxfi_connect.html">mlfi_connect</a>(ctx, hostname, hostaddr)
+ SMFICTX *ctx;
+ char *hostname;
+ _SOCK_ADDR *hostaddr;
+{
+ struct mlfiPriv *priv;
+ char *ident;
+
+ /* allocate some private memory */
+ priv = malloc(sizeof *priv);
+ if (priv == NULL)
+ {
+ /* can't accept this message right now */
+ return SMFIS_TEMPFAIL;
+ }
+ memset(priv, '\0', sizeof *priv);
+
+ /* save the private data */
+ <a href="smfi_setpriv.html">smfi_setpriv</a>(ctx, priv);
+
+ ident = <a href="smfi_getsymval.html">smfi_getsymval</a>(ctx, "_");
+ if(!ident) ident = "???";
+ if(!(priv-&gt;mlfi_connectfrom = strdup(ident))) {
+ return SMFIS_TEMPFAIL;
+ }
+ /* Continue processing. */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+<a href="xxfi_helo.html">mlfi_helo</a>(ctx, helohost)
+ SMFICTX *ctx;
+ char *helohost;
+{
+ char *tls;
+ char *buf;
+ struct mlfiPriv *priv = MLFIPRIV;
+ tls = <a href="smfi_getsymval.html">smfi_getsymval</a>(ctx, "{tls_version}");
+ if(!tls) tls = "No TLS";
+ if(!helohost) helohost = "???";
+ if(!(buf = (char*)malloc(strlen(tls) + strlen(helohost) + 3))) {
+ return SMFIS_TEMPFAIL;
+ }
+ sprintf(buf, "%s, %s", helohost, tls);
+ if(priv-&gt;mlfi_helofrom)
+ free(priv-&gt;mlfi_helofrom);
+ priv-&gt;mlfi_helofrom = buf;
+ /* Continue processing. */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+<a href="xxfi_envfrom.html">mlfi_envfrom</a>(ctx, argv)
+ SMFICTX *ctx;
+ char **argv;
+{
+ struct mlfiPriv *priv = MLFIPRIV;
+ char *mailaddr = <a href="smfi_getsymval.html">smfi_getsymval</a>(ctx, "{mail_addr}");
+ int argc = 0;
+
+ /* open a file to store this message */
+ priv-&gt;mlfi_fname = strdup("/tmp/msg.XXXXXX");
+ mkstemp(priv-&gt;mlfi_fname);
+ if (priv-&gt;mlfi_fname == NULL)
+ return SMFIS_TEMPFAIL;
+ if ((priv-&gt;mlfi_fp = fopen(priv-&gt;mlfi_fname, "w+")) == NULL)
+ {
+ free(priv-&gt;mlfi_fname);
+ return SMFIS_TEMPFAIL;
+ }
+
+ /* count the arguments */
+ while(*argv++) ++argc;
+ /* log the connection information we stored earlier: */
+ if(fprintf(priv-&gt;mlfi_fp, "Connect from %s (%s)\n\n",
+ priv-&gt;mlfi_helofrom, priv-&gt;mlfi_connectfrom) == EOF) {
+ (void) mlfi_cleanup(ctx, FALSE);
+ return SMFIS_TEMPFAIL;
+ }
+ /* log the sender */
+ if(fprintf(priv-&gt;mlfi_fp, "FROM %s (%d argument%s)\n",
+ mailaddr?mailaddr:"???", argc,
+ (argc == 1)?"":"s")
+ == EOF) {
+ (void) mlfi_cleanup(ctx, FALSE);
+ return SMFIS_TEMPFAIL;
+ }
+ /* continue processing */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+<a href="xxfi_envrcpt.html">mlfi_envrcpt</a>(ctx, argv)
+ SMFICTX *ctx;
+ char **argv;
+{
+ struct mlfiPriv *priv = MLFIPRIV;
+ char *rcptaddr = <a href="smfi_getsymval.html">smfi_getsymval</a>(ctx, "{rcpt_addr}");
+ int argc = 0;
+ /* count the arguments */
+ while(*argv++) ++argc;
+ /* log this recipient */
+ if(reject && rcptaddr && (strcmp(rcptaddr, reject) == 0)) {
+ if(fprintf(priv-&gt;mlfi_fp, "RCPT %s -- REJECTED\n", rcptaddr)
+ == EOF) {
+ (void) mlfi_cleanup(ctx, FALSE);
+ return SMFIS_TEMPFAIL;
+ }
+ return SMFIS_REJECT;
+ }
+ if(fprintf(priv-&gt;mlfi_fp, "RCPT %s (%d argument%s)\n",
+ rcptaddr?rcptaddr:"???", argc,
+ (argc == 1)?"":"s")
+ == EOF) {
+ (void) mlfi_cleanup(ctx, FALSE);
+ return SMFIS_TEMPFAIL;
+ }
+ /* continue processing */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+<a href="xxfi_header.html">mlfi_header</a>(ctx, headerf, headerv)
+ SMFICTX *ctx;
+ char *headerf;
+ unsigned char *headerv;
+{
+ /* write the header to the log file */
+ fprintf(MLFIPRIV-&gt;mlfi_fp, "%s: %s\n", headerf, headerv);
+
+ /* continue processing */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+<a href="xxfi_eoh.html">mlfi_eoh</a>(ctx)
+ SMFICTX *ctx;
+{
+ /* output the blank line between the header and the body */
+ fprintf(MLFIPRIV-&gt;mlfi_fp, "\n");
+
+ /* continue processing */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+<a href="xxfi_body.html">mlfi_body</a>(ctx, bodyp, bodylen)
+ SMFICTX *ctx;
+ unsigned char *bodyp;
+ size_t bodylen;
+{
+ /* output body block to log file */
+ int nwritten;
+ if ((nwritten = fwrite(bodyp, bodylen, 1, MLFIPRIV-&gt;mlfi_fp)) != 1)
+ {
+ /* write failed */
+ perror("error logging body");
+ (void) mlfi_cleanup(ctx, FALSE);
+ return SMFIS_TEMPFAIL;
+ }
+
+ /* continue processing */
+ return SMFIS_CONTINUE;
+}
+
+sfsistat
+<a href="xxfi_eom.html">mlfi_eom</a>(ctx)
+ SMFICTX *ctx;
+{
+ bool ok = TRUE;
+ /* change recipients, if requested */
+ if(add)
+ ok = ok && (<a href="smfi_addrcpt.html">smfi_addrcpt</a>(ctx, add) == MI_SUCCESS);
+ return mlfi_cleanup(ctx, ok);
+}
+
+sfsistat
+<a href="xxfi_abort.html">mlfi_abort</a>(ctx)
+ SMFICTX *ctx;
+{
+ return mlfi_cleanup(ctx, FALSE);
+}
+
+sfsistat
+mlfi_cleanup(ctx, ok)
+ SMFICTX *ctx;
+ bool ok;
+{
+ sfsistat rstat = SMFIS_CONTINUE;
+ struct mlfiPriv *priv = MLFIPRIV;
+ char *p;
+ char host[512];
+ char hbuf[1024];
+
+ if (priv == NULL)
+ return rstat;
+
+ /* close the archive file */
+ if (priv-&gt;mlfi_fp != NULL && fclose(priv-&gt;mlfi_fp) == EOF)
+ {
+ /* failed; we have to wait until later */
+ fprintf(stderr, "Couldn't close archive file %s: %s\n",
+ priv-&gt;mlfi_fname, strerror(errno));
+ rstat = SMFIS_TEMPFAIL;
+ (void) unlink(priv-&gt;mlfi_fname);
+ }
+ else if (ok)
+ {
+ /* add a header to the message announcing our presence */
+ if (gethostname(host, sizeof host) &lt; 0)
+ strncpy(host, "localhost", sizeof host);
+ p = strrchr(priv-&gt;mlfi_fname, '/');
+ if (p == NULL)
+ p = priv-&gt;mlfi_fname;
+ else
+ p++;
+ snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
+ <a href="smfi_addheader.html">smfi_addheader</a>(ctx, "X-Archived", hbuf);
+ }
+ else
+ {
+ /* message was aborted -- delete the archive file */
+ fprintf(stderr, "Message aborted. Removing %s\n",
+ priv-&gt;mlfi_fname);
+ rstat = SMFIS_TEMPFAIL;
+ (void) unlink(priv-&gt;mlfi_fname);
+ }
+
+ /* release private memory */
+ free(priv-&gt;mlfi_fname);
+
+ /* return status */
+ return rstat;
+}
+
+sfsistat
+<a href="xxfi_close.html">mlfi_close</a>(ctx)
+ SMFICTX *ctx;
+{
+ struct mlfiPriv *priv = MLFIPRIV;
+ if(priv-&gt;mlfi_connectfrom)
+ free(priv-&gt;mlfi_connectfrom);
+ if(priv-&gt;mlfi_helofrom)
+ free(priv-&gt;mlfi_helofrom);
+ free(priv);
+ <a href="smfi_setpriv.html">smfi_setpriv</a>(ctx, NULL);
+ return SMFIS_CONTINUE;
+}
+
+struct smfiDesc smfilter =
+{
+ "SampleFilter", /* filter name */
+ SMFI_VERSION, /* version code -- do not change */
+ SMFIF_ADDHDRS, /* flags */
+ <a href="xxfi_connect.html">mlfi_connect</a>, /* connection info filter */
+ <a href="xxfi_helo.html">mlfi_helo</a>, /* SMTP HELO command filter */
+ <a href="xxfi_envfrom.html">mlfi_envfrom</a>, /* envelope sender filter */
+ <a href="xxfi_envrcpt.html">mlfi_envrcpt</a>, /* envelope recipient filter */
+ <a href="xxfi_header.html">mlfi_header</a>, /* header filter */
+ <a href="xxfi_eoh.html">mlfi_eoh</a>, /* end of header */
+ <a href="xxfi_body.html">mlfi_body</a>, /* body block filter */
+ <a href="xxfi_eom.html">mlfi_eom</a>, /* end of message */
+ <a href="xxfi_abort.html">mlfi_abort</a>, /* message aborted */
+ <a href="xxfi_close.html">mlfi_close</a>, /* connection cleanup */
+};
+
+static void
+usage()
+{
+ fprintf(stderr,
+ "Usage: sample [-p socket-addr] [-t timeout] [-r reject-addr] \n\
+\t[-a accept-addr]\n");
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int retval;
+ char c;
+ const char *args = "p:t:r:a:h";
+ extern char *optarg;
+
+ /* Process command line options */
+ while ((c = getopt(argc, argv, args)) != (char)EOF)
+ {
+ switch (c)
+ {
+ case 'p':
+ if (optarg == NULL || *optarg == '\0')
+ {
+ (void) fprintf(stderr, "Illegal conn: %s\n",
+ optarg);
+ exit(EX_USAGE);
+ }
+ if(<a href="smfi_setconn.html">smfi_setconn</a>(optarg) == MI_FAILURE)
+ {
+ (void) fputs("smfi_setconn failed", stderr);
+ exit(EX_SOFTWARE);
+ }
+ /*
+ ** If we're using a local socket, make sure it doesn't
+ ** already exist.
+ */
+ if(strncmp(optarg, "unix:", 5) == 0)
+ unlink(optarg + 5);
+ else if(strncmp(optarg, "local:", 6) == 0)
+ unlink(optarg + 6);
+ break;
+
+ case 't':
+ if (optarg == NULL || *optarg == '\0')
+ {
+ (void) fprintf(stderr, "Illegal timeout: %s\n",
+ optarg);
+ exit(EX_USAGE);
+ }
+ if(<a href="smfi_settimeout.html">smfi_settimeout</a>(atoi(optarg)) == MI_FAILURE)
+ {
+ (void) fputs("smfi_settimeout failed", stderr);
+ exit(EX_SOFTWARE);
+ }
+ break;
+
+ case 'r':
+ if (optarg == NULL)
+ {
+ (void) fprintf(stderr, "Illegal reject rcpt: %s\n",
+ optarg);
+ exit(EX_USAGE);
+ }
+ reject = optarg;
+ break;
+
+ case 'a':
+ if (optarg == NULL)
+ {
+ (void) fprintf(stderr, "Illegal add rcpt: %s\n",
+ optarg);
+ exit(EX_USAGE);
+ }
+ add = optarg;
+ smfilter.xxfi_flags |= SMFIF_ADDRCPT;
+ break;
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ }
+ }
+ if (<a href="smfi_register.html">smfi_register</a>(smfilter) == MI_FAILURE)
+ {
+ fprintf(stderr, "smfi_register failed\n");
+ exit(EX_UNAVAILABLE);
+ }
+ retval = <a href="smfi_main.html">smfi_main</a>();
+ return retval;
+}
+
+/* eof */
+
+</pre>
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_addheader.html b/contrib/sendmail/libmilter/docs/smfi_addheader.html
new file mode 100644
index 0000000..c6417e2
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_addheader.html
@@ -0,0 +1,94 @@
+<html>
+<head><title>smfi_addheader</title></head>
+<body>
+<h1>smfi_addheader</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_addheader(
+ SMFICTX *ctx,
+ char *headerf,
+ char *headerv
+);
+</pre>
+Add a header to the current message.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>Called only from <a href="xxfi_eom.html">xxfi_eom</a>.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>Adds a header to the current message.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>headerf</td>
+ <td>The header name, a non-NULL, null-terminated string.
+ </td></tr>
+ <tr valign="top"><td>headerv</td>
+ <td>The header value to be added, a non-NULL, null-terminated string. This may be the empty string.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_addheader returns MI_FAILURE if:
+<ul><li>headerf or headerv is NULL.
+ <li>Adding headers in the current connection state is invalid.
+ <li>Memory allocation fails.
+ <li>A network error occurs.
+ <li>SMFIF_ADDHDRS was not set when <a href="smfi_register.html">smfi_register</a> was called.
+</ul>
+Otherwise, it returns MI_SUCCESS.
+</td>
+</tr>
+
+<!----------- Notes ---------->
+<tr align="left" valign=top>
+<th>NOTES</th>
+<td>
+<ul><li>smfi_addheader does not change a message's existing headers.
+To change a header's current value, use <a
+href="smfi_chgheader.html">smfi_chgheader</a>.
+ <li>A filter which calls smfi_addheader must have set the SMFIF_ADDHDRS flag in the smfiDesc_str passed to <a href="smfi_register.html">smfi_register</a>.
+ <li>For smfi_chgheader, filter order is important. <b>Later filters will see the header changes made by earlier ones.</b>
+ <li>Neither the name nor the value of the header is checked for
+ standards compliance. However, each line of the header must be under
+ 2048 characters and should be under 998 characters. If longer headers
+ are needed, make them multiline.
+ <b>It is the filter writer's responsibility to ensure that no standards
+ are violated.</b>
+</ul>
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_addrcpt.html b/contrib/sendmail/libmilter/docs/smfi_addrcpt.html
new file mode 100644
index 0000000..d0a5963
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_addrcpt.html
@@ -0,0 +1,80 @@
+<html>
+<head><title>smfi_addrcpt</title></head>
+<body>
+<h1>smfi_addrcpt</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_addrcpt(
+ SMFICTX *ctx,
+ char *rcpt
+);
+</pre>
+Add a recipient for the current message.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>Called only from <a href="xxfi_eom.html">xxfi_eom</a>.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>Add a recipient to the message envelope.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>rcpt</td>
+ <td>The new recipient's address.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_addrcpt will fail and return MI_FAILURE if:
+<ul><li>rcpt is NULL.
+ <li>Adding headers in the current connection state is invalid.
+ <li>A network error occurs.
+ <li>SMFIF_ADDRCPT was not set when <a href="smfi_register.html">smfi_register</a> was called.
+</ul>
+Otherwise, it will return MI_SUCCESS.
+</td>
+</tr>
+
+<!----------- Notes ---------->
+<tr align="left" valign=top>
+<th>NOTES</th>
+<td>
+A filter which calls smfi_addrcpt must have set the SMFIF_ADDRCPT flag
+in the smfiDesc_str passed to
+<a href="smfi_register.html">smfi_register</a>.
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_chgheader.html b/contrib/sendmail/libmilter/docs/smfi_chgheader.html
new file mode 100644
index 0000000..4969674
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_chgheader.html
@@ -0,0 +1,96 @@
+<html>
+<head><title>smfi_chgheader</title></head>
+<body>
+<h1>smfi_chgheader</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_chgheader(
+ SMFICTX *ctx,
+ char *headerf,
+ mi_int32 hdridx,
+ char *headerv
+);
+</pre>
+Change or delete a message header.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>Called only from <a href="xxfi_eom.html">xxfi_eom</a>.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>Changes a header's value for the current message.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>headerf</td>
+ <td>The header name, a non-NULL, null-terminated string.
+ </td></tr>
+ <tr valign="top"><td>hdridx</td>
+ <td>Header index value (1-based). A hdridx value of 1 will modify the first occurrence of a header named headerf. If hdridx is greater than the number of times headerf appears, a new copy of headerf will be added.
+ </td></tr>
+ <tr valign="top"><td>headerv</td>
+ <td>The new value of the given header. headerv == NULL implies that the header should be deleted.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>
+smfi_chgheader will return MI_FAILURE if
+<ul><li>headerf is NULL
+ <li>Modifying headers in the current connection state is invalid.
+ <li>Memory allocation fails.
+ <li>A network error occurs.
+ <li>SMFIF_CHGHDRS was not set when <a href="smfi_register.html">smfi_register</a> was called.
+</ul>
+Otherwise, it returns MI_SUCCESS.
+</tr>
+
+<!----------- Notes ---------->
+<tr align="left" valign=top>
+<th>NOTES</th>
+<td>
+<ul><li>While smfi_chgheader may be used to add new headers, it is more efficient and far safer to use <a href="smfi_addheader.html">smfi_addheader</a>.
+ <li>A filter which calls smfi_chgheader must have set the SMFIF_CHGHDRS flag in the smfiDesc_str passed to <a href="smfi_register.html">smfi_register</a>.
+ <li>For smfi_chgheader, filter order is important. <b>Later filters will see the header changes made by earlier ones.</b>
+ <li>Neither the name nor the value of the header is checked for
+ standards compliance. However, each line of the header must be under
+ 2048 characters and should be under 998 characters. If longer headers
+ are needed, make them multiline.
+ <b>It is the filter writer's responsibility to ensure that no standards
+ are violated.</b>
+</ul>
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_delrcpt.html b/contrib/sendmail/libmilter/docs/smfi_delrcpt.html
new file mode 100644
index 0000000..f86fd2e
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_delrcpt.html
@@ -0,0 +1,79 @@
+<html>
+<head><title>smfi_delrcpt</title></head>
+<body>
+<h1>smfi_delrcpt</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_delrcpt(
+ SMFICTX *ctx;
+ char *rcpt;
+);
+</pre>
+Remove a recipient from the current message's envelope.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>Called only from <a href="xxfi_eom.html">xxfi_eom</a>.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>smfi_delrcpt removes the named recipient from the current message's envelope.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>rcpt</td>
+ <td>The recipient address to be removed, a non-NULL, null-terminated string.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_delrcpt will fail and return MI_FAILURE if:
+<ul>
+ <li>rcpt is NULL.
+ <li>Adding headers in the current connection state is invalid.
+ <li>A network error occurs.
+ <li>SMFIF_DELRCPT was not set when <a href="smfi_register.html">smfi_register</a> was called.
+</ul>
+Otherwise, it will return MI_SUCCESS
+</td>
+</tr>
+
+<!----------- Notes ---------->
+<tr align="left" valign=top>
+<th>NOTES</th>
+<td>
+The addresses to be removed must match exactly. For example, an address and its expanded form do not match.
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_getpriv.html b/contrib/sendmail/libmilter/docs/smfi_getpriv.html
new file mode 100644
index 0000000..8bb6efa
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_getpriv.html
@@ -0,0 +1,59 @@
+<html>
+<head><title>smfi_getpriv</title></head>
+<body>
+<h1>smfi_getpriv</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+void* smfi_getpriv(
+ SMFICTX *ctx
+);
+</pre>
+Get the connection-specific data pointer for this connection.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>smfi_getpriv may be called in any of the xxfi_* callbacks.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>None.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_getpriv returns the private data pointer stored by a prior call to <a href="smfi_setpriv.html">smfi_setpriv</a>, or NULL if none has been set.</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_getsymval.html b/contrib/sendmail/libmilter/docs/smfi_getsymval.html
new file mode 100644
index 0000000..d8a3304
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_getsymval.html
@@ -0,0 +1,92 @@
+<html>
+<head><title>smfi_getsymval</title></head>
+<body>
+<h1>smfi_getsymval</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+char* smfi_getsymval(
+ SMFICTX *ctx,
+ char *symname
+);
+</pre>
+Get the value of a sendmail macro.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>smfi_getsymval may be called from within any of the xxfi_* callbacks. Which macros are defined will depend on when it is called.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>None.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>The opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>symname</td>
+ <td>The name of a sendmail macro, optinally enclosed in braces ("{" and "}"). <a href="#notes">See below</a> for default macros.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_getsymval returns the value of the given macro as a null-terminated string, or NULL if the macro is not defined.</td>
+</tr>
+
+<!----------- Notes ---------->
+<tr align="left" valign=top>
+<th><a name="notes">NOTES</A></th>
+<td>
+By default, the following macros are valid in the given contexts:
+
+<table border="1" cellspacing=0>
+<tr bgcolor="#dddddd"><th>Sent With</th><th>Macros</th></tr>
+<tr><td>xxfi_connect</td> <td>daemon_name, if_name, if_addr, j, _</td></tr>
+<tr><td>xxfi_helo</td> <td>tls_version, cipher, cipher_bits, cert_subject, cert_issuer</td></tr>
+<tr><td>xxfi_envfrom</td> <td>i, auth_type, auth_authen, auth_ssf, auth_author,
+ mail_mailer, mail_host, mail_addr</td></tr>
+<tr><td>xxfi_envrcpt</td> <td>rcpt_mailer, rcpt_host, rcpt_addr</td></tr>
+</table>
+<p>
+All macros stay in effect from the point they are received until the
+end of the connection for the first two sets, the end of the message
+for the third (xxfi_envfrom), and just for each recipient for the
+final set (xxfi_envrcpt).
+<p>
+The macro list can be changed using the confMILTER_MACROS_* options in
+sendmail.mc. The scopes of such macros will be determined by when
+they are set by sendmail. For descriptions of macros' values, please
+see the "Sendmail Installation and Operation Guide" provided with your
+sendmail distribution.
+
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_main.html b/contrib/sendmail/libmilter/docs/smfi_main.html
new file mode 100644
index 0000000..9652eaa
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_main.html
@@ -0,0 +1,48 @@
+<html>
+<head><title>smfi_main</title></head>
+<body>
+<h1>smfi_main</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_main(
+);
+</pre>
+Hand control to libmilter event loop.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>smfi_main is called after a filter's initialization is complete.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>smfi_main hands control to the Milter event loop.</td>
+</tr>
+</table>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_main will return MI_FAILURE if it fails to establish a connection. This may occur for any of a variety of reasons (e.g. invalid address passed to <a href="smfi_setconn.html">smfi_setconn</a>). The reason for the failure will be logged. Otherwise, smfi_main will return MI_SUCCESS.</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_register.html b/contrib/sendmail/libmilter/docs/smfi_register.html
new file mode 100644
index 0000000..705b3a4
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_register.html
@@ -0,0 +1,160 @@
+<html>
+<head><title>smfi_register</title></head>
+<body>
+<h1>smfi_register</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_register(
+ smfiDesc_str descr
+);
+</pre>
+Register a set of filter callbacks.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=1>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>smfi_register must be called before smfi_main</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>smfi_register creates a filter using the information given in the
+smfiDesc_str argument. Multiple calls to smfi_register within a
+single process are not allowed.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>descr</td>
+ <td>
+A filter descriptor of type smfiDesc_str describing the filter's
+functions. The structure has the following members:
+<pre>
+struct smfiDesc
+{
+ char *xxfi_name; /* filter name */
+ int xxfi_version; /* version code -- do not change */
+ unsigned long xxfi_flags; /* <a href="#flags">flags</a> */
+
+ /* connection info filter */
+ sfsistat (*<a href="xxfi_connect.html">xxfi_connect</a>)(SMFICTX *, char *, _SOCK_ADDR *);
+ /* SMTP HELO command filter */
+ sfsistat (*<a href="xxfi_helo.html">xxfi_helo</a>)(SMFICTX *, char *);
+ /* envelope sender filter */
+ sfsistat (*<a href="xxfi_envfrom.html">xxfi_envfrom</a>)(SMFICTX *, char **);
+ /* envelope recipient filter */
+ sfsistat (*<a href="xxfi_envrcpt.html">xxfi_envrcpt</a>)(SMFICTX *, char **);
+ /* header filter */
+ sfsistat (*<a href="xxfi_header.html">xxfi_header</a>)(SMFICTX *, char *, char *);
+ /* end of header */
+ sfsistat (*<a href="xxfi_eoh.html">xxfi_eoh</a>)(SMFICTX *);
+ /* body block */
+ sfsistat (*<a href="xxfi_body.html">xxfi_body</a>)(SMFICTX *, unsigned char *, size_t);
+ /* end of message */
+ sfsistat (*<a href="xxfi_eom.html">xxfi_eom</a>)(SMFICTX *);
+ /* message aborted */
+ sfsistat (*<a href="xxfi_abort.html">xxfi_abort</a>)(SMFICTX *);
+ /* connection cleanup */
+ sfsistat (*<a href="xxfi_close.html">xxfi_close</a>)(SMFICTX *);
+};
+</pre>
+
+A NULL value for any callback function indicates that the filter does
+not wish to process the given type of information, simply returning
+SMFIS_CONTINUE.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>
+smfi_register may return MI_FAILURE for any of the following reasons:
+<ul>
+<li>memory allocation failed.
+<li>incompatible version or illegal flags value.
+</ul>
+
+</td>
+</tr>
+
+<!----------- Notes ---------->
+<tr align="left" valign=top>
+<th>NOTES</th>
+<td>
+
+<a name="flags"></A>
+The xxfi_flags field should contain the bitwise OR of zero or more of
+the following values, describing the actions the filter may take:
+<TABLE BORDER CELLPADDING="1" cellspacing=1>
+<tr valign="top" bgcolor="#dddddd"><th align="left">Flag</th><th align="center">Description</th></tr>
+ <TR align="left" valign=top>
+ <TD>
+ SMFIF_ADDHDRS
+ </TD>
+ <TD>
+ This filter may add headers.
+ </TD>
+ </TR>
+ <TR align="left" valign=top>
+ <TD>
+ SMFIF_CHGHDRS
+ </TD>
+ <TD>
+ This filter may change and/or delete headers.
+ </TD>
+ </TR>
+ <TR align="left" valign=top>
+ <TD VALIGN="TOP">
+ SMFIF_CHGBODY
+ </TD>
+ <TD>
+ This filter may replace the body during filtering.
+ This may have significant performance impact
+ if other filters do body filtering after this filter.
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN="TOP">
+ SMFIF_ADDRCPT
+ </TD>
+ <TD>
+ This filter may add recipients to the message.
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN="TOP">
+ SMFIF_DELRCPT
+ </TD>
+ <TD>
+ This filter may remove recipients from the message.
+ </TD>
+ </TR>
+</TABLE>
+
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_replacebody.html b/contrib/sendmail/libmilter/docs/smfi_replacebody.html
new file mode 100644
index 0000000..204c2dc
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_replacebody.html
@@ -0,0 +1,90 @@
+<html>
+<head><title>smfi_replacebody</title></head>
+<body>
+<h1>smfi_replacebody</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_replacebody(
+ SMFICTX *ctx,
+ unsigned char *bodyp,
+ int bodylen
+);
+</pre>
+Replace message-body data.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>Called only from <a href="xxfi_eom.html">xxfi_eom</a>. smfi_replacebody may be called more than once.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>smfi_replacebody replaces the body of the current message. If called
+more than once, subsequent calls result in data being appended to the new
+body.
+</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>bodyp</td>
+ <td>A pointer to the start of the new body data, which does not have to be null-terminated. If bodyp is NULL, it is treated as having length == 0. Body data should be in CR/LF form.
+ </td></tr>
+ <tr valign="top"><td>bodylen</td>
+ <td>The number of data bytes pointed to by bodyp.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_replacebody fails and returns MI_FAILURE if:
+<ul>
+ <li>bodyp == NULL and bodylen &gt; 0.
+ <li>Changing the body in the current connection state is invalid.
+ <li>A network error occurs.
+ <li>SMFIF_CHGBODY was not set when <a href="smfi_register.html">smfi_register</a> was called.
+</ul>
+Otherwise, it will return MI_SUCCESS.
+</td>
+</tr>
+
+<!----------- Notes ---------->
+<tr align="left" valign=top>
+<th>NOTES</th>
+<td>
+<ul>
+ <li>Since the message body may be very large, setting SMFIF_CHGBODY may significantly affect filter performance.
+ <li>If a filter sets SMFIF_CHGBODY but does not call smfi_replacebody, the original body remains unchanged.
+ <li>For smfi_replacebody, filter order is important. <b>Later filters will see the new body contents created by earlier ones.</b>
+</ul>
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_setconn.html b/contrib/sendmail/libmilter/docs/smfi_setconn.html
new file mode 100644
index 0000000..0d46a5b
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_setconn.html
@@ -0,0 +1,77 @@
+<html>
+<head><title>smfi_setconn</title></head>
+<body>
+<h1>smfi_setconn</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_setconn(
+ char *oconn;
+);
+</pre>
+Set the socket through which this filter should communicate with sendmail.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>smfi_setconn must be called once before <a href="smfi_main.html">smfi_main</a>.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>Sets the socket through which the filter communicates with sendmail.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>oconn</td>
+ <td>The address of the desired communication socket.
+ The address should be a NULL-terminated string in "proto:address"
+ format:
+ <ul>
+ <li><code>{unix|local}:/path/to/file</code> -- A named pipe.
+ <li><code>inet:port@{hostname|ip-address}</code> -- An IPV4 socket.
+ <li><code>inet6:port@{hostname|ip-address}</code> -- An IPV6 socket.
+ </ul>
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_setconn will not fail on an invalid address. The failure will
+only be detected in <a href="smfi_main.html">smfi_main</a></td>
+</tr>
+
+<tr>
+<th valign="top" align=left>NOTES</th>
+
+<td>
+<ul><li>If possible, filters should not run as root when communicating over unix/local domain sockets.
+ <li>Unix/local sockets should have their permissions set to 0600 (read/write permission only for the socket's owner).
+</ul>
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_setpriv.html b/contrib/sendmail/libmilter/docs/smfi_setpriv.html
new file mode 100644
index 0000000..e800cc8
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_setpriv.html
@@ -0,0 +1,77 @@
+<html>
+<head><title>smfi_setpriv</title></head>
+<body>
+<h1>smfi_setpriv</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_setpriv(
+ SMFICTX *ctx,
+ void *privatedata
+);
+</pre>
+Set the private data pointer for this connection.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>smfi_setpriv may be called in any of the xxfi_* callbacks.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>Sets the private data pointer for the context ctx.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>privatedata</td>
+ <td>Pointer to private data. This value will be returned by subsequent calls to <a href="smfi_getpriv.html">smfi_getpriv</a> using ctx.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_setpriv returns MI_FAILURE if ctx is an invalid context.
+Otherwise, it returns MI_SUCCESS.</td>
+</tr>
+
+<tr>
+<th valign="top" align=left>NOTES</th>
+
+<td>There is only one private data pointer per connection; multiple
+calls to smfi_setpriv with different values will cause previous values
+to be lost.
+<P>
+Before a filter terminates it should release the private data
+and set the pointer to NULL.
+</td>
+
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_setreply.html b/contrib/sendmail/libmilter/docs/smfi_setreply.html
new file mode 100644
index 0000000..962f167
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_setreply.html
@@ -0,0 +1,92 @@
+<html>
+<head><title>smfi_setreply</title></head>
+<body>
+<h1>smfi_setreply</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_setreply(
+ SMFICTX *ctx,
+ char *rcode,
+ char *xcode,
+ char *message
+);
+</pre>
+Set the default SMTP error reply code.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>smfi_setreply may be called from any of the xxfi_ callbacks.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>Directly set the SMTP error reply code for this connection. This code
+will be used on subsequent error replies resulting from actions taken by
+this filter.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>rcode</td>
+ <td>The three-digit (RFC 821) SMTP reply code, as a null-terminated string. rcode cannot be NULL, and must be a valid reply code.
+ </td></tr>
+ <tr valign="top"><td>xcode</td>
+ <td>The extended (RFC 2034) reply code. If xcode is NULL, no extended code is used. Otherwise, xcode must conform to RFC 2034.
+ </td></tr>
+ <tr valign="top"><td>message</td>
+ <td>The text part of the SMTP reply. If message is NULL, an empty message is used.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_setreply will fail and return MI_FAILURE if:
+<ul>
+ <li>The rcode or xcode argument is invalid.
+ <li>A memory-allocation failure occurs.
+</ul>
+Otherwise, it return MI_SUCCESS.
+</td>
+</tr>
+
+<!----------- Notes ---------->
+<tr align="left" valign=top>
+<th>NOTES</th>
+<td>
+<ul>
+<li>Values passed to smfi_setreply are not checked for standards compliance.
+<li>For details about reply codes and their meanings, please see RFC's
+<a href="http://www.cis.ohio-state.edu/htbin/rfc/rfc821.html">821</a>
+and <a href="http://www.cis.ohio-state.edu/htbin/rfc/rfc2034.html">2034</a>.
+</ul>
+</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/smfi_settimeout.html b/contrib/sendmail/libmilter/docs/smfi_settimeout.html
new file mode 100644
index 0000000..a9e870a
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/smfi_settimeout.html
@@ -0,0 +1,60 @@
+<html>
+<head><title>smfi_settimeout</title></head>
+<body>
+<h1>smfi_settimeout</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+int smfi_settimeout(
+ int otimeout
+);
+</pre>
+Set the filter's connection timeout value.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>smfi_settimeout should only be called before <a href="smfi_main.html">smfi_main</a>.</td>
+</tr>
+<tr align="left" valign=top>
+<th width="80">Effects</th>
+<td>Sets the number of seconds libmilter will wait for an MTA connection before timing out a socket. If smfi_settimeout is not called, a default timeout of 1800 seconds is used.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>otimeout</td>
+ <td>The number of seconds to wait before timing out (&gt; 0). Zero means
+no wait, <b>not</b> "wait forever".
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>RETURN VALUES</th>
+
+<td>smfi_settimeout always returns MI_SUCCESS.</td>
+</tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_abort.html b/contrib/sendmail/libmilter/docs/xxfi_abort.html
new file mode 100644
index 0000000..aeddf6f
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_abort.html
@@ -0,0 +1,80 @@
+<html>
+<head><title>xxfi_abort</title></head>
+<body>
+<h1>xxfi_abort</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_abort)(
+ SMFICTX * ctx
+);
+</pre>
+Handle the current message's being aborted.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>xxfi_abort may be called at any time during message processing (i.e. between some message-oriented routine and <a href="xxfi_eom.html">xxfi_eom</a>).</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Notes ---------->
+<tr>
+<th valign="top" align=left>NOTES</th>
+<td>
+<ul>
+<li>xxfi_abort must reclaim any resources allocated on a per-message
+basis, and must be tolerant of being called between any two
+message-oriented callbacks.
+
+<li>Calls to xxfi_abort and <a href="xxfi_eom.html">xxfi_eom</a> are
+mutually exclusive.
+
+<li>xxfi_abort is not responsible for reclaiming connection-specific
+data, since <a href="xxfi_close.html">xxfi_close</a> is always called
+when a connection is closed.
+
+<li>Since the current message is already being aborted, the return
+value is currently ignored.
+
+<li>xxfi_abort is only called if the message is aborted outside the
+filter's control <b>and</b> the filter has not completed its
+message-oriented processing. For example, if a filter has already
+returned SMFIS_ACCEPT, SMFIS_REJECT, or SMFIS_DISCARD from a
+message-oriented routine, xxfi_abort will not be called even if the
+message is later aborted outside its control.
+</ul>
+</td>
+</tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_body.html b/contrib/sendmail/libmilter/docs/xxfi_body.html
new file mode 100644
index 0000000..b19e0d4
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_body.html
@@ -0,0 +1,80 @@
+<html>
+<head><title>xxfi_body</title></head>
+<body>
+<h1>xxfi_body</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_body)(
+ SMFICTX * ctx,
+ unsigned char * bodyp,
+ size_t len
+);
+</pre>
+Handle a piece of a message's body.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>xxfi_body is called zero or more times between xxfi_eoh and xxfi_eom.</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>bodyp</td>
+ <td>Pointer to the start of this block of body data. bodyp is not valid outside this call to xxfi_body.
+ </td></tr>
+ <tr valign="top"><td>len</td>
+ <td>The amount of data pointed to by bodyp.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Notes ---------->
+<tr>
+<th valign="top" align=left>NOTES</th>
+<td>
+<ul>
+<li>bodyp points to a sequence of bytes.
+It is <em>not</em> a C string (a sequence of characters that is terminated by '\0').
+Therefore, do not use the usual C string functions like strlen() on this byte block.
+Moreover, the byte sequence may contain '\0' characters inside the block.
+Hence even if a trailing '\0' is added, C string functions may still fail
+to work as expected.
+<li>Since message bodies can be very large, defining xxfi_body can
+significantly impact filter performance.
+<li>End-of-lines are represented as received from SMTP (normally CR/LF).
+<li>Later filters will see body changes made by earlier ones.
+<li>Message bodies may be sent in multiple chunks, with one call to
+ xxfi_body per chunk.
+</ul>
+</td>
+</tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2002 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_close.html b/contrib/sendmail/libmilter/docs/xxfi_close.html
new file mode 100644
index 0000000..07742be
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_close.html
@@ -0,0 +1,66 @@
+<html>
+<head><title>xxfi_close</title></head>
+<body>
+<h1>xxfi_close</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_close)(
+ SMFICTX * ctx
+);
+</pre>
+The current connection is being closed.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>xxfi_close is always called once at the end of each connection.</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Notes ---------->
+<tr>
+<th valign="top" align=left>NOTES</th>
+<td>
+<ul>
+<li>xxfi_close is called on close even if the previous mail
+transaction was aborted.
+<li>xxfi_close is responsible for freeing any resources allocated on a
+per-connection basis.
+<li>Since the connection is already closing, the return value is
+currently ignored.
+</ul>
+</td>
+</tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_connect.html b/contrib/sendmail/libmilter/docs/xxfi_connect.html
new file mode 100644
index 0000000..1710285
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_connect.html
@@ -0,0 +1,90 @@
+<html>
+<head><title>xxfi_connect</title></head>
+<body>
+<h1>xxfi_connect</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_connect)(
+ SMFICTX *ctx,
+ char *hostname,
+ _SOCK_ADDR *hostaddr);
+</pre>
+</td></tr>
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr>
+<th valign="top" align=left width=80>Called When</th>
+<td>Once, at the start of each SMTP connection.</td>
+</tr>
+<tr>
+<th valign="top" align=left width=80>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+<!--
+This callback function is invoked on each connection to the mail
+filter program. The callback is to be implemented by the Milter
+application developers. The name of the callback can be any valid
+function name. The function pointer is to be assigned to the
+smfiDesc.xxfi_connect and the pointer to the smfiDesc structure
+is passed to smfi_register().
+</td></tr>
+-->
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr><td>ctx</td>
+ <td>the opaque context structure.
+ </td></tr>
+ <tr><td>hostname</td>
+ <td>the host name of the message sender, as determined by a
+ reverse lookup on the host address. If the reverse lookup
+ fails, hostname will contain the message sender's IP
+ address enclosed in square brackets (e.g. `[a.b.c.d]').
+ </td></tr>
+ <tr><td>hostaddr</td>
+ <td>the host address, as determined by a getpeername() call on the SMTP socket.
+ NULL if the type is not supported in the current version or if
+ the SMTP connection is made via stdin.
+ </td></tr>
+ </table>
+</td></tr>
+<!----------- Return values ---------->
+<!--
+<tr>
+<th valign="top" align=left>SPECIAL RETURN VALUES</th>
+<td><table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Return value</th><th>Description</th></tr>
+ <tr valign="top">
+ <td>SMFIS_DISCARD</td>
+ <td>Not meaningful, as
+ this is only meaningful from message-oriented routines.
+ </td>
+ </tr>
+</table>
+</tr>
+-->
+<!----------- Notes ---------->
+<tr>
+<th valign="top" align=left>NOTES</th>
+<td>If an earlier filter rejects the connection in its xxfi_connect()
+routine, this filter's xxfi_connect() will not be called.</td>
+</tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_envfrom.html b/contrib/sendmail/libmilter/docs/xxfi_envfrom.html
new file mode 100644
index 0000000..d023c40
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_envfrom.html
@@ -0,0 +1,92 @@
+<html>
+<head><title>xxfi_envfrom</title></head>
+<body>
+<h1>xxfi_envfrom</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_envfrom)(
+ SMFICTX * ctx,
+ char ** argv
+);
+</pre>
+Handle the envelope FROM command.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>xxfi_envfrom is called once at the beginning of each message, before xxfi_envrcpt.</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>argv</td>
+ <td>Null-terminated SMTP command arguments;
+ argv[0] is guaranteed to be the sender address.
+ Later arguments are the ESMTP arguments.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>SPECIAL RETURN VALUES</th>
+<td><table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Return value</th><th>Description</th></tr>
+ <tr valign="top">
+ <td>SMFIS_TEMPFAIL</td>
+ <td>Reject this sender and message with a temporary error; a new sender (and hence a new message) may subsequently be specified. <a href="xxfi_abort.html">xxfi_abort</a> is not called.
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_REJECT</td>
+ <td>Reject this sender and message; a new sender/message may be specified. <a href="xxfi_abort.html">xxfi_abort</a> is not called.
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_DISCARD</td>
+ <td>Accept and silently discard this message. <a href="xxfi_abort.html">xxfi_abort</a> is not called.
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_ACCEPT</td>
+ <td>Accept this message. <a href="xxfi_abort.html">xxfi_abort</a> is not called.
+ </td>
+ </tr>
+</table>
+</tr>
+
+<!----------- Notes ---------->
+<tr>
+<th valign="top" align=left>NOTES</th>
+<td>For more details on ESTMP responses, please see RFC
+<a href="http://www.cis.ohio-state.edu/rfc/rfc1869.txt">1869</a>.</td>
+</tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html b/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html
new file mode 100644
index 0000000..f13626a
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html
@@ -0,0 +1,94 @@
+<html>
+<head><title>xxfi_envrcpt</title></head>
+<body>
+<h1>xxfi_envrcpt</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_envrcpt)(
+ SMFICTX * ctx,
+ char ** argv
+);
+</pre>
+Handle the envelope RCPT command.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>xxfi_envrcpt is called once per recipient, hence one or more times per message, immediately after xxfi_envfrom.</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>argv</td>
+ <td>Null-terminated SMTP command arguments;
+ argv[0] is guaranteed to be the recipient address.
+ Later arguments are the ESMTP arguments.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Return values ---------->
+<tr>
+<th valign="top" align=left>SPECIAL RETURN VALUES</th>
+<td><table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Return value</th><th>Description</th></tr>
+ <tr valign="top">
+ <td>SMFIS_TEMPFAIL</td>
+ <td>Temporarily fail for this particular recipient; further recipients
+ maystill be sent. <a href="xxfi_abort.html">xxfi_abort</a> is not called.
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_REJECT</td>
+ <td>Reject this particular recipient; further recipients maystill be sent.
+ <a href="xxfi_abort.html">xxfi_abort</a> is not called.
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_DISCARD</td>
+ <td>Accept and discard the message. <a href="xxfi_abort.html">xxfi_abort</a> will be called.
+ </td>
+ </tr>
+ <tr valign="top">
+ <td>SMFIS_ACCEPT</td>
+ <td>Accept recipient. <a href="xxfi_abort.html">xxfi_abort</a> will not be called.
+ </td>
+ </tr>
+</table>
+</tr>
+
+<!----------- Notes ---------->
+<tr>
+<th valign="top" align=left>NOTES</th>
+<td>For more details on ESTMP responses, please see RFC
+<a href="http://www.cis.ohio-state.edu/rfc/rfc1869.txt">1869</a>.</td>
+</tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_eoh.html b/contrib/sendmail/libmilter/docs/xxfi_eoh.html
new file mode 100644
index 0000000..46c7925
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_eoh.html
@@ -0,0 +1,53 @@
+<html>
+<head><title>xxfi_eoh</title></head>
+<body>
+<h1>xxfi_eoh</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_eoh)(
+ SMFICTX * ctx
+);
+</pre>
+Handle the end of message headers.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>xxfi_eoh is called once after all headers have been sent and processed.
+</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ </table>
+</td></tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_eom.html b/contrib/sendmail/libmilter/docs/xxfi_eom.html
new file mode 100644
index 0000000..40f6dee
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_eom.html
@@ -0,0 +1,58 @@
+<html>
+<head><title>xxfi_eom</title></head>
+<body>
+<h1>xxfi_eom</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_eom)(
+ SMFICTX * ctx
+);
+</pre>
+End of a message.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>xxfi_eom is called once after all calls to <a href="xxfi_body.html">xxfi_body</a> for a given message.</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Notes ---------->
+<tr>
+<th valign="top" align=left>NOTES</th>
+<td>A filter is required to make all its modifications to the message headers, body, and envelope in xxfi_eom. Modifications are made via the smfi_* routines.
+</td>
+</tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_header.html b/contrib/sendmail/libmilter/docs/xxfi_header.html
new file mode 100644
index 0000000..a6c6322
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_header.html
@@ -0,0 +1,74 @@
+<html>
+<head><title>xxfi_header</title></head>
+<body>
+<h1>xxfi_header</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_header)(
+ SMFICTX * ctx,
+ char * headerf,
+ char * headerv
+);
+</pre>
+Handle a message header.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th>
+<td>xxfi_header is called zero or more times between xxfi_envrcpt and xxfi_eoh, once per message header.</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>headerf</td>
+ <td> Header field name.
+ </td></tr>
+ <tr valign="top"><td>headerv</td>
+ <td>Header field value. The
+ content of the header may include folded white space (i.e. multiple
+ lines with following white space). The trailing line terminator (CR/LF)
+ is removed.
+ </td></tr>
+ </table>
+</td></tr>
+
+<!----------- Notes ---------->
+<tr>
+<th valign="top" align=left>NOTES</th>
+<td>
+<ul>
+<li>Later filters will see header changes/additions made by earlier ones.
+<li>For much more detail about header format, please see
+RFC <a href="http://www.cis.ohio-state.edu/htbin/rfc/rfc822.html">822</a>
+</ul>
+</td>
+</tr>
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/docs/xxfi_helo.html b/contrib/sendmail/libmilter/docs/xxfi_helo.html
new file mode 100644
index 0000000..b1aa9e9
--- /dev/null
+++ b/contrib/sendmail/libmilter/docs/xxfi_helo.html
@@ -0,0 +1,59 @@
+<html>
+<head><title>xxfi_helo</title></head>
+<body>
+<h1>xxfi_helo</h1>
+
+<table border="0" cellspacing=4 cellpadding=4>
+<!---------- Synopsis ----------->
+<tr><th valign="top" align=left width=150>SYNOPSIS</th><td>
+<pre>
+#include &lt;libmilter/mfapi.h&gt;
+sfsistat (*xxfi_helo)(
+ SMFICTX * ctx,
+ char * helohost
+);
+</pre>
+Handle the HELO/EHLO command.
+</td></tr>
+
+<!----------- Description ---------->
+<tr><th valign="top" align=left>DESCRIPTION</th><td>
+<table border="1" cellspacing=1 cellpadding=4>
+<tr align="left" valign=top>
+<th width="80">Called When</th> <td>xxfi_helo is called whenever the client
+sends a HELO/EHLO command. It may therefore be called between zero and
+three times</td>
+</tr>
+<tr align="left" valign=top>
+<th>Default Behavior</th>
+<td>Do nothing; return SMFIS_CONTINUE.</td>
+</tr>
+</table>
+
+<!----------- Arguments ---------->
+<tr><th valign="top" align=left>ARGUMENTS</th><td>
+ <table border="1" cellspacing=0>
+ <tr bgcolor="#dddddd"><th>Argument</th><th>Description</th></tr>
+ <tr valign="top"><td>ctx</td>
+ <td>Opaque context structure.
+ </td></tr>
+ <tr valign="top"><td>helohost</td>
+ <td>Value passed to HELO/EHLO command, which should be
+ the domain name of the sending host (but is, in practice,
+ anything the sending host wants to send).
+ </td></tr>
+ </table>
+</td></tr>
+
+</table>
+
+<hr size="1">
+<font size="-1">
+Copyright (c) 2000 Sendmail, Inc. and its suppliers.
+All rights reserved.
+<br>
+By using this file, you agree to the terms and conditions set
+forth in the <a href="LICENSE.txt">LICENSE</a>.
+</font>
+</body>
+</html>
diff --git a/contrib/sendmail/libmilter/engine.c b/contrib/sendmail/libmilter/engine.c
index 0fd48eb..aabfe6c 100644
--- a/contrib/sendmail/libmilter/engine.c
+++ b/contrib/sendmail/libmilter/engine.c
@@ -8,13 +8,10 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: engine.c,v 8.67.4.17 2001/01/22 19:00:16 gshapiro Exp $";
-#endif /* ! lint */
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: engine.c,v 8.102 2001/12/13 17:10:00 ca Exp $")
-#if _FFR_MILTER
#include "libmilter.h"
-#include "sendmail/useful.h"
#if NETINET || NETINET6
# include <arpa/inet.h>
@@ -118,13 +115,16 @@ static int dec_arg2 __P((char *, size_t, char **, char **));
** is set in the NX_* value
** this function is coded in trans_ok(), see below.
*/
+
#define MASK(x) (0x0001 << (x)) /* generate a bit "mask" for a state */
#define NX_INIT (MASK(ST_OPTS))
#define NX_OPTS (MASK(ST_CONN))
#define NX_CONN (MASK(ST_HELO) | MASK(ST_MAIL))
#define NX_HELO (MASK(ST_HELO) | MASK(ST_MAIL))
#define NX_MAIL (MASK(ST_RCPT) | MASK(ST_ABRT))
-#define NX_RCPT (MASK(ST_HDRS) | MASK(ST_EOHS) | MASK(ST_RCPT) | MASK(ST_ABRT))
+#define NX_RCPT (MASK(ST_HDRS) | MASK(ST_EOHS) | \
+ MASK(ST_BODY) | MASK(ST_ENDM) | \
+ MASK(ST_RCPT) | MASK(ST_ABRT))
#define NX_HDRS (MASK(ST_EOHS) | MASK(ST_HDRS) | MASK(ST_ABRT))
#define NX_EOHS (MASK(ST_BODY) | MASK(ST_ENDM) | MASK(ST_ABRT))
#define NX_BODY (MASK(ST_ENDM) | MASK(ST_BODY) | MASK(ST_ABRT))
@@ -172,8 +172,9 @@ static cmdfct cmds[] =
#define _SMFIS_OPTIONS 22
#define _SMFIS_NOREPLY 23
#define _SMFIS_FAIL (-1)
+#define _SMFIS_NONE (-2)
- /*
+/*
** MI_ENGINE -- receive commands and process them
**
** Parameters:
@@ -208,6 +209,7 @@ mi_engine(ctx)
fi_abort = ctx->ctx_smfi->xxfi_abort;
mi_clr_macros(ctx, 0);
fix_stm(ctx);
+ r = _SMFIS_NONE;
do
{
/* call abort only if in a mail transaction */
@@ -217,17 +219,29 @@ mi_engine(ctx)
if (mi_stop() == MILTER_ABRT)
{
if (ctx->ctx_dbg > 3)
- dprintf("[%d] milter_abort\n",
+ sm_dprintf("[%d] milter_abort\n",
(int) ctx->ctx_id);
ret = MI_FAILURE;
break;
}
+
+ /*
+ ** Notice: buf is allocated by mi_rd_cmd() and it will
+ ** usually be free()d after it has been used in f().
+ ** However, if the function returns _SMFIS_KEEP then buf
+ ** contains macros and will not be free()d.
+ ** Hence r must be set to _SMFIS_NONE if a new buf is
+ ** allocated to avoid problem with housekeeping, esp.
+ ** if the code "break"s out of the loop.
+ */
+
+ r = _SMFIS_NONE;
if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len,
ctx->ctx_smfi->xxfi_name)) == NULL &&
cmd < SMFIC_VALIDCMD)
{
if (ctx->ctx_dbg > 5)
- dprintf("[%d] mi_engine: mi_rd_cmd error (%x)\n",
+ sm_dprintf("[%d] mi_engine: mi_rd_cmd error (%x)\n",
(int) ctx->ctx_id, (int) cmd);
/*
@@ -240,7 +254,7 @@ mi_engine(ctx)
break;
}
if (ctx->ctx_dbg > 4)
- dprintf("[%d] got cmd '%c' len %d\n",
+ sm_dprintf("[%d] got cmd '%c' len %d\n",
(int) ctx->ctx_id, cmd, len);
for (i = 0; i < ncmds; i++)
{
@@ -251,7 +265,7 @@ mi_engine(ctx)
{
/* unknown command */
if (ctx->ctx_dbg > 1)
- dprintf("[%d] cmd '%c' unknown\n",
+ sm_dprintf("[%d] cmd '%c' unknown\n",
(int) ctx->ctx_id, cmd);
ret = MI_FAILURE;
break;
@@ -260,7 +274,7 @@ mi_engine(ctx)
{
/* stop for now */
if (ctx->ctx_dbg > 1)
- dprintf("[%d] cmd '%c' not impl\n",
+ sm_dprintf("[%d] cmd '%c' not impl\n",
(int) ctx->ctx_id, cmd);
ret = MI_FAILURE;
break;
@@ -269,14 +283,14 @@ mi_engine(ctx)
/* is new state ok? */
newstate = cmds[i].cm_next;
if (ctx->ctx_dbg > 5)
- dprintf("[%d] cur %x new %x nextmask %x\n",
+ sm_dprintf("[%d] cur %x new %x nextmask %x\n",
(int) ctx->ctx_id,
curstate, newstate, next_states[curstate]);
if (newstate != ST_NONE && !trans_ok(curstate, newstate))
{
if (ctx->ctx_dbg > 1)
- dprintf("[%d] abort: cur %d (%x) new %d (%x) next %x\n",
+ sm_dprintf("[%d] abort: cur %d (%x) new %d (%x) next %x\n",
(int) ctx->ctx_id,
curstate, MASK(curstate),
newstate, MASK(newstate),
@@ -293,7 +307,11 @@ mi_engine(ctx)
curstate = ST_HELO;
if (!trans_ok(curstate, newstate))
+ {
+ free(buf);
+ buf = NULL;
continue;
+ }
}
arg.a_len = len;
arg.a_buf = buf;
@@ -337,7 +355,7 @@ mi_engine(ctx)
else if (r == _SMFIS_ABORT)
{
if (ctx->ctx_dbg > 5)
- dprintf("[%d] function returned abort\n",
+ sm_dprintf("[%d] function returned abort\n",
(int) ctx->ctx_id);
ret = MI_FAILURE;
break;
@@ -354,12 +372,12 @@ mi_engine(ctx)
/* close must always be called */
if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL)
(void) (*fi_close)(ctx);
- if (buf != NULL)
+ if (r != _SMFIS_KEEP && buf != NULL)
free(buf);
mi_clr_macros(ctx, 0);
return ret;
}
- /*
+/*
** SENDREPLY -- send a reply to the MTA
**
** Parameters:
@@ -462,7 +480,7 @@ mi_clr_macros(ctx, m)
}
}
}
- /*
+/*
** ST_OPTIONNEG -- negotiate options
**
** Parameters:
@@ -543,7 +561,7 @@ st_optionneg(g)
return _SMFIS_OPTIONS;
}
- /*
+/*
** ST_CONNECTINFO -- receive connection information
**
** Parameters:
@@ -560,7 +578,7 @@ st_connectinfo(g)
size_t l;
size_t i;
char *s, family;
- u_short port = 0;
+ unsigned short port = 0;
_SOCK_ADDR sockaddr;
sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *));
@@ -617,11 +635,11 @@ st_connectinfo(g)
# if NETINET6
if (family == SMFIA_INET6)
{
- if (inet_pton(AF_INET6, s + i,
- &sockaddr.sin6.sin6_addr) != 1)
+ if (mi_inet_pton(AF_INET6, s + i,
+ &sockaddr.sin6.sin6_addr) != 1)
{
smi_log(SMI_LOG_ERR,
- "%s: connect[%d]: inet_pton failed",
+ "%s: connect[%d]: mi_inet_pton failed",
g->a_ctx->ctx_smfi->xxfi_name,
(int) g->a_ctx->ctx_id);
return _SMFIS_ABORT;
@@ -635,7 +653,7 @@ st_connectinfo(g)
# if NETUNIX
if (family == SMFIA_UNIX)
{
- if (strlcpy(sockaddr.sunix.sun_path, s + i,
+ if (sm_strlcpy(sockaddr.sunix.sun_path, s + i,
sizeof sockaddr.sunix.sun_path) >=
sizeof sockaddr.sunix.sun_path)
{
@@ -660,7 +678,7 @@ st_connectinfo(g)
return (*fi_connect)(g->a_ctx, g->a_buf,
family != SMFIA_UNKNOWN ? &sockaddr : NULL);
}
- /*
+/*
** ST_EOH -- end of headers
**
** Parameters:
@@ -683,7 +701,7 @@ st_eoh(g)
return (*fi_eoh)(g->a_ctx);
return SMFIS_CONTINUE;
}
- /*
+/*
** ST_HELO -- helo/ehlo command
**
** Parameters:
@@ -706,7 +724,7 @@ st_helo(g)
return (*fi_helo)(g->a_ctx, g->a_buf);
return SMFIS_CONTINUE;
}
- /*
+/*
** ST_HEADER -- header line
**
** Parameters:
@@ -734,24 +752,24 @@ st_header(g)
return _SMFIS_ABORT;
}
-#define ARGV_FCT(lf, rf, idx) \
- char **argv; \
- sfsistat (*lf) __P((SMFICTX *, char **)); \
- int r; \
- \
- if (g == NULL) \
- return _SMFIS_ABORT; \
- mi_clr_macros(g->a_ctx, g->a_idx + 1); \
- if (g->a_ctx->ctx_smfi == NULL || \
- (lf = g->a_ctx->ctx_smfi->rf) == NULL) \
- return SMFIS_CONTINUE; \
+#define ARGV_FCT(lf, rf, idx) \
+ char **argv; \
+ sfsistat (*lf) __P((SMFICTX *, char **)); \
+ int r; \
+ \
+ if (g == NULL) \
+ return _SMFIS_ABORT; \
+ mi_clr_macros(g->a_ctx, g->a_idx + 1); \
+ if (g->a_ctx->ctx_smfi == NULL || \
+ (lf = g->a_ctx->ctx_smfi->rf) == NULL) \
+ return SMFIS_CONTINUE; \
if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL) \
- return _SMFIS_ABORT; \
- r = (*lf)(g->a_ctx, argv); \
- free(argv); \
+ return _SMFIS_ABORT; \
+ r = (*lf)(g->a_ctx, argv); \
+ free(argv); \
return r;
- /*
+/*
** ST_SENDER -- MAIL FROM command
**
** Parameters:
@@ -767,7 +785,7 @@ st_sender(g)
{
ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL)
}
- /*
+/*
** ST_RCPT -- RCPT TO command
**
** Parameters:
@@ -783,7 +801,7 @@ st_rcpt(g)
{
ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT)
}
- /*
+/*
** ST_MACROS -- deal with macros received from the MTA
**
** Parameters:
@@ -833,7 +851,7 @@ st_macros(g)
g->a_ctx->ctx_mac_buf[i] = g->a_buf;
return _SMFIS_KEEP;
}
- /*
+/*
** ST_QUIT -- quit command
**
** Parameters:
@@ -849,7 +867,7 @@ st_quit(g)
{
return _SMFIS_NOREPLY;
}
- /*
+/*
** ST_BODYCHUNK -- deal with a piece of the mail body
**
** Parameters:
@@ -863,16 +881,17 @@ static int
st_bodychunk(g)
genarg *g;
{
- sfsistat (*fi_body) __P((SMFICTX *, u_char *, size_t));
+ sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t));
if (g == NULL)
return _SMFIS_ABORT;
if (g->a_ctx->ctx_smfi != NULL &&
(fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL)
- return (*fi_body)(g->a_ctx, (u_char *)g->a_buf, g->a_len);
+ return (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf,
+ g->a_len);
return SMFIS_CONTINUE;
}
- /*
+/*
** ST_BODYEND -- deal with the last piece of the mail body
**
** Parameters:
@@ -890,7 +909,7 @@ st_bodyend(g)
genarg *g;
{
sfsistat r;
- sfsistat (*fi_body) __P((SMFICTX *, u_char *, size_t));
+ sfsistat (*fi_body) __P((SMFICTX *, unsigned char *, size_t));
sfsistat (*fi_eom) __P((SMFICTX *));
if (g == NULL)
@@ -907,7 +926,8 @@ st_bodyend(g)
timeout.tv_sec = g->a_ctx->ctx_timeout;
timeout.tv_usec = 0;
sd = g->a_ctx->ctx_sd;
- r = (*fi_body)(g->a_ctx, (u_char *)g->a_buf, g->a_len);
+ r = (*fi_body)(g->a_ctx, (unsigned char *)g->a_buf,
+ g->a_len);
if (r != SMFIS_CONTINUE &&
sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS)
return _SMFIS_ABORT;
@@ -918,7 +938,7 @@ st_bodyend(g)
return (*fi_eom)(g->a_ctx);
return r;
}
- /*
+/*
** ST_ABORTFCT -- deal with aborts
**
** Parameters:
@@ -941,7 +961,7 @@ st_abortfct(g)
(void) (*fi_abort)(g->a_ctx);
return _SMFIS_NOREPLY;
}
- /*
+/*
** TRANS_OK -- is the state transition ok?
**
** Parameters:
@@ -963,13 +983,14 @@ trans_ok(old, new)
{
/* is this state transition allowed? */
if ((MASK(new) & next_states[s]) != 0)
- return TRUE;
+ return true;
/*
** no: try next state;
** this works since the relevant states are ordered
** strict sequentially
*/
+
n = s + 1;
/*
@@ -977,14 +998,15 @@ trans_ok(old, new)
** see fix_stm() which sets this bit for those
** states which the filter program is not interested in
*/
+
if (bitset(NX_SKIP, next_states[n]))
s = n;
else
- return FALSE;
+ return false;
} while (s <= ST_LAST);
- return FALSE;
+ return false;
}
- /*
+/*
** FIX_STM -- add "skip" bits to the state transition table
**
** Parameters:
@@ -1001,7 +1023,7 @@ static void
fix_stm(ctx)
SMFICTX_PTR ctx;
{
- u_long fl;
+ unsigned long fl;
if (ctx == NULL || ctx->ctx_smfi == NULL)
return;
@@ -1021,7 +1043,7 @@ fix_stm(ctx)
if (bitset(SMFIP_NOBODY, fl))
next_states[ST_BODY] |= NX_SKIP;
}
- /*
+/*
** DEC_ARGV -- split a buffer into a list of strings, NULL terminated
**
** Parameters:
@@ -1065,7 +1087,7 @@ dec_argv(buf, len)
s[elem] = NULL;
return s;
}
- /*
+/*
** DEC_ARG2 -- split a buffer into two strings
**
** Parameters:
@@ -1094,7 +1116,7 @@ dec_arg2(buf, len, s1, s2)
*s2 = buf + i + 1;
return MI_SUCCESS;
}
- /*
+/*
** SENDOK -- is it ok for the filter to send stuff to the MTA?
**
** Parameters:
@@ -1111,9 +1133,12 @@ mi_sendok(ctx, flag)
int flag;
{
if (ctx == NULL || ctx->ctx_smfi == NULL)
- return FALSE;
+ return false;
+
+ /* did the milter request this operation? */
if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags))
- return FALSE;
+ return false;
+
+ /* are we in the correct state? It must be "End of Message". */
return ctx->ctx_state == ST_ENDM;
}
-#endif /* _FFR_MILTER */
diff --git a/contrib/sendmail/libmilter/handler.c b/contrib/sendmail/libmilter/handler.c
index 2ee5203..29ea446 100644
--- a/contrib/sendmail/libmilter/handler.c
+++ b/contrib/sendmail/libmilter/handler.c
@@ -8,11 +8,9 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: handler.c,v 8.19.4.3 2000/12/29 19:45:39 gshapiro Exp $";
-#endif /* ! lint */
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: handler.c,v 8.29 2001/11/15 00:17:15 msk Exp $")
-#if _FFR_MILTER
#include "libmilter.h"
@@ -45,7 +43,7 @@ mi_handle_session(ctx)
ret = mi_engine(ctx);
if (ValidSocket(ctx->ctx_sd))
{
- (void) close(ctx->ctx_sd);
+ (void) closesocket(ctx->ctx_sd);
ctx->ctx_sd = INVALID_SOCKET;
}
if (ctx->ctx_reply != NULL)
@@ -64,4 +62,3 @@ mi_handle_session(ctx)
ctx = NULL;
return ret;
}
-#endif /* _FFR_MILTER */
diff --git a/contrib/sendmail/libmilter/libmilter.h b/contrib/sendmail/libmilter/libmilter.h
index 49ac70f..d135aab 100644
--- a/contrib/sendmail/libmilter/libmilter.h
+++ b/contrib/sendmail/libmilter/libmilter.h
@@ -13,12 +13,13 @@
#ifndef _LIBMILTER_H
# define _LIBMILTER_H 1
+
+#include <sm/gen.h>
+
#ifdef _DEFINE
# define EXTERN
# define INIT(x) = x
-# ifndef lint
-static char MilterlId[] = "@(#)$Id: libmilter.h,v 8.3.6.16 2001/06/07 23:21:35 geir Exp $";
-# endif /* ! lint */
+SM_IDSTR(MilterlId, "@(#)$Id: libmilter.h,v 8.32 2001/11/29 02:21:02 ca Exp $")
#else /* _DEFINE */
# define EXTERN extern
# define INIT(x)
@@ -31,15 +32,12 @@ static char MilterlId[] = "@(#)$Id: libmilter.h,v 8.3.6.16 2001/06/07 23:21:35 g
#include "libmilter/milter.h"
-#ifndef __P
-# include "sendmail/cdefs.h"
-#endif /* ! __P */
-#include "sendmail/useful.h"
-
# define ValidSocket(sd) ((sd) >= 0)
-# define INVALID_SOCKET -1
-# define MI_SOCK_READ(s, b, l) (read(s, b, l))
-# define MI_SOCK_WRITE(s, b, l) (write(s, b, l))
+# define INVALID_SOCKET (-1)
+# define closesocket close
+# define MI_SOCK_READ(s, b, l) read(s, b, l)
+# define MI_SOCK_READ_FAIL(x) ((x) < 0)
+# define MI_SOCK_WRITE(s, b, l) write(s, b, l)
# define thread_create(ptid,wr,arg) pthread_create(ptid, NULL, wr, arg)
# define sthread_get_id() pthread_self()
@@ -61,16 +59,19 @@ typedef pthread_mutex_t smutex_t;
#define MI_TIMEOUT 7210 /* default timeout for read/write */
#define MI_CHK_TIME 5 /* checking whether to terminate */
-#if SOMAXCONN > 20
-# define MI_SOMAXCONN SOMAXCONN
-#else /* SOMAXCONN */
-# define MI_SOMAXCONN 20
-#endif /* SOMAXCONN */
+#ifndef MI_SOMAXCONN
+# if SOMAXCONN > 20
+# define MI_SOMAXCONN SOMAXCONN
+# else /* SOMAXCONN */
+# define MI_SOMAXCONN 20
+# endif /* SOMAXCONN */
+#endif /* ! MI_SOMAXCONN */
/* maximum number of repeated failures in mi_listener() */
#define MAX_FAILS_M 16 /* malloc() */
#define MAX_FAILS_T 16 /* thread creation */
#define MAX_FAILS_A 16 /* accept() */
+#define MAX_FAILS_S 16 /* select() */
/* internal "commands", i.e., error codes */
#define SMFIC_TIMEOUT ((char) 1) /* timeout */
@@ -84,6 +85,7 @@ typedef pthread_mutex_t smutex_t;
/* hack */
#define smi_log syslog
+#define sm_dprintf printf
#define milter_ret int
#define SMI_LOG_ERR LOG_ERR
#define SMI_LOG_FATAL LOG_ERR
@@ -106,6 +108,7 @@ extern int mi_control_startup __P((char *));
extern void mi_stop_milters __P((int));
extern void mi_clean_signals __P((void));
extern struct hostent *mi_gethostbyname __P((char *, int));
+extern int mi_inet_pton __P((int, const char *, void *));
extern void mi_closener __P((void));
/* communication functions */
@@ -113,4 +116,5 @@ extern char *mi_rd_cmd __P((socket_t, struct timeval *, char *, size_t *, char *
extern int mi_wr_cmd __P((socket_t, struct timeval *, int, char *, size_t));
extern bool mi_sendok __P((SMFICTX_PTR, int));
+
#endif /* !_LIBMILTER_H */
diff --git a/contrib/sendmail/libmilter/listener.c b/contrib/sendmail/libmilter/listener.c
index 6a59955..9b75ce0 100644
--- a/contrib/sendmail/libmilter/listener.c
+++ b/contrib/sendmail/libmilter/listener.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2002 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -8,22 +8,24 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: listener.c,v 8.38.2.1.2.22 2001/05/16 17:15:58 ca Exp $";
-#endif /* ! lint */
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: listener.c,v 8.81 2002/01/08 23:14:23 ca Exp $")
-#if _FFR_MILTER
/*
** listener.c -- threaded network listener
*/
#include "libmilter.h"
+#include <sm/errstring.h>
# if NETINET || NETINET6
# include <arpa/inet.h>
# endif /* NETINET || NETINET6 */
- /*
+
+static smutex_t L_Mutex;
+
+/*
** MI_MILTEROPEN -- setup socket to listen on
**
** Parameters:
@@ -35,8 +37,15 @@ static char id[] = "@(#)$Id: listener.c,v 8.38.2.1.2.22 2001/05/16 17:15:58 ca E
**
** Returns:
** socket upon success, error code otherwise.
+**
+** Side effect:
+** sets sockpath if UNIX socket.
*/
+#if NETUNIX
+static char *sockpath = NULL;
+#endif /* NETUNIX */
+
static socket_t
mi_milteropen(conn, backlog, socksize, family, name)
char *conn;
@@ -47,6 +56,7 @@ mi_milteropen(conn, backlog, socksize, family, name)
{
socket_t sock;
int sockopt = 1;
+ size_t len = 0;
char *p;
char *colon;
char *at;
@@ -157,15 +167,16 @@ mi_milteropen(conn, backlog, socksize, family, name)
# endif /* 0 */
at = colon;
- if (strlcpy(addr.sunix.sun_path, colon,
- sizeof addr.sunix.sun_path) >=
- sizeof addr.sunix.sun_path)
+ len = strlen(colon) + 1;
+ if (len >= sizeof addr.sunix.sun_path)
{
errno = EINVAL;
smi_log(SMI_LOG_ERR, "%s: UNIX socket name %s too long",
name, colon);
return INVALID_SOCKET;
}
+ (void) sm_strlcpy(addr.sunix.sun_path, colon,
+ sizeof addr.sunix.sun_path);
# if 0
errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff,
S_IRUSR|S_IWUSR, NULL);
@@ -179,7 +190,6 @@ mi_milteropen(conn, backlog, socksize, family, name)
return INVALID_SOCKET;
}
# endif /* 0 */
-
}
#endif /* NETUNIX */
@@ -196,7 +206,7 @@ mi_milteropen(conn, backlog, socksize, family, name)
# endif /* NETINET6 */
)
{
- u_short port;
+ unsigned short port;
/* Parse port@host */
at = strchr(colon, '@');
@@ -221,7 +231,7 @@ mi_milteropen(conn, backlog, socksize, family, name)
*at = '\0';
if (isascii(*colon) && isdigit(*colon))
- port = htons((u_short) atoi(colon));
+ port = htons((unsigned short) atoi(colon));
else
{
# ifdef NO_GETSERVBYNAME
@@ -252,7 +262,7 @@ mi_milteropen(conn, backlog, socksize, family, name)
end = strchr(at, ']');
if (end != NULL)
{
- bool found = FALSE;
+ bool found = false;
# if NETINET
unsigned long hid = INADDR_NONE;
# endif /* NETINET */
@@ -263,23 +273,22 @@ mi_milteropen(conn, backlog, socksize, family, name)
*end = '\0';
# if NETINET
if (addr.sa.sa_family == AF_INET &&
- (hid = inet_addr(&at[1])) !=
- INADDR_NONE)
+ (hid = inet_addr(&at[1])) != INADDR_NONE)
{
addr.sin.sin_addr.s_addr = hid;
addr.sin.sin_port = port;
- found = TRUE;
+ found = true;
}
# endif /* NETINET */
# if NETINET6
(void) memset(&hid6, '\0', sizeof hid6);
if (addr.sa.sa_family == AF_INET6 &&
- inet_pton(AF_INET6, &at[1],
- &hid6.sin6_addr) == 1)
+ mi_inet_pton(AF_INET6, &at[1],
+ &hid6.sin6_addr) == 1)
{
addr.sin6.sin6_addr = hid6.sin6_addr;
addr.sin6.sin6_port = port;
- found = TRUE;
+ found = true;
}
# endif /* NETINET6 */
*end = ']';
@@ -338,9 +347,9 @@ mi_milteropen(conn, backlog, socksize, family, name)
name, at, hp->h_addrtype);
return INVALID_SOCKET;
}
-# if _FFR_FREEHOSTENT && NETINET6
+# if NETINET6
freehostent(hp);
-# endif /* _FFR_FREEHOSTENT && NETINET6 */
+# endif /* NETINET6 */
}
}
else
@@ -367,7 +376,7 @@ mi_milteropen(conn, backlog, socksize, family, name)
{
smi_log(SMI_LOG_ERR,
"%s: Unable to create new socket: %s",
- name, strerror(errno));
+ name, sm_errstring(errno));
return INVALID_SOCKET;
}
@@ -375,8 +384,9 @@ mi_milteropen(conn, backlog, socksize, family, name)
sizeof(sockopt)) == -1)
{
smi_log(SMI_LOG_ERR,
- "%s: Unable to setsockopt: %s", name, strerror(errno));
- (void) close(sock);
+ "%s: Unable to setsockopt: %s", name,
+ sm_errstring(errno));
+ (void) closesocket(sock);
return INVALID_SOCKET;
}
@@ -384,22 +394,45 @@ mi_milteropen(conn, backlog, socksize, family, name)
{
smi_log(SMI_LOG_ERR,
"%s: Unable to bind to port %s: %s",
- name, conn, strerror(errno));
- (void) close(sock);
+ name, conn, sm_errstring(errno));
+ (void) closesocket(sock);
return INVALID_SOCKET;
}
if (listen(sock, backlog) < 0)
{
smi_log(SMI_LOG_ERR,
- "%s: listen call failed: %s", name, strerror(errno));
- (void) close(sock);
+ "%s: listen call failed: %s", name,
+ sm_errstring(errno));
+ (void) closesocket(sock);
return INVALID_SOCKET;
}
+
+#if NETUNIX
+ if (addr.sa.sa_family == AF_UNIX && len > 0)
+ {
+ /*
+ ** Set global variable sockpath so the UNIX socket can be
+ ** unlink()ed at exit.
+ */
+
+ sockpath = (char *) malloc(len);
+ if (sockpath != NULL)
+ (void) sm_strlcpy(sockpath, colon, len);
+ else
+ {
+ smi_log(SMI_LOG_ERR,
+ "%s: can't malloc(%d) for sockpath: %s",
+ name, len, sm_errstring(errno));
+ (void) closesocket(sock);
+ return INVALID_SOCKET;
+ }
+ }
+#endif /* NETUNIX */
*family = addr.sa.sa_family;
return sock;
}
- /*
+/*
** MI_THREAD_HANDLE_WRAPPER -- small wrapper to handle session
**
** Parameters:
@@ -418,11 +451,12 @@ mi_thread_handle_wrapper(arg)
static socket_t listenfd = INVALID_SOCKET;
-static smutex_t L_Mutex;
-
- /*
+/*
** MI_CLOSENER -- close listen socket
**
+** NOTE: It is assumed that this function is called from a
+** function that has a mutex lock (currently mi_stop_milters()).
+**
** Parameters:
** none.
**
@@ -436,13 +470,54 @@ mi_closener()
(void) smutex_lock(&L_Mutex);
if (ValidSocket(listenfd))
{
- (void) close(listenfd);
+#if NETUNIX
+ bool removable;
+ struct stat sockinfo;
+ struct stat fileinfo;
+
+ removable = sockpath != NULL &&
+#if _FFR_MILTER_ROOT_UNSAFE
+ geteuid() != 0 &&
+#endif /* _FFR_MILTER_ROOT_UNSAFE */
+ fstat(listenfd, &sockinfo) == 0 &&
+ (S_ISFIFO(sockinfo.st_mode)
+# ifdef S_ISSOCK
+ || S_ISSOCK(sockinfo.st_mode)
+# endif /* S_ISSOCK */
+ );
+#endif /* NETUNIX */
+
+ (void) closesocket(listenfd);
listenfd = INVALID_SOCKET;
+
+#if NETUNIX
+ /* XXX sleep() some time before doing this? */
+ if (sockpath != NULL)
+ {
+ if (removable &&
+ stat(sockpath, &fileinfo) == 0 &&
+ ((fileinfo.st_dev == sockinfo.st_dev &&
+ fileinfo.st_ino == sockinfo.st_ino)
+# ifdef S_ISSOCK
+ || S_ISSOCK(fileinfo.st_mode)
+# endif /* S_ISSOCK */
+ )
+ &&
+ (S_ISFIFO(fileinfo.st_mode)
+# ifdef S_ISSOCK
+ || S_ISSOCK(fileinfo.st_mode)
+# endif /* S_ISSOCK */
+ ))
+ (void) unlink(sockpath);
+ free(sockpath);
+ sockpath = NULL;
+ }
+#endif /* NETUNIX */
}
(void) smutex_unlock(&L_Mutex);
}
- /*
+/*
** MI_LISTENER -- Generic listener harness
**
** Open up listen port
@@ -460,7 +535,7 @@ mi_closener()
** MI_FAILURE -- Network initialization failed.
*/
-# if BROKEN_PTHREAD_SLEEP
+#if BROKEN_PTHREAD_SLEEP
/*
** Solaris 2.6, perhaps others, gets an internal threads library panic
@@ -480,7 +555,7 @@ mi_closener()
** 0
*/
-# define MI_SLEEP(s) \
+# define MI_SLEEP(s) \
{ \
int rs = 0; \
struct timeval st; \
@@ -496,9 +571,9 @@ mi_closener()
rs, errno); \
} \
}
-# else /* BROKEN_PTHREAD_SLEEP */
-# define MI_SLEEP(s) sleep((s))
-# endif /* BROKEN_PTHREAD_SLEEP */
+#else /* BROKEN_PTHREAD_SLEEP */
+# define MI_SLEEP(s) sleep((s))
+#endif /* BROKEN_PTHREAD_SLEEP */
int
mi_listener(conn, dbg, smfi, timeout, backlog)
@@ -513,9 +588,10 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
int sockopt = 1;
int r;
int ret = MI_SUCCESS;
- int mcnt = 0;
- int tcnt = 0;
- int acnt = 0;
+ int mcnt = 0; /* error count for malloc() failures */
+ int tcnt = 0; /* error count for thread_create() failures */
+ int acnt = 0; /* error count for accept() failures */
+ int scnt = 0; /* error count for select() failures */
int save_errno = 0;
sthread_t thread_id;
_SOCK_ADDR cliaddr;
@@ -564,8 +640,8 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
/* select on interface ports */
FD_ZERO(&readset);
FD_ZERO(&excset);
- FD_SET((u_int) listenfd, &readset);
- FD_SET((u_int) listenfd, &excset);
+ FD_SET((unsigned int) listenfd, &readset);
+ FD_SET((unsigned int) listenfd, &excset);
chktime.tv_sec = MI_CHK_TIME;
chktime.tv_usec = 0;
r = select(listenfd + 1, &readset, NULL, &excset, &chktime);
@@ -580,16 +656,30 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
(void) smutex_unlock(&L_Mutex);
if (save_errno == EINTR)
continue;
- ret = MI_FAILURE;
- break;
+ scnt++;
+ smi_log(SMI_LOG_ERR,
+ "%s: select() failed (%s), %s",
+ smfi->xxfi_name, sm_errstring(save_errno),
+ scnt >= MAX_FAILS_S ? "abort" : "try again");
+ MI_SLEEP(scnt);
+ if (scnt >= MAX_FAILS_S)
+ {
+ ret = MI_FAILURE;
+ break;
+ }
+ continue;
}
if (!FD_ISSET(listenfd, &readset))
{
/* some error: just stop for now... */
ret = MI_FAILURE;
(void) smutex_unlock(&L_Mutex);
+ smi_log(SMI_LOG_ERR,
+ "%s: select() returned exception for socket, abort",
+ smfi->xxfi_name);
break;
}
+ scnt = 0; /* reset error counter for select() */
memset(&cliaddr, '\0', sizeof cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr,
@@ -610,19 +700,20 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
# endif /* BSD4_4_SOCKADDR */
cliaddr.sa.sa_family != family))
{
- (void) close(connfd);
+ (void) closesocket(connfd);
connfd = INVALID_SOCKET;
save_errno = EINVAL;
}
if (!ValidSocket(connfd))
{
- smi_log(SMI_LOG_ERR,
- "%s: accept() returned invalid socket (%s)",
- smfi->xxfi_name, strerror(save_errno));
if (save_errno == EINTR)
continue;
acnt++;
+ smi_log(SMI_LOG_ERR,
+ "%s: accept() returned invalid socket (%s), %s",
+ smfi->xxfi_name, sm_errstring(save_errno),
+ acnt >= MAX_FAILS_A ? "abort" : "try again");
MI_SLEEP(acnt);
if (acnt >= MAX_FAILS_A)
{
@@ -631,20 +722,22 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
}
continue;
}
+ acnt = 0; /* reset error counter for accept() */
if (setsockopt(connfd, SOL_SOCKET, SO_KEEPALIVE,
(void *) &sockopt, sizeof sockopt) < 0)
{
- smi_log(SMI_LOG_WARN, "%s: setsockopt() failed",
- smfi->xxfi_name);
+ smi_log(SMI_LOG_WARN, "%s: setsockopt() failed (%s)",
+ smfi->xxfi_name, sm_errstring(errno));
/* XXX: continue? */
}
if ((ctx = (SMFICTX_PTR) malloc(sizeof *ctx)) == NULL)
{
- (void) close(connfd);
- smi_log(SMI_LOG_ERR, "%s: malloc(ctx) failed",
- smfi->xxfi_name);
+ (void) closesocket(connfd);
mcnt++;
+ smi_log(SMI_LOG_ERR, "%s: malloc(ctx) failed (%s), %s",
+ smfi->xxfi_name, sm_errstring(save_errno),
+ mcnt >= MAX_FAILS_M ? "abort" : "try again");
MI_SLEEP(mcnt);
if (mcnt >= MAX_FAILS_M)
{
@@ -653,8 +746,7 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
}
continue;
}
- mcnt = 0;
- acnt = 0;
+ mcnt = 0; /* reset error counter for malloc() */
memset(ctx, '\0', sizeof *ctx);
ctx->ctx_sd = connfd;
ctx->ctx_dbg = dbg;
@@ -685,12 +777,13 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
mi_thread_handle_wrapper,
(void *) ctx)) != 0)
{
- smi_log(SMI_LOG_ERR,
- "%s: thread_create() failed: %d",
- smfi->xxfi_name, r);
tcnt++;
+ smi_log(SMI_LOG_ERR,
+ "%s: thread_create() failed: %d, %s",
+ smfi->xxfi_name, r,
+ tcnt >= MAX_FAILS_T ? "abort" : "try again");
MI_SLEEP(tcnt);
- (void) close(connfd);
+ (void) closesocket(connfd);
free(ctx);
if (tcnt >= MAX_FAILS_T)
{
@@ -708,4 +801,3 @@ mi_listener(conn, dbg, smfi, timeout, backlog)
(void) smutex_destroy(&L_Mutex);
return ret;
}
-#endif /* _FFR_MILTER */
diff --git a/contrib/sendmail/libmilter/main.c b/contrib/sendmail/libmilter/main.c
index 6afebdb..ee440e3 100644
--- a/contrib/sendmail/libmilter/main.c
+++ b/contrib/sendmail/libmilter/main.c
@@ -8,11 +8,9 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: main.c,v 8.34.4.11 2001/05/07 22:06:37 gshapiro Exp $";
-#endif /* ! lint */
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: main.c,v 8.53 2001/11/29 02:21:02 ca Exp $")
-#if _FFR_MILTER
#define _DEFINE 1
#include "libmilter.h"
#include <fcntl.h>
@@ -51,7 +49,7 @@ smfi_register(smfilter)
smfi->xxfi_name = (char *) malloc(len);
if (smfi->xxfi_name == NULL)
return MI_FAILURE;
- (void) strlcpy(smfi->xxfi_name, smfilter.xxfi_name, len);
+ (void) sm_strlcpy(smfi->xxfi_name, smfilter.xxfi_name, len);
/* compare milter version with hard coded version */
if (smfi->xxfi_version != SMFI_VERSION)
@@ -61,13 +59,16 @@ smfi_register(smfilter)
"%s: smfi_register: version mismatch application: %d != milter: %d",
smfi->xxfi_name, smfi->xxfi_version,
(int) SMFI_VERSION);
+
+ /* XXX how about smfi? */
+ free(smfi->xxfi_name);
return MI_FAILURE;
}
return MI_SUCCESS;
}
- /*
+/*
** SMFI_STOP -- stop milter
**
** Parameters:
@@ -84,11 +85,26 @@ smfi_stop()
return MI_SUCCESS;
}
+/*
+** default values for some variables.
+** Most of these can be changed with the functions below.
+*/
+
static int dbg = 0;
static char *conn = NULL;
static int timeout = MI_TIMEOUT;
static int backlog= MI_SOMAXCONN;
+/*
+** SMFI_SETDBG -- set debug level.
+**
+** Parameters:
+** odbg -- new debug level.
+**
+** Returns:
+** MI_SUCCESS
+*/
+
int
smfi_setdbg(odbg)
int odbg;
@@ -97,6 +113,16 @@ smfi_setdbg(odbg)
return MI_SUCCESS;
}
+/*
+** SMFI_SETTIMEOUT -- set timeout (for read/write).
+**
+** Parameters:
+** otimeout -- new timeout.
+**
+** Returns:
+** MI_SUCCESS
+*/
+
int
smfi_settimeout(otimeout)
int otimeout;
@@ -105,6 +131,16 @@ smfi_settimeout(otimeout)
return MI_SUCCESS;
}
+/*
+** SMFI_SETCONN -- set connection information (socket description)
+**
+** Parameters:
+** oconn -- new connection information.
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
int
smfi_setconn(oconn)
char *oconn;
@@ -116,11 +152,21 @@ smfi_setconn(oconn)
l = strlen(oconn) + 1;
if ((conn = (char *) malloc(l)) == NULL)
return MI_FAILURE;
- if (strlcpy(conn, oconn, l) >= l)
+ if (sm_strlcpy(conn, oconn, l) >= l)
return MI_FAILURE;
return MI_SUCCESS;
}
+/*
+** SMFI_SETBACKLOG -- set backlog
+**
+** Parameters:
+** odbg -- new backlog.
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
int
smfi_setbacklog(obacklog)
int obacklog;
@@ -132,11 +178,22 @@ smfi_setbacklog(obacklog)
}
+/*
+** SMFI_MAIN -- setup milter connnection and start listener.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
int
smfi_main()
{
+ int r;
- signal(SIGPIPE, SIG_IGN);
+ (void) signal(SIGPIPE, SIG_IGN);
if (conn == NULL)
{
smi_log(SMI_LOG_FATAL, "%s: missing connection information",
@@ -152,12 +209,11 @@ smfi_main()
smfi->xxfi_name);
return MI_FAILURE;
}
-
+ r = MI_SUCCESS;
/* Startup the listener */
if (mi_listener(conn, dbg, smfi, timeout, backlog) != MI_SUCCESS)
- return MI_FAILURE;
+ r = MI_FAILURE;
- return MI_SUCCESS;
+ return r;
}
-#endif /* _FFR_MILTER */
diff --git a/contrib/sendmail/libmilter/signal.c b/contrib/sendmail/libmilter/signal.c
index 0bc5081..b160f5d 100644
--- a/contrib/sendmail/libmilter/signal.c
+++ b/contrib/sendmail/libmilter/signal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -8,11 +8,9 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: signal.c,v 8.10.4.8 2000/11/20 21:15:37 ca Exp $";
-#endif /* ! lint */
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: signal.c,v 8.35 2002/01/10 01:34:55 ca Exp $")
-#if _FFR_MILTER
#include "libmilter.h"
/*
@@ -23,7 +21,7 @@ static smutex_t M_Mutex;
static int MilterStop = MILTER_CONT;
- /*
+/*
** MI_STOP -- return value of MilterStop
**
** Parameters:
@@ -38,7 +36,7 @@ mi_stop()
{
return MilterStop;
}
- /*
+/*
** MI_STOP_MILTERS -- set value of MilterStop
**
** Parameters:
@@ -60,7 +58,7 @@ mi_stop_milters(v)
mi_closener();
(void) smutex_unlock(&M_Mutex);
}
- /*
+/*
** MI_CLEAN_SIGNALS -- clean up signal handler thread
**
** Parameters:
@@ -75,7 +73,7 @@ mi_clean_signals()
{
(void) smutex_destroy(&M_Mutex);
}
- /*
+/*
** MI_SIGNAL_THREAD -- thread to deal with signals
**
** Parameters:
@@ -100,18 +98,18 @@ mi_signal_thread(name)
sigaddset(&set, SIGINT);
errs = 0;
- while (TRUE)
+ while (true)
{
sig = 0;
-#ifdef SOLARIS
+#if defined(SOLARIS) || defined(__svr5__)
if ((sig = sigwait(&set)) < 0)
-#else /* SOLARIS */
+#else /* defined(SOLARIS) || defined(__svr5__) */
if (sigwait(&set, &sig) != 0)
-#endif /* SOLARIS */
+#endif /* defined(SOLARIS) || defined(__svr5__) */
{
smi_log(SMI_LOG_ERR,
- "%s: sigwait returned error: %s",
- (char *)name, strerror(errno));
+ "%s: sigwait returned error: %d",
+ (char *)name, errno);
if (++errs > MAX_FAILS_T)
{
mi_stop_milters(MILTER_ABRT);
@@ -138,7 +136,7 @@ mi_signal_thread(name)
}
}
}
- /*
+/*
** MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals
**
** Parameters:
@@ -153,6 +151,7 @@ mi_spawn_signal_thread(name)
char *name;
{
sthread_t tid;
+ int r;
sigset_t set;
/* Mask HUP and KILL signals */
@@ -167,16 +166,17 @@ mi_spawn_signal_thread(name)
"%s: Couldn't mask HUP and KILL signals", name);
return MI_FAILURE;
}
- if (thread_create(&tid, mi_signal_thread,
- (void *)name) != MI_SUCCESS)
+ r = thread_create(&tid, mi_signal_thread, (void *)name);
+ if (r != 0)
{
smi_log(SMI_LOG_ERR,
- "%s: Couldn't start signal thread", name);
+ "%s: Couldn't start signal thread: %d",
+ name, r);
return MI_FAILURE;
}
return MI_SUCCESS;
}
- /*
+/*
** MI_CONTROL_STARTUP -- startup for thread to handle signals
**
** Parameters:
@@ -212,4 +212,3 @@ mi_control_startup(name)
}
return MI_SUCCESS;
}
-#endif /* _FFR_MILTER */
diff --git a/contrib/sendmail/libmilter/sm_gethost.c b/contrib/sendmail/libmilter/sm_gethost.c
index c1e80b1..1714741 100644
--- a/contrib/sendmail/libmilter/sm_gethost.c
+++ b/contrib/sendmail/libmilter/sm_gethost.c
@@ -8,17 +8,15 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: sm_gethost.c,v 8.7.8.11 2001/07/21 00:10:23 gshapiro Exp $";
-#endif /* ! lint */
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: sm_gethost.c,v 8.26 2001/09/11 04:04:45 gshapiro Exp $")
-#if _FFR_MILTER
#include <sendmail.h>
#if NETINET || NETINET6
# include <arpa/inet.h>
#endif /* NETINET || NETINET6 */
- /*
+/*
** MI_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
**
** Some operating systems have wierd problems with the gethostbyXXX
@@ -48,7 +46,7 @@ getipnodebyname(name, family, flags, err)
int flags;
int *err;
{
- bool resv6 = TRUE;
+ bool resv6 = true;
struct hostent *h;
if (family == AF_INET6)
@@ -59,13 +57,12 @@ getipnodebyname(name, family, flags, err)
}
SM_SET_H_ERRNO(0);
h = gethostbyname(name);
- *err = h_errno;
if (family == AF_INET6 && !resv6)
_res.options &= ~RES_USE_INET6;
+ *err = h_errno;
return h;
}
-# if _FFR_FREEHOSTENT
void
freehostent(h)
struct hostent *h;
@@ -77,7 +74,6 @@ freehostent(h)
return;
}
-# endif /* _FFR_FREEHOSTENT */
#endif /* NEEDSGETIPNODE && NETINET6 */
struct hostent *
@@ -117,4 +113,33 @@ mi_gethostbyname(name, family)
#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
return h;
}
-#endif /* _FFR_MILTER */
+
+#if NETINET6
+/*
+** MI_INET_PTON -- convert printed form to network address.
+**
+** Wrapper for inet_pton() which handles IPv6: labels.
+**
+** Parameters:
+** family -- address family
+** src -- string
+** dst -- destination address structure
+**
+** Returns:
+** 1 if the address was valid
+** 0 if the address wasn't parseable
+** -1 if error
+*/
+
+int
+mi_inet_pton(family, src, dst)
+ int family;
+ const char *src;
+ void *dst;
+{
+ if (family == AF_INET6 &&
+ strncasecmp(src, "IPv6:", 5) == 0)
+ src += 5;
+ return inet_pton(family, src, dst);
+}
+#endif /* NETINET6 */
diff --git a/contrib/sendmail/libmilter/smfi.c b/contrib/sendmail/libmilter/smfi.c
index e034aa8..fd564d5 100644
--- a/contrib/sendmail/libmilter/smfi.c
+++ b/contrib/sendmail/libmilter/smfi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers.
+ * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@@ -8,13 +8,14 @@
*
*/
-#ifndef lint
-static char id[] = "@(#)$Id: smfi.c,v 8.28.4.6 2000/06/28 23:48:56 gshapiro Exp $";
-#endif /* ! lint */
-
-#if _FFR_MILTER
+#include <sm/gen.h>
+SM_RCSID("@(#)$Id: smfi.c,v 8.57 2001/11/20 18:47:49 ca Exp $")
+#include <sm/varargs.h>
#include "libmilter.h"
-#include "sendmail/useful.h"
+
+/* for smfi_set{ml}reply, let's be generous. 256/16 should be sufficient */
+#define MAXREPLYLEN 980 /* max. length of a reply string */
+#define MAXREPLIES 32 /* max. number of reply strings */
/*
** SMFI_ADDHEADER -- send a new header to the MTA
@@ -110,7 +111,7 @@ smfi_chgheader(ctx, headerf, hdridx, headerv)
free(buf);
return r;
}
- /*
+/*
** SMFI_ADDRCPT -- send an additional recipient to the MTA
**
** Parameters:
@@ -138,7 +139,7 @@ smfi_addrcpt(ctx, rcpt)
len = strlen(rcpt) + 1;
return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_ADDRCPT, rcpt, len);
}
- /*
+/*
** SMFI_DELRCPT -- send a recipient to be removed to the MTA
**
** Parameters:
@@ -166,7 +167,7 @@ smfi_delrcpt(ctx, rcpt)
len = strlen(rcpt) + 1;
return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_DELRCPT, rcpt, len);
}
- /*
+/*
** SMFI_REPLACEBODY -- send a body chunk to the MTA
**
** Parameters:
@@ -181,13 +182,14 @@ smfi_delrcpt(ctx, rcpt)
int
smfi_replacebody(ctx, bodyp, bodylen)
SMFICTX *ctx;
- u_char *bodyp;
+ unsigned char *bodyp;
int bodylen;
{
int len, off, r;
struct timeval timeout;
- if (bodyp == NULL && bodylen > 0)
+ if (bodylen < 0 ||
+ (bodyp == NULL && bodylen > 0))
return MI_FAILURE;
if (!mi_sendok(ctx, SMFIF_CHGBODY))
return MI_FAILURE;
@@ -208,7 +210,46 @@ smfi_replacebody(ctx, bodyp, bodylen)
}
return MI_SUCCESS;
}
- /*
+#if _FFR_QUARANTINE
+/*
+** SMFI_QUARANTINE -- quarantine an envelope
+**
+** Parameters:
+** ctx -- Opaque context structure
+** reason -- why?
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+int
+smfi_quarantine(ctx, reason)
+ SMFICTX *ctx;
+ char *reason;
+{
+ size_t len;
+ int r;
+ char *buf;
+ struct timeval timeout;
+
+ if (reason == NULL || *reason == '\0')
+ return MI_FAILURE;
+ if (!mi_sendok(ctx, SMFIF_QUARANTINE))
+ return MI_FAILURE;
+ timeout.tv_sec = ctx->ctx_timeout;
+ timeout.tv_usec = 0;
+ len = strlen(reason) + 1;
+ buf = malloc(len);
+ if (buf == NULL)
+ return MI_FAILURE;
+ (void) memcpy(buf, reason, len);
+ r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_QUARANTINE, buf, len);
+ free(buf);
+ return r;
+}
+#endif /* _FFR_QUARANTINE */
+
+/*
** MYISENHSC -- check whether a string contains an enhanced status code
**
** Parameters:
@@ -247,7 +288,8 @@ myisenhsc(s, delim)
return 0;
return l + h;
}
- /*
+
+/*
** SMFI_SETREPLY -- set the reply code for the next reply to the MTA
**
** Parameters:
@@ -267,35 +309,170 @@ smfi_setreply(ctx, rcode, xcode, message)
char *xcode;
char *message;
{
- size_t len, l1, l2, l3;
+ size_t len;
char *buf;
if (rcode == NULL || ctx == NULL)
return MI_FAILURE;
- l1 = strlen(rcode) + 1;
- if (l1 != 4)
+
+ /* ### <sp> \0 */
+ len = strlen(rcode) + 2;
+ if (len != 5)
return MI_FAILURE;
if ((rcode[0] != '4' && rcode[0] != '5') ||
!isascii(rcode[1]) || !isdigit(rcode[1]) ||
!isascii(rcode[2]) || !isdigit(rcode[2]))
return MI_FAILURE;
- l2 = xcode == NULL ? 1 : strlen(xcode) + 1;
- if (xcode != NULL && !myisenhsc(xcode, '\0'))
+ if (xcode != NULL)
+ {
+ if (!myisenhsc(xcode, '\0'))
+ return MI_FAILURE;
+ len += strlen(xcode) + 1;
+ }
+ if (message != NULL)
+ {
+ size_t ml;
+
+ /* XXX check also for unprintable chars? */
+ if (strpbrk(message, "\r\n") != NULL)
+ return MI_FAILURE;
+ ml = strlen(message);
+ if (ml > MAXREPLYLEN)
+ return MI_FAILURE;
+ len += ml + 1;
+ }
+ buf = malloc(len);
+ if (buf == NULL)
+ return MI_FAILURE; /* oops */
+ (void) sm_strlcpy(buf, rcode, len);
+ (void) sm_strlcat(buf, " ", len);
+ if (xcode != NULL)
+ (void) sm_strlcat(buf, xcode, len);
+ if (message != NULL)
+ {
+ if (xcode != NULL)
+ (void) sm_strlcat(buf, " ", len);
+ (void) sm_strlcat(buf, message, len);
+ }
+ if (ctx->ctx_reply != NULL)
+ free(ctx->ctx_reply);
+ ctx->ctx_reply = buf;
+ return MI_SUCCESS;
+}
+
+#if _FFR_MULTILINE
+/*
+** SMFI_SETMLREPLY -- set multiline reply code for the next reply to the MTA
+**
+** Parameters:
+** ctx -- Opaque context structure
+** rcode -- The three-digit (RFC 821) SMTP reply code.
+** xcode -- The extended (RFC 2034) reply code.
+** txt, ... -- The text part of the SMTP reply,
+** MUST be terminated with NULL.
+**
+** Returns:
+** MI_SUCCESS/MI_FAILURE
+*/
+
+int
+#if SM_VA_STD
+smfi_setmlreply(SMFICTX *ctx, const char *rcode, const char *xcode, ...)
+#else /* SM_VA_STD */
+smfi_setmlreply(ctx, rcode, xcode, va_alist)
+ SMFICTX *ctx;
+ const char *rcode;
+ const char *xcode;
+ va_dcl
+#endif /* SM_VA_STD */
+{
+ size_t len;
+ size_t rlen;
+ int args;
+ char *buf, *txt;
+ const char *xc;
+ char repl[16];
+ SM_VA_LOCAL_DECL
+
+ if (rcode == NULL || ctx == NULL)
+ return MI_FAILURE;
+
+ /* ### <sp> */
+ len = strlen(rcode) + 1;
+ if (len != 4)
return MI_FAILURE;
- l3 = message == NULL ? 1 : strlen(message) + 1;
- len = l1 + l2 + l3;
+ if ((rcode[0] != '4' && rcode[0] != '5') ||
+ !isascii(rcode[1]) || !isdigit(rcode[1]) ||
+ !isascii(rcode[2]) || !isdigit(rcode[2]))
+ return MI_FAILURE;
+ if (xcode != NULL)
+ {
+ if (!myisenhsc(xcode, '\0'))
+ return MI_FAILURE;
+ xc = xcode;
+ }
+ else
+ {
+ if (rcode[0] == '4')
+ xc = "4.0.0";
+ else
+ xc = "5.0.0";
+ }
+
+ /* add trailing space */
+ len += strlen(xc) + 1;
+ rlen = len;
+ args = 0;
+ SM_VA_START(ap, xcode);
+ while ((txt = SM_VA_ARG(ap, char *)) != NULL)
+ {
+ size_t tl;
+
+ tl = strlen(txt);
+ if (tl > MAXREPLYLEN)
+ return MI_FAILURE;
+
+ /* this text, reply codes, \r\n */
+ len += tl + 2 + rlen;
+ if (++args > MAXREPLIES)
+ return MI_FAILURE;
+
+ /* XXX check also for unprintable chars? */
+ if (strpbrk(txt, "\r\n") != NULL)
+ return MI_FAILURE;
+ }
+ SM_VA_END(ap);
+
+ /* trailing '\0' */
+ ++len;
buf = malloc(len);
if (buf == NULL)
return MI_FAILURE; /* oops */
- (void) snprintf(buf, len, "%s %s %s", rcode,
- xcode == NULL ? "" : xcode,
- message == NULL ? "" : message);
+ (void) sm_strlcpyn(buf, len, 3, rcode, args == 1 ? " " : "-", xc);
+ (void) sm_strlcpyn(repl, sizeof repl, 4, rcode, args == 1 ? " " : "-",
+ xc, " ");
+ SM_VA_START(ap, xcode);
+ txt = SM_VA_ARG(ap, char *);
+ if (txt != NULL)
+ {
+ (void) sm_strlcat2(buf, " ", txt, len);
+ while ((txt = SM_VA_ARG(ap, char *)) != NULL)
+ {
+ if (--args <= 1)
+ repl[3] = ' ';
+ (void) sm_strlcat2(buf, "\r\n", repl, len);
+ (void) sm_strlcat(buf, txt, len);
+ }
+ }
if (ctx->ctx_reply != NULL)
free(ctx->ctx_reply);
ctx->ctx_reply = buf;
+ SM_VA_END(ap);
return MI_SUCCESS;
}
- /*
+#endif /* _FFR_MULTILINE */
+
+/*
** SMFI_SETPRIV -- set private data
**
** Parameters:
@@ -316,7 +493,7 @@ smfi_setpriv(ctx, privatedata)
ctx->ctx_privdata = privatedata;
return MI_SUCCESS;
}
- /*
+/*
** SMFI_GETPRIV -- get private data
**
** Parameters:
@@ -334,7 +511,7 @@ smfi_getpriv(ctx)
return NULL;
return ctx->ctx_privdata;
}
- /*
+/*
** SMFI_GETSYMVAL -- get the value of a macro
**
** See explanation in mfapi.h about layout of the structures.
@@ -397,4 +574,3 @@ smfi_getsymval(ctx, symname)
}
return NULL;
}
-#endif /* _FFR_MILTER */
OpenPOWER on IntegriCloud