Postfix3.3.1
dsn_buf.c
[詳解]
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 
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((void *) 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) \
210  do { VSTRING_RESET(s); VSTRING_TERMINATE(s); } while (0)
211 
212 #define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
213 
214 #define DSB_ACTION(dsb, stat, act) \
215  vstring_strcpy((dsb)->action, !NULL_OR_EMPTY(act) ? (act) : "")
216 
217 #define DSB_MTA(dsb, type, name) do { \
218  if (NULL_OR_EMPTY(type) || NULL_OR_EMPTY(name)) { \
219  DSB_TRUNCATE((dsb)->mtype); \
220  DSB_TRUNCATE((dsb)->mname); \
221  } else { \
222  vstring_strcpy((dsb)->mtype, (type)); \
223  vstring_strcpy((dsb)->mname, (name)); \
224  } \
225 } while (0)
226 
227 #define DSB_DIAG(dsb, type, text) do { \
228  if (NULL_OR_EMPTY(type) || NULL_OR_EMPTY(text)) { \
229  DSB_TRUNCATE((dsb)->dtype); \
230  DSB_TRUNCATE((dsb)->dtext); \
231  } else { \
232  vstring_strcpy((dsb)->dtype, (type)); \
233  vstring_strcpy((dsb)->dtext, (text)); \
234  } \
235 } while (0)
236 
237 /* dsb_update - update formal attributes and informal text */
238 
239 DSN_BUF *dsb_update(DSN_BUF *dsb, const char *status, const char *action,
240  const char *mtype, const char *mname,
241  const char *dtype, const char *dtext,
242  const char *format,...)
243 {
244  va_list ap;
245 
246  vstring_strcpy(dsb->status, status);
247  DSB_ACTION(dsb, status, action);
248  DSB_MTA(dsb, mtype, mname);
249  DSB_DIAG(dsb, dtype, dtext);
250  va_start(ap, format);
251  vstring_vsprintf(dsb->reason, format, ap);
252  va_end(ap);
253 
254  return (dsb);
255 }
256 
257 /* vdsb_simple - update status and informal text, va_list form */
258 
259 DSN_BUF *vdsb_simple(DSN_BUF *dsb, const char *status, const char *format,
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  vstring_vsprintf(dsb->reason, format, ap);
269 
270  return (dsb);
271 }
272 
273 /* dsb_simple - update status and informal text */
274 
275 DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
276 {
277  va_list ap;
278 
279  va_start(ap, format);
280  (void) vdsb_simple(dsb, status, format, ap);
281  va_end(ap);
282  return (dsb);
283 }
284 
285 /* dsb_unix - update status, UNIX diagnostic and informal text */
286 
287 DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status,
288  const char *dtext, const char *format,...)
289 {
290  va_list ap;
291 
292  vstring_strcpy(dsb->status, status);
293  DSB_TRUNCATE(dsb->action);
294  DSB_TRUNCATE(dsb->mtype);
295  DSB_TRUNCATE(dsb->mname);
297  vstring_strcpy(dsb->dtext, dtext);
298  va_start(ap, format);
299  vstring_vsprintf(dsb->reason, format, ap);
300  va_end(ap);
301 
302  return (dsb);
303 }
304 
305 /* dsb_formal - update the formal fields */
306 
307 DSN_BUF *dsb_formal(DSN_BUF *dsb, const char *status, const char *action,
308  const char *mtype, const char *mname,
309  const char *dtype, const char *dtext)
310 {
311  vstring_strcpy(dsb->status, status);
312  DSB_ACTION(dsb, status, action);
313  DSB_MTA(dsb, mtype, mname);
314  DSB_DIAG(dsb, dtype, dtext);
315  return (dsb);
316 }
317 
318 /* dsb_status - update the status, reset other formal fields */
319 
320 DSN_BUF *dsb_status(DSN_BUF *dsb, const char *status)
321 {
322  vstring_strcpy(dsb->status, status);
323  DSB_TRUNCATE(dsb->action);
324  DSB_TRUNCATE(dsb->mtype);
325  DSB_TRUNCATE(dsb->mname);
326  DSB_TRUNCATE(dsb->dtype);
327  DSB_TRUNCATE(dsb->dtext);
328  return (dsb);
329 }
330 
331 /* dsb_reset - reset all fields */
332 
333 void dsb_reset(DSN_BUF *dsb)
334 {
335  DSB_TRUNCATE(dsb->status);
336  DSB_TRUNCATE(dsb->action);
337  DSB_TRUNCATE(dsb->mtype);
338  DSB_TRUNCATE(dsb->mname);
339  DSB_TRUNCATE(dsb->dtype);
340  DSB_TRUNCATE(dsb->dtext);
341  DSB_TRUNCATE(dsb->reason);
342 }
void myfree(void *ptr)
Definition: mymalloc.c:207
DSN_BUF * dsb_create(void)
Definition: dsn_buf.c:169
DSN_BUF * dsb_update(DSN_BUF *dsb, const char *status, const char *action, const char *mtype, const char *mname, const char *dtype, const char *dtext, const char *format,...)
Definition: dsn_buf.c:239
void dsb_reset(DSN_BUF *dsb)
Definition: dsn_buf.c:333
void dsb_free(DSN_BUF *dsb)
Definition: dsn_buf.c:190
VSTRING * mname
Definition: dsn_buf.h:33
DSN_BUF * vdsb_simple(DSN_BUF *dsb, const char *status, const char *format, va_list ap)
Definition: dsn_buf.c:259
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
VSTRING * vstring_vsprintf(VSTRING *vp, const char *format, va_list ap)
Definition: vstring.c:614
VSTRING * dtype
Definition: dsn_buf.h:34
VSTRING * action
Definition: dsn_buf.h:31
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define DSB_DIAG(dsb, type, text)
Definition: dsn_buf.c:227
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
Definition: dsn_buf.c:275
#define DSB_MTA(dsb, type, name)
Definition: dsn_buf.c:217
VSTRING * mtype
Definition: dsn_buf.h:32
VSTRING * reason
Definition: dsn_buf.h:37
DSN_BUF * dsb_status(DSN_BUF *dsb, const char *status)
Definition: dsn_buf.c:320
DSN_BUF * dsb_unix(DSN_BUF *dsb, const char *status, const char *dtext, const char *format,...)
Definition: dsn_buf.c:287
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
DSN_BUF * dsb_formal(DSN_BUF *dsb, const char *status, const char *action, const char *mtype, const char *mname, const char *dtype, const char *dtext)
Definition: dsn_buf.c:307
VSTRING * dtext
Definition: dsn_buf.h:35
#define DSB_ACTION(dsb, stat, act)
Definition: dsn_buf.c:214
#define DSB_TRUNCATE(s)
Definition: dsn_buf.c:209
VSTRING * status
Definition: dsn_buf.h:30
void * mymalloc(ssize_t len)
Definition: mymalloc.c:150
#define DSB_DTYPE_UNIX
Definition: dsn_buf.h:49