Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / util / attr_print0.c
blobebd8df99343efcc3aae1691fad03ec1c0a16306e
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* attr_print0 3
6 /* SUMMARY
7 /* send attributes over byte stream
8 /* SYNOPSIS
9 /* #include <attr.h>
11 /* int attr_print0(fp, flags, type, name, ..., ATTR_TYPE_END)
12 /* VSTREAM fp;
13 /* int flags;
14 /* int type;
15 /* char *name;
17 /* int attr_vprint0(fp, flags, ap)
18 /* VSTREAM fp;
19 /* int flags;
20 /* va_list ap;
21 /* DESCRIPTION
22 /* attr_print0() takes zero or more (name, value) simple attributes
23 /* and converts its input to a byte stream that can be recovered with
24 /* attr_scan0(). The stream is not flushed.
26 /* attr_vprint0() provides an alternate interface that is convenient
27 /* for calling from within variadic functions.
29 /* Attributes are sent in the requested order as specified with the
30 /* attr_print0() argument list. This routine satisfies the formatting
31 /* rules as outlined in attr_scan0(3).
33 /* Arguments:
34 /* .IP fp
35 /* Stream to write the result to.
36 /* .IP flags
37 /* The bit-wise OR of zero or more of the following.
38 /* .RS
39 /* .IP ATTR_FLAG_MORE
40 /* After sending the requested attributes, leave the output stream in
41 /* a state that is usable for more attribute sending operations on
42 /* the same output attribute list.
43 /* By default, attr_print0() automatically appends an attribute list
44 /* terminator when it has sent the last requested attribute.
45 /* .RE
46 /* .IP type
47 /* The type determines the arguments that follow.
48 /* .RS
49 /* .IP "ATTR_TYPE_INT (char *, int)"
50 /* This argument is followed by an attribute name and an integer.
51 /* .IP "ATTR_TYPE_LONG (char *, long)"
52 /* This argument is followed by an attribute name and a long integer.
53 /* .IP "ATTR_TYPE_STR (char *, char *)"
54 /* This argument is followed by an attribute name and a null-terminated
55 /* string.
56 /* .IP "ATTR_TYPE_DATA (char *, ssize_t, char *)"
57 /* This argument is followed by an attribute name, an attribute value
58 /* length, and an attribute value pointer.
59 /* .IP "ATTR_TYPE_FUNC (ATTR_PRINT_SLAVE_FN, void *)"
60 /* This argument is followed by a function pointer and generic data
61 /* pointer. The caller-specified function returns whatever the
62 /* specified attribute printing function returns.
63 /* .IP "ATTR_TYPE_HASH (HTABLE *)"
64 /* .IP "ATTR_TYPE_NAMEVAL (NVTABLE *)"
65 /* The content of the table is sent as a sequence of string-valued
66 /* attributes with names equal to the table lookup keys.
67 /* .IP ATTR_TYPE_END
68 /* This terminates the attribute list.
69 /* .RE
70 /* DIAGNOSTICS
71 /* The result value is 0 in case of success, VSTREAM_EOF in case
72 /* of trouble.
74 /* Panic: interface violation. All system call errors are fatal.
75 /* SEE ALSO
76 /* attr_scan0(3) recover attributes from byte stream
77 /* LICENSE
78 /* .ad
79 /* .fi
80 /* The Secure Mailer license must be distributed with this software.
81 /* AUTHOR(S)
82 /* Wietse Venema
83 /* IBM T.J. Watson Research
84 /* P.O. Box 704
85 /* Yorktown Heights, NY 10598, USA
86 /*--*/
88 /* System library. */
90 #include <sys_defs.h>
91 #include <stdarg.h>
92 #include <string.h>
94 /* Utility library. */
96 #include <msg.h>
97 #include <mymalloc.h>
98 #include <vstream.h>
99 #include <htable.h>
100 #include <attr.h>
101 #include <base64_code.h>
103 #define STR(x) vstring_str(x)
104 #define LEN(x) VSTRING_LEN(x)
106 /* attr_vprint0 - send attribute list to stream */
108 int attr_vprint0(VSTREAM *fp, int flags, va_list ap)
110 const char *myname = "attr_print0";
111 int attr_type;
112 char *attr_name;
113 unsigned int_val;
114 unsigned long long_val;
115 char *str_val;
116 HTABLE_INFO **ht_info_list;
117 HTABLE_INFO **ht;
118 ssize_t len_val;
119 static VSTRING *base64_buf;
120 ATTR_PRINT_SLAVE_FN print_fn;
121 void *print_arg;
124 * Sanity check.
126 if (flags & ~ATTR_FLAG_ALL)
127 msg_panic("%s: bad flags: 0x%x", myname, flags);
130 * Iterate over all (type, name, value) triples, and produce output on
131 * the fly.
133 while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) {
134 switch (attr_type) {
135 case ATTR_TYPE_INT:
136 attr_name = va_arg(ap, char *);
137 vstream_fwrite(fp, attr_name, strlen(attr_name) + 1);
138 int_val = va_arg(ap, int);
139 vstream_fprintf(fp, "%u", (unsigned) int_val);
140 VSTREAM_PUTC('\0', fp);
141 if (msg_verbose)
142 msg_info("send attr %s = %u", attr_name, int_val);
143 break;
144 case ATTR_TYPE_LONG:
145 attr_name = va_arg(ap, char *);
146 vstream_fwrite(fp, attr_name, strlen(attr_name) + 1);
147 long_val = va_arg(ap, unsigned long);
148 vstream_fprintf(fp, "%lu", (unsigned long) long_val);
149 VSTREAM_PUTC('\0', fp);
150 if (msg_verbose)
151 msg_info("send attr %s = %lu", attr_name, long_val);
152 break;
153 case ATTR_TYPE_STR:
154 attr_name = va_arg(ap, char *);
155 vstream_fwrite(fp, attr_name, strlen(attr_name) + 1);
156 str_val = va_arg(ap, char *);
157 vstream_fwrite(fp, str_val, strlen(str_val) + 1);
158 if (msg_verbose)
159 msg_info("send attr %s = %s", attr_name, str_val);
160 break;
161 case ATTR_TYPE_DATA:
162 attr_name = va_arg(ap, char *);
163 vstream_fwrite(fp, attr_name, strlen(attr_name) + 1);
164 len_val = va_arg(ap, ssize_t);
165 str_val = va_arg(ap, char *);
166 if (base64_buf == 0)
167 base64_buf = vstring_alloc(10);
168 base64_encode(base64_buf, str_val, len_val);
169 vstream_fwrite(fp, STR(base64_buf), LEN(base64_buf) + 1);
170 if (msg_verbose)
171 msg_info("send attr %s = [data %ld bytes]",
172 attr_name, (long) len_val);
173 break;
174 case ATTR_TYPE_FUNC:
175 print_fn = va_arg(ap, ATTR_PRINT_SLAVE_FN);
176 print_arg = va_arg(ap, void *);
177 print_fn(attr_print0, fp, flags | ATTR_FLAG_MORE, print_arg);
178 break;
179 case ATTR_TYPE_HASH:
180 ht_info_list = htable_list(va_arg(ap, HTABLE *));
181 for (ht = ht_info_list; *ht; ht++) {
182 vstream_fwrite(fp, ht[0]->key, strlen(ht[0]->key) + 1);
183 vstream_fwrite(fp, ht[0]->value, strlen(ht[0]->value) + 1);
184 if (msg_verbose)
185 msg_info("send attr name %s value %s",
186 ht[0]->key, ht[0]->value);
188 myfree((char *) ht_info_list);
189 break;
190 default:
191 msg_panic("%s: unknown type code: %d", myname, attr_type);
194 if ((flags & ATTR_FLAG_MORE) == 0)
195 VSTREAM_PUTC('\0', fp);
196 return (vstream_ferror(fp));
199 int attr_print0(VSTREAM *fp, int flags,...)
201 va_list ap;
202 int ret;
204 va_start(ap, flags);
205 ret = attr_vprint0(fp, flags, ap);
206 va_end(ap);
207 return (ret);
210 #ifdef TEST
213 * Proof of concept test program. Mirror image of the attr_scan0 test
214 * program.
216 #include <msg_vstream.h>
218 int main(int unused_argc, char **argv)
220 HTABLE *table = htable_create(1);
222 msg_vstream_init(argv[0], VSTREAM_ERR);
223 msg_verbose = 1;
224 htable_enter(table, "foo-name", mystrdup("foo-value"));
225 htable_enter(table, "bar-name", mystrdup("bar-value"));
226 attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
227 ATTR_TYPE_INT, ATTR_NAME_INT, 4711,
228 ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234,
229 ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee",
230 ATTR_TYPE_DATA, ATTR_NAME_DATA, strlen("whoopee"), "whoopee",
231 ATTR_TYPE_HASH, table,
232 ATTR_TYPE_END);
233 attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
234 ATTR_TYPE_INT, ATTR_NAME_INT, 4711,
235 ATTR_TYPE_LONG, ATTR_NAME_LONG, 1234,
236 ATTR_TYPE_STR, ATTR_NAME_STR, "whoopee",
237 ATTR_TYPE_DATA, ATTR_NAME_DATA, strlen("whoopee"), "whoopee",
238 ATTR_TYPE_END);
239 if (vstream_fflush(VSTREAM_OUT) != 0)
240 msg_fatal("write error: %m");
242 htable_free(table, myfree);
243 return (0);
246 #endif