5
/* delivery status buffer
7
/* #include <dsn_buf.h>
11
/* /* Convenience member */
12
/* DSN dsn; /* light-weight, dsn(3) */
13
/* /* Formal members... */
14
/* VSTRING *status; /* RFC 3463 */
15
/* VSTRING *action; /* RFC 3464 */
16
/* VSTRING *mtype; /* dns */
17
/* VSTRING *mname; /* host or domain */
18
/* VSTRING *dtype; /* smtp, x-unix */
19
/* VSTRING *dtext; /* RFC 2821, sysexits.h */
20
/* /* Informal members... */
21
/* VSTRING *reason; /* informal text */
25
/* DSN_BUF *dsb_create(void)
27
/* DSN_BUF *dsb_update(dsb, status, action, mtype, mname, dtype,
28
/* dtext, reason_fmt, ...)
30
/* const char *status;
31
/* const char *action;
36
/* const char *reason_fmt;
38
/* DSN_BUF *dsb_simple(dsb, status, reason_fmt, ...)
40
/* const char *status;
41
/* const char *reason_fmt;
43
/* DSN_BUF *dsb_unix(dsb, status, dtext, reason_fmt, ...)
45
/* const char *status;
46
/* const char *reason_fmt;
48
/* DSN_BUF *dsb_formal(dsb, status, action, mtype, mname, dtype,
51
/* const char *status;
52
/* const char *action;
58
/* DSN_BUF *dsb_status(dsb, status)
60
/* const char *status;
62
/* void dsb_reset(dsb)
68
/* DSN *DSN_FROM_DSN_BUF(dsb)
71
/* This module implements a simple to update delivery status
72
/* buffer for Postfix-internal use. Typically it is filled in
73
/* the course of delivery attempt, and then formatted into a
74
/* DSN structure for external notification.
76
/* dsb_create() creates initialized storage for formal RFC 3464
77
/* attributes, and human-readable informal text.
79
/* dsb_update() updates all fields.
81
/* dsb_simple() updates the status and informal text, and resets all
82
/* other fields to defaults.
84
/* dsb_unix() updates the status, diagnostic code, diagnostic
85
/* text, and informal text, sets the diagnostic type to UNIX,
86
/* and resets all other fields to defaults.
88
/* dsb_formal() updates all fields except the informal text.
90
/* dsb_status() updates the status field, and resets all
91
/* formal fields to defaults.
93
/* dsb_reset() resets all fields in a DSN_BUF structure without
94
/* deallocating memory.
96
/* dsb_free() recycles the storage that was allocated by
97
/* dsb_create(), and so on.
99
/* DSN_FROM_DSN_BUF() populates the DSN member with a shallow
100
/* copy of the contents of the formal and informal fields, and
101
/* returns a pointer to the DSN member. This is typically used
102
/* for external reporting.
106
/* Delivery status buffer.
108
/* RFC 3463 "enhanced" status code.
110
/* RFC 3464 action code; specify DSB_DEF_ACTION to derive the
111
/* action from the status value. The only values that really
112
/* matter here are "expanded" and "relayed"; all other values
113
/* are already implied by the context.
115
/* The remote MTA type.
116
/* The only valid type is DSB_MTYPE_DNS. The macro DSB_SKIP_RMTA
117
/* conveniently expands into a null argument list for the
118
/* remote MTA type and name.
123
/* DSB_DTYPE_SMTP or DSB_DTYPE_UNIX. The macro DSB_SKIP_REPLY
124
/* conveniently expands into a null argument list for the reply
127
/* The reply text. The reply text is reset when dtype is
130
/* The informal reason format.
132
/* msg(3) diagnostics interface
134
/* Fatal: out of memory.
138
/* The Secure Mailer license must be distributed with this software.
141
/* IBM T.J. Watson Research
143
/* Yorktown Heights, NY 10598, USA
146
/* System library. */
148
#include <sys_defs.h>
149
#include <stdlib.h> /* 44BSD stdarg.h uses abort() */
153
/* Utility library. */
156
#include <mymalloc.h>
159
/* Global library. */
163
/* Application-specific. */
165
#define STR(x) vstring_str(x)
167
/* dsb_create - create delivery status buffer */
169
DSN_BUF *dsb_create(void)
174
* Some fields aren't needed until we want to report an error.
176
dsb = (DSN_BUF *) mymalloc(sizeof(*dsb));
177
dsb->status = vstring_alloc(10);
178
dsb->action = vstring_alloc(10);
179
dsb->mtype = vstring_alloc(10);
180
dsb->mname = vstring_alloc(100);
181
dsb->dtype = vstring_alloc(10);
182
dsb->dtext = vstring_alloc(100);
183
dsb->reason = vstring_alloc(100);
188
/* dsb_free - destroy storage */
190
void dsb_free(DSN_BUF *dsb)
192
vstring_free(dsb->status);
193
vstring_free(dsb->action);
194
vstring_free(dsb->mtype);
195
vstring_free(dsb->mname);
196
vstring_free(dsb->dtype);
197
vstring_free(dsb->dtext);
198
vstring_free(dsb->reason);
199
myfree((char *) dsb);
203
* Initial versions of this code represented unavailable inputs with null
204
* pointers, which produced fragile and hard to maintain code. The current
205
* code uses empty strings instead of null pointers.
207
* For safety we keep the test for null pointers in input. It's cheap.
209
#define DSB_TRUNCATE(s) (STR(s)[0] = 0)
211
#define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
213
#define DSB_ACTION(dsb, stat, act) \
214
vstring_strcpy((dsb)->action, !NULL_OR_EMPTY(act) ? (act) : "")
216
#define DSB_MTA(dsb, type, name) do { \
217
if (NULL_OR_EMPTY(type) || NULL_OR_EMPTY(name)) { \
218
DSB_TRUNCATE((dsb)->mtype); \
219
DSB_TRUNCATE((dsb)->mname); \
221
vstring_strcpy((dsb)->mtype, (type)); \
222
vstring_strcpy((dsb)->mname, (name)); \
226
#define DSB_DIAG(dsb, type, text) do { \
227
if (NULL_OR_EMPTY(type) || NULL_OR_EMPTY(text)) { \
228
DSB_TRUNCATE((dsb)->dtype); \
229
DSB_TRUNCATE((dsb)->dtext); \
231
vstring_strcpy((dsb)->dtype, (type)); \
232
vstring_strcpy((dsb)->dtext, (text)); \
236
/* dsb_update - update formal attributes and informal text */
238
DSN_BUF *dsb_update(DSN_BUF *dsb, const char *status, const char *action,
239
const char *mtype, const char *mname,
240
const char *dtype, const char *dtext,
241
const char *format,...)
245
vstring_strcpy(dsb->status, status);
246
DSB_ACTION(dsb, status, action);
247
DSB_MTA(dsb, mtype, mname);
248
DSB_DIAG(dsb, dtype, dtext);
249
va_start(ap, format);
250
vstring_vsprintf(dsb->reason, format, ap);
256
/* dsb_simple - update status and informal text */
258
DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
262
vstring_strcpy(dsb->status, status);
263
DSB_TRUNCATE(dsb->action);
264
DSB_TRUNCATE(dsb->mtype);
265
DSB_TRUNCATE(dsb->mname);
266
DSB_TRUNCATE(dsb->dtype);
267
DSB_TRUNCATE(dsb->dtext);
268
va_start(ap, format);
269
vstring_vsprintf(dsb->reason, format, ap);
275
/* dsb_unix - update status, UNIX diagnostic and informal text */
277
DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status,
278
const char *dtext, const char *format,...)
282
vstring_strcpy(dsb->status, status);
283
DSB_TRUNCATE(dsb->action);
284
DSB_TRUNCATE(dsb->mtype);
285
DSB_TRUNCATE(dsb->mname);
286
vstring_strcpy(dsb->dtype, DSB_DTYPE_UNIX);
287
vstring_strcpy(dsb->dtext, dtext);
288
va_start(ap, format);
289
vstring_vsprintf(dsb->reason, format, ap);
295
/* dsb_formal - update the formal fields */
297
DSN_BUF *dsb_formal(DSN_BUF *dsb, const char *status, const char *action,
298
const char *mtype, const char *mname,
299
const char *dtype, const char *dtext)
301
vstring_strcpy(dsb->status, status);
302
DSB_ACTION(dsb, status, action);
303
DSB_MTA(dsb, mtype, mname);
304
DSB_DIAG(dsb, dtype, dtext);
308
/* dsb_status - update the status, reset other formal fields */
310
DSN_BUF *dsb_status(DSN_BUF *dsb, const char *status)
312
vstring_strcpy(dsb->status, status);
313
DSB_TRUNCATE(dsb->action);
314
DSB_TRUNCATE(dsb->mtype);
315
DSB_TRUNCATE(dsb->mname);
316
DSB_TRUNCATE(dsb->dtype);
317
DSB_TRUNCATE(dsb->dtext);
321
/* dsb_reset - reset all fields */
323
void dsb_reset(DSN_BUF *dsb)
325
DSB_TRUNCATE(dsb->status);
326
DSB_TRUNCATE(dsb->action);
327
DSB_TRUNCATE(dsb->mtype);
328
DSB_TRUNCATE(dsb->mname);
329
DSB_TRUNCATE(dsb->dtype);
330
DSB_TRUNCATE(dsb->dtext);
331
DSB_TRUNCATE(dsb->reason);