xref: /titanic_53/usr/src/cmd/sendmail/libmilter/README (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate#
2*7c478bd9Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate# Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate#
5*7c478bd9Sstevel@tonic-gate# ident	"%Z%%M%	%I%	%E% SMI"
6*7c478bd9Sstevel@tonic-gate#
7*7c478bd9Sstevel@tonic-gate
8*7c478bd9Sstevel@tonic-gateThe sendmail Mail Filter API (Milter) is designed to allow third-party
9*7c478bd9Sstevel@tonic-gateprograms access to mail messages as they are being processed in order to
10*7c478bd9Sstevel@tonic-gatefilter meta-information and content.
11*7c478bd9Sstevel@tonic-gate
12*7c478bd9Sstevel@tonic-gateThis README file describes the steps needed to compile and run a filter,
13*7c478bd9Sstevel@tonic-gatethrough reference to a sample filter which is attached at the end of this
14*7c478bd9Sstevel@tonic-gatefile.
15*7c478bd9Sstevel@tonic-gate
16*7c478bd9Sstevel@tonic-gate+----------------+
17*7c478bd9Sstevel@tonic-gate| SECURITY HINTS |
18*7c478bd9Sstevel@tonic-gate+----------------+
19*7c478bd9Sstevel@tonic-gate
20*7c478bd9Sstevel@tonic-gateNote: we strongly recommend not to run any milter as root.  Libmilter
21*7c478bd9Sstevel@tonic-gatedoes not need root access to communicate with sendmail.  It is a
22*7c478bd9Sstevel@tonic-gategood security practice to run a program only with root privileges
23*7c478bd9Sstevel@tonic-gateif really necessary.  A milter should probably check first whether
24*7c478bd9Sstevel@tonic-gateit runs as root and refuse to start in that case.  libmilter will
25*7c478bd9Sstevel@tonic-gatenot unlink a socket when running as root.
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate+-------------------+
28*7c478bd9Sstevel@tonic-gate| BUILDING A FILTER |
29*7c478bd9Sstevel@tonic-gate+-------------------+
30*7c478bd9Sstevel@tonic-gate
31*7c478bd9Sstevel@tonic-gateThe following command presumes that the sample code from the end of this
32*7c478bd9Sstevel@tonic-gateREADME is saved to a file named 'sample.c'.
33*7c478bd9Sstevel@tonic-gate
34*7c478bd9Sstevel@tonic-gate	cc -D_REENTRANT -o sample sample.c -lmilter
35*7c478bd9Sstevel@tonic-gate
36*7c478bd9Sstevel@tonic-gateFilters must be thread-safe!
37*7c478bd9Sstevel@tonic-gate
38*7c478bd9Sstevel@tonic-gateNote that since filters use threads, it may be necessary to alter per
39*7c478bd9Sstevel@tonic-gateprocess limits in your filter.  For example, you might look at using
40*7c478bd9Sstevel@tonic-gatesetrlimit() to increase the number of open file descriptors if your filter
41*7c478bd9Sstevel@tonic-gateis going to be busy.
42*7c478bd9Sstevel@tonic-gate
43*7c478bd9Sstevel@tonic-gate
44*7c478bd9Sstevel@tonic-gate+----------------------------------------+
45*7c478bd9Sstevel@tonic-gate| SPECIFYING FILTERS IN SENDMAIL CONFIGS |
46*7c478bd9Sstevel@tonic-gate+----------------------------------------+
47*7c478bd9Sstevel@tonic-gate
48*7c478bd9Sstevel@tonic-gateFilters are specified with a key letter ``X'' (for ``eXternal'').
49*7c478bd9Sstevel@tonic-gate
50*7c478bd9Sstevel@tonic-gateFor example:
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gate	Xfilter1, S=local:/var/run/f1.sock, F=R
53*7c478bd9Sstevel@tonic-gate	Xfilter2, S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m
54*7c478bd9Sstevel@tonic-gate	Xfilter3, S=inet:3333@localhost
55*7c478bd9Sstevel@tonic-gate
56*7c478bd9Sstevel@tonic-gatespecifies three filters.  Filters can be specified in your .mc file using
57*7c478bd9Sstevel@tonic-gatethe following:
58*7c478bd9Sstevel@tonic-gate
59*7c478bd9Sstevel@tonic-gate	INPUT_MAIL_FILTER(`filter1', `S=local:/var/run/f1.sock, F=R')
60*7c478bd9Sstevel@tonic-gate	INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m')
61*7c478bd9Sstevel@tonic-gate	INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost')
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gateThe first attaches to a Unix-domain socket in the /var/run directory; the
64*7c478bd9Sstevel@tonic-gatesecond uses an IPv6 socket on port 999 of localhost, and the third uses an
65*7c478bd9Sstevel@tonic-gateIPv4 socket on port 3333 of localhost.  The current flags (F=) are:
66*7c478bd9Sstevel@tonic-gate
67*7c478bd9Sstevel@tonic-gate	R		Reject connection if filter unavailable
68*7c478bd9Sstevel@tonic-gate	T		Temporary fail connection if filter unavailable
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gateIf neither F=R nor F=T is specified, the message is passed through sendmail
71*7c478bd9Sstevel@tonic-gatein case of filter errors as if the failing filters were not present.
72*7c478bd9Sstevel@tonic-gate
73*7c478bd9Sstevel@tonic-gateFinally, you can override the default timeouts used by sendmail when
74*7c478bd9Sstevel@tonic-gatetalking to the filters using the T= equate.  There are four fields inside
75*7c478bd9Sstevel@tonic-gateof the T= equate:
76*7c478bd9Sstevel@tonic-gate
77*7c478bd9Sstevel@tonic-gateLetter		Meaning
78*7c478bd9Sstevel@tonic-gate  C		Timeout for connecting to a filter (if 0, use system timeout)
79*7c478bd9Sstevel@tonic-gate  S		Timeout for sending information from the MTA to a filter
80*7c478bd9Sstevel@tonic-gate  R		Timeout for reading reply from the filter
81*7c478bd9Sstevel@tonic-gate  E		Overall timeout between sending end-of-message to filter
82*7c478bd9Sstevel@tonic-gate		and waiting for the final acknowledgment
83*7c478bd9Sstevel@tonic-gate
84*7c478bd9Sstevel@tonic-gateNote the separator between each is a ';' as a ',' already separates equates
85*7c478bd9Sstevel@tonic-gateand therefore can't separate timeouts.  The default values (if not set in
86*7c478bd9Sstevel@tonic-gatethe config) are:
87*7c478bd9Sstevel@tonic-gate
88*7c478bd9Sstevel@tonic-gateT=C:5m;S:10s;R:10s;E:5m
89*7c478bd9Sstevel@tonic-gate
90*7c478bd9Sstevel@tonic-gatewhere 's' is seconds and 'm' is minutes.
91*7c478bd9Sstevel@tonic-gate
92*7c478bd9Sstevel@tonic-gateWhich filters are invoked and their sequencing is handled by the
93*7c478bd9Sstevel@tonic-gateInputMailFilters option. Note: if InputMailFilters is not defined no filters
94*7c478bd9Sstevel@tonic-gatewill be used.
95*7c478bd9Sstevel@tonic-gate
96*7c478bd9Sstevel@tonic-gate	O InputMailFilters=filter1, filter2, filter3
97*7c478bd9Sstevel@tonic-gate
98*7c478bd9Sstevel@tonic-gateThis is is set automatically according to the order of the
99*7c478bd9Sstevel@tonic-gateINPUT_MAIL_FILTER commands in your .mc file.  Alternatively, you can
100*7c478bd9Sstevel@tonic-gatereset its value by setting confINPUT_MAIL_FILTERS in your .mc file.
101*7c478bd9Sstevel@tonic-gateThis options causes the three filters to be called in the same order
102*7c478bd9Sstevel@tonic-gatethey were specified.  It allows for possible future filtering on output
103*7c478bd9Sstevel@tonic-gate(although this is not intended for this release).
104*7c478bd9Sstevel@tonic-gate
105*7c478bd9Sstevel@tonic-gateAlso note that a filter can be defined without adding it to the input
106*7c478bd9Sstevel@tonic-gatefilter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your
107*7c478bd9Sstevel@tonic-gate.mc file.
108*7c478bd9Sstevel@tonic-gate
109*7c478bd9Sstevel@tonic-gateTo test sendmail with the sample filter, the following might be added (in
110*7c478bd9Sstevel@tonic-gatethe appropriate locations) to your .mc file:
111*7c478bd9Sstevel@tonic-gate
112*7c478bd9Sstevel@tonic-gate	INPUT_MAIL_FILTER(`sample', `S=local:/var/run/f1.sock')
113*7c478bd9Sstevel@tonic-gate
114*7c478bd9Sstevel@tonic-gate
115*7c478bd9Sstevel@tonic-gate+------------------+
116*7c478bd9Sstevel@tonic-gate| TESTING A FILTER |
117*7c478bd9Sstevel@tonic-gate+------------------+
118*7c478bd9Sstevel@tonic-gate
119*7c478bd9Sstevel@tonic-gateOnce you have compiled a filter, modified your .mc file and restarted
120*7c478bd9Sstevel@tonic-gatethe sendmail process, you will want to test that the filter performs as
121*7c478bd9Sstevel@tonic-gateintended.
122*7c478bd9Sstevel@tonic-gate
123*7c478bd9Sstevel@tonic-gateThe sample filter takes one argument -p, which indicates the local port
124*7c478bd9Sstevel@tonic-gateon which to create a listening socket for the filter.  Maintaining
125*7c478bd9Sstevel@tonic-gateconsistency with the suggested options for sendmail.cf, this would be the
126*7c478bd9Sstevel@tonic-gateUNIX domain socket located in /var/run/f1.sock.
127*7c478bd9Sstevel@tonic-gate
128*7c478bd9Sstevel@tonic-gate	% ./sample -p local:/var/run/f1.sock
129*7c478bd9Sstevel@tonic-gate
130*7c478bd9Sstevel@tonic-gateIf the sample filter returns immediately to a command line, there was either
131*7c478bd9Sstevel@tonic-gatean error with your command or a problem creating the specified socket.
132*7c478bd9Sstevel@tonic-gateFurther logging can be captured through the syslogd daemon.  Using the
133*7c478bd9Sstevel@tonic-gate'netstat -a' command can ensure that your filter process is listening on
134*7c478bd9Sstevel@tonic-gatethe appropriate local socket.
135*7c478bd9Sstevel@tonic-gate
136*7c478bd9Sstevel@tonic-gateEmail messages must be injected via SMTP to be filtered.  There are two
137*7c478bd9Sstevel@tonic-gatesimple means of doing this; either using the 'sendmail -bs' command, or
138*7c478bd9Sstevel@tonic-gateby telnetting to port 25 of the machine configured for milter.  Once
139*7c478bd9Sstevel@tonic-gateconnected via one of these options, the session can be continued through
140*7c478bd9Sstevel@tonic-gatethe use of standard SMTP commands.
141*7c478bd9Sstevel@tonic-gate
142*7c478bd9Sstevel@tonic-gate% sendmail -bs
143*7c478bd9Sstevel@tonic-gate220 test.sendmail.com ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST)
144*7c478bd9Sstevel@tonic-gateHELO localhost
145*7c478bd9Sstevel@tonic-gate250 test.sendmail.com Hello testy@localhost, pleased to meet you
146*7c478bd9Sstevel@tonic-gateMAIL From:<testy>
147*7c478bd9Sstevel@tonic-gate250 2.1.0 <testy>... Sender ok
148*7c478bd9Sstevel@tonic-gateRCPT To:<root>
149*7c478bd9Sstevel@tonic-gate250 2.1.5 <root>... Recipient ok
150*7c478bd9Sstevel@tonic-gateDATA
151*7c478bd9Sstevel@tonic-gate354 Enter mail, end with "." on a line by itself
152*7c478bd9Sstevel@tonic-gateFrom: testy@test.sendmail.com
153*7c478bd9Sstevel@tonic-gateTo: root@test.sendmail.com
154*7c478bd9Sstevel@tonic-gateSubject: testing sample filter
155*7c478bd9Sstevel@tonic-gate
156*7c478bd9Sstevel@tonic-gateSample body
157*7c478bd9Sstevel@tonic-gate.
158*7c478bd9Sstevel@tonic-gate250 2.0.0 dB73Zxi25236 Message accepted for delivery
159*7c478bd9Sstevel@tonic-gateQUIT
160*7c478bd9Sstevel@tonic-gate221 2.0.0 test.sendmail.com closing connection
161*7c478bd9Sstevel@tonic-gate
162*7c478bd9Sstevel@tonic-gateIn the above example, the lines beginning with numbers are output by the
163*7c478bd9Sstevel@tonic-gatemail server, and those without are your input.  If everything is working
164*7c478bd9Sstevel@tonic-gateproperly, you will find a file in /tmp by the name of msg.XXXXXXXX (where
165*7c478bd9Sstevel@tonic-gatethe Xs represent any combination of letters and numbers).  This file should
166*7c478bd9Sstevel@tonic-gatecontain the message body and headers from the test email entered above.
167*7c478bd9Sstevel@tonic-gate
168*7c478bd9Sstevel@tonic-gateIf the sample filter did not log your test email, there are a number of
169*7c478bd9Sstevel@tonic-gatemethods to narrow down the source of the problem.  Check your system
170*7c478bd9Sstevel@tonic-gatelogs written by syslogd and see if there are any pertinent lines.  You
171*7c478bd9Sstevel@tonic-gatemay need to reconfigure syslogd to capture all relevant data.  Additionally,
172*7c478bd9Sstevel@tonic-gatethe logging level of sendmail can be raised with the LogLevel option.
173*7c478bd9Sstevel@tonic-gateSee the sendmail(8) manual page for more information.
174*7c478bd9Sstevel@tonic-gate
175*7c478bd9Sstevel@tonic-gate
176*7c478bd9Sstevel@tonic-gate+--------------------------+
177*7c478bd9Sstevel@tonic-gate| SOURCE FOR SAMPLE FILTER |
178*7c478bd9Sstevel@tonic-gate+--------------------------+
179*7c478bd9Sstevel@tonic-gate
180*7c478bd9Sstevel@tonic-gate/* A trivial filter that logs all email to a file. */
181*7c478bd9Sstevel@tonic-gate
182*7c478bd9Sstevel@tonic-gate#include <sys/types.h>
183*7c478bd9Sstevel@tonic-gate#include <stdio.h>
184*7c478bd9Sstevel@tonic-gate#include <stdlib.h>
185*7c478bd9Sstevel@tonic-gate#include <string.h>
186*7c478bd9Sstevel@tonic-gate#include <sysexits.h>
187*7c478bd9Sstevel@tonic-gate#include <unistd.h>
188*7c478bd9Sstevel@tonic-gate
189*7c478bd9Sstevel@tonic-gate#include "libmilter/mfapi.h"
190*7c478bd9Sstevel@tonic-gate
191*7c478bd9Sstevel@tonic-gate#ifndef true
192*7c478bd9Sstevel@tonic-gatetypedef int bool;
193*7c478bd9Sstevel@tonic-gate# define false	0
194*7c478bd9Sstevel@tonic-gate# define true	1
195*7c478bd9Sstevel@tonic-gate#endif /* ! true */
196*7c478bd9Sstevel@tonic-gate
197*7c478bd9Sstevel@tonic-gatestruct mlfiPriv
198*7c478bd9Sstevel@tonic-gate{
199*7c478bd9Sstevel@tonic-gate	char	*mlfi_fname;
200*7c478bd9Sstevel@tonic-gate	FILE	*mlfi_fp;
201*7c478bd9Sstevel@tonic-gate};
202*7c478bd9Sstevel@tonic-gate
203*7c478bd9Sstevel@tonic-gate#define MLFIPRIV	((struct mlfiPriv *) smfi_getpriv(ctx))
204*7c478bd9Sstevel@tonic-gate
205*7c478bd9Sstevel@tonic-gateextern sfsistat	 mlfi_cleanup(SMFICTX *, bool);
206*7c478bd9Sstevel@tonic-gate
207*7c478bd9Sstevel@tonic-gatesfsistat
208*7c478bd9Sstevel@tonic-gatemlfi_envfrom(ctx, envfrom)
209*7c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
210*7c478bd9Sstevel@tonic-gate	char **envfrom;
211*7c478bd9Sstevel@tonic-gate{
212*7c478bd9Sstevel@tonic-gate	struct mlfiPriv *priv;
213*7c478bd9Sstevel@tonic-gate	int fd = -1;
214*7c478bd9Sstevel@tonic-gate
215*7c478bd9Sstevel@tonic-gate	/* allocate some private memory */
216*7c478bd9Sstevel@tonic-gate	priv = malloc(sizeof *priv);
217*7c478bd9Sstevel@tonic-gate	if (priv == NULL)
218*7c478bd9Sstevel@tonic-gate	{
219*7c478bd9Sstevel@tonic-gate		/* can't accept this message right now */
220*7c478bd9Sstevel@tonic-gate		return SMFIS_TEMPFAIL;
221*7c478bd9Sstevel@tonic-gate	}
222*7c478bd9Sstevel@tonic-gate	memset(priv, '\0', sizeof *priv);
223*7c478bd9Sstevel@tonic-gate
224*7c478bd9Sstevel@tonic-gate	/* open a file to store this message */
225*7c478bd9Sstevel@tonic-gate	priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX");
226*7c478bd9Sstevel@tonic-gate	if (priv->mlfi_fname == NULL)
227*7c478bd9Sstevel@tonic-gate	{
228*7c478bd9Sstevel@tonic-gate		free(priv);
229*7c478bd9Sstevel@tonic-gate		return SMFIS_TEMPFAIL;
230*7c478bd9Sstevel@tonic-gate	}
231*7c478bd9Sstevel@tonic-gate	if ((fd = mkstemp(priv->mlfi_fname)) < 0 ||
232*7c478bd9Sstevel@tonic-gate	    (priv->mlfi_fp = fdopen(fd, "w+")) == NULL)
233*7c478bd9Sstevel@tonic-gate	{
234*7c478bd9Sstevel@tonic-gate		if (fd >= 0)
235*7c478bd9Sstevel@tonic-gate			(void) close(fd);
236*7c478bd9Sstevel@tonic-gate		free(priv->mlfi_fname);
237*7c478bd9Sstevel@tonic-gate		free(priv);
238*7c478bd9Sstevel@tonic-gate		return SMFIS_TEMPFAIL;
239*7c478bd9Sstevel@tonic-gate	}
240*7c478bd9Sstevel@tonic-gate
241*7c478bd9Sstevel@tonic-gate	/* save the private data */
242*7c478bd9Sstevel@tonic-gate	smfi_setpriv(ctx, priv);
243*7c478bd9Sstevel@tonic-gate
244*7c478bd9Sstevel@tonic-gate	/* continue processing */
245*7c478bd9Sstevel@tonic-gate	return SMFIS_CONTINUE;
246*7c478bd9Sstevel@tonic-gate}
247*7c478bd9Sstevel@tonic-gate
248*7c478bd9Sstevel@tonic-gatesfsistat
249*7c478bd9Sstevel@tonic-gatemlfi_header(ctx, headerf, headerv)
250*7c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
251*7c478bd9Sstevel@tonic-gate	char *headerf;
252*7c478bd9Sstevel@tonic-gate	char *headerv;
253*7c478bd9Sstevel@tonic-gate{
254*7c478bd9Sstevel@tonic-gate	/* write the header to the log file */
255*7c478bd9Sstevel@tonic-gate	fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv);
256*7c478bd9Sstevel@tonic-gate
257*7c478bd9Sstevel@tonic-gate	/* continue processing */
258*7c478bd9Sstevel@tonic-gate	return SMFIS_CONTINUE;
259*7c478bd9Sstevel@tonic-gate}
260*7c478bd9Sstevel@tonic-gate
261*7c478bd9Sstevel@tonic-gatesfsistat
262*7c478bd9Sstevel@tonic-gatemlfi_eoh(ctx)
263*7c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
264*7c478bd9Sstevel@tonic-gate{
265*7c478bd9Sstevel@tonic-gate	/* output the blank line between the header and the body */
266*7c478bd9Sstevel@tonic-gate	fprintf(MLFIPRIV->mlfi_fp, "\r\n");
267*7c478bd9Sstevel@tonic-gate
268*7c478bd9Sstevel@tonic-gate	/* continue processing */
269*7c478bd9Sstevel@tonic-gate	return SMFIS_CONTINUE;
270*7c478bd9Sstevel@tonic-gate}
271*7c478bd9Sstevel@tonic-gate
272*7c478bd9Sstevel@tonic-gatesfsistat
273*7c478bd9Sstevel@tonic-gatemlfi_body(ctx, bodyp, bodylen)
274*7c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
275*7c478bd9Sstevel@tonic-gate	u_char *bodyp;
276*7c478bd9Sstevel@tonic-gate	size_t bodylen;
277*7c478bd9Sstevel@tonic-gate{
278*7c478bd9Sstevel@tonic-gate	/* output body block to log file */
279*7c478bd9Sstevel@tonic-gate	if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) == 0)
280*7c478bd9Sstevel@tonic-gate	{
281*7c478bd9Sstevel@tonic-gate		/* write failed */
282*7c478bd9Sstevel@tonic-gate		(void) mlfi_cleanup(ctx, false);
283*7c478bd9Sstevel@tonic-gate		return SMFIS_TEMPFAIL;
284*7c478bd9Sstevel@tonic-gate	}
285*7c478bd9Sstevel@tonic-gate
286*7c478bd9Sstevel@tonic-gate	/* continue processing */
287*7c478bd9Sstevel@tonic-gate	return SMFIS_CONTINUE;
288*7c478bd9Sstevel@tonic-gate}
289*7c478bd9Sstevel@tonic-gate
290*7c478bd9Sstevel@tonic-gatesfsistat
291*7c478bd9Sstevel@tonic-gatemlfi_eom(ctx)
292*7c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
293*7c478bd9Sstevel@tonic-gate{
294*7c478bd9Sstevel@tonic-gate	return mlfi_cleanup(ctx, true);
295*7c478bd9Sstevel@tonic-gate}
296*7c478bd9Sstevel@tonic-gate
297*7c478bd9Sstevel@tonic-gatesfsistat
298*7c478bd9Sstevel@tonic-gatemlfi_close(ctx)
299*7c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
300*7c478bd9Sstevel@tonic-gate{
301*7c478bd9Sstevel@tonic-gate	return SMFIS_ACCEPT;
302*7c478bd9Sstevel@tonic-gate}
303*7c478bd9Sstevel@tonic-gate
304*7c478bd9Sstevel@tonic-gatesfsistat
305*7c478bd9Sstevel@tonic-gatemlfi_abort(ctx)
306*7c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
307*7c478bd9Sstevel@tonic-gate{
308*7c478bd9Sstevel@tonic-gate	return mlfi_cleanup(ctx, false);
309*7c478bd9Sstevel@tonic-gate}
310*7c478bd9Sstevel@tonic-gate
311*7c478bd9Sstevel@tonic-gatesfsistat
312*7c478bd9Sstevel@tonic-gatemlfi_cleanup(ctx, ok)
313*7c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
314*7c478bd9Sstevel@tonic-gate	bool ok;
315*7c478bd9Sstevel@tonic-gate{
316*7c478bd9Sstevel@tonic-gate	sfsistat rstat = SMFIS_CONTINUE;
317*7c478bd9Sstevel@tonic-gate	struct mlfiPriv *priv = MLFIPRIV;
318*7c478bd9Sstevel@tonic-gate	char *p;
319*7c478bd9Sstevel@tonic-gate	char host[512];
320*7c478bd9Sstevel@tonic-gate	char hbuf[1024];
321*7c478bd9Sstevel@tonic-gate
322*7c478bd9Sstevel@tonic-gate	if (priv == NULL)
323*7c478bd9Sstevel@tonic-gate		return rstat;
324*7c478bd9Sstevel@tonic-gate
325*7c478bd9Sstevel@tonic-gate	/* close the archive file */
326*7c478bd9Sstevel@tonic-gate	if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF)
327*7c478bd9Sstevel@tonic-gate	{
328*7c478bd9Sstevel@tonic-gate		/* failed; we have to wait until later */
329*7c478bd9Sstevel@tonic-gate		rstat = SMFIS_TEMPFAIL;
330*7c478bd9Sstevel@tonic-gate		(void) unlink(priv->mlfi_fname);
331*7c478bd9Sstevel@tonic-gate	}
332*7c478bd9Sstevel@tonic-gate	else if (ok)
333*7c478bd9Sstevel@tonic-gate	{
334*7c478bd9Sstevel@tonic-gate		/* add a header to the message announcing our presence */
335*7c478bd9Sstevel@tonic-gate		if (gethostname(host, sizeof host) < 0)
336*7c478bd9Sstevel@tonic-gate			snprintf(host, sizeof host, "localhost");
337*7c478bd9Sstevel@tonic-gate		p = strrchr(priv->mlfi_fname, '/');
338*7c478bd9Sstevel@tonic-gate		if (p == NULL)
339*7c478bd9Sstevel@tonic-gate			p = priv->mlfi_fname;
340*7c478bd9Sstevel@tonic-gate		else
341*7c478bd9Sstevel@tonic-gate			p++;
342*7c478bd9Sstevel@tonic-gate		snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
343*7c478bd9Sstevel@tonic-gate		smfi_addheader(ctx, "X-Archived", hbuf);
344*7c478bd9Sstevel@tonic-gate	}
345*7c478bd9Sstevel@tonic-gate	else
346*7c478bd9Sstevel@tonic-gate	{
347*7c478bd9Sstevel@tonic-gate		/* message was aborted -- delete the archive file */
348*7c478bd9Sstevel@tonic-gate		(void) unlink(priv->mlfi_fname);
349*7c478bd9Sstevel@tonic-gate	}
350*7c478bd9Sstevel@tonic-gate
351*7c478bd9Sstevel@tonic-gate	/* release private memory */
352*7c478bd9Sstevel@tonic-gate	free(priv->mlfi_fname);
353*7c478bd9Sstevel@tonic-gate	free(priv);
354*7c478bd9Sstevel@tonic-gate	smfi_setpriv(ctx, NULL);
355*7c478bd9Sstevel@tonic-gate
356*7c478bd9Sstevel@tonic-gate	/* return status */
357*7c478bd9Sstevel@tonic-gate	return rstat;
358*7c478bd9Sstevel@tonic-gate}
359*7c478bd9Sstevel@tonic-gate
360*7c478bd9Sstevel@tonic-gatestruct smfiDesc smfilter =
361*7c478bd9Sstevel@tonic-gate{
362*7c478bd9Sstevel@tonic-gate	"SampleFilter",	/* filter name */
363*7c478bd9Sstevel@tonic-gate	SMFI_VERSION,	/* version code -- do not change */
364*7c478bd9Sstevel@tonic-gate	SMFIF_ADDHDRS,	/* flags */
365*7c478bd9Sstevel@tonic-gate	NULL,		/* connection info filter */
366*7c478bd9Sstevel@tonic-gate	NULL,		/* SMTP HELO command filter */
367*7c478bd9Sstevel@tonic-gate	mlfi_envfrom,	/* envelope sender filter */
368*7c478bd9Sstevel@tonic-gate	NULL,		/* envelope recipient filter */
369*7c478bd9Sstevel@tonic-gate	mlfi_header,	/* header filter */
370*7c478bd9Sstevel@tonic-gate	mlfi_eoh,	/* end of header */
371*7c478bd9Sstevel@tonic-gate	mlfi_body,	/* body block filter */
372*7c478bd9Sstevel@tonic-gate	mlfi_eom,	/* end of message */
373*7c478bd9Sstevel@tonic-gate	mlfi_abort,	/* message aborted */
374*7c478bd9Sstevel@tonic-gate	mlfi_close	/* connection cleanup */
375*7c478bd9Sstevel@tonic-gate};
376*7c478bd9Sstevel@tonic-gate
377*7c478bd9Sstevel@tonic-gate
378*7c478bd9Sstevel@tonic-gateint
379*7c478bd9Sstevel@tonic-gatemain(argc, argv)
380*7c478bd9Sstevel@tonic-gate	int argc;
381*7c478bd9Sstevel@tonic-gate	char *argv[];
382*7c478bd9Sstevel@tonic-gate{
383*7c478bd9Sstevel@tonic-gate	bool setconn = false;
384*7c478bd9Sstevel@tonic-gate	int c;
385*7c478bd9Sstevel@tonic-gate	const char *args = "p:";
386*7c478bd9Sstevel@tonic-gate
387*7c478bd9Sstevel@tonic-gate	/* Process command line options */
388*7c478bd9Sstevel@tonic-gate	while ((c = getopt(argc, argv, args)) != -1)
389*7c478bd9Sstevel@tonic-gate	{
390*7c478bd9Sstevel@tonic-gate		switch (c)
391*7c478bd9Sstevel@tonic-gate		{
392*7c478bd9Sstevel@tonic-gate		  case 'p':
393*7c478bd9Sstevel@tonic-gate			if (optarg == NULL || *optarg == '\0')
394*7c478bd9Sstevel@tonic-gate			{
395*7c478bd9Sstevel@tonic-gate				(void) fprintf(stderr, "Illegal conn: %s\n",
396*7c478bd9Sstevel@tonic-gate					       optarg);
397*7c478bd9Sstevel@tonic-gate				exit(EX_USAGE);
398*7c478bd9Sstevel@tonic-gate			}
399*7c478bd9Sstevel@tonic-gate			(void) smfi_setconn(optarg);
400*7c478bd9Sstevel@tonic-gate			setconn = true;
401*7c478bd9Sstevel@tonic-gate			break;
402*7c478bd9Sstevel@tonic-gate
403*7c478bd9Sstevel@tonic-gate		}
404*7c478bd9Sstevel@tonic-gate	}
405*7c478bd9Sstevel@tonic-gate	if (!setconn)
406*7c478bd9Sstevel@tonic-gate	{
407*7c478bd9Sstevel@tonic-gate		fprintf(stderr, "%s: Missing required -p argument\n", argv[0]);
408*7c478bd9Sstevel@tonic-gate		exit(EX_USAGE);
409*7c478bd9Sstevel@tonic-gate	}
410*7c478bd9Sstevel@tonic-gate	if (smfi_register(smfilter) == MI_FAILURE)
411*7c478bd9Sstevel@tonic-gate	{
412*7c478bd9Sstevel@tonic-gate		fprintf(stderr, "smfi_register failed\n");
413*7c478bd9Sstevel@tonic-gate		exit(EX_UNAVAILABLE);
414*7c478bd9Sstevel@tonic-gate	}
415*7c478bd9Sstevel@tonic-gate	return smfi_main();
416*7c478bd9Sstevel@tonic-gate}
417*7c478bd9Sstevel@tonic-gate
418*7c478bd9Sstevel@tonic-gate/* eof */
419*7c478bd9Sstevel@tonic-gate
420*7c478bd9Sstevel@tonic-gate$Revision: 8.35.2.2 $, Last updated $Date: 2003/05/26 04:10:06 $
421