xref: /illumos-gate/usr/src/lib/libc/port/print/vwprintf.c (revision 2bbdd445a21f9d61f4a0ca0faf05d5ceb2bd91f3)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 #include "lint.h"
32 #include "file64.h"
33 #include <mtlib.h>
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <errno.h>
37 #include <thread.h>
38 #include <synch.h>
39 #include <values.h>
40 #include <wchar.h>
41 #include "print.h"
42 #include "stdiom.h"
43 #include <sys/types.h>
44 #include "libc.h"
45 #include "mse.h"
46 
47 /*
48  * 32-bit shadow functions _vwprintf_c89(), _vfwprintf_c89(),
49  * _vswprintf_c89() are included here.
50  * When using the c89 compiler to build 32-bit applications, the size
51  * of intmax_t is 32-bits, otherwise the size of intmax_t is 64-bits.
52  * The shadow function uses 32-bit size of intmax_t for j conversion.
53  * The #pragma redefine_extname in <wchar.h> selects the proper routine
54  * at compile time for the user application.
55  * NOTE: shadow functions only exist in the 32-bit library.
56  */
57 
58 int
59 #ifdef _C89_INTMAX32		/* _C89_INTMAX32 version in 32-bit libc only */
60 _vwprintf_c89(const wchar_t *format, va_list ap)
61 #else
62 vwprintf(const wchar_t *format, va_list ap)
63 #endif
64 {
65 	ssize_t	count;
66 	rmutex_t	*lk;
67 
68 	FLOCKFILE(lk, stdout);
69 
70 	if (GET_NO_MODE(stdout))
71 		_setorientation(stdout, _WC_MODE);
72 	if (!(stdout->_flag & _IOWRT)) {
73 		/* if no write flag */
74 		if (stdout->_flag & _IORW) {
75 			/* if ok, cause read-write */
76 			stdout->_flag |= _IOWRT;
77 		} else {
78 			/* else error */
79 			errno = EBADF;
80 			FUNLOCKFILE(lk);
81 			return (EOF);
82 		}
83 	}
84 #ifdef _C89_INTMAX32
85 	count = _wndoprnt(format, ap, stdout, _F_INTMAX32);
86 #else
87 	count = _wndoprnt(format, ap, stdout, 0);
88 #endif  /* _C89_INTMAX32 */
89 
90 	if (FERROR(stdout) || count == EOF) {
91 		FUNLOCKFILE(lk);
92 		return (EOF);
93 	}
94 	FUNLOCKFILE(lk);
95 	/* check for overflow */
96 	if ((size_t)count > MAXINT) {
97 		errno = EOVERFLOW;
98 		return (EOF);
99 	} else {
100 		return ((int)count);
101 	}
102 }
103 
104 int
105 #ifdef _C89_INTMAX32		/* _C89_INTMAX32 version in 32-bit libc only */
106 _vfwprintf_c89(FILE *iop, const wchar_t *format, va_list ap)
107 #else
108 vfwprintf(FILE *iop, const wchar_t *format, va_list ap)
109 #endif
110 {
111 	ssize_t	count;
112 	rmutex_t	*lk;
113 
114 	FLOCKFILE(lk, iop);
115 
116 	if (GET_NO_MODE(iop))
117 		_setorientation(iop, _WC_MODE);
118 
119 	if (!(iop->_flag & _IOWRT)) {
120 		/* if no write flag */
121 		if (iop->_flag & _IORW) {
122 			/* if ok, cause read-write */
123 			iop->_flag |= _IOWRT;
124 		} else {
125 			/* else error */
126 			errno = EBADF;
127 			FUNLOCKFILE(lk);
128 			return (EOF);
129 		}
130 	}
131 #ifdef _C89_INTMAX32
132 	count = _wndoprnt(format, ap, iop, _F_INTMAX32);
133 #else
134 	count = _wndoprnt(format, ap, iop, 0);
135 #endif
136 	if (FERROR(iop) || count == EOF) {
137 		FUNLOCKFILE(lk);
138 		return (EOF);
139 	}
140 	FUNLOCKFILE(lk);
141 	/* check for overflow */
142 	if ((size_t)count > MAXINT) {
143 		errno = EOVERFLOW;
144 		return (EOF);
145 	} else {
146 		return ((int)count);
147 	}
148 }
149 
150 int
151 #ifdef _C89_INTMAX32		/* _C89_INTMAX32 version in 32-bit libc only */
152 _vswprintf_c89(wchar_t *string, size_t n, const wchar_t *format, va_list ap)
153 #else
154 vswprintf(wchar_t *string, size_t n, const wchar_t *format, va_list ap)
155 #endif
156 {
157 	ssize_t	count;
158 	FILE	siop;
159 	wchar_t	*wp;
160 
161 	if (n == 0)
162 		return (EOF);
163 
164 	siop._cnt = (ssize_t)n - 1;
165 	siop._base = siop._ptr = (unsigned char *)string;
166 	siop._flag = _IOREAD;
167 
168 #ifdef _C89_INTMAX32
169 	count = _wndoprnt(format, ap, &siop, _F_INTMAX32);
170 #else
171 	count = _wndoprnt(format, ap, &siop, 0);
172 #endif
173 	wp = (wchar_t *)(uintptr_t)siop._ptr;
174 	*wp = L'\0';
175 	if (count == EOF) {
176 		return (EOF);
177 	}
178 	/* check for overflow */
179 	if ((size_t)count > MAXINT) {
180 		errno = EOVERFLOW;
181 		return (EOF);
182 	} else {
183 		return ((int)count);
184 	}
185 }
186