xref: /freebsd/contrib/sendmail/libmilter/README (revision 4e4196cb7454f47341efebe4e0a17f1b8cd534c7)
106f25ae9SGregory Neil ShapiroThis directory contains the source files for libmilter.
206f25ae9SGregory Neil Shapiro
306f25ae9SGregory Neil ShapiroThe sendmail Mail Filter API (Milter) is designed to allow third-party
406f25ae9SGregory Neil Shapiroprograms access to mail messages as they are being processed in order to
506f25ae9SGregory Neil Shapirofilter meta-information and content.
606f25ae9SGregory Neil Shapiro
706f25ae9SGregory Neil ShapiroThis README file describes the steps needed to compile and run a filter,
806f25ae9SGregory Neil Shapirothrough reference to a sample filter which is attached at the end of this
906f25ae9SGregory Neil Shapirofile.  It is necessary to first build libmilter.a, which can be done by
1006f25ae9SGregory Neil Shapiroissuing the './Build' command in SRCDIR/libmilter .
1106f25ae9SGregory Neil Shapiro
12e92d3f3fSGregory Neil ShapiroStarting with 8.13 sendmail is compiled by default with support for
13e92d3f3fSGregory Neil Shapirothe milter API.
1406f25ae9SGregory Neil Shapiro
154e4196cbSGregory Neil ShapiroNote: if you want to write a milter in Java, then see
164e4196cbSGregory Neil Shapirohttp://sendmail-jilter.sourceforge.net/
174e4196cbSGregory Neil Shapiro
1840266059SGregory Neil Shapiro+----------------+
1940266059SGregory Neil Shapiro| SECURITY HINTS |
2040266059SGregory Neil Shapiro+----------------+
2140266059SGregory Neil Shapiro
2240266059SGregory Neil ShapiroNote: we strongly recommend not to run any milter as root.  Libmilter
2340266059SGregory Neil Shapirodoes not need root access to communicate with sendmail.  It is a
2440266059SGregory Neil Shapirogood security practice to run a program only with root privileges
2540266059SGregory Neil Shapiroif really necessary.  A milter should probably check first whether
26e92d3f3fSGregory Neil Shapiroit runs as root and refuse to start in that case.  libmilter will
27e92d3f3fSGregory Neil Shapironot unlink a socket when running as root.
2840266059SGregory Neil Shapiro
29e92d3f3fSGregory Neil Shapiro+----------------------+
30e92d3f3fSGregory Neil Shapiro| CONFIGURATION MACROS |
31e92d3f3fSGregory Neil Shapiro+----------------------+
3240266059SGregory Neil Shapiro
33e92d3f3fSGregory Neil ShapiroLibmilter uses a set of C preprocessor macros to specify platform specific
34e92d3f3fSGregory Neil Shapirofeatures of the C compiler and standard C libraries.
35e92d3f3fSGregory Neil Shapiro
36e92d3f3fSGregory Neil ShapiroSM_CONF_POLL
37e92d3f3fSGregory Neil Shapiro	Set to 1 if poll(2) should be used instead of select(2).
3806f25ae9SGregory Neil Shapiro
3906f25ae9SGregory Neil Shapiro+-------------------+
4006f25ae9SGregory Neil Shapiro| BUILDING A FILTER |
4106f25ae9SGregory Neil Shapiro+-------------------+
4206f25ae9SGregory Neil Shapiro
4306f25ae9SGregory Neil ShapiroThe following command presumes that the sample code from the end of this
4406f25ae9SGregory Neil ShapiroREADME is saved to a file named 'sample.c' and built in the local platform-
4506f25ae9SGregory Neil Shapirospecific build subdirectory (SRCDIR/obj.*/libmilter).
4606f25ae9SGregory Neil Shapiro
4713bd1963SGregory Neil Shapiro	cc -I../../include -o sample sample.c libmilter.a ../libsm/libsm.a -pthread
4806f25ae9SGregory Neil Shapiro
4906f25ae9SGregory Neil ShapiroIt is recommended that you build your filters in a location outside of
5006f25ae9SGregory Neil Shapirothe sendmail source tree.  Modify the compiler include references (-I)
5106f25ae9SGregory Neil Shapiroand the library locations accordingly.  Also, some operating systems may
5206f25ae9SGregory Neil Shapirorequire additional libraries.  For example, SunOS 5.X requires '-lresolv
5340266059SGregory Neil Shapiro-lsocket -lnsl'.  Depending on your operating system you may need a library
5440266059SGregory Neil Shapiroinstead of the option -pthread, e.g., -lpthread.
5506f25ae9SGregory Neil Shapiro
5606f25ae9SGregory Neil ShapiroFilters must be thread-safe!  Many operating systems now provide support for
5706f25ae9SGregory Neil ShapiroPOSIX threads in the standard C libraries.  The compiler flag to link with
5806f25ae9SGregory Neil Shapirothreading support differs according to the compiler and linker used.  Check
5906f25ae9SGregory Neil Shapirothe Makefile in your appropriate obj.*/libmilter build subdirectory if you
6006f25ae9SGregory Neil Shapiroare unsure of the local flag used.
6106f25ae9SGregory Neil Shapiro
62602a2b1bSGregory Neil ShapiroNote that since filters use threads, it may be necessary to alter per
63602a2b1bSGregory Neil Shapiroprocess limits in your filter.  For example, you might look at using
64602a2b1bSGregory Neil Shapirosetrlimit() to increase the number of open file descriptors if your filter
65602a2b1bSGregory Neil Shapirois going to be busy.
66602a2b1bSGregory Neil Shapiro
6706f25ae9SGregory Neil Shapiro
6806f25ae9SGregory Neil Shapiro+----------------------------------------+
6906f25ae9SGregory Neil Shapiro| SPECIFYING FILTERS IN SENDMAIL CONFIGS |
7006f25ae9SGregory Neil Shapiro+----------------------------------------+
7106f25ae9SGregory Neil Shapiro
7206f25ae9SGregory Neil ShapiroFilters are specified with a key letter ``X'' (for ``eXternal'').
7306f25ae9SGregory Neil Shapiro
7406f25ae9SGregory Neil ShapiroFor example:
7506f25ae9SGregory Neil Shapiro
7606f25ae9SGregory Neil Shapiro	Xfilter1, S=local:/var/run/f1.sock, F=R
7713058a91SGregory Neil Shapiro	Xfilter2, S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m
7806f25ae9SGregory Neil Shapiro	Xfilter3, S=inet:3333@localhost
7906f25ae9SGregory Neil Shapiro
8006f25ae9SGregory Neil Shapirospecifies three filters.  Filters can be specified in your .mc file using
8106f25ae9SGregory Neil Shapirothe following:
8206f25ae9SGregory Neil Shapiro
8306f25ae9SGregory Neil Shapiro	INPUT_MAIL_FILTER(`filter1', `S=local:/var/run/f1.sock, F=R')
8413058a91SGregory Neil Shapiro	INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m')
8506f25ae9SGregory Neil Shapiro	INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost')
8606f25ae9SGregory Neil Shapiro
8706f25ae9SGregory Neil ShapiroThe first attaches to a Unix-domain socket in the /var/run directory; the
8806f25ae9SGregory Neil Shapirosecond uses an IPv6 socket on port 999 of localhost, and the third uses an
8906f25ae9SGregory Neil ShapiroIPv4 socket on port 3333 of localhost.  The current flags (F=) are:
9006f25ae9SGregory Neil Shapiro
9106f25ae9SGregory Neil Shapiro	R		Reject connection if filter unavailable
9206f25ae9SGregory Neil Shapiro	T		Temporary fail connection if filter unavailable
9306f25ae9SGregory Neil Shapiro
9442e5d165SGregory Neil ShapiroIf neither F=R nor F=T is specified, the message is passed through sendmail
9540266059SGregory Neil Shapiroin case of filter errors as if the failing filters were not present.
9642e5d165SGregory Neil Shapiro
9706f25ae9SGregory Neil ShapiroFinally, you can override the default timeouts used by sendmail when
9813058a91SGregory Neil Shapirotalking to the filters using the T= equate.  There are four fields inside
9906f25ae9SGregory Neil Shapiroof the T= equate:
10006f25ae9SGregory Neil Shapiro
10106f25ae9SGregory Neil ShapiroLetter		Meaning
10213058a91SGregory Neil Shapiro  C		Timeout for connecting to a filter (if 0, use system timeout)
10306f25ae9SGregory Neil Shapiro  S		Timeout for sending information from the MTA to a filter
10406f25ae9SGregory Neil Shapiro  R		Timeout for reading reply from the filter
10506f25ae9SGregory Neil Shapiro  E		Overall timeout between sending end-of-message to filter
10606f25ae9SGregory Neil Shapiro		and waiting for the final acknowledgment
10706f25ae9SGregory Neil Shapiro
10806f25ae9SGregory Neil ShapiroNote the separator between each is a ';' as a ',' already separates equates
10913058a91SGregory Neil Shapiroand therefore can't separate timeouts.  The default values (if not set in
11013058a91SGregory Neil Shapirothe config) are:
11106f25ae9SGregory Neil Shapiro
11240266059SGregory Neil ShapiroT=C:5m;S:10s;R:10s;E:5m
11306f25ae9SGregory Neil Shapiro
11406f25ae9SGregory Neil Shapirowhere 's' is seconds and 'm' is minutes.
11506f25ae9SGregory Neil Shapiro
11642e5d165SGregory Neil ShapiroWhich filters are invoked and their sequencing is handled by the
1178774250cSGregory Neil ShapiroInputMailFilters option. Note: if InputMailFilters is not defined no filters
1188774250cSGregory Neil Shapirowill be used.
11942e5d165SGregory Neil Shapiro
12042e5d165SGregory Neil Shapiro	O InputMailFilters=filter1, filter2, filter3
12142e5d165SGregory Neil Shapiro
12242e5d165SGregory Neil ShapiroThis is is set automatically according to the order of the
12342e5d165SGregory Neil ShapiroINPUT_MAIL_FILTER commands in your .mc file.  Alternatively, you can
12442e5d165SGregory Neil Shapiroreset its value by setting confINPUT_MAIL_FILTERS in your .mc file.
12542e5d165SGregory Neil ShapiroThis options causes the three filters to be called in the same order
12642e5d165SGregory Neil Shapirothey were specified.  It allows for possible future filtering on output
12742e5d165SGregory Neil Shapiro(although this is not intended for this release).
12806f25ae9SGregory Neil Shapiro
12906f25ae9SGregory Neil ShapiroAlso note that a filter can be defined without adding it to the input
13006f25ae9SGregory Neil Shapirofilter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your
13106f25ae9SGregory Neil Shapiro.mc file.
13206f25ae9SGregory Neil Shapiro
13306f25ae9SGregory Neil ShapiroTo test sendmail with the sample filter, the following might be added (in
13406f25ae9SGregory Neil Shapirothe appropriate locations) to your .mc file:
13506f25ae9SGregory Neil Shapiro
13606f25ae9SGregory Neil Shapiro	INPUT_MAIL_FILTER(`sample', `S=local:/var/run/f1.sock')
13706f25ae9SGregory Neil Shapiro
13806f25ae9SGregory Neil Shapiro
13906f25ae9SGregory Neil Shapiro+------------------+
14006f25ae9SGregory Neil Shapiro| TESTING A FILTER |
14106f25ae9SGregory Neil Shapiro+------------------+
14206f25ae9SGregory Neil Shapiro
14306f25ae9SGregory Neil ShapiroOnce you have compiled a filter, modified your .mc file and restarted
14406f25ae9SGregory Neil Shapirothe sendmail process, you will want to test that the filter performs as
14506f25ae9SGregory Neil Shapirointended.
14606f25ae9SGregory Neil Shapiro
14706f25ae9SGregory Neil ShapiroThe sample filter takes one argument -p, which indicates the local port
14806f25ae9SGregory Neil Shapiroon which to create a listening socket for the filter.  Maintaining
14906f25ae9SGregory Neil Shapiroconsistency with the suggested options for sendmail.cf, this would be the
15006f25ae9SGregory Neil ShapiroUNIX domain socket located in /var/run/f1.sock.
15106f25ae9SGregory Neil Shapiro
15206f25ae9SGregory Neil Shapiro	% ./sample -p local:/var/run/f1.sock
15306f25ae9SGregory Neil Shapiro
15406f25ae9SGregory Neil ShapiroIf the sample filter returns immediately to a command line, there was either
15506f25ae9SGregory Neil Shapiroan error with your command or a problem creating the specified socket.
15606f25ae9SGregory Neil ShapiroFurther logging can be captured through the syslogd daemon.  Using the
15706f25ae9SGregory Neil Shapiro'netstat -a' command can ensure that your filter process is listening on
15806f25ae9SGregory Neil Shapirothe appropriate local socket.
15906f25ae9SGregory Neil Shapiro
16006f25ae9SGregory Neil ShapiroEmail messages must be injected via SMTP to be filtered.  There are two
16106f25ae9SGregory Neil Shapirosimple means of doing this; either using the 'sendmail -bs' command, or
16206f25ae9SGregory Neil Shapiroby telnetting to port 25 of the machine configured for milter.  Once
16306f25ae9SGregory Neil Shapiroconnected via one of these options, the session can be continued through
16406f25ae9SGregory Neil Shapirothe use of standard SMTP commands.
16506f25ae9SGregory Neil Shapiro
16606f25ae9SGregory Neil Shapiro% sendmail -bs
16742e5d165SGregory Neil Shapiro220 test.sendmail.com ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST)
16806f25ae9SGregory Neil ShapiroHELO localhost
16906f25ae9SGregory Neil Shapiro250 test.sendmail.com Hello testy@localhost, pleased to meet you
17006f25ae9SGregory Neil ShapiroMAIL From:<testy>
17106f25ae9SGregory Neil Shapiro250 2.1.0 <testy>... Sender ok
17206f25ae9SGregory Neil ShapiroRCPT To:<root>
17306f25ae9SGregory Neil Shapiro250 2.1.5 <root>... Recipient ok
17406f25ae9SGregory Neil ShapiroDATA
17506f25ae9SGregory Neil Shapiro354 Enter mail, end with "." on a line by itself
17606f25ae9SGregory Neil ShapiroFrom: testy@test.sendmail.com
17706f25ae9SGregory Neil ShapiroTo: root@test.sendmail.com
17806f25ae9SGregory Neil ShapiroSubject: testing sample filter
17906f25ae9SGregory Neil Shapiro
18006f25ae9SGregory Neil ShapiroSample body
18106f25ae9SGregory Neil Shapiro.
18206f25ae9SGregory Neil Shapiro250 2.0.0 dB73Zxi25236 Message accepted for delivery
18306f25ae9SGregory Neil ShapiroQUIT
18406f25ae9SGregory Neil Shapiro221 2.0.0 test.sendmail.com closing connection
18506f25ae9SGregory Neil Shapiro
18606f25ae9SGregory Neil ShapiroIn the above example, the lines beginning with numbers are output by the
18706f25ae9SGregory Neil Shapiromail server, and those without are your input.  If everything is working
18806f25ae9SGregory Neil Shapiroproperly, you will find a file in /tmp by the name of msg.XXXXXXXX (where
18906f25ae9SGregory Neil Shapirothe Xs represent any combination of letters and numbers).  This file should
19006f25ae9SGregory Neil Shapirocontain the message body and headers from the test email entered above.
19106f25ae9SGregory Neil Shapiro
19206f25ae9SGregory Neil ShapiroIf the sample filter did not log your test email, there are a number of
19306f25ae9SGregory Neil Shapiromethods to narrow down the source of the problem.  Check your system
19406f25ae9SGregory Neil Shapirologs written by syslogd and see if there are any pertinent lines.  You
19506f25ae9SGregory Neil Shapiromay need to reconfigure syslogd to capture all relevant data.  Additionally,
19606f25ae9SGregory Neil Shapirothe logging level of sendmail can be raised with the LogLevel option.
19706f25ae9SGregory Neil ShapiroSee the sendmail(8) manual page for more information.
19806f25ae9SGregory Neil Shapiro
19906f25ae9SGregory Neil Shapiro
20040266059SGregory Neil Shapiro+--------------+
20140266059SGregory Neil Shapiro| REQUIREMENTS |
20240266059SGregory Neil Shapiro+--------------+
20340266059SGregory Neil Shapiro
20440266059SGregory Neil Shapirolibmilter requires pthread support in the operating system.  Moreover, it
20540266059SGregory Neil Shapirorequires that the library functions it uses are thread safe; which is true
20640266059SGregory Neil Shapirofor the operating systems libmilter has been developed and tested on.  On
20740266059SGregory Neil Shapirosome operating systems this requires special compile time options (e.g.,
20840266059SGregory Neil Shapironot just -pthread).  libmilter is currently known to work on (modulo problems
20940266059SGregory Neil Shapiroin the pthread support of some specific versions):
21040266059SGregory Neil Shapiro
21140266059SGregory Neil ShapiroFreeBSD 3.x, 4.x
21240266059SGregory Neil ShapiroSunOS 5.x (x >= 5)
21340266059SGregory Neil ShapiroAIX 4.3.x
21440266059SGregory Neil ShapiroHP UX 11.x
21540266059SGregory Neil ShapiroLinux (recent versions/distributions)
21640266059SGregory Neil Shapiro
21740266059SGregory Neil Shapirolibmilter is currently not supported on:
21840266059SGregory Neil Shapiro
21940266059SGregory Neil ShapiroIRIX 6.x
22040266059SGregory Neil ShapiroUltrix
22140266059SGregory Neil Shapiro
22240266059SGregory Neil ShapiroFeedback about problems (and possible fixes) is welcome.
22340266059SGregory Neil Shapiro
22406f25ae9SGregory Neil Shapiro+--------------------------+
22506f25ae9SGregory Neil Shapiro| SOURCE FOR SAMPLE FILTER |
22606f25ae9SGregory Neil Shapiro+--------------------------+
22706f25ae9SGregory Neil Shapiro
228193538b7SGregory Neil ShapiroNote that the filter below may not be thread safe on some operating
229193538b7SGregory Neil Shapirosystems.  You should check your system man pages for the functions used
230193538b7SGregory Neil Shapirobelow to verify the functions are thread safe.
231193538b7SGregory Neil Shapiro
23206f25ae9SGregory Neil Shapiro/* A trivial filter that logs all email to a file. */
23306f25ae9SGregory Neil Shapiro
23406f25ae9SGregory Neil Shapiro#include <sys/types.h>
23506f25ae9SGregory Neil Shapiro#include <stdio.h>
23606f25ae9SGregory Neil Shapiro#include <stdlib.h>
23706f25ae9SGregory Neil Shapiro#include <string.h>
23806f25ae9SGregory Neil Shapiro#include <sysexits.h>
23906f25ae9SGregory Neil Shapiro#include <unistd.h>
24006f25ae9SGregory Neil Shapiro
24106f25ae9SGregory Neil Shapiro#include "libmilter/mfapi.h"
24206f25ae9SGregory Neil Shapiro
24340266059SGregory Neil Shapiro#ifndef true
24406f25ae9SGregory Neil Shapirotypedef int bool;
24540266059SGregory Neil Shapiro# define false	0
24640266059SGregory Neil Shapiro# define true	1
24740266059SGregory Neil Shapiro#endif /* ! true */
24806f25ae9SGregory Neil Shapiro
24906f25ae9SGregory Neil Shapirostruct mlfiPriv
25006f25ae9SGregory Neil Shapiro{
25106f25ae9SGregory Neil Shapiro	char	*mlfi_fname;
25206f25ae9SGregory Neil Shapiro	FILE	*mlfi_fp;
25306f25ae9SGregory Neil Shapiro};
25406f25ae9SGregory Neil Shapiro
25506f25ae9SGregory Neil Shapiro#define MLFIPRIV	((struct mlfiPriv *) smfi_getpriv(ctx))
25606f25ae9SGregory Neil Shapiro
25706f25ae9SGregory Neil Shapiroextern sfsistat	 mlfi_cleanup(SMFICTX *, bool);
25806f25ae9SGregory Neil Shapiro
25906f25ae9SGregory Neil Shapirosfsistat
26006f25ae9SGregory Neil Shapiromlfi_envfrom(ctx, envfrom)
26106f25ae9SGregory Neil Shapiro	SMFICTX *ctx;
26206f25ae9SGregory Neil Shapiro	char **envfrom;
26306f25ae9SGregory Neil Shapiro{
26406f25ae9SGregory Neil Shapiro	struct mlfiPriv *priv;
2658774250cSGregory Neil Shapiro	int fd = -1;
26606f25ae9SGregory Neil Shapiro
26706f25ae9SGregory Neil Shapiro	/* allocate some private memory */
26806f25ae9SGregory Neil Shapiro	priv = malloc(sizeof *priv);
26906f25ae9SGregory Neil Shapiro	if (priv == NULL)
27006f25ae9SGregory Neil Shapiro	{
27106f25ae9SGregory Neil Shapiro		/* can't accept this message right now */
27206f25ae9SGregory Neil Shapiro		return SMFIS_TEMPFAIL;
27306f25ae9SGregory Neil Shapiro	}
27406f25ae9SGregory Neil Shapiro	memset(priv, '\0', sizeof *priv);
27506f25ae9SGregory Neil Shapiro
27606f25ae9SGregory Neil Shapiro	/* open a file to store this message */
27706f25ae9SGregory Neil Shapiro	priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX");
27806f25ae9SGregory Neil Shapiro	if (priv->mlfi_fname == NULL)
27906f25ae9SGregory Neil Shapiro	{
28006f25ae9SGregory Neil Shapiro		free(priv);
28106f25ae9SGregory Neil Shapiro		return SMFIS_TEMPFAIL;
28206f25ae9SGregory Neil Shapiro	}
28306f25ae9SGregory Neil Shapiro	if ((fd = mkstemp(priv->mlfi_fname)) < 0 ||
28406f25ae9SGregory Neil Shapiro	    (priv->mlfi_fp = fdopen(fd, "w+")) == NULL)
28506f25ae9SGregory Neil Shapiro	{
2868774250cSGregory Neil Shapiro		if (fd >= 0)
2878774250cSGregory Neil Shapiro			(void) close(fd);
28806f25ae9SGregory Neil Shapiro		free(priv->mlfi_fname);
28906f25ae9SGregory Neil Shapiro		free(priv);
29006f25ae9SGregory Neil Shapiro		return SMFIS_TEMPFAIL;
29106f25ae9SGregory Neil Shapiro	}
29206f25ae9SGregory Neil Shapiro
29306f25ae9SGregory Neil Shapiro	/* save the private data */
29406f25ae9SGregory Neil Shapiro	smfi_setpriv(ctx, priv);
29506f25ae9SGregory Neil Shapiro
29606f25ae9SGregory Neil Shapiro	/* continue processing */
29706f25ae9SGregory Neil Shapiro	return SMFIS_CONTINUE;
29806f25ae9SGregory Neil Shapiro}
29906f25ae9SGregory Neil Shapiro
30006f25ae9SGregory Neil Shapirosfsistat
30106f25ae9SGregory Neil Shapiromlfi_header(ctx, headerf, headerv)
30206f25ae9SGregory Neil Shapiro	SMFICTX *ctx;
30306f25ae9SGregory Neil Shapiro	char *headerf;
30406f25ae9SGregory Neil Shapiro	char *headerv;
30506f25ae9SGregory Neil Shapiro{
30606f25ae9SGregory Neil Shapiro	/* write the header to the log file */
30706f25ae9SGregory Neil Shapiro	fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv);
30806f25ae9SGregory Neil Shapiro
30906f25ae9SGregory Neil Shapiro	/* continue processing */
31006f25ae9SGregory Neil Shapiro	return SMFIS_CONTINUE;
31106f25ae9SGregory Neil Shapiro}
31206f25ae9SGregory Neil Shapiro
31306f25ae9SGregory Neil Shapirosfsistat
31406f25ae9SGregory Neil Shapiromlfi_eoh(ctx)
31506f25ae9SGregory Neil Shapiro	SMFICTX *ctx;
31606f25ae9SGregory Neil Shapiro{
31706f25ae9SGregory Neil Shapiro	/* output the blank line between the header and the body */
31806f25ae9SGregory Neil Shapiro	fprintf(MLFIPRIV->mlfi_fp, "\r\n");
31906f25ae9SGregory Neil Shapiro
32006f25ae9SGregory Neil Shapiro	/* continue processing */
32106f25ae9SGregory Neil Shapiro	return SMFIS_CONTINUE;
32206f25ae9SGregory Neil Shapiro}
32306f25ae9SGregory Neil Shapiro
32406f25ae9SGregory Neil Shapirosfsistat
32506f25ae9SGregory Neil Shapiromlfi_body(ctx, bodyp, bodylen)
32606f25ae9SGregory Neil Shapiro	SMFICTX *ctx;
32706f25ae9SGregory Neil Shapiro	u_char *bodyp;
32806f25ae9SGregory Neil Shapiro	size_t bodylen;
32906f25ae9SGregory Neil Shapiro{
33006f25ae9SGregory Neil Shapiro	/* output body block to log file */
33106f25ae9SGregory Neil Shapiro	if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0)
33206f25ae9SGregory Neil Shapiro	{
33306f25ae9SGregory Neil Shapiro		/* write failed */
33440266059SGregory Neil Shapiro		(void) mlfi_cleanup(ctx, false);
33506f25ae9SGregory Neil Shapiro		return SMFIS_TEMPFAIL;
33606f25ae9SGregory Neil Shapiro	}
33706f25ae9SGregory Neil Shapiro
33806f25ae9SGregory Neil Shapiro	/* continue processing */
33906f25ae9SGregory Neil Shapiro	return SMFIS_CONTINUE;
34006f25ae9SGregory Neil Shapiro}
34106f25ae9SGregory Neil Shapiro
34206f25ae9SGregory Neil Shapirosfsistat
34306f25ae9SGregory Neil Shapiromlfi_eom(ctx)
34406f25ae9SGregory Neil Shapiro	SMFICTX *ctx;
34506f25ae9SGregory Neil Shapiro{
34640266059SGregory Neil Shapiro	return mlfi_cleanup(ctx, true);
34706f25ae9SGregory Neil Shapiro}
34806f25ae9SGregory Neil Shapiro
34906f25ae9SGregory Neil Shapirosfsistat
35006f25ae9SGregory Neil Shapiromlfi_close(ctx)
35106f25ae9SGregory Neil Shapiro	SMFICTX *ctx;
35206f25ae9SGregory Neil Shapiro{
35306f25ae9SGregory Neil Shapiro	return SMFIS_ACCEPT;
35406f25ae9SGregory Neil Shapiro}
35506f25ae9SGregory Neil Shapiro
35606f25ae9SGregory Neil Shapirosfsistat
35706f25ae9SGregory Neil Shapiromlfi_abort(ctx)
35806f25ae9SGregory Neil Shapiro	SMFICTX *ctx;
35906f25ae9SGregory Neil Shapiro{
36040266059SGregory Neil Shapiro	return mlfi_cleanup(ctx, false);
36106f25ae9SGregory Neil Shapiro}
36206f25ae9SGregory Neil Shapiro
36306f25ae9SGregory Neil Shapirosfsistat
36406f25ae9SGregory Neil Shapiromlfi_cleanup(ctx, ok)
36506f25ae9SGregory Neil Shapiro	SMFICTX *ctx;
36606f25ae9SGregory Neil Shapiro	bool ok;
36706f25ae9SGregory Neil Shapiro{
36806f25ae9SGregory Neil Shapiro	sfsistat rstat = SMFIS_CONTINUE;
36906f25ae9SGregory Neil Shapiro	struct mlfiPriv *priv = MLFIPRIV;
37006f25ae9SGregory Neil Shapiro	char *p;
37106f25ae9SGregory Neil Shapiro	char host[512];
37206f25ae9SGregory Neil Shapiro	char hbuf[1024];
37306f25ae9SGregory Neil Shapiro
37406f25ae9SGregory Neil Shapiro	if (priv == NULL)
37506f25ae9SGregory Neil Shapiro		return rstat;
37606f25ae9SGregory Neil Shapiro
37706f25ae9SGregory Neil Shapiro	/* close the archive file */
37806f25ae9SGregory Neil Shapiro	if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF)
37906f25ae9SGregory Neil Shapiro	{
38006f25ae9SGregory Neil Shapiro		/* failed; we have to wait until later */
38106f25ae9SGregory Neil Shapiro		rstat = SMFIS_TEMPFAIL;
38206f25ae9SGregory Neil Shapiro		(void) unlink(priv->mlfi_fname);
38306f25ae9SGregory Neil Shapiro	}
38406f25ae9SGregory Neil Shapiro	else if (ok)
38506f25ae9SGregory Neil Shapiro	{
38606f25ae9SGregory Neil Shapiro		/* add a header to the message announcing our presence */
38706f25ae9SGregory Neil Shapiro		if (gethostname(host, sizeof host) < 0)
38840266059SGregory Neil Shapiro			snprintf(host, sizeof host, "localhost");
38906f25ae9SGregory Neil Shapiro		p = strrchr(priv->mlfi_fname, '/');
39006f25ae9SGregory Neil Shapiro		if (p == NULL)
39106f25ae9SGregory Neil Shapiro			p = priv->mlfi_fname;
39206f25ae9SGregory Neil Shapiro		else
39306f25ae9SGregory Neil Shapiro			p++;
39406f25ae9SGregory Neil Shapiro		snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
39506f25ae9SGregory Neil Shapiro		smfi_addheader(ctx, "X-Archived", hbuf);
39606f25ae9SGregory Neil Shapiro	}
39706f25ae9SGregory Neil Shapiro	else
39806f25ae9SGregory Neil Shapiro	{
39906f25ae9SGregory Neil Shapiro		/* message was aborted -- delete the archive file */
40006f25ae9SGregory Neil Shapiro		(void) unlink(priv->mlfi_fname);
40106f25ae9SGregory Neil Shapiro	}
40206f25ae9SGregory Neil Shapiro
40306f25ae9SGregory Neil Shapiro	/* release private memory */
40406f25ae9SGregory Neil Shapiro	free(priv->mlfi_fname);
40506f25ae9SGregory Neil Shapiro	free(priv);
40606f25ae9SGregory Neil Shapiro	smfi_setpriv(ctx, NULL);
40706f25ae9SGregory Neil Shapiro
40806f25ae9SGregory Neil Shapiro	/* return status */
40906f25ae9SGregory Neil Shapiro	return rstat;
41006f25ae9SGregory Neil Shapiro}
41106f25ae9SGregory Neil Shapiro
41206f25ae9SGregory Neil Shapirostruct smfiDesc smfilter =
41306f25ae9SGregory Neil Shapiro{
41406f25ae9SGregory Neil Shapiro	"SampleFilter",	/* filter name */
41506f25ae9SGregory Neil Shapiro	SMFI_VERSION,	/* version code -- do not change */
41606f25ae9SGregory Neil Shapiro	SMFIF_ADDHDRS,	/* flags */
41706f25ae9SGregory Neil Shapiro	NULL,		/* connection info filter */
41806f25ae9SGregory Neil Shapiro	NULL,		/* SMTP HELO command filter */
41906f25ae9SGregory Neil Shapiro	mlfi_envfrom,	/* envelope sender filter */
42006f25ae9SGregory Neil Shapiro	NULL,		/* envelope recipient filter */
42106f25ae9SGregory Neil Shapiro	mlfi_header,	/* header filter */
42206f25ae9SGregory Neil Shapiro	mlfi_eoh,	/* end of header */
42306f25ae9SGregory Neil Shapiro	mlfi_body,	/* body block filter */
42406f25ae9SGregory Neil Shapiro	mlfi_eom,	/* end of message */
42506f25ae9SGregory Neil Shapiro	mlfi_abort,	/* message aborted */
42606f25ae9SGregory Neil Shapiro	mlfi_close	/* connection cleanup */
42706f25ae9SGregory Neil Shapiro};
42806f25ae9SGregory Neil Shapiro
42906f25ae9SGregory Neil Shapiro
43006f25ae9SGregory Neil Shapiroint
43106f25ae9SGregory Neil Shapiromain(argc, argv)
43206f25ae9SGregory Neil Shapiro	int argc;
43306f25ae9SGregory Neil Shapiro	char *argv[];
43406f25ae9SGregory Neil Shapiro{
435a7ec597cSGregory Neil Shapiro	bool setconn = false;
43606f25ae9SGregory Neil Shapiro	int c;
43706f25ae9SGregory Neil Shapiro	const char *args = "p:";
43806f25ae9SGregory Neil Shapiro
43906f25ae9SGregory Neil Shapiro	/* Process command line options */
44006f25ae9SGregory Neil Shapiro	while ((c = getopt(argc, argv, args)) != -1)
44106f25ae9SGregory Neil Shapiro	{
44206f25ae9SGregory Neil Shapiro		switch (c)
44306f25ae9SGregory Neil Shapiro		{
44406f25ae9SGregory Neil Shapiro		  case 'p':
44506f25ae9SGregory Neil Shapiro			if (optarg == NULL || *optarg == '\0')
44606f25ae9SGregory Neil Shapiro			{
44706f25ae9SGregory Neil Shapiro				(void) fprintf(stderr, "Illegal conn: %s\n",
44806f25ae9SGregory Neil Shapiro					       optarg);
44906f25ae9SGregory Neil Shapiro				exit(EX_USAGE);
45006f25ae9SGregory Neil Shapiro			}
45106f25ae9SGregory Neil Shapiro			(void) smfi_setconn(optarg);
452a7ec597cSGregory Neil Shapiro			setconn = true;
45306f25ae9SGregory Neil Shapiro			break;
45406f25ae9SGregory Neil Shapiro
45506f25ae9SGregory Neil Shapiro		}
45606f25ae9SGregory Neil Shapiro	}
457a7ec597cSGregory Neil Shapiro	if (!setconn)
458a7ec597cSGregory Neil Shapiro	{
459a7ec597cSGregory Neil Shapiro		fprintf(stderr, "%s: Missing required -p argument\n", argv[0]);
460a7ec597cSGregory Neil Shapiro		exit(EX_USAGE);
461a7ec597cSGregory Neil Shapiro	}
46206f25ae9SGregory Neil Shapiro	if (smfi_register(smfilter) == MI_FAILURE)
46306f25ae9SGregory Neil Shapiro	{
46406f25ae9SGregory Neil Shapiro		fprintf(stderr, "smfi_register failed\n");
46506f25ae9SGregory Neil Shapiro		exit(EX_UNAVAILABLE);
46606f25ae9SGregory Neil Shapiro	}
46706f25ae9SGregory Neil Shapiro	return smfi_main();
46806f25ae9SGregory Neil Shapiro}
46906f25ae9SGregory Neil Shapiro
47006f25ae9SGregory Neil Shapiro/* eof */
47106f25ae9SGregory Neil Shapiro
4724e4196cbSGregory Neil Shapiro$Revision: 8.41 $, Last updated $Date: 2005/04/27 22:47:42 $
473