xref: /freebsd/contrib/sendmail/libsm/vasprintf.c (revision 2fb4f839f3fc72ce2bab12f9ba4760f97f73e97f)
140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *      All rights reserved.
440266059SGregory Neil Shapiro  *
540266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro  * the sendmail distribution.
840266059SGregory Neil Shapiro  */
940266059SGregory Neil Shapiro 
1040266059SGregory Neil Shapiro /*
1140266059SGregory Neil Shapiro  * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
1240266059SGregory Neil Shapiro  *
13a7ec597cSGregory Neil Shapiro  * Permission to use, copy, modify, and distribute this software for any
14a7ec597cSGregory Neil Shapiro  * purpose with or without fee is hereby granted, provided that the above
15a7ec597cSGregory Neil Shapiro  * copyright notice and this permission notice appear in all copies.
1640266059SGregory Neil Shapiro  *
17a7ec597cSGregory Neil Shapiro  * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
18a7ec597cSGregory Neil Shapiro  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
19a7ec597cSGregory Neil Shapiro  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
20a7ec597cSGregory Neil Shapiro  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21a7ec597cSGregory Neil Shapiro  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22a7ec597cSGregory Neil Shapiro  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23a7ec597cSGregory Neil Shapiro  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2440266059SGregory Neil Shapiro  */
2540266059SGregory Neil Shapiro 
2640266059SGregory Neil Shapiro #include <sm/gen.h>
274313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: vasprintf.c,v 1.28 2013-11-22 20:51:44 ca Exp $")
2840266059SGregory Neil Shapiro #include <stdlib.h>
2940266059SGregory Neil Shapiro #include <errno.h>
3040266059SGregory Neil Shapiro #include <sm/io.h>
3140266059SGregory Neil Shapiro #include <sm/heap.h>
3240266059SGregory Neil Shapiro #include "local.h"
3340266059SGregory Neil Shapiro 
3440266059SGregory Neil Shapiro /*
3540266059SGregory Neil Shapiro **  SM_VASPRINTF -- printf to a dynamically allocated string
3640266059SGregory Neil Shapiro **
3740266059SGregory Neil Shapiro **  Write 'printf' output to a dynamically allocated string
3840266059SGregory Neil Shapiro **  buffer which is returned to the caller.
3940266059SGregory Neil Shapiro **
4040266059SGregory Neil Shapiro **	Parameters:
4140266059SGregory Neil Shapiro **		str -- *str receives a pointer to the allocated string
4240266059SGregory Neil Shapiro **		fmt -- format directives for printing
4340266059SGregory Neil Shapiro **		ap -- variable argument list
4440266059SGregory Neil Shapiro **
4540266059SGregory Neil Shapiro **	Results:
4640266059SGregory Neil Shapiro **		On failure, set *str to NULL, set errno, and return -1.
4740266059SGregory Neil Shapiro **
4840266059SGregory Neil Shapiro **		On success, set *str to a pointer to a nul-terminated
4940266059SGregory Neil Shapiro **		string buffer containing printf output,	and return the
5040266059SGregory Neil Shapiro **		length of the string (not counting the nul).
5140266059SGregory Neil Shapiro */
5240266059SGregory Neil Shapiro 
5340266059SGregory Neil Shapiro #define SM_VA_BUFSIZE	128
5440266059SGregory Neil Shapiro 
5540266059SGregory Neil Shapiro int
5640266059SGregory Neil Shapiro sm_vasprintf(str, fmt, ap)
5740266059SGregory Neil Shapiro 	char **str;
5840266059SGregory Neil Shapiro 	const char *fmt;
59*2fb4f839SGregory Neil Shapiro 	va_list ap;
6040266059SGregory Neil Shapiro {
6140266059SGregory Neil Shapiro 	int ret;
6240266059SGregory Neil Shapiro 	SM_FILE_T fake;
6340266059SGregory Neil Shapiro 	unsigned char *base;
6440266059SGregory Neil Shapiro 
6540266059SGregory Neil Shapiro 	fake.sm_magic = SmFileMagic;
6640266059SGregory Neil Shapiro 	fake.f_timeout = SM_TIME_FOREVER;
6740266059SGregory Neil Shapiro 	fake.f_timeoutstate = SM_TIME_BLOCK;
6840266059SGregory Neil Shapiro 	fake.f_file = -1;
6940266059SGregory Neil Shapiro 	fake.f_flags = SMWR | SMSTR | SMALC;
7040266059SGregory Neil Shapiro 	fake.f_bf.smb_base = fake.f_p = (unsigned char *)sm_malloc(SM_VA_BUFSIZE);
7140266059SGregory Neil Shapiro 	if (fake.f_bf.smb_base == NULL)
7240266059SGregory Neil Shapiro 		goto err2;
7340266059SGregory Neil Shapiro 	fake.f_close = NULL;
7440266059SGregory Neil Shapiro 	fake.f_open = NULL;
7540266059SGregory Neil Shapiro 	fake.f_read = NULL;
7640266059SGregory Neil Shapiro 	fake.f_write = NULL;
7740266059SGregory Neil Shapiro 	fake.f_seek = NULL;
7840266059SGregory Neil Shapiro 	fake.f_setinfo = fake.f_getinfo = NULL;
7940266059SGregory Neil Shapiro 	fake.f_type = "sm_vasprintf:fake";
8040266059SGregory Neil Shapiro 	fake.f_bf.smb_size = fake.f_w = SM_VA_BUFSIZE - 1;
8140266059SGregory Neil Shapiro 	fake.f_timeout = SM_TIME_FOREVER;
8240266059SGregory Neil Shapiro 	ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap);
8340266059SGregory Neil Shapiro 	if (ret == -1)
8440266059SGregory Neil Shapiro 		goto err;
8540266059SGregory Neil Shapiro 	*fake.f_p = '\0';
8640266059SGregory Neil Shapiro 
8740266059SGregory Neil Shapiro 	/* use no more space than necessary */
8840266059SGregory Neil Shapiro 	base = (unsigned char *) sm_realloc(fake.f_bf.smb_base, ret + 1);
8940266059SGregory Neil Shapiro 	if (base == NULL)
9040266059SGregory Neil Shapiro 		goto err;
9140266059SGregory Neil Shapiro 	*str = (char *)base;
9240266059SGregory Neil Shapiro 	return ret;
9340266059SGregory Neil Shapiro 
9440266059SGregory Neil Shapiro err:
9540266059SGregory Neil Shapiro 	if (fake.f_bf.smb_base != NULL)
9640266059SGregory Neil Shapiro 	{
9740266059SGregory Neil Shapiro 		sm_free(fake.f_bf.smb_base);
9840266059SGregory Neil Shapiro 		fake.f_bf.smb_base = NULL;
9940266059SGregory Neil Shapiro 	}
10040266059SGregory Neil Shapiro err2:
10140266059SGregory Neil Shapiro 	*str = NULL;
10240266059SGregory Neil Shapiro 	errno = ENOMEM;
10340266059SGregory Neil Shapiro 	return -1;
10440266059SGregory Neil Shapiro }
105