diff options
Diffstat (limited to 'contrib/sendmail/libmilter/docs/sample.html')
-rw-r--r-- | contrib/sendmail/libmilter/docs/sample.html | 426 |
1 files changed, 426 insertions, 0 deletions
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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sysexits.h> +#include <unistd.h> +#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->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->mlfi_helofrom) + free(priv->mlfi_helofrom); + priv->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->mlfi_fname = strdup("/tmp/msg.XXXXXX"); + mkstemp(priv->mlfi_fname); + if (priv->mlfi_fname == NULL) + return SMFIS_TEMPFAIL; + if ((priv->mlfi_fp = fopen(priv->mlfi_fname, "w+")) == NULL) + { + free(priv->mlfi_fname); + return SMFIS_TEMPFAIL; + } + + /* count the arguments */ + while(*argv++) ++argc; + /* log the connection information we stored earlier: */ + if(fprintf(priv->mlfi_fp, "Connect from %s (%s)\n\n", + priv->mlfi_helofrom, priv->mlfi_connectfrom) == EOF) { + (void) mlfi_cleanup(ctx, FALSE); + return SMFIS_TEMPFAIL; + } + /* log the sender */ + if(fprintf(priv->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->mlfi_fp, "RCPT %s -- REJECTED\n", rcptaddr) + == EOF) { + (void) mlfi_cleanup(ctx, FALSE); + return SMFIS_TEMPFAIL; + } + return SMFIS_REJECT; + } + if(fprintf(priv->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->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->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->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->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF) + { + /* failed; we have to wait until later */ + fprintf(stderr, "Couldn't close archive file %s: %s\n", + priv->mlfi_fname, strerror(errno)); + rstat = SMFIS_TEMPFAIL; + (void) unlink(priv->mlfi_fname); + } + else if (ok) + { + /* add a header to the message announcing our presence */ + if (gethostname(host, sizeof host) < 0) + strncpy(host, "localhost", sizeof host); + p = strrchr(priv->mlfi_fname, '/'); + if (p == NULL) + p = priv->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->mlfi_fname); + rstat = SMFIS_TEMPFAIL; + (void) unlink(priv->mlfi_fname); + } + + /* release private memory */ + free(priv->mlfi_fname); + + /* return status */ + return rstat; +} + +sfsistat +<a href="xxfi_close.html">mlfi_close</a>(ctx) + SMFICTX *ctx; +{ + struct mlfiPriv *priv = MLFIPRIV; + if(priv->mlfi_connectfrom) + free(priv->mlfi_connectfrom); + if(priv->mlfi_helofrom) + free(priv->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> |