Postfix3.3.1
attr_print64.c
[詳解]
1 /*++
2 /* NAME
3 /* attr_print64 3
4 /* SUMMARY
5 /* send attributes over byte stream
6 /* SYNOPSIS
7 /* #include <attr.h>
8 /*
9 /* int attr_print64(fp, flags, type, name, ..., ATTR_TYPE_END)
10 /* VSTREAM fp;
11 /* int flags;
12 /* int type;
13 /* char *name;
14 /*
15 /* int attr_vprint64(fp, flags, ap)
16 /* VSTREAM fp;
17 /* int flags;
18 /* va_list ap;
19 /* DESCRIPTION
20 /* attr_print64() takes zero or more (name, value) simple attributes
21 /* and converts its input to a byte stream that can be recovered with
22 /* attr_scan64(). The stream is not flushed.
23 /*
24 /* attr_vprint64() provides an alternate interface that is convenient
25 /* for calling from within variadic functions.
26 /*
27 /* Attributes are sent in the requested order as specified with the
28 /* attr_print64() argument list. This routine satisfies the formatting
29 /* rules as outlined in attr_scan64(3).
30 /*
31 /* Arguments:
32 /* .IP fp
33 /* Stream to write the result to.
34 /* .IP flags
35 /* The bit-wise OR of zero or more of the following.
36 /* .RS
37 /* .IP ATTR_FLAG_MORE
38 /* After sending the requested attributes, leave the output stream in
39 /* a state that is usable for more attribute sending operations on
40 /* the same output attribute list.
41 /* By default, attr_print64() automatically appends an attribute list
42 /* terminator when it has sent the last requested attribute.
43 /* .RE
44 /* .IP List of attributes followed by terminator:
45 /* .RS
46 /* .IP "SEND_ATTR_INT(const char *name, int value)"
47 /* The arguments are an attribute name and an integer.
48 /* .IP "SEND_ATTR_LONG(const char *name, long value)"
49 /* The arguments are an attribute name and a long integer.
50 /* .IP "SEND_ATTR_STR(const char *name, const char *value)"
51 /* The arguments are an attribute name and a null-terminated
52 /* string.
53 /* .IP "SEND_ATTR_DATA(const char *name, ssize_t len, const void *value)"
54 /* The arguments are an attribute name, an attribute value
55 /* length, and an attribute value pointer.
56 /* .IP "SEND_ATTR_FUNC(ATTR_PRINT_SLAVE_FN, const void *value)"
57 /* The arguments are a function pointer and generic data
58 /* pointer. The caller-specified function returns whatever the
59 /* specified attribute printing function returns.
60 /* .IP "SEND_ATTR_HASH(const HTABLE *table)"
61 /* .IP "SEND_ATTR_NAMEVAL(const NVTABLE *table)"
62 /* The content of the table is sent as a sequence of string-valued
63 /* attributes with names equal to the table lookup keys.
64 /* .IP ATTR_TYPE_END
65 /* This terminates the attribute list.
66 /* .RE
67 /* DIAGNOSTICS
68 /* The result value is 0 in case of success, VSTREAM_EOF in case
69 /* of trouble.
70 /*
71 /* Panic: interface violation. All system call errors are fatal.
72 /* SEE ALSO
73 /* attr_scan64(3) recover attributes from byte stream
74 /* LICENSE
75 /* .ad
76 /* .fi
77 /* The Secure Mailer license must be distributed with this software.
78 /* AUTHOR(S)
79 /* Wietse Venema
80 /* IBM T.J. Watson Research
81 /* P.O. Box 704
82 /* Yorktown Heights, NY 10598, USA
83 /*
84 /* Wietse Venema
85 /* Google, Inc.
86 /* 111 8th Avenue
87 /* New York, NY 10011, USA
88 /*--*/
89 
90 /* System library. */
91 
92 #include <sys_defs.h>
93 #include <stdarg.h>
94 #include <string.h>
95 
96 /* Utility library. */
97 
98 #include <msg.h>
99 #include <mymalloc.h>
100 #include <vstream.h>
101 #include <htable.h>
102 #include <base64_code.h>
103 #include <attr.h>
104 
105 #define STR(x) vstring_str(x)
106 #define LEN(x) VSTRING_LEN(x)
107 
108 /* attr_print64_str - encode and send attribute information */
109 
110 static void attr_print64_str(VSTREAM *fp, const char *str, ssize_t len)
111 {
112  static VSTRING *base64_buf;
113 
114  if (base64_buf == 0)
115  base64_buf = vstring_alloc(10);
116 
117  base64_encode(base64_buf, str, len);
118  vstream_fputs(STR(base64_buf), fp);
119 }
120 
121 static void attr_print64_num(VSTREAM *fp, unsigned num)
122 {
123  static VSTRING *plain;
124 
125  if (plain == 0)
126  plain = vstring_alloc(10);
127 
128  vstring_sprintf(plain, "%u", num);
129  attr_print64_str(fp, STR(plain), LEN(plain));
130 }
131 
132 static void attr_print64_long_num(VSTREAM *fp, unsigned long long_num)
133 {
134  static VSTRING *plain;
135 
136  if (plain == 0)
137  plain = vstring_alloc(10);
138 
139  vstring_sprintf(plain, "%lu", long_num);
140  attr_print64_str(fp, STR(plain), LEN(plain));
141 }
142 
143 /* attr_vprint64 - send attribute list to stream */
144 
145 int attr_vprint64(VSTREAM *fp, int flags, va_list ap)
146 {
147  const char *myname = "attr_print64";
148  int attr_type;
149  char *attr_name;
150  unsigned int_val;
151  unsigned long long_val;
152  char *str_val;
153  HTABLE_INFO **ht_info_list;
154  HTABLE_INFO **ht;
155  ssize_t len_val;
156  ATTR_PRINT_SLAVE_FN print_fn;
157  void *print_arg;
158 
159  /*
160  * Sanity check.
161  */
162  if (flags & ~ATTR_FLAG_ALL)
163  msg_panic("%s: bad flags: 0x%x", myname, flags);
164 
165  /*
166  * Iterate over all (type, name, value) triples, and produce output on
167  * the fly.
168  */
169  while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) {
170  switch (attr_type) {
171  case ATTR_TYPE_INT:
172  attr_name = va_arg(ap, char *);
173  attr_print64_str(fp, attr_name, strlen(attr_name));
174  int_val = va_arg(ap, int);
175  VSTREAM_PUTC(':', fp);
176  attr_print64_num(fp, (unsigned) int_val);
177  VSTREAM_PUTC('\n', fp);
178  if (msg_verbose)
179  msg_info("send attr %s = %u", attr_name, int_val);
180  break;
181  case ATTR_TYPE_LONG:
182  attr_name = va_arg(ap, char *);
183  attr_print64_str(fp, attr_name, strlen(attr_name));
184  long_val = va_arg(ap, long);
185  VSTREAM_PUTC(':', fp);
186  attr_print64_long_num(fp, (unsigned long) long_val);
187  VSTREAM_PUTC('\n', fp);
188  if (msg_verbose)
189  msg_info("send attr %s = %lu", attr_name, long_val);
190  break;
191  case ATTR_TYPE_STR:
192  attr_name = va_arg(ap, char *);
193  attr_print64_str(fp, attr_name, strlen(attr_name));
194  str_val = va_arg(ap, char *);
195  VSTREAM_PUTC(':', fp);
196  attr_print64_str(fp, str_val, strlen(str_val));
197  VSTREAM_PUTC('\n', fp);
198  if (msg_verbose)
199  msg_info("send attr %s = %s", attr_name, str_val);
200  break;
201  case ATTR_TYPE_DATA:
202  attr_name = va_arg(ap, char *);
203  attr_print64_str(fp, attr_name, strlen(attr_name));
204  len_val = va_arg(ap, ssize_t);
205  str_val = va_arg(ap, char *);
206  VSTREAM_PUTC(':', fp);
207  attr_print64_str(fp, str_val, len_val);
208  VSTREAM_PUTC('\n', fp);
209  if (msg_verbose)
210  msg_info("send attr %s = [data %ld bytes]",
211  attr_name, (long) len_val);
212  break;
213  case ATTR_TYPE_FUNC:
214  print_fn = va_arg(ap, ATTR_PRINT_SLAVE_FN);
215  print_arg = va_arg(ap, void *);
216  print_fn(attr_print64, fp, flags | ATTR_FLAG_MORE, print_arg);
217  break;
218  case ATTR_TYPE_HASH:
219  attr_print64_str(fp, ATTR_NAME_OPEN, sizeof(ATTR_NAME_OPEN) - 1);
220  VSTREAM_PUTC('\n', fp);
221  ht_info_list = htable_list(va_arg(ap, HTABLE *));
222  for (ht = ht_info_list; *ht; ht++) {
223  attr_print64_str(fp, ht[0]->key, strlen(ht[0]->key));
224  VSTREAM_PUTC(':', fp);
225  attr_print64_str(fp, ht[0]->value, strlen(ht[0]->value));
226  VSTREAM_PUTC('\n', fp);
227  if (msg_verbose)
228  msg_info("send attr name %s value %s",
229  ht[0]->key, (char *) ht[0]->value);
230  }
231  myfree((void *) ht_info_list);
232  attr_print64_str(fp, ATTR_NAME_CLOSE, sizeof(ATTR_NAME_CLOSE) - 1);
233  VSTREAM_PUTC('\n', fp);
234  break;
235  default:
236  msg_panic("%s: unknown type code: %d", myname, attr_type);
237  }
238  }
239  if ((flags & ATTR_FLAG_MORE) == 0)
240  VSTREAM_PUTC('\n', fp);
241  return (vstream_ferror(fp));
242 }
243 
244 int attr_print64(VSTREAM *fp, int flags,...)
245 {
246  va_list ap;
247  int ret;
248 
249  va_start(ap, flags);
250  ret = attr_vprint64(fp, flags, ap);
251  va_end(ap);
252  return (ret);
253 }
254 
255 #ifdef TEST
256 
257  /*
258  * Proof of concept test program. Mirror image of the attr_scan64 test
259  * program.
260  */
261 #include <msg_vstream.h>
262 
263 int main(int unused_argc, char **argv)
264 {
265  HTABLE *table = htable_create(1);
266 
267  msg_vstream_init(argv[0], VSTREAM_ERR);
268  msg_verbose = 1;
269  htable_enter(table, "foo-name", mystrdup("foo-value"));
270  htable_enter(table, "bar-name", mystrdup("bar-value"));
272  SEND_ATTR_INT(ATTR_NAME_INT, 4711),
273  SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
274  SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
275  SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
276  SEND_ATTR_HASH(table),
277  SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
278  ATTR_TYPE_END);
280  SEND_ATTR_INT(ATTR_NAME_INT, 4711),
281  SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
282  SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
283  SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
284  ATTR_TYPE_END);
285  if (vstream_fflush(VSTREAM_OUT) != 0)
286  msg_fatal("write error: %m");
287 
288  htable_free(table, myfree);
289  return (0);
290 }
291 
292 #endif
int msg_verbose
Definition: msg.c:177
void htable_free(HTABLE *table, void(*free_fn)(void *))
Definition: htable.c:287
#define STR(x)
Definition: attr_print64.c:105
#define ATTR_FLAG_NONE
Definition: attr.h:98
void myfree(void *ptr)
Definition: mymalloc.c:207
char * mystrdup(const char *str)
Definition: mymalloc.c:225
#define SEND_ATTR_HASH(val)
Definition: attr.h:65
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define VSTREAM_OUT
Definition: vstream.h:67
int main(int argc, char **argv)
Definition: anvil.c:1010
#define ATTR_TYPE_FUNC
Definition: attr.h:47
#define ATTR_TYPE_END
Definition: attr.h:39
int(* ATTR_PRINT_SLAVE_FN)(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *)
Definition: attr.h:34
Definition: htable.h:25
int attr_print64(VSTREAM *fp, int flags,...)
Definition: attr_print64.c:244
HTABLE * htable_create(ssize_t size)
Definition: htable.c:179
HTABLE_INFO ** htable_list(HTABLE *table)
Definition: htable.c:330
#define ATTR_TYPE_INT
Definition: attr.h:40
#define ATTR_TYPE_HASH
Definition: attr.h:43
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
int attr_vprint64(VSTREAM *fp, int flags, va_list ap)
Definition: attr_print64.c:145
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
#define SEND_ATTR_INT(name, val)
Definition: attr.h:63
#define ATTR_TYPE_STR
Definition: attr.h:42
#define SEND_ATTR_LONG(name, val)
Definition: attr.h:67
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
#define LEN(x)
Definition: attr_print64.c:106
VSTRING * base64_encode(VSTRING *, const char *, ssize_t)
Definition: base64_code.c:90
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
#define ATTR_TYPE_LONG
Definition: attr.h:45
#define VSTREAM_PUTC(ch, vp)
Definition: vstream.h:107
#define ATTR_TYPE_DATA
Definition: attr.h:46
#define vstream_ferror(vp)
Definition: vstream.h:120
#define ATTR_NAME_OPEN
Definition: attr.h:54
#define ATTR_FLAG_MORE
Definition: attr.h:101
#define SEND_ATTR_STR(name, val)
Definition: attr.h:64
#define ATTR_NAME_CLOSE
Definition: attr.h:55
#define SEND_ATTR_DATA(name, len, val)
Definition: attr.h:68
#define VSTREAM_ERR
Definition: vstream.h:68
#define ATTR_FLAG_ALL
Definition: attr.h:104
int vstream_fputs(const char *str, VSTREAM *stream)
Definition: vstream.c:1360
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
Definition: htable.c:212
void msg_info(const char *fmt,...)
Definition: msg.c:199