7 /* send attributes over byte stream
11 /* int attr_print64(fp, flags, type, name, ..., ATTR_TYPE_END)
17 /* int attr_vprint64(fp, flags, ap)
22 /* attr_print64() takes zero or more (name, value) simple attributes
23 /* and converts its input to a byte stream that can be recovered with
24 /* attr_scan64(). The stream is not flushed.
26 /* attr_vprint64() 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_print64() argument list. This routine satisfies the formatting
31 /* rules as outlined in attr_scan64(3).
35 /* Stream to write the result to.
37 /* The bit-wise OR of zero or more of the following.
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_print64() automatically appends an attribute list
44 /* terminator when it has sent the last requested attribute.
47 /* The type determines the arguments that follow.
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
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.
68 /* This terminates the attribute list.
71 /* The result value is 0 in case of success, VSTREAM_EOF in case
74 /* Panic: interface violation. All system call errors are fatal.
76 /* attr_scan64(3) recover attributes from byte stream
80 /* The Secure Mailer license must be distributed with this software.
83 /* IBM T.J. Watson Research
85 /* Yorktown Heights, NY 10598, USA
94 /* Utility library. */
100 #include <base64_code.h>
103 #define STR(x) vstring_str(x)
104 #define LEN(x) VSTRING_LEN(x)
106 /* attr_print64_str - encode and send attribute information */
108 static void attr_print64_str(VSTREAM
*fp
, const char *str
, ssize_t len
)
110 static VSTRING
*base64_buf
;
113 base64_buf
= vstring_alloc(10);
115 base64_encode(base64_buf
, str
, len
);
116 vstream_fputs(STR(base64_buf
), fp
);
119 static void attr_print64_num(VSTREAM
*fp
, unsigned num
)
121 static VSTRING
*plain
;
124 plain
= vstring_alloc(10);
126 vstring_sprintf(plain
, "%u", num
);
127 attr_print64_str(fp
, STR(plain
), LEN(plain
));
130 static void attr_print64_long_num(VSTREAM
*fp
, unsigned long long_num
)
132 static VSTRING
*plain
;
135 plain
= vstring_alloc(10);
137 vstring_sprintf(plain
, "%lu", long_num
);
138 attr_print64_str(fp
, STR(plain
), LEN(plain
));
141 /* attr_vprint64 - send attribute list to stream */
143 int attr_vprint64(VSTREAM
*fp
, int flags
, va_list ap
)
145 const char *myname
= "attr_print64";
149 unsigned long long_val
;
151 HTABLE_INFO
**ht_info_list
;
154 ATTR_PRINT_SLAVE_FN print_fn
;
160 if (flags
& ~ATTR_FLAG_ALL
)
161 msg_panic("%s: bad flags: 0x%x", myname
, flags
);
164 * Iterate over all (type, name, value) triples, and produce output on
167 while ((attr_type
= va_arg(ap
, int)) != ATTR_TYPE_END
) {
170 attr_name
= va_arg(ap
, char *);
171 attr_print64_str(fp
, attr_name
, strlen(attr_name
));
172 int_val
= va_arg(ap
, int);
173 VSTREAM_PUTC(':', fp
);
174 attr_print64_num(fp
, (unsigned) int_val
);
175 VSTREAM_PUTC('\n', fp
);
177 msg_info("send attr %s = %u", attr_name
, int_val
);
180 attr_name
= va_arg(ap
, char *);
181 attr_print64_str(fp
, attr_name
, strlen(attr_name
));
182 long_val
= va_arg(ap
, long);
183 VSTREAM_PUTC(':', fp
);
184 attr_print64_long_num(fp
, (unsigned long) long_val
);
185 VSTREAM_PUTC('\n', fp
);
187 msg_info("send attr %s = %lu", attr_name
, long_val
);
190 attr_name
= va_arg(ap
, char *);
191 attr_print64_str(fp
, attr_name
, strlen(attr_name
));
192 str_val
= va_arg(ap
, char *);
193 VSTREAM_PUTC(':', fp
);
194 attr_print64_str(fp
, str_val
, strlen(str_val
));
195 VSTREAM_PUTC('\n', fp
);
197 msg_info("send attr %s = %s", attr_name
, str_val
);
200 attr_name
= va_arg(ap
, char *);
201 attr_print64_str(fp
, attr_name
, strlen(attr_name
));
202 len_val
= va_arg(ap
, ssize_t
);
203 str_val
= va_arg(ap
, char *);
204 VSTREAM_PUTC(':', fp
);
205 attr_print64_str(fp
, str_val
, len_val
);
206 VSTREAM_PUTC('\n', fp
);
208 msg_info("send attr %s = [data %ld bytes]",
209 attr_name
, (long) len_val
);
212 print_fn
= va_arg(ap
, ATTR_PRINT_SLAVE_FN
);
213 print_arg
= va_arg(ap
, void *);
214 print_fn(attr_print64
, fp
, flags
| ATTR_FLAG_MORE
, print_arg
);
217 ht_info_list
= htable_list(va_arg(ap
, HTABLE
*));
218 for (ht
= ht_info_list
; *ht
; ht
++) {
219 attr_print64_str(fp
, ht
[0]->key
, strlen(ht
[0]->key
));
220 VSTREAM_PUTC(':', fp
);
221 attr_print64_str(fp
, ht
[0]->value
, strlen(ht
[0]->value
));
222 VSTREAM_PUTC('\n', fp
);
224 msg_info("send attr name %s value %s",
225 ht
[0]->key
, ht
[0]->value
);
227 myfree((char *) ht_info_list
);
230 msg_panic("%s: unknown type code: %d", myname
, attr_type
);
233 if ((flags
& ATTR_FLAG_MORE
) == 0)
234 VSTREAM_PUTC('\n', fp
);
235 return (vstream_ferror(fp
));
238 int attr_print64(VSTREAM
*fp
, int flags
,...)
244 ret
= attr_vprint64(fp
, flags
, ap
);
252 * Proof of concept test program. Mirror image of the attr_scan64 test
255 #include <msg_vstream.h>
257 int main(int unused_argc
, char **argv
)
259 HTABLE
*table
= htable_create(1);
261 msg_vstream_init(argv
[0], VSTREAM_ERR
);
263 htable_enter(table
, "foo-name", mystrdup("foo-value"));
264 htable_enter(table
, "bar-name", mystrdup("bar-value"));
265 attr_print64(VSTREAM_OUT
, ATTR_FLAG_NONE
,
266 ATTR_TYPE_INT
, ATTR_NAME_INT
, 4711,
267 ATTR_TYPE_LONG
, ATTR_NAME_LONG
, 1234,
268 ATTR_TYPE_STR
, ATTR_NAME_STR
, "whoopee",
269 ATTR_TYPE_DATA
, ATTR_NAME_DATA
, strlen("whoopee"), "whoopee",
270 ATTR_TYPE_HASH
, table
,
272 attr_print64(VSTREAM_OUT
, ATTR_FLAG_NONE
,
273 ATTR_TYPE_INT
, ATTR_NAME_INT
, 4711,
274 ATTR_TYPE_LONG
, ATTR_NAME_LONG
, 1234,
275 ATTR_TYPE_STR
, ATTR_NAME_STR
, "whoopee",
276 ATTR_TYPE_DATA
, ATTR_NAME_DATA
, strlen("whoopee"), "whoopee",
278 if (vstream_fflush(VSTREAM_OUT
) != 0)
279 msg_fatal("write error: %m");
281 htable_free(table
, myfree
);