1/* $NetBSD: vswprintf.c,v 1.1 2005/05/14 23:51:02 christos Exp $ */ 2 3/* 4 * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31#if defined(LIBC_SCCS) && !defined(lint) 32#if 0 33__FBSDID("$FreeBSD: src/lib/libc/stdio/vswprintf.c,v 1.6 2005/02/21 19:41:44 fjoe Exp $"); 34#else 35__RCSID("$NetBSD: vswprintf.c,v 1.1 2005/05/14 23:51:02 christos Exp $"); 36#endif 37#endif /* LIBC_SCCS and not lint */ 38 39#include <errno.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <wchar.h> 43#include <stdarg.h> 44#include "reentrant.h" 45#include "local.h" 46 47int 48vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, 49 va_list ap) 50{ 51 static const mbstate_t initial; 52 mbstate_t mbs; 53 FILE f; 54 char *mbp; 55 int ret, sverrno; 56 size_t nwc; 57 struct __sfileext fext; 58 59 if (n == 0) { 60 errno = EINVAL; 61 return (-1); 62 } 63 64 _FILEEXT_SETUP(&f, &fext); 65 f._file = -1; 66 f._flags = __SWR | __SSTR | __SALC; 67 f._bf._base = f._p = (unsigned char *)malloc(128); 68 if (f._bf._base == NULL) { 69 errno = ENOMEM; 70 return (-1); 71 } 72 f._bf._size = f._w = 127; /* Leave room for the NUL */ 73 ret = __vfwprintf_unlocked(&f, fmt, ap); 74 if (ret < 0) { 75 sverrno = errno; 76 free(f._bf._base); 77 errno = sverrno; 78 return (-1); 79 } 80 *f._p = '\0'; 81 mbp = (char *)f._bf._base; 82 /* 83 * XXX Undo the conversion from wide characters to multibyte that 84 * fputwc() did in __vfwprintf(). 85 */ 86 mbs = initial; 87 nwc = mbsrtowcs(s, (void *)&mbp, n, &mbs); 88 free(f._bf._base); 89 if (nwc == (size_t)-1) { 90 errno = EILSEQ; 91 return (-1); 92 } 93 if (nwc == n) { 94 s[n - 1] = L'\0'; 95 errno = EOVERFLOW; 96 return (-1); 97 } 98 99 return (ret); 100} 101