/*
 * Copyright (c) 2005 Sendmail, Inc. and its suppliers.
 *      All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: asprintf.c,v 1.2 2007/01/09 06:06:23 ca Exp $")

#if !HAVE_ASPRINTF
#include "sm/varargs.h"
#include "sm/io.h"
#include "sm/assert.h"
#include "sm/heap.h"

/*
**  ASPRINTF -- printf to a dynamically allocated string
**
**	Parameters:
**		str -- *str receives a pointer to the allocated string
**		fmt -- format directives for printing
**		... -- argument list
**
**	Results:
**		On failure, set *str to NULL, set errno, and return -1.
**
**		On success, set *str to a pointer to a nul-terminated
**		string buffer containing printf output,	and return the
**		length of the string (not counting the nul).
*/

#define SM_VA_BUFSIZE	128

#if !HAVE_VSNPRINTF
# define vsnprintf sm_vsnprintf
#else
# include <stdio.h>
#endif

int
asprintf(char **str, const char *fmt, ...)
{
	int ret;
	va_list ap;
	size_t len;
	char *buf;

	SM_REQUIRE(str != NULL);
	SM_REQUIRE(fmt != NULL);
	len = SM_VA_BUFSIZE;
	buf = NULL;
	do
	{
		buf = malloc(len);
		if (buf == NULL)
			goto err2;
		va_start(ap, fmt);
		ret = vsnprintf(buf, len, fmt, ap);
		va_end(ap);
		if (ret == -1)
			goto err;

		if (ret >= len)
		{
			len = ret + 1;
			free(buf);
			buf = NULL;
		}
	} while (buf == NULL);
	*str = buf;
	return ret;

err:
	if (buf != NULL)
		free(buf);
err2:
	*str = NULL;
	errno = ENOMEM;
	return -1;
}
#endif /* !HAVE_ASPRINTF */


syntax highlighted by Code2HTML, v. 0.9.1