190792Sgshapiro/*
2261370Sgshapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *      All rights reserved.
490792Sgshapiro * Copyright (c) 1990, 1993
590792Sgshapiro *	The Regents of the University of California.  All rights reserved.
690792Sgshapiro *
790792Sgshapiro * This code is derived from software contributed to Berkeley by
890792Sgshapiro * Chris Torek.
990792Sgshapiro *
1090792Sgshapiro * By using this file, you agree to the terms and conditions set
1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of
1290792Sgshapiro * the sendmail distribution.
1390792Sgshapiro */
1490792Sgshapiro
1590792Sgshapiro#include <sm/gen.h>
16266711SgshapiroSM_RCSID("@(#)$Id: vsnprintf.c,v 1.24 2013-11-22 20:51:44 ca Exp $")
1790792Sgshapiro#include <limits.h>
1890792Sgshapiro#include <sm/io.h>
1990792Sgshapiro#include "local.h"
2090792Sgshapiro
2190792Sgshapiro/*
2290792Sgshapiro**  SM_VSNPRINTF -- format data for "output" into a string
2390792Sgshapiro**
2490792Sgshapiro**	Assigned 'str' to a "fake" file pointer. This allows common
2590792Sgshapiro**	o/p formatting function sm_vprintf() to be used.
2690792Sgshapiro**
2790792Sgshapiro**	Parameters:
2890792Sgshapiro**		str -- location for output
2990792Sgshapiro**		n -- maximum size for o/p
3090792Sgshapiro**		fmt -- format directives
3190792Sgshapiro**		ap -- data unit vectors for use by 'fmt'
3290792Sgshapiro**
3390792Sgshapiro**	Results:
3490792Sgshapiro**		result from sm_io_vfprintf()
3590792Sgshapiro**
3690792Sgshapiro**	Side Effects:
3790792Sgshapiro**		Limits the size ('n') to INT_MAX.
3890792Sgshapiro*/
3990792Sgshapiro
4090792Sgshapiroint
4190792Sgshapirosm_vsnprintf(str, n, fmt, ap)
4290792Sgshapiro	char *str;
4390792Sgshapiro	size_t n;
4490792Sgshapiro	const char *fmt;
4590792Sgshapiro	SM_VA_LOCAL_DECL
4690792Sgshapiro{
4790792Sgshapiro	int ret;
4890792Sgshapiro	char dummy;
4990792Sgshapiro	SM_FILE_T fake;
5090792Sgshapiro
5190792Sgshapiro	/* While snprintf(3) specifies size_t stdio uses an int internally */
5290792Sgshapiro	if (n > INT_MAX)
5390792Sgshapiro		n = INT_MAX;
5490792Sgshapiro
5590792Sgshapiro	/* Stdio internals do not deal correctly with zero length buffer */
5690792Sgshapiro	if (n == 0)
5790792Sgshapiro	{
5890792Sgshapiro		str = &dummy;
5990792Sgshapiro		n = 1;
6090792Sgshapiro	}
6190792Sgshapiro	fake.sm_magic = SmFileMagic;
6290792Sgshapiro	fake.f_timeout = SM_TIME_FOREVER;
6390792Sgshapiro	fake.f_timeoutstate = SM_TIME_BLOCK;
6490792Sgshapiro	fake.f_file = -1;
6590792Sgshapiro	fake.f_flags = SMWR | SMSTR;
6690792Sgshapiro	fake.f_bf.smb_base = fake.f_p = (unsigned char *)str;
6790792Sgshapiro	fake.f_bf.smb_size = fake.f_w = n - 1;
6890792Sgshapiro	fake.f_close = NULL;
6990792Sgshapiro	fake.f_open = NULL;
7090792Sgshapiro	fake.f_read = NULL;
7190792Sgshapiro	fake.f_write = NULL;
7290792Sgshapiro	fake.f_seek = NULL;
7390792Sgshapiro	fake.f_setinfo = fake.f_getinfo = NULL;
7490792Sgshapiro	fake.f_type = "sm_vsnprintf:fake";
7590792Sgshapiro	ret = sm_io_vfprintf(&fake, SM_TIME_FOREVER, fmt, ap);
7690792Sgshapiro	*fake.f_p = 0;
7790792Sgshapiro	return ret;
7890792Sgshapiro}
79