8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sendmail / libmilter / example.c
blobcef4b0f33aa280b3e3341ca67ddd63848101d812
1 /*
2 * Copyright (c) 2006 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
9 * $Id: example.c,v 8.4 2008/07/22 15:12:47 ca Exp $
13 ** A trivial example filter that logs all email to a file.
14 ** This milter also has some callbacks which it does not really use,
15 ** but they are defined to serve as an example.
18 #include <sys/types.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sysexits.h>
23 #include <unistd.h>
25 #include "libmilter/mfapi.h"
26 #include "libmilter/mfdef.h"
28 #ifndef true
29 # define false 0
30 # define true 1
31 #endif /* ! true */
33 struct mlfiPriv
35 char *mlfi_fname;
36 FILE *mlfi_fp;
39 #define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx))
41 static unsigned long mta_caps = 0;
43 sfsistat
44 mlfi_cleanup(ctx, ok)
45 SMFICTX *ctx;
46 bool ok;
48 sfsistat rstat = SMFIS_CONTINUE;
49 struct mlfiPriv *priv = MLFIPRIV;
50 char *p;
51 char host[512];
52 char hbuf[1024];
54 if (priv == NULL)
55 return rstat;
57 /* close the archive file */
58 if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF)
60 /* failed; we have to wait until later */
61 rstat = SMFIS_TEMPFAIL;
62 (void) unlink(priv->mlfi_fname);
64 else if (ok)
66 /* add a header to the message announcing our presence */
67 if (gethostname(host, sizeof host) < 0)
68 snprintf(host, sizeof host, "localhost");
69 p = strrchr(priv->mlfi_fname, '/');
70 if (p == NULL)
71 p = priv->mlfi_fname;
72 else
73 p++;
74 snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
75 smfi_addheader(ctx, "X-Archived", hbuf);
77 else
79 /* message was aborted -- delete the archive file */
80 (void) unlink(priv->mlfi_fname);
83 /* release private memory */
84 free(priv->mlfi_fname);
85 free(priv);
86 smfi_setpriv(ctx, NULL);
88 /* return status */
89 return rstat;
93 sfsistat
94 mlfi_envfrom(ctx, envfrom)
95 SMFICTX *ctx;
96 char **envfrom;
98 struct mlfiPriv *priv;
99 int fd = -1;
101 /* allocate some private memory */
102 priv = malloc(sizeof *priv);
103 if (priv == NULL)
105 /* can't accept this message right now */
106 return SMFIS_TEMPFAIL;
108 memset(priv, '\0', sizeof *priv);
110 /* open a file to store this message */
111 priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX");
112 if (priv->mlfi_fname == NULL)
114 free(priv);
115 return SMFIS_TEMPFAIL;
117 if ((fd = mkstemp(priv->mlfi_fname)) < 0 ||
118 (priv->mlfi_fp = fdopen(fd, "w+")) == NULL)
120 if (fd >= 0)
121 (void) close(fd);
122 free(priv->mlfi_fname);
123 free(priv);
124 return SMFIS_TEMPFAIL;
127 /* save the private data */
128 smfi_setpriv(ctx, priv);
130 /* continue processing */
131 return SMFIS_CONTINUE;
134 sfsistat
135 mlfi_header(ctx, headerf, headerv)
136 SMFICTX *ctx;
137 char *headerf;
138 char *headerv;
140 /* write the header to the log file */
141 fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv);
143 /* continue processing */
144 return ((mta_caps & SMFIP_NR_HDR) != 0)
145 ? SMFIS_NOREPLY : SMFIS_CONTINUE;
148 sfsistat
149 mlfi_eoh(ctx)
150 SMFICTX *ctx;
152 /* output the blank line between the header and the body */
153 fprintf(MLFIPRIV->mlfi_fp, "\r\n");
155 /* continue processing */
156 return SMFIS_CONTINUE;
159 sfsistat
160 mlfi_body(ctx, bodyp, bodylen)
161 SMFICTX *ctx;
162 u_char *bodyp;
163 size_t bodylen;
165 /* output body block to log file */
166 if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0)
168 /* write failed */
169 (void) mlfi_cleanup(ctx, false);
170 return SMFIS_TEMPFAIL;
173 /* continue processing */
174 return SMFIS_CONTINUE;
177 sfsistat
178 mlfi_eom(ctx)
179 SMFICTX *ctx;
181 return mlfi_cleanup(ctx, true);
184 sfsistat
185 mlfi_close(ctx)
186 SMFICTX *ctx;
188 return SMFIS_ACCEPT;
191 sfsistat
192 mlfi_abort(ctx)
193 SMFICTX *ctx;
195 return mlfi_cleanup(ctx, false);
198 sfsistat
199 mlfi_unknown(ctx, cmd)
200 SMFICTX *ctx;
201 char *cmd;
203 return SMFIS_CONTINUE;
206 sfsistat
207 mlfi_data(ctx)
208 SMFICTX *ctx;
210 return SMFIS_CONTINUE;
213 sfsistat
214 mlfi_negotiate(ctx, f0, f1, f2, f3, pf0, pf1, pf2, pf3)
215 SMFICTX *ctx;
216 unsigned long f0;
217 unsigned long f1;
218 unsigned long f2;
219 unsigned long f3;
220 unsigned long *pf0;
221 unsigned long *pf1;
222 unsigned long *pf2;
223 unsigned long *pf3;
225 /* milter actions: add headers */
226 *pf0 = SMFIF_ADDHDRS;
228 /* milter protocol steps: all but connect, HELO, RCPT */
229 *pf1 = SMFIP_NOCONNECT|SMFIP_NOHELO|SMFIP_NORCPT;
230 mta_caps = f1;
231 if ((mta_caps & SMFIP_NR_HDR) != 0)
232 *pf1 |= SMFIP_NR_HDR;
233 *pf2 = 0;
234 *pf3 = 0;
235 return SMFIS_CONTINUE;
238 struct smfiDesc smfilter =
240 "SampleFilter", /* filter name */
241 SMFI_VERSION, /* version code -- do not change */
242 SMFIF_ADDHDRS, /* flags */
243 NULL, /* connection info filter */
244 NULL, /* SMTP HELO command filter */
245 mlfi_envfrom, /* envelope sender filter */
246 NULL, /* envelope recipient filter */
247 mlfi_header, /* header filter */
248 mlfi_eoh, /* end of header */
249 mlfi_body, /* body block filter */
250 mlfi_eom, /* end of message */
251 mlfi_abort, /* message aborted */
252 mlfi_close, /* connection cleanup */
253 mlfi_unknown, /* unknown/unimplemented SMTP commands */
254 mlfi_data, /* DATA command filter */
255 mlfi_negotiate /* option negotiation at connection startup */
259 main(argc, argv)
260 int argc;
261 char *argv[];
263 bool setconn;
264 int c;
266 setconn = false;
268 /* Process command line options */
269 while ((c = getopt(argc, argv, "p:")) != -1)
271 switch (c)
273 case 'p':
274 if (optarg == NULL || *optarg == '\0')
276 (void) fprintf(stderr, "Illegal conn: %s\n",
277 optarg);
278 exit(EX_USAGE);
280 (void) smfi_setconn(optarg);
281 setconn = true;
282 break;
286 if (!setconn)
288 fprintf(stderr, "%s: Missing required -p argument\n", argv[0]);
289 exit(EX_USAGE);
291 if (smfi_register(smfilter) == MI_FAILURE)
293 fprintf(stderr, "smfi_register failed\n");
294 exit(EX_UNAVAILABLE);
296 return smfi_main();