1 /* $NetBSD: attr_print64.c,v 1.1.1.1 2009/06/23 10:08:58 tron Exp $ */ 2 3 /*++ 4 /* NAME 5 /* attr_print64 3 6 /* SUMMARY 7 /* send attributes over byte stream 8 /* SYNOPSIS 9 /* #include <attr.h> 10 /* 11 /* int attr_print64(fp, flags, type, name, ..., ATTR_TYPE_END) 12 /* VSTREAM fp; 13 /* int flags; 14 /* int type; 15 /* char *name; 16 /* 17 /* int attr_vprint64(fp, flags, ap) 18 /* VSTREAM fp; 19 /* int flags; 20 /* va_list ap; 21 /* DESCRIPTION 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. 25 /* 26 /* attr_vprint64() provides an alternate interface that is convenient 27 /* for calling from within variadic functions. 28 /* 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). 32 /* 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_print64() 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. 73 /* 74 /* Panic: interface violation. All system call errors are fatal. 75 /* SEE ALSO 76 /* attr_scan64(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 /*--*/ 87 88 /* System library. */ 89 90 #include <sys_defs.h> 91 #include <stdarg.h> 92 #include <string.h> 93 94 /* Utility library. */ 95 96 #include <msg.h> 97 #include <mymalloc.h> 98 #include <vstream.h> 99 #include <htable.h> 100 #include <base64_code.h> 101 #include <attr.h> 102 103 #define STR(x) vstring_str(x) 104 #define LEN(x) VSTRING_LEN(x) 105 106 /* attr_print64_str - encode and send attribute information */ 107 108 static void attr_print64_str(VSTREAM *fp, const char *str, ssize_t len) 109 { 110 static VSTRING *base64_buf; 111 112 if (base64_buf == 0) 113 base64_buf = vstring_alloc(10); 114 115 base64_encode(base64_buf, str, len); 116 vstream_fputs(STR(base64_buf), fp); 117 } 118 119 static void attr_print64_num(VSTREAM *fp, unsigned num) 120 { 121 static VSTRING *plain; 122 123 if (plain == 0) 124 plain = vstring_alloc(10); 125 126 vstring_sprintf(plain, "%u", num); 127 attr_print64_str(fp, STR(plain), LEN(plain)); 128 } 129 130 static void attr_print64_long_num(VSTREAM *fp, unsigned long long_num) 131 { 132 static VSTRING *plain; 133 134 if (plain == 0) 135 plain = vstring_alloc(10); 136 137 vstring_sprintf(plain, "%lu", long_num); 138 attr_print64_str(fp, STR(plain), LEN(plain)); 139 } 140 141 /* attr_vprint64 - send attribute list to stream */ 142 143 int attr_vprint64(VSTREAM *fp, int flags, va_list ap) 144 { 145 const char *myname = "attr_print64"; 146 int attr_type; 147 char *attr_name; 148 unsigned int_val; 149 unsigned long long_val; 150 char *str_val; 151 HTABLE_INFO **ht_info_list; 152 HTABLE_INFO **ht; 153 ssize_t len_val; 154 ATTR_PRINT_SLAVE_FN print_fn; 155 void *print_arg; 156 157 /* 158 * Sanity check. 159 */ 160 if (flags & ~ATTR_FLAG_ALL) 161 msg_panic("%s: bad flags: 0x%x", myname, flags); 162 163 /* 164 * Iterate over all (type, name, value) triples, and produce output on 165 * the fly. 166 */ 167 while ((attr_type = va_arg(ap, int)) != ATTR_TYPE_END) { 168 switch (attr_type) { 169 case ATTR_TYPE_INT: 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); 176 if (msg_verbose) 177 msg_info("send attr %s = %u", attr_name, int_val); 178 break; 179 case ATTR_TYPE_LONG: 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); 186 if (msg_verbose) 187 msg_info("send attr %s = %lu", attr_name, long_val); 188 break; 189 case ATTR_TYPE_STR: 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); 196 if (msg_verbose) 197 msg_info("send attr %s = %s", attr_name, str_val); 198 break; 199 case ATTR_TYPE_DATA: 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); 207 if (msg_verbose) 208 msg_info("send attr %s = [data %ld bytes]", 209 attr_name, (long) len_val); 210 break; 211 case ATTR_TYPE_FUNC: 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); 215 break; 216 case ATTR_TYPE_HASH: 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); 223 if (msg_verbose) 224 msg_info("send attr name %s value %s", 225 ht[0]->key, ht[0]->value); 226 } 227 myfree((char *) ht_info_list); 228 break; 229 default: 230 msg_panic("%s: unknown type code: %d", myname, attr_type); 231 } 232 } 233 if ((flags & ATTR_FLAG_MORE) == 0) 234 VSTREAM_PUTC('\n', fp); 235 return (vstream_ferror(fp)); 236 } 237 238 int attr_print64(VSTREAM *fp, int flags,...) 239 { 240 va_list ap; 241 int ret; 242 243 va_start(ap, flags); 244 ret = attr_vprint64(fp, flags, ap); 245 va_end(ap); 246 return (ret); 247 } 248 249 #ifdef TEST 250 251 /* 252 * Proof of concept test program. Mirror image of the attr_scan64 test 253 * program. 254 */ 255 #include <msg_vstream.h> 256 257 int main(int unused_argc, char **argv) 258 { 259 HTABLE *table = htable_create(1); 260 261 msg_vstream_init(argv[0], VSTREAM_ERR); 262 msg_verbose = 1; 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, 271 ATTR_TYPE_END); 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", 277 ATTR_TYPE_END); 278 if (vstream_fflush(VSTREAM_OUT) != 0) 279 msg_fatal("write error: %m"); 280 281 htable_free(table, myfree); 282 return (0); 283 } 284 285 #endif 286