#include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "portability.h" /* * vasprintf() and asprintf() for platforms with a C99-compliant * snprintf() - so that, if you format into a 1-byte buffer, it * will return how many characters it would have produced had * it been given an infinite-sized buffer. */ int pcap_vasprintf(char **strp, const char *format, va_list args) { char buf; int len; size_t str_size; char *str; int ret; /* * XXX - the C99 standard says, in section 7.19.6.5 "Thes * nprintf function": * * The snprintf function is equivalent to fprintf, except that * the output is written into an array (specified by argument s) * rather than to a stream. If n is zero, nothing is written, * and s may be a null pointer. Otherwise, output characters * beyond the n-1st are discarded rather than being written * to the array, and a null character is written at the end * of the characters actually written into the array. * * ... * * The snprintf function returns the number of characters that * would have been written had n been sufficiently large, not * counting the terminating null character, or a negative value * if an encoding error occurred. Thus, the null-terminated * output has been completely written if and only if the returned * value is nonnegative and less than n. * * That doesn't make it entirely clear whether, if a null buffer * pointer and a zero count are passed, it will return the number * of characters that would have been written had a buffer been * passed. * * And, even if C99 *does*, in fact, say it has to work, it * doesn't work in Solaris 8, for example - it returns -1 for * NULL/0, but returns the correct character count for a 1-byte * buffer. * * So we pass a one-character pointer in order to find out how * many characters this format and those arguments will need * without actually generating any more of those characters * than we need. * * (The fact that it might happen to work with GNU libc or with * various BSD libcs is completely uninteresting, as those tend * to have asprintf() already and thus don't even *need* this * code; this is for use in those UN*Xes that *don't* have * asprintf().) */ len = vsnprintf(&buf, sizeof buf, format, args); if (len == -1) { *strp = NULL; return (-1); } str_size = len + 1; str = malloc(str_size); if (str == NULL) { *strp = NULL; return (-1); } ret = vsnprintf(str, str_size, format, args); if (ret == -1) { free(str); *strp = NULL; return (-1); } *strp = str; /* * vsnprintf() shouldn't truncate the string, as we have * allocated a buffer large enough to hold the string, so its * return value should be the number of characters written. */ return (ret); } int pcap_asprintf(char **strp, const char *format, ...) { va_list args; int ret; va_start(args, format); ret = pcap_vasprintf(strp, format, args); va_end(args); return (ret); } |