xref: /titanic_51/usr/src/cmd/sendmail/libmilter/README (revision 49218d4f8e4d84d1c08aeb267bcf6e451f2056dc)
17c478bd9Sstevel@tonic-gate#
27c478bd9Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate# Use is subject to license terms.
47c478bd9Sstevel@tonic-gate#
57c478bd9Sstevel@tonic-gate# ident	"%Z%%M%	%I%	%E% SMI"
67c478bd9Sstevel@tonic-gate#
77c478bd9Sstevel@tonic-gate
87c478bd9Sstevel@tonic-gateThe sendmail Mail Filter API (Milter) is designed to allow third-party
97c478bd9Sstevel@tonic-gateprograms access to mail messages as they are being processed in order to
107c478bd9Sstevel@tonic-gatefilter meta-information and content.
117c478bd9Sstevel@tonic-gate
127c478bd9Sstevel@tonic-gateThis README file describes the steps needed to compile and run a filter,
137c478bd9Sstevel@tonic-gatethrough reference to a sample filter which is attached at the end of this
147c478bd9Sstevel@tonic-gatefile.
157c478bd9Sstevel@tonic-gate
16*49218d4fSjbeckNote: if you want to write a milter in Java, then see
17*49218d4fSjbeckhttp://sendmail-jilter.sourceforge.net/
18*49218d4fSjbeck
197c478bd9Sstevel@tonic-gate+----------------+
207c478bd9Sstevel@tonic-gate| SECURITY HINTS |
217c478bd9Sstevel@tonic-gate+----------------+
227c478bd9Sstevel@tonic-gate
237c478bd9Sstevel@tonic-gateNote: we strongly recommend not to run any milter as root.  Libmilter
247c478bd9Sstevel@tonic-gatedoes not need root access to communicate with sendmail.  It is a
257c478bd9Sstevel@tonic-gategood security practice to run a program only with root privileges
267c478bd9Sstevel@tonic-gateif really necessary.  A milter should probably check first whether
277c478bd9Sstevel@tonic-gateit runs as root and refuse to start in that case.  libmilter will
287c478bd9Sstevel@tonic-gatenot unlink a socket when running as root.
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate+-------------------+
317c478bd9Sstevel@tonic-gate| BUILDING A FILTER |
327c478bd9Sstevel@tonic-gate+-------------------+
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gateThe following command presumes that the sample code from the end of this
357c478bd9Sstevel@tonic-gateREADME is saved to a file named 'sample.c'.
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate	cc -D_REENTRANT -o sample sample.c -lmilter
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gateFilters must be thread-safe!
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gateNote that since filters use threads, it may be necessary to alter per
427c478bd9Sstevel@tonic-gateprocess limits in your filter.  For example, you might look at using
437c478bd9Sstevel@tonic-gatesetrlimit() to increase the number of open file descriptors if your filter
447c478bd9Sstevel@tonic-gateis going to be busy.
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate+----------------------------------------+
487c478bd9Sstevel@tonic-gate| SPECIFYING FILTERS IN SENDMAIL CONFIGS |
497c478bd9Sstevel@tonic-gate+----------------------------------------+
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gateFilters are specified with a key letter ``X'' (for ``eXternal'').
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gateFor example:
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate	Xfilter1, S=local:/var/run/f1.sock, F=R
567c478bd9Sstevel@tonic-gate	Xfilter2, S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m
577c478bd9Sstevel@tonic-gate	Xfilter3, S=inet:3333@localhost
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gatespecifies three filters.  Filters can be specified in your .mc file using
607c478bd9Sstevel@tonic-gatethe following:
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate	INPUT_MAIL_FILTER(`filter1', `S=local:/var/run/f1.sock, F=R')
637c478bd9Sstevel@tonic-gate	INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m')
647c478bd9Sstevel@tonic-gate	INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost')
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gateThe first attaches to a Unix-domain socket in the /var/run directory; the
677c478bd9Sstevel@tonic-gatesecond uses an IPv6 socket on port 999 of localhost, and the third uses an
687c478bd9Sstevel@tonic-gateIPv4 socket on port 3333 of localhost.  The current flags (F=) are:
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate	R		Reject connection if filter unavailable
717c478bd9Sstevel@tonic-gate	T		Temporary fail connection if filter unavailable
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gateIf neither F=R nor F=T is specified, the message is passed through sendmail
747c478bd9Sstevel@tonic-gatein case of filter errors as if the failing filters were not present.
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gateFinally, you can override the default timeouts used by sendmail when
777c478bd9Sstevel@tonic-gatetalking to the filters using the T= equate.  There are four fields inside
787c478bd9Sstevel@tonic-gateof the T= equate:
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gateLetter		Meaning
817c478bd9Sstevel@tonic-gate  C		Timeout for connecting to a filter (if 0, use system timeout)
827c478bd9Sstevel@tonic-gate  S		Timeout for sending information from the MTA to a filter
837c478bd9Sstevel@tonic-gate  R		Timeout for reading reply from the filter
847c478bd9Sstevel@tonic-gate  E		Overall timeout between sending end-of-message to filter
857c478bd9Sstevel@tonic-gate		and waiting for the final acknowledgment
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gateNote the separator between each is a ';' as a ',' already separates equates
887c478bd9Sstevel@tonic-gateand therefore can't separate timeouts.  The default values (if not set in
897c478bd9Sstevel@tonic-gatethe config) are:
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gateT=C:5m;S:10s;R:10s;E:5m
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gatewhere 's' is seconds and 'm' is minutes.
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gateWhich filters are invoked and their sequencing is handled by the
967c478bd9Sstevel@tonic-gateInputMailFilters option. Note: if InputMailFilters is not defined no filters
977c478bd9Sstevel@tonic-gatewill be used.
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate	O InputMailFilters=filter1, filter2, filter3
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gateThis is is set automatically according to the order of the
1027c478bd9Sstevel@tonic-gateINPUT_MAIL_FILTER commands in your .mc file.  Alternatively, you can
1037c478bd9Sstevel@tonic-gatereset its value by setting confINPUT_MAIL_FILTERS in your .mc file.
1047c478bd9Sstevel@tonic-gateThis options causes the three filters to be called in the same order
1057c478bd9Sstevel@tonic-gatethey were specified.  It allows for possible future filtering on output
1067c478bd9Sstevel@tonic-gate(although this is not intended for this release).
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gateAlso note that a filter can be defined without adding it to the input
1097c478bd9Sstevel@tonic-gatefilter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your
1107c478bd9Sstevel@tonic-gate.mc file.
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gateTo test sendmail with the sample filter, the following might be added (in
1137c478bd9Sstevel@tonic-gatethe appropriate locations) to your .mc file:
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate	INPUT_MAIL_FILTER(`sample', `S=local:/var/run/f1.sock')
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate+------------------+
1197c478bd9Sstevel@tonic-gate| TESTING A FILTER |
1207c478bd9Sstevel@tonic-gate+------------------+
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gateOnce you have compiled a filter, modified your .mc file and restarted
1237c478bd9Sstevel@tonic-gatethe sendmail process, you will want to test that the filter performs as
1247c478bd9Sstevel@tonic-gateintended.
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gateThe sample filter takes one argument -p, which indicates the local port
1277c478bd9Sstevel@tonic-gateon which to create a listening socket for the filter.  Maintaining
1287c478bd9Sstevel@tonic-gateconsistency with the suggested options for sendmail.cf, this would be the
1297c478bd9Sstevel@tonic-gateUNIX domain socket located in /var/run/f1.sock.
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate	% ./sample -p local:/var/run/f1.sock
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gateIf the sample filter returns immediately to a command line, there was either
1347c478bd9Sstevel@tonic-gatean error with your command or a problem creating the specified socket.
1357c478bd9Sstevel@tonic-gateFurther logging can be captured through the syslogd daemon.  Using the
1367c478bd9Sstevel@tonic-gate'netstat -a' command can ensure that your filter process is listening on
1377c478bd9Sstevel@tonic-gatethe appropriate local socket.
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gateEmail messages must be injected via SMTP to be filtered.  There are two
1407c478bd9Sstevel@tonic-gatesimple means of doing this; either using the 'sendmail -bs' command, or
1417c478bd9Sstevel@tonic-gateby telnetting to port 25 of the machine configured for milter.  Once
1427c478bd9Sstevel@tonic-gateconnected via one of these options, the session can be continued through
1437c478bd9Sstevel@tonic-gatethe use of standard SMTP commands.
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate% sendmail -bs
1467c478bd9Sstevel@tonic-gate220 test.sendmail.com ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST)
1477c478bd9Sstevel@tonic-gateHELO localhost
1487c478bd9Sstevel@tonic-gate250 test.sendmail.com Hello testy@localhost, pleased to meet you
1497c478bd9Sstevel@tonic-gateMAIL From:<testy>
1507c478bd9Sstevel@tonic-gate250 2.1.0 <testy>... Sender ok
1517c478bd9Sstevel@tonic-gateRCPT To:<root>
1527c478bd9Sstevel@tonic-gate250 2.1.5 <root>... Recipient ok
1537c478bd9Sstevel@tonic-gateDATA
1547c478bd9Sstevel@tonic-gate354 Enter mail, end with "." on a line by itself
1557c478bd9Sstevel@tonic-gateFrom: testy@test.sendmail.com
1567c478bd9Sstevel@tonic-gateTo: root@test.sendmail.com
1577c478bd9Sstevel@tonic-gateSubject: testing sample filter
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gateSample body
1607c478bd9Sstevel@tonic-gate.
1617c478bd9Sstevel@tonic-gate250 2.0.0 dB73Zxi25236 Message accepted for delivery
1627c478bd9Sstevel@tonic-gateQUIT
1637c478bd9Sstevel@tonic-gate221 2.0.0 test.sendmail.com closing connection
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gateIn the above example, the lines beginning with numbers are output by the
1667c478bd9Sstevel@tonic-gatemail server, and those without are your input.  If everything is working
1677c478bd9Sstevel@tonic-gateproperly, you will find a file in /tmp by the name of msg.XXXXXXXX (where
1687c478bd9Sstevel@tonic-gatethe Xs represent any combination of letters and numbers).  This file should
1697c478bd9Sstevel@tonic-gatecontain the message body and headers from the test email entered above.
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gateIf the sample filter did not log your test email, there are a number of
1727c478bd9Sstevel@tonic-gatemethods to narrow down the source of the problem.  Check your system
1737c478bd9Sstevel@tonic-gatelogs written by syslogd and see if there are any pertinent lines.  You
1747c478bd9Sstevel@tonic-gatemay need to reconfigure syslogd to capture all relevant data.  Additionally,
1757c478bd9Sstevel@tonic-gatethe logging level of sendmail can be raised with the LogLevel option.
1767c478bd9Sstevel@tonic-gateSee the sendmail(8) manual page for more information.
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate+--------------------------+
1807c478bd9Sstevel@tonic-gate| SOURCE FOR SAMPLE FILTER |
1817c478bd9Sstevel@tonic-gate+--------------------------+
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate/* A trivial filter that logs all email to a file. */
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate#include <sys/types.h>
1867c478bd9Sstevel@tonic-gate#include <stdio.h>
1877c478bd9Sstevel@tonic-gate#include <stdlib.h>
1887c478bd9Sstevel@tonic-gate#include <string.h>
1897c478bd9Sstevel@tonic-gate#include <sysexits.h>
1907c478bd9Sstevel@tonic-gate#include <unistd.h>
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate#include "libmilter/mfapi.h"
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate#ifndef true
1957c478bd9Sstevel@tonic-gatetypedef int bool;
1967c478bd9Sstevel@tonic-gate# define false	0
1977c478bd9Sstevel@tonic-gate# define true	1
1987c478bd9Sstevel@tonic-gate#endif /* ! true */
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gatestruct mlfiPriv
2017c478bd9Sstevel@tonic-gate{
2027c478bd9Sstevel@tonic-gate	char	*mlfi_fname;
2037c478bd9Sstevel@tonic-gate	FILE	*mlfi_fp;
2047c478bd9Sstevel@tonic-gate};
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate#define MLFIPRIV	((struct mlfiPriv *) smfi_getpriv(ctx))
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gateextern sfsistat	 mlfi_cleanup(SMFICTX *, bool);
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gatesfsistat
2117c478bd9Sstevel@tonic-gatemlfi_envfrom(ctx, envfrom)
2127c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
2137c478bd9Sstevel@tonic-gate	char **envfrom;
2147c478bd9Sstevel@tonic-gate{
2157c478bd9Sstevel@tonic-gate	struct mlfiPriv *priv;
2167c478bd9Sstevel@tonic-gate	int fd = -1;
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate	/* allocate some private memory */
2197c478bd9Sstevel@tonic-gate	priv = malloc(sizeof *priv);
2207c478bd9Sstevel@tonic-gate	if (priv == NULL)
2217c478bd9Sstevel@tonic-gate	{
2227c478bd9Sstevel@tonic-gate		/* can't accept this message right now */
2237c478bd9Sstevel@tonic-gate		return SMFIS_TEMPFAIL;
2247c478bd9Sstevel@tonic-gate	}
2257c478bd9Sstevel@tonic-gate	memset(priv, '\0', sizeof *priv);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate	/* open a file to store this message */
2287c478bd9Sstevel@tonic-gate	priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX");
2297c478bd9Sstevel@tonic-gate	if (priv->mlfi_fname == NULL)
2307c478bd9Sstevel@tonic-gate	{
2317c478bd9Sstevel@tonic-gate		free(priv);
2327c478bd9Sstevel@tonic-gate		return SMFIS_TEMPFAIL;
2337c478bd9Sstevel@tonic-gate	}
2347c478bd9Sstevel@tonic-gate	if ((fd = mkstemp(priv->mlfi_fname)) < 0 ||
2357c478bd9Sstevel@tonic-gate	    (priv->mlfi_fp = fdopen(fd, "w+")) == NULL)
2367c478bd9Sstevel@tonic-gate	{
2377c478bd9Sstevel@tonic-gate		if (fd >= 0)
2387c478bd9Sstevel@tonic-gate			(void) close(fd);
2397c478bd9Sstevel@tonic-gate		free(priv->mlfi_fname);
2407c478bd9Sstevel@tonic-gate		free(priv);
2417c478bd9Sstevel@tonic-gate		return SMFIS_TEMPFAIL;
2427c478bd9Sstevel@tonic-gate	}
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate	/* save the private data */
2457c478bd9Sstevel@tonic-gate	smfi_setpriv(ctx, priv);
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate	/* continue processing */
2487c478bd9Sstevel@tonic-gate	return SMFIS_CONTINUE;
2497c478bd9Sstevel@tonic-gate}
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gatesfsistat
2527c478bd9Sstevel@tonic-gatemlfi_header(ctx, headerf, headerv)
2537c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
2547c478bd9Sstevel@tonic-gate	char *headerf;
2557c478bd9Sstevel@tonic-gate	char *headerv;
2567c478bd9Sstevel@tonic-gate{
2577c478bd9Sstevel@tonic-gate	/* write the header to the log file */
2587c478bd9Sstevel@tonic-gate	fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv);
2597c478bd9Sstevel@tonic-gate
2607c478bd9Sstevel@tonic-gate	/* continue processing */
2617c478bd9Sstevel@tonic-gate	return SMFIS_CONTINUE;
2627c478bd9Sstevel@tonic-gate}
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gatesfsistat
2657c478bd9Sstevel@tonic-gatemlfi_eoh(ctx)
2667c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
2677c478bd9Sstevel@tonic-gate{
2687c478bd9Sstevel@tonic-gate	/* output the blank line between the header and the body */
2697c478bd9Sstevel@tonic-gate	fprintf(MLFIPRIV->mlfi_fp, "\r\n");
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate	/* continue processing */
2727c478bd9Sstevel@tonic-gate	return SMFIS_CONTINUE;
2737c478bd9Sstevel@tonic-gate}
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gatesfsistat
2767c478bd9Sstevel@tonic-gatemlfi_body(ctx, bodyp, bodylen)
2777c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
2787c478bd9Sstevel@tonic-gate	u_char *bodyp;
2797c478bd9Sstevel@tonic-gate	size_t bodylen;
2807c478bd9Sstevel@tonic-gate{
2817c478bd9Sstevel@tonic-gate	/* output body block to log file */
2827c478bd9Sstevel@tonic-gate	if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) == 0)
2837c478bd9Sstevel@tonic-gate	{
2847c478bd9Sstevel@tonic-gate		/* write failed */
2857c478bd9Sstevel@tonic-gate		(void) mlfi_cleanup(ctx, false);
2867c478bd9Sstevel@tonic-gate		return SMFIS_TEMPFAIL;
2877c478bd9Sstevel@tonic-gate	}
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate	/* continue processing */
2907c478bd9Sstevel@tonic-gate	return SMFIS_CONTINUE;
2917c478bd9Sstevel@tonic-gate}
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gatesfsistat
2947c478bd9Sstevel@tonic-gatemlfi_eom(ctx)
2957c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
2967c478bd9Sstevel@tonic-gate{
2977c478bd9Sstevel@tonic-gate	return mlfi_cleanup(ctx, true);
2987c478bd9Sstevel@tonic-gate}
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gatesfsistat
3017c478bd9Sstevel@tonic-gatemlfi_close(ctx)
3027c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
3037c478bd9Sstevel@tonic-gate{
3047c478bd9Sstevel@tonic-gate	return SMFIS_ACCEPT;
3057c478bd9Sstevel@tonic-gate}
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gatesfsistat
3087c478bd9Sstevel@tonic-gatemlfi_abort(ctx)
3097c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
3107c478bd9Sstevel@tonic-gate{
3117c478bd9Sstevel@tonic-gate	return mlfi_cleanup(ctx, false);
3127c478bd9Sstevel@tonic-gate}
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gatesfsistat
3157c478bd9Sstevel@tonic-gatemlfi_cleanup(ctx, ok)
3167c478bd9Sstevel@tonic-gate	SMFICTX *ctx;
3177c478bd9Sstevel@tonic-gate	bool ok;
3187c478bd9Sstevel@tonic-gate{
3197c478bd9Sstevel@tonic-gate	sfsistat rstat = SMFIS_CONTINUE;
3207c478bd9Sstevel@tonic-gate	struct mlfiPriv *priv = MLFIPRIV;
3217c478bd9Sstevel@tonic-gate	char *p;
3227c478bd9Sstevel@tonic-gate	char host[512];
3237c478bd9Sstevel@tonic-gate	char hbuf[1024];
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate	if (priv == NULL)
3267c478bd9Sstevel@tonic-gate		return rstat;
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate	/* close the archive file */
3297c478bd9Sstevel@tonic-gate	if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF)
3307c478bd9Sstevel@tonic-gate	{
3317c478bd9Sstevel@tonic-gate		/* failed; we have to wait until later */
3327c478bd9Sstevel@tonic-gate		rstat = SMFIS_TEMPFAIL;
3337c478bd9Sstevel@tonic-gate		(void) unlink(priv->mlfi_fname);
3347c478bd9Sstevel@tonic-gate	}
3357c478bd9Sstevel@tonic-gate	else if (ok)
3367c478bd9Sstevel@tonic-gate	{
3377c478bd9Sstevel@tonic-gate		/* add a header to the message announcing our presence */
3387c478bd9Sstevel@tonic-gate		if (gethostname(host, sizeof host) < 0)
3397c478bd9Sstevel@tonic-gate			snprintf(host, sizeof host, "localhost");
3407c478bd9Sstevel@tonic-gate		p = strrchr(priv->mlfi_fname, '/');
3417c478bd9Sstevel@tonic-gate		if (p == NULL)
3427c478bd9Sstevel@tonic-gate			p = priv->mlfi_fname;
3437c478bd9Sstevel@tonic-gate		else
3447c478bd9Sstevel@tonic-gate			p++;
3457c478bd9Sstevel@tonic-gate		snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
3467c478bd9Sstevel@tonic-gate		smfi_addheader(ctx, "X-Archived", hbuf);
3477c478bd9Sstevel@tonic-gate	}
3487c478bd9Sstevel@tonic-gate	else
3497c478bd9Sstevel@tonic-gate	{
3507c478bd9Sstevel@tonic-gate		/* message was aborted -- delete the archive file */
3517c478bd9Sstevel@tonic-gate		(void) unlink(priv->mlfi_fname);
3527c478bd9Sstevel@tonic-gate	}
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate	/* release private memory */
3557c478bd9Sstevel@tonic-gate	free(priv->mlfi_fname);
3567c478bd9Sstevel@tonic-gate	free(priv);
3577c478bd9Sstevel@tonic-gate	smfi_setpriv(ctx, NULL);
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate	/* return status */
3607c478bd9Sstevel@tonic-gate	return rstat;
3617c478bd9Sstevel@tonic-gate}
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gatestruct smfiDesc smfilter =
3647c478bd9Sstevel@tonic-gate{
3657c478bd9Sstevel@tonic-gate	"SampleFilter",	/* filter name */
3667c478bd9Sstevel@tonic-gate	SMFI_VERSION,	/* version code -- do not change */
3677c478bd9Sstevel@tonic-gate	SMFIF_ADDHDRS,	/* flags */
3687c478bd9Sstevel@tonic-gate	NULL,		/* connection info filter */
3697c478bd9Sstevel@tonic-gate	NULL,		/* SMTP HELO command filter */
3707c478bd9Sstevel@tonic-gate	mlfi_envfrom,	/* envelope sender filter */
3717c478bd9Sstevel@tonic-gate	NULL,		/* envelope recipient filter */
3727c478bd9Sstevel@tonic-gate	mlfi_header,	/* header filter */
3737c478bd9Sstevel@tonic-gate	mlfi_eoh,	/* end of header */
3747c478bd9Sstevel@tonic-gate	mlfi_body,	/* body block filter */
3757c478bd9Sstevel@tonic-gate	mlfi_eom,	/* end of message */
3767c478bd9Sstevel@tonic-gate	mlfi_abort,	/* message aborted */
3777c478bd9Sstevel@tonic-gate	mlfi_close	/* connection cleanup */
3787c478bd9Sstevel@tonic-gate};
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gateint
3827c478bd9Sstevel@tonic-gatemain(argc, argv)
3837c478bd9Sstevel@tonic-gate	int argc;
3847c478bd9Sstevel@tonic-gate	char *argv[];
3857c478bd9Sstevel@tonic-gate{
3867c478bd9Sstevel@tonic-gate	bool setconn = false;
3877c478bd9Sstevel@tonic-gate	int c;
3887c478bd9Sstevel@tonic-gate	const char *args = "p:";
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate	/* Process command line options */
3917c478bd9Sstevel@tonic-gate	while ((c = getopt(argc, argv, args)) != -1)
3927c478bd9Sstevel@tonic-gate	{
3937c478bd9Sstevel@tonic-gate		switch (c)
3947c478bd9Sstevel@tonic-gate		{
3957c478bd9Sstevel@tonic-gate		  case 'p':
3967c478bd9Sstevel@tonic-gate			if (optarg == NULL || *optarg == '\0')
3977c478bd9Sstevel@tonic-gate			{
3987c478bd9Sstevel@tonic-gate				(void) fprintf(stderr, "Illegal conn: %s\n",
3997c478bd9Sstevel@tonic-gate					       optarg);
4007c478bd9Sstevel@tonic-gate				exit(EX_USAGE);
4017c478bd9Sstevel@tonic-gate			}
4027c478bd9Sstevel@tonic-gate			(void) smfi_setconn(optarg);
4037c478bd9Sstevel@tonic-gate			setconn = true;
4047c478bd9Sstevel@tonic-gate			break;
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate		}
4077c478bd9Sstevel@tonic-gate	}
4087c478bd9Sstevel@tonic-gate	if (!setconn)
4097c478bd9Sstevel@tonic-gate	{
4107c478bd9Sstevel@tonic-gate		fprintf(stderr, "%s: Missing required -p argument\n", argv[0]);
4117c478bd9Sstevel@tonic-gate		exit(EX_USAGE);
4127c478bd9Sstevel@tonic-gate	}
4137c478bd9Sstevel@tonic-gate	if (smfi_register(smfilter) == MI_FAILURE)
4147c478bd9Sstevel@tonic-gate	{
4157c478bd9Sstevel@tonic-gate		fprintf(stderr, "smfi_register failed\n");
4167c478bd9Sstevel@tonic-gate		exit(EX_UNAVAILABLE);
4177c478bd9Sstevel@tonic-gate	}
4187c478bd9Sstevel@tonic-gate	return smfi_main();
4197c478bd9Sstevel@tonic-gate}
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate/* eof */
4227c478bd9Sstevel@tonic-gate
423*49218d4fSjbeck$Revision: 8.41 $, Last updated $Date: 2005/04/27 22:47:42 $
424