190792Sgshapiro/*
2261370Sgshapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *      All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro */
990792Sgshapiro
1090792Sgshapiro/*
1190792Sgshapiro * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
1290792Sgshapiro *
13120256Sgshapiro * Permission to use, copy, modify, and distribute this software for any
14120256Sgshapiro * purpose with or without fee is hereby granted, provided that the above
15120256Sgshapiro * copyright notice and this permission notice appear in all copies.
1690792Sgshapiro *
17120256Sgshapiro * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
18120256Sgshapiro * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
19120256Sgshapiro * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
20120256Sgshapiro * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21120256Sgshapiro * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22120256Sgshapiro * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23120256Sgshapiro * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2490792Sgshapiro */
2590792Sgshapiro
2690792Sgshapiro#include <sm/gen.h>
27266711SgshapiroSM_RCSID("@(#)$Id: vasprintf.c,v 1.28 2013-11-22 20:51:44 ca Exp $")
2890792Sgshapiro#include <stdlib.h>
2990792Sgshapiro#include <errno.h>
3090792Sgshapiro#include <sm/io.h>
3190792Sgshapiro#include <sm/heap.h>
3290792Sgshapiro#include "local.h"
3390792Sgshapiro
3490792Sgshapiro/*
3590792Sgshapiro**  SM_VASPRINTF -- printf to a dynamically allocated string
3690792Sgshapiro**
3790792Sgshapiro**  Write 'printf' output to a dynamically allocated string
3890792Sgshapiro**  buffer which is returned to the caller.
3990792Sgshapiro**
4090792Sgshapiro**	Parameters:
4190792Sgshapiro**		str -- *str receives a pointer to the allocated string
4290792Sgshapiro**		fmt -- format directives for printing
4390792Sgshapiro**		ap -- variable argument list
4490792Sgshapiro**
4590792Sgshapiro**	Results:
4690792Sgshapiro**		On failure, set *str to NULL, set errno, and return -1.
4790792Sgshapiro**
4890792Sgshapiro**		On success, set *str to a pointer to a nul-terminated
4990792Sgshapiro**		string buffer containing printf output,	and return the
5090792Sgshapiro**		length of the string (not counting the nul).
5190792Sgshapiro*/
5290792Sgshapiro
5390792Sgshapiro#define SM_VA_BUFSIZE	128
5490792Sgshapiro
5590792Sgshapiroint
5690792Sgshapirosm_vasprintf(str, fmt, ap)
5790792Sgshapiro	char **str;
5890792Sgshapiro	const char *fmt;
5990792Sgshapiro	SM_VA_LOCAL_DECL
6090792Sgshapiro{
6190792Sgshapiro	int ret;
6290792Sgshapiro	SM_FILE_T fake;
6390792Sgshapiro	unsigned char *base;
6490792Sgshapiro
6590792Sgshapiro	fake.sm_magic = SmFileMagic;
6690792Sgshapiro	fake.f_timeout = SM_TIME_FOREVER;
6790792Sgshapiro	fake.f_timeoutstate = SM_TIME_BLOCK;
6890792Sgshapiro	fake.f_file = -1;
6990792Sgshapiro	fake.f_flags = SMWR | SMSTR | SMALC;
7090792Sgshapiro	fake.f_bf.smb_base = fake.f_p = (unsigned char *)sm_malloc(SM_VA_BUFSIZE);
7190792Sgshapiro	if (fake.f_bf.smb_base == NULL)
7290792Sgshapiro		goto err2;
7390792Sgshapiro	fake.f_close = NULL;
7490792Sgshapiro	fake.f_open = NULL;
7590792Sgshapiro	fake.f_read = NULL;
7690792Sgshapiro	fake.f_write = NULL;
7790792Sgshapiro	fake.f_seek = NULL;
7890792Sgshapiro	fake.f_setinfo = fake.f_getinfo = NULL;
7990792Sgshapiro	fake.f_type = "sm_vasprintf:fake";
8090792Sgshapiro	fake.f_bf.smb_size = fake.f_w = SM_VA_BUFSIZE - 1;
8190792Sgshapiro	fake.f_timeout = SM_TIME_FOREVER;
8290792Sgshapiro	ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap);
8390792Sgshapiro	if (ret == -1)
8490792Sgshapiro		goto err;
8590792Sgshapiro	*fake.f_p = '\0';
8690792Sgshapiro
8790792Sgshapiro	/* use no more space than necessary */
8890792Sgshapiro	base = (unsigned char *) sm_realloc(fake.f_bf.smb_base, ret + 1);
8990792Sgshapiro	if (base == NULL)
9090792Sgshapiro		goto err;
9190792Sgshapiro	*str = (char *)base;
9290792Sgshapiro	return ret;
9390792Sgshapiro
9490792Sgshapiroerr:
9590792Sgshapiro	if (fake.f_bf.smb_base != NULL)
9690792Sgshapiro	{
9790792Sgshapiro		sm_free(fake.f_bf.smb_base);
9890792Sgshapiro		fake.f_bf.smb_base = NULL;
9990792Sgshapiro	}
10090792Sgshapiroerr2:
10190792Sgshapiro	*str = NULL;
10290792Sgshapiro	errno = ENOMEM;
10390792Sgshapiro	return -1;
10490792Sgshapiro}
105