xref: /freebsd/contrib/libpcap/missing/asprintf.c (revision afdbf109c6a661a729938f68211054a0a50d38ac)
157e22627SCy Schubert #include <stdio.h>
257e22627SCy Schubert #include <stdlib.h>
357e22627SCy Schubert #include <stdarg.h>
457e22627SCy Schubert 
557e22627SCy Schubert #include "portability.h"
657e22627SCy Schubert 
757e22627SCy Schubert /*
857e22627SCy Schubert  * vasprintf() and asprintf() for platforms with a C99-compliant
957e22627SCy Schubert  * snprintf() - so that, if you format into a 1-byte buffer, it
1057e22627SCy Schubert  * will return how many characters it would have produced had
1157e22627SCy Schubert  * it been given an infinite-sized buffer.
1257e22627SCy Schubert  */
1357e22627SCy Schubert int
pcapint_vasprintf(char ** strp,const char * format,va_list args)14*afdbf109SJoseph Mingrone pcapint_vasprintf(char **strp, const char *format, va_list args)
1557e22627SCy Schubert {
1657e22627SCy Schubert 	char buf;
1757e22627SCy Schubert 	int len;
1857e22627SCy Schubert 	size_t str_size;
1957e22627SCy Schubert 	char *str;
2057e22627SCy Schubert 	int ret;
2157e22627SCy Schubert 
2257e22627SCy Schubert 	/*
236f9cba8fSJoseph Mingrone 	 * XXX - the C99 standard says, in section 7.19.6.5 "The
24*afdbf109SJoseph Mingrone 	 * snprintf function":
2557e22627SCy Schubert 	 *
2657e22627SCy Schubert 	 *    The snprintf function is equivalent to fprintf, except that
2757e22627SCy Schubert 	 *    the output is written into an array (specified by argument s)
2857e22627SCy Schubert 	 *    rather than to a stream.  If n is zero, nothing is written,
2957e22627SCy Schubert 	 *    and s may be a null pointer.  Otherwise, output characters
3057e22627SCy Schubert 	 *    beyond the n-1st are discarded rather than being written
3157e22627SCy Schubert 	 *    to the array, and a null character is written at the end
3257e22627SCy Schubert 	 *    of the characters actually written into the array.
3357e22627SCy Schubert 	 *
3457e22627SCy Schubert 	 *        ...
3557e22627SCy Schubert 	 *
3657e22627SCy Schubert 	 *    The snprintf function returns the number of characters that
3757e22627SCy Schubert 	 *    would have been written had n been sufficiently large, not
3857e22627SCy Schubert 	 *    counting the terminating null character, or a negative value
3957e22627SCy Schubert 	 *    if an encoding error occurred. Thus, the null-terminated
4057e22627SCy Schubert 	 *    output has been completely written if and only if the returned
4157e22627SCy Schubert 	 *    value is nonnegative and less than n.
4257e22627SCy Schubert 	 *
4357e22627SCy Schubert 	 * That doesn't make it entirely clear whether, if a null buffer
4457e22627SCy Schubert 	 * pointer and a zero count are passed, it will return the number
4557e22627SCy Schubert 	 * of characters that would have been written had a buffer been
4657e22627SCy Schubert 	 * passed.
4757e22627SCy Schubert 	 *
4857e22627SCy Schubert 	 * And, even if C99 *does*, in fact, say it has to work, it
4957e22627SCy Schubert 	 * doesn't work in Solaris 8, for example - it returns -1 for
5057e22627SCy Schubert 	 * NULL/0, but returns the correct character count for a 1-byte
5157e22627SCy Schubert 	 * buffer.
5257e22627SCy Schubert 	 *
5357e22627SCy Schubert 	 * So we pass a one-character pointer in order to find out how
5457e22627SCy Schubert 	 * many characters this format and those arguments will need
5557e22627SCy Schubert 	 * without actually generating any more of those characters
5657e22627SCy Schubert 	 * than we need.
5757e22627SCy Schubert 	 *
5857e22627SCy Schubert 	 * (The fact that it might happen to work with GNU libc or with
5957e22627SCy Schubert 	 * various BSD libcs is completely uninteresting, as those tend
6057e22627SCy Schubert 	 * to have asprintf() already and thus don't even *need* this
6157e22627SCy Schubert 	 * code; this is for use in those UN*Xes that *don't* have
6257e22627SCy Schubert 	 * asprintf().)
6357e22627SCy Schubert 	 */
6457e22627SCy Schubert 	len = vsnprintf(&buf, sizeof buf, format, args);
6557e22627SCy Schubert 	if (len == -1) {
6657e22627SCy Schubert 		*strp = NULL;
6757e22627SCy Schubert 		return (-1);
6857e22627SCy Schubert 	}
6957e22627SCy Schubert 	str_size = len + 1;
7057e22627SCy Schubert 	str = malloc(str_size);
7157e22627SCy Schubert 	if (str == NULL) {
7257e22627SCy Schubert 		*strp = NULL;
7357e22627SCy Schubert 		return (-1);
7457e22627SCy Schubert 	}
7557e22627SCy Schubert 	ret = vsnprintf(str, str_size, format, args);
7657e22627SCy Schubert 	if (ret == -1) {
7757e22627SCy Schubert 		free(str);
7857e22627SCy Schubert 		*strp = NULL;
7957e22627SCy Schubert 		return (-1);
8057e22627SCy Schubert 	}
8157e22627SCy Schubert 	*strp = str;
8257e22627SCy Schubert 	/*
8357e22627SCy Schubert 	 * vsnprintf() shouldn't truncate the string, as we have
8457e22627SCy Schubert 	 * allocated a buffer large enough to hold the string, so its
8557e22627SCy Schubert 	 * return value should be the number of characters written.
8657e22627SCy Schubert 	 */
8757e22627SCy Schubert 	return (ret);
8857e22627SCy Schubert }
8957e22627SCy Schubert 
9057e22627SCy Schubert int
pcapint_asprintf(char ** strp,const char * format,...)91*afdbf109SJoseph Mingrone pcapint_asprintf(char **strp, const char *format, ...)
9257e22627SCy Schubert {
9357e22627SCy Schubert 	va_list args;
9457e22627SCy Schubert 	int ret;
9557e22627SCy Schubert 
9657e22627SCy Schubert 	va_start(args, format);
97*afdbf109SJoseph Mingrone 	ret = pcapint_vasprintf(strp, format, args);
9857e22627SCy Schubert 	va_end(args);
9957e22627SCy Schubert 	return (ret);
10057e22627SCy Schubert }
10157e22627SCy Schubert 
102