11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1990, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Chris Torek.
71573Srgrimes *
8227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation
9227753Stheraven * All rights reserved.
10227753Stheraven * Portions of this software were developed by David Chisnall
11227753Stheraven * under sponsorship from the FreeBSD Foundation.
12227753Stheraven *
131573Srgrimes * Redistribution and use in source and binary forms, with or without
141573Srgrimes * modification, are permitted provided that the following conditions
151573Srgrimes * are met:
161573Srgrimes * 1. Redistributions of source code must retain the above copyright
171573Srgrimes *    notice, this list of conditions and the following disclaimer.
181573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
191573Srgrimes *    notice, this list of conditions and the following disclaimer in the
201573Srgrimes *    documentation and/or other materials provided with the distribution.
21249808Semaste * 3. Neither the name of the University nor the names of its contributors
221573Srgrimes *    may be used to endorse or promote products derived from this software
231573Srgrimes *    without specific prior written permission.
241573Srgrimes *
251573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
261573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
271573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
291573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
301573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
311573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
321573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
331573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
341573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
351573Srgrimes * SUCH DAMAGE.
361573Srgrimes */
371573Srgrimes
381573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
391573Srgrimesstatic char sccsid[] = "@(#)vsnprintf.c	8.1 (Berkeley) 6/4/93";
401573Srgrimes#endif /* LIBC_SCCS and not lint */
4192986Sobrien#include <sys/cdefs.h>
4292986Sobrien__FBSDID("$FreeBSD$");
431573Srgrimes
44234531Sdas#include <errno.h>
4532168Sache#include <limits.h>
461573Srgrimes#include <stdio.h>
4771579Sdeischen#include "local.h"
48227753Stheraven#include "xlocale_private.h"
491573Srgrimes
5013545Sjulianint
51227753Stheravenvsnprintf_l(char * __restrict str, size_t n, locale_t locale,
52227753Stheraven		const char * __restrict fmt, __va_list ap)
531573Srgrimes{
5432168Sache	size_t on;
551573Srgrimes	int ret;
56117147Sjkh	char dummy[2];
57205021Sjhb	FILE f = FAKE_FILE;
58227753Stheraven	FIX_LOCALE(locale);
591573Srgrimes
6031980Sache	on = n;
6132168Sache	if (n != 0)
6231980Sache		n--;
63234531Sdas	if (n > INT_MAX) {
64234531Sdas		errno = EOVERFLOW;
65234531Sdas		*str = '\0';
66234531Sdas		return (EOF);
67234531Sdas	}
68103480Smaxim	/* Stdio internals do not deal correctly with zero length buffer */
69103480Smaxim	if (n == 0) {
70117147Sjkh		if (on > 0)
71117147Sjkh	  		*str = '\0';
72117147Sjkh		str = dummy;
73117147Sjkh		n = 1;
74103480Smaxim	}
751573Srgrimes	f._flags = __SWR | __SSTR;
761573Srgrimes	f._bf._base = f._p = (unsigned char *)str;
7731966Sache	f._bf._size = f._w = n;
78227753Stheraven	ret = __vfprintf(&f, locale, fmt, ap);
7931980Sache	if (on > 0)
8031980Sache		*f._p = '\0';
8131980Sache	return (ret);
821573Srgrimes}
83227753Stheravenint
84227753Stheravenvsnprintf(char * __restrict str, size_t n, const char * __restrict fmt,
85227753Stheraven    __va_list ap)
86227753Stheraven{
87227753Stheraven	return vsnprintf_l(str, n, __get_locale(), fmt, ap);
88227753Stheraven}
89