~ubuntu-branches/ubuntu/trusty/postfix/trusty-updates

« back to all changes in this revision

Viewing changes to src/global/dsn_buf.c

Tags: upstream-2.3.1
ImportĀ upstreamĀ versionĀ 2.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      dsn_buf 3
 
4
/* SUMMARY
 
5
/*      delivery status buffer
 
6
/* SYNOPSIS
 
7
/*      #include <dsn_buf.h>
 
8
/*
 
9
/*      typedef struct {
 
10
/* .in +4
 
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 */
 
22
/* .in -4
 
23
/*      } DSN_BUF;
 
24
/*
 
25
/*      DSN_BUF *dsb_create(void)
 
26
/*
 
27
/*      DSN_BUF *dsb_update(dsb, status, action, mtype, mname, dtype,
 
28
/*                              dtext, reason_fmt, ...)
 
29
/*      DSN_BUF *dsb;
 
30
/*      const char *status;
 
31
/*      const char *action;
 
32
/*      const char *mtype;
 
33
/*      const char *mname;
 
34
/*      const char *dtype;
 
35
/*      const char *dtext;
 
36
/*      const char *reason_fmt;
 
37
/*
 
38
/*      DSN_BUF *dsb_simple(dsb, status, reason_fmt, ...)
 
39
/*      DSN_BUF *dsb;
 
40
/*      const char *status;
 
41
/*      const char *reason_fmt;
 
42
/*
 
43
/*      DSN_BUF *dsb_unix(dsb, status, dtext, reason_fmt, ...)
 
44
/*      DSN_BUF *dsb;
 
45
/*      const char *status;
 
46
/*      const char *reason_fmt;
 
47
/*
 
48
/*      DSN_BUF *dsb_formal(dsb, status, action, mtype, mname, dtype,
 
49
/*                              dtext)
 
50
/*      DSN_BUF *dsb;
 
51
/*      const char *status;
 
52
/*      const char *action;
 
53
/*      const char *mtype;
 
54
/*      const char *mname;
 
55
/*      const char *dtype;
 
56
/*      const char *dtext;
 
57
/*
 
58
/*      DSN_BUF *dsb_status(dsb, status)
 
59
/*      DSN_BUF *dsb;
 
60
/*      const char *status;
 
61
/*
 
62
/*      void    dsb_reset(dsb)
 
63
/*      DSN_BUF *dsb;
 
64
/*
 
65
/*      void    dsb_free(dsb)
 
66
/*      DSN_BUF *dsb;
 
67
/*
 
68
/*      DSN     *DSN_FROM_DSN_BUF(dsb)
 
69
/*      DSN_BUF *dsb;
 
70
/* DESCRIPTION
 
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.
 
75
/*
 
76
/*      dsb_create() creates initialized storage for formal RFC 3464
 
77
/*      attributes, and human-readable informal text.
 
78
/*
 
79
/*      dsb_update() updates all fields.
 
80
/*
 
81
/*      dsb_simple() updates the status and informal text, and resets all
 
82
/*      other fields to defaults.
 
83
/*
 
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.
 
87
/*
 
88
/*      dsb_formal() updates all fields except the informal text.
 
89
/*
 
90
/*      dsb_status() updates the status field, and resets all
 
91
/*      formal fields to defaults.
 
92
/*
 
93
/*      dsb_reset() resets all fields in a DSN_BUF structure without
 
94
/*      deallocating memory.
 
95
/*
 
96
/*      dsb_free() recycles the storage that was allocated by
 
97
/*      dsb_create(), and so on.
 
98
/*
 
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.
 
103
/*
 
104
/*      Arguments:
 
105
/* .IP dsb
 
106
/*      Delivery status buffer.
 
107
/* .IP status
 
108
/*      RFC 3463 "enhanced" status code.
 
109
/* .IP action
 
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.
 
114
/* .IP mtype
 
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.
 
119
/* .IP mname
 
120
/*      Remote MTA name.
 
121
/* .IP dtype
 
122
/*      The reply type.
 
123
/*      DSB_DTYPE_SMTP or DSB_DTYPE_UNIX.  The macro DSB_SKIP_REPLY
 
124
/*      conveniently expands into a null argument list for the reply
 
125
/*      type and text.
 
126
/* .IP dtext
 
127
/*      The reply text. The reply text is reset when dtype is
 
128
/*      DSB_SKIP_REPLY.
 
129
/* .IP reason_fmt
 
130
/*      The informal reason format.
 
131
/* SEE ALSO
 
132
/*      msg(3) diagnostics interface
 
133
/* DIAGNOSTICS
 
134
/*      Fatal: out of memory.
 
135
/* LICENSE
 
136
/* .ad
 
137
/* .fi
 
138
/*      The Secure Mailer license must be distributed with this software.
 
139
/* AUTHOR(S)
 
140
/*      Wietse Venema
 
141
/*      IBM T.J. Watson Research
 
142
/*      P.O. Box 704
 
143
/*      Yorktown Heights, NY 10598, USA
 
144
/*--*/
 
145
 
 
146
/* System library. */
 
147
 
 
148
#include <sys_defs.h>
 
149
#include <stdlib.h>                     /* 44BSD stdarg.h uses abort() */
 
150
#include <stdarg.h>
 
151
#include <string.h>
 
152
 
 
153
/* Utility library. */
 
154
 
 
155
#include <msg.h>
 
156
#include <mymalloc.h>
 
157
#include <vstring.h>
 
158
 
 
159
/* Global library. */
 
160
 
 
161
#include <dsn_buf.h>
 
162
 
 
163
/* Application-specific. */
 
164
 
 
165
#define STR(x)  vstring_str(x)
 
166
 
 
167
/* dsb_create - create delivery status buffer */
 
168
 
 
169
DSN_BUF *dsb_create(void)
 
170
{
 
171
    DSN_BUF *dsb;
 
172
 
 
173
    /*
 
174
     * Some fields aren't needed until we want to report an error.
 
175
     */
 
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);
 
184
 
 
185
    return (dsb);
 
186
}
 
187
 
 
188
/* dsb_free - destroy storage */
 
189
 
 
190
void    dsb_free(DSN_BUF *dsb)
 
191
{
 
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);
 
200
}
 
201
 
 
202
 /*
 
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.
 
206
  * 
 
207
  * For safety we keep the test for null pointers in input. It's cheap.
 
208
  */
 
209
#define DSB_TRUNCATE(s) (STR(s)[0] = 0)
 
210
 
 
211
#define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
 
212
 
 
213
#define DSB_ACTION(dsb, stat, act) \
 
214
    vstring_strcpy((dsb)->action, !NULL_OR_EMPTY(act) ? (act) : "")
 
215
 
 
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); \
 
220
    } else { \
 
221
        vstring_strcpy((dsb)->mtype, (type)); \
 
222
        vstring_strcpy((dsb)->mname, (name)); \
 
223
    } \
 
224
} while (0)
 
225
 
 
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); \
 
230
    } else { \
 
231
        vstring_strcpy((dsb)->dtype, (type)); \
 
232
        vstring_strcpy((dsb)->dtext, (text)); \
 
233
    } \
 
234
} while (0)
 
235
 
 
236
/* dsb_update - update formal attributes and informal text */
 
237
 
 
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,...)
 
242
{
 
243
    va_list ap;
 
244
 
 
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);
 
251
    va_end(ap);
 
252
 
 
253
    return (dsb);
 
254
}
 
255
 
 
256
/* dsb_simple - update status and informal text */
 
257
 
 
258
DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
 
259
{
 
260
    va_list ap;
 
261
 
 
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);
 
270
    va_end(ap);
 
271
 
 
272
    return (dsb);
 
273
}
 
274
 
 
275
/* dsb_unix - update status, UNIX diagnostic and informal text */
 
276
 
 
277
DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status,
 
278
                          const char *dtext, const char *format,...)
 
279
{
 
280
    va_list ap;
 
281
 
 
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);
 
290
    va_end(ap);
 
291
 
 
292
    return (dsb);
 
293
}
 
294
 
 
295
/* dsb_formal - update the formal fields */
 
296
 
 
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)
 
300
{
 
301
    vstring_strcpy(dsb->status, status);
 
302
    DSB_ACTION(dsb, status, action);
 
303
    DSB_MTA(dsb, mtype, mname);
 
304
    DSB_DIAG(dsb, dtype, dtext);
 
305
    return (dsb);
 
306
}
 
307
 
 
308
/* dsb_status - update the status, reset other formal fields */
 
309
 
 
310
DSN_BUF *dsb_status(DSN_BUF *dsb, const char *status)
 
311
{
 
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);
 
318
    return (dsb);
 
319
}
 
320
 
 
321
/* dsb_reset - reset all fields */
 
322
 
 
323
void    dsb_reset(DSN_BUF *dsb)
 
324
{
 
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);
 
332
}