xref: /freebsd/libexec/rtld-elf/rtld_printf.c (revision 0e9a2605200b721fdfcf32d2c95f79a81fc84352)
1*0e9a2605SKonstantin Belousov /*-
2*0e9a2605SKonstantin Belousov  * Copyright (c) 1986, 1988, 1991, 1993
3*0e9a2605SKonstantin Belousov  *	The Regents of the University of California.  All rights reserved.
4*0e9a2605SKonstantin Belousov  * (c) UNIX System Laboratories, Inc.
5*0e9a2605SKonstantin Belousov  * All or some portions of this file are derived from material licensed
6*0e9a2605SKonstantin Belousov  * to the University of California by American Telephone and Telegraph
7*0e9a2605SKonstantin Belousov  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8*0e9a2605SKonstantin Belousov  * the permission of UNIX System Laboratories, Inc.
9*0e9a2605SKonstantin Belousov  * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
10*0e9a2605SKonstantin Belousov  *
11*0e9a2605SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
12*0e9a2605SKonstantin Belousov  * modification, are permitted provided that the following conditions
13*0e9a2605SKonstantin Belousov  * are met:
14*0e9a2605SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
15*0e9a2605SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
16*0e9a2605SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
17*0e9a2605SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
18*0e9a2605SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
19*0e9a2605SKonstantin Belousov  * 4. Neither the name of the University nor the names of its contributors
20*0e9a2605SKonstantin Belousov  *    may be used to endorse or promote products derived from this software
21*0e9a2605SKonstantin Belousov  *    without specific prior written permission.
22*0e9a2605SKonstantin Belousov  *
23*0e9a2605SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24*0e9a2605SKonstantin Belousov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*0e9a2605SKonstantin Belousov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*0e9a2605SKonstantin Belousov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27*0e9a2605SKonstantin Belousov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*0e9a2605SKonstantin Belousov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*0e9a2605SKonstantin Belousov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*0e9a2605SKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*0e9a2605SKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*0e9a2605SKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*0e9a2605SKonstantin Belousov  * SUCH DAMAGE.
34*0e9a2605SKonstantin Belousov  *
35*0e9a2605SKonstantin Belousov  * $FreeBSD$
36*0e9a2605SKonstantin Belousov  */
37*0e9a2605SKonstantin Belousov 
38*0e9a2605SKonstantin Belousov #include <sys/param.h>
39*0e9a2605SKonstantin Belousov #include <ctype.h>
40*0e9a2605SKonstantin Belousov #include <inttypes.h>
41*0e9a2605SKonstantin Belousov #include <stdarg.h>
42*0e9a2605SKonstantin Belousov #include <stddef.h>
43*0e9a2605SKonstantin Belousov #include <string.h>
44*0e9a2605SKonstantin Belousov #include <unistd.h>
45*0e9a2605SKonstantin Belousov #include "rtld_printf.h"
46*0e9a2605SKonstantin Belousov 
47*0e9a2605SKonstantin Belousov #define MAXNBUF	(sizeof(intmax_t) * NBBY + 1)
48*0e9a2605SKonstantin Belousov 
49*0e9a2605SKonstantin Belousov struct snprintf_arg {
50*0e9a2605SKonstantin Belousov 	char	*str;
51*0e9a2605SKonstantin Belousov 	char	*buf;
52*0e9a2605SKonstantin Belousov 	size_t	remain;
53*0e9a2605SKonstantin Belousov 	size_t	buf_total;
54*0e9a2605SKonstantin Belousov 	int	fd;
55*0e9a2605SKonstantin Belousov };
56*0e9a2605SKonstantin Belousov 
57*0e9a2605SKonstantin Belousov static void
58*0e9a2605SKonstantin Belousov snprintf_func(int ch, struct snprintf_arg *const info)
59*0e9a2605SKonstantin Belousov {
60*0e9a2605SKonstantin Belousov 
61*0e9a2605SKonstantin Belousov 	if (info->remain >= 2) {
62*0e9a2605SKonstantin Belousov 		*info->str++ = ch;
63*0e9a2605SKonstantin Belousov 		info->remain--;
64*0e9a2605SKonstantin Belousov 	}
65*0e9a2605SKonstantin Belousov }
66*0e9a2605SKonstantin Belousov 
67*0e9a2605SKonstantin Belousov static void
68*0e9a2605SKonstantin Belousov printf_out(struct snprintf_arg *info)
69*0e9a2605SKonstantin Belousov {
70*0e9a2605SKonstantin Belousov 
71*0e9a2605SKonstantin Belousov 	if (info->remain == info->buf_total)
72*0e9a2605SKonstantin Belousov 		return;
73*0e9a2605SKonstantin Belousov 	write(info->fd, info->buf, info->buf_total - info->remain);
74*0e9a2605SKonstantin Belousov 	info->str = info->buf;
75*0e9a2605SKonstantin Belousov 	info->remain = info->buf_total;
76*0e9a2605SKonstantin Belousov }
77*0e9a2605SKonstantin Belousov 
78*0e9a2605SKonstantin Belousov static void
79*0e9a2605SKonstantin Belousov printf_func(int ch, struct snprintf_arg *const info)
80*0e9a2605SKonstantin Belousov {
81*0e9a2605SKonstantin Belousov 
82*0e9a2605SKonstantin Belousov 	if (info->remain > 0) {
83*0e9a2605SKonstantin Belousov 		*info->str++ = ch;
84*0e9a2605SKonstantin Belousov 		info->remain--;
85*0e9a2605SKonstantin Belousov 	} else
86*0e9a2605SKonstantin Belousov 		printf_out(info);
87*0e9a2605SKonstantin Belousov }
88*0e9a2605SKonstantin Belousov 
89*0e9a2605SKonstantin Belousov static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
90*0e9a2605SKonstantin Belousov #define	hex2ascii(hex)	(hex2ascii_data[hex])
91*0e9a2605SKonstantin Belousov 
92*0e9a2605SKonstantin Belousov static __inline int
93*0e9a2605SKonstantin Belousov imax(int a, int b)
94*0e9a2605SKonstantin Belousov {
95*0e9a2605SKonstantin Belousov 
96*0e9a2605SKonstantin Belousov 	return (a > b ? a : b);
97*0e9a2605SKonstantin Belousov }
98*0e9a2605SKonstantin Belousov 
99*0e9a2605SKonstantin Belousov static char *
100*0e9a2605SKonstantin Belousov ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
101*0e9a2605SKonstantin Belousov {
102*0e9a2605SKonstantin Belousov 	char *p, c;
103*0e9a2605SKonstantin Belousov 
104*0e9a2605SKonstantin Belousov 	p = nbuf;
105*0e9a2605SKonstantin Belousov 	*p = '\0';
106*0e9a2605SKonstantin Belousov 	do {
107*0e9a2605SKonstantin Belousov 		c = hex2ascii(num % base);
108*0e9a2605SKonstantin Belousov 		*++p = upper ? toupper(c) : c;
109*0e9a2605SKonstantin Belousov 	} while (num /= base);
110*0e9a2605SKonstantin Belousov 	if (lenp)
111*0e9a2605SKonstantin Belousov 		*lenp = p - nbuf;
112*0e9a2605SKonstantin Belousov 	return (p);
113*0e9a2605SKonstantin Belousov }
114*0e9a2605SKonstantin Belousov 
115*0e9a2605SKonstantin Belousov static int
116*0e9a2605SKonstantin Belousov kvprintf(char const *fmt, void (*func)(int c, struct snprintf_arg *const arg),
117*0e9a2605SKonstantin Belousov     struct snprintf_arg *arg, int radix, va_list ap)
118*0e9a2605SKonstantin Belousov {
119*0e9a2605SKonstantin Belousov #define PCHAR(c) func((c), arg)
120*0e9a2605SKonstantin Belousov 	char nbuf[MAXNBUF];
121*0e9a2605SKonstantin Belousov 	const char *p, *percent, *q;
122*0e9a2605SKonstantin Belousov 	u_char *up;
123*0e9a2605SKonstantin Belousov 	int ch, n;
124*0e9a2605SKonstantin Belousov 	uintmax_t num;
125*0e9a2605SKonstantin Belousov 	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
126*0e9a2605SKonstantin Belousov 	int cflag, hflag, jflag, tflag, zflag;
127*0e9a2605SKonstantin Belousov 	int dwidth, upper;
128*0e9a2605SKonstantin Belousov 	char padc;
129*0e9a2605SKonstantin Belousov 	int stop = 0, retval = 0;
130*0e9a2605SKonstantin Belousov 
131*0e9a2605SKonstantin Belousov 	num = 0;
132*0e9a2605SKonstantin Belousov 
133*0e9a2605SKonstantin Belousov 	if (fmt == NULL)
134*0e9a2605SKonstantin Belousov 		fmt = "(fmt null)\n";
135*0e9a2605SKonstantin Belousov 
136*0e9a2605SKonstantin Belousov 	if (radix < 2 || radix > 36)
137*0e9a2605SKonstantin Belousov 		radix = 10;
138*0e9a2605SKonstantin Belousov 
139*0e9a2605SKonstantin Belousov 	for (;;) {
140*0e9a2605SKonstantin Belousov 		padc = ' ';
141*0e9a2605SKonstantin Belousov 		width = 0;
142*0e9a2605SKonstantin Belousov 		while ((ch = (u_char)*fmt++) != '%' || stop) {
143*0e9a2605SKonstantin Belousov 			if (ch == '\0')
144*0e9a2605SKonstantin Belousov 				return (retval);
145*0e9a2605SKonstantin Belousov 			PCHAR(ch);
146*0e9a2605SKonstantin Belousov 		}
147*0e9a2605SKonstantin Belousov 		percent = fmt - 1;
148*0e9a2605SKonstantin Belousov 		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
149*0e9a2605SKonstantin Belousov 		sign = 0; dot = 0; dwidth = 0; upper = 0;
150*0e9a2605SKonstantin Belousov 		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
151*0e9a2605SKonstantin Belousov reswitch:	switch (ch = (u_char)*fmt++) {
152*0e9a2605SKonstantin Belousov 		case '.':
153*0e9a2605SKonstantin Belousov 			dot = 1;
154*0e9a2605SKonstantin Belousov 			goto reswitch;
155*0e9a2605SKonstantin Belousov 		case '#':
156*0e9a2605SKonstantin Belousov 			sharpflag = 1;
157*0e9a2605SKonstantin Belousov 			goto reswitch;
158*0e9a2605SKonstantin Belousov 		case '+':
159*0e9a2605SKonstantin Belousov 			sign = 1;
160*0e9a2605SKonstantin Belousov 			goto reswitch;
161*0e9a2605SKonstantin Belousov 		case '-':
162*0e9a2605SKonstantin Belousov 			ladjust = 1;
163*0e9a2605SKonstantin Belousov 			goto reswitch;
164*0e9a2605SKonstantin Belousov 		case '%':
165*0e9a2605SKonstantin Belousov 			PCHAR(ch);
166*0e9a2605SKonstantin Belousov 			break;
167*0e9a2605SKonstantin Belousov 		case '*':
168*0e9a2605SKonstantin Belousov 			if (!dot) {
169*0e9a2605SKonstantin Belousov 				width = va_arg(ap, int);
170*0e9a2605SKonstantin Belousov 				if (width < 0) {
171*0e9a2605SKonstantin Belousov 					ladjust = !ladjust;
172*0e9a2605SKonstantin Belousov 					width = -width;
173*0e9a2605SKonstantin Belousov 				}
174*0e9a2605SKonstantin Belousov 			} else {
175*0e9a2605SKonstantin Belousov 				dwidth = va_arg(ap, int);
176*0e9a2605SKonstantin Belousov 			}
177*0e9a2605SKonstantin Belousov 			goto reswitch;
178*0e9a2605SKonstantin Belousov 		case '0':
179*0e9a2605SKonstantin Belousov 			if (!dot) {
180*0e9a2605SKonstantin Belousov 				padc = '0';
181*0e9a2605SKonstantin Belousov 				goto reswitch;
182*0e9a2605SKonstantin Belousov 			}
183*0e9a2605SKonstantin Belousov 		case '1': case '2': case '3': case '4':
184*0e9a2605SKonstantin Belousov 		case '5': case '6': case '7': case '8': case '9':
185*0e9a2605SKonstantin Belousov 				for (n = 0;; ++fmt) {
186*0e9a2605SKonstantin Belousov 					n = n * 10 + ch - '0';
187*0e9a2605SKonstantin Belousov 					ch = *fmt;
188*0e9a2605SKonstantin Belousov 					if (ch < '0' || ch > '9')
189*0e9a2605SKonstantin Belousov 						break;
190*0e9a2605SKonstantin Belousov 				}
191*0e9a2605SKonstantin Belousov 			if (dot)
192*0e9a2605SKonstantin Belousov 				dwidth = n;
193*0e9a2605SKonstantin Belousov 			else
194*0e9a2605SKonstantin Belousov 				width = n;
195*0e9a2605SKonstantin Belousov 			goto reswitch;
196*0e9a2605SKonstantin Belousov 		case 'b':
197*0e9a2605SKonstantin Belousov 			num = (u_int)va_arg(ap, int);
198*0e9a2605SKonstantin Belousov 			p = va_arg(ap, char *);
199*0e9a2605SKonstantin Belousov 			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
200*0e9a2605SKonstantin Belousov 				PCHAR(*q--);
201*0e9a2605SKonstantin Belousov 
202*0e9a2605SKonstantin Belousov 			if (num == 0)
203*0e9a2605SKonstantin Belousov 				break;
204*0e9a2605SKonstantin Belousov 
205*0e9a2605SKonstantin Belousov 			for (tmp = 0; *p;) {
206*0e9a2605SKonstantin Belousov 				n = *p++;
207*0e9a2605SKonstantin Belousov 				if (num & (1 << (n - 1))) {
208*0e9a2605SKonstantin Belousov 					PCHAR(tmp ? ',' : '<');
209*0e9a2605SKonstantin Belousov 					for (; (n = *p) > ' '; ++p)
210*0e9a2605SKonstantin Belousov 						PCHAR(n);
211*0e9a2605SKonstantin Belousov 					tmp = 1;
212*0e9a2605SKonstantin Belousov 				} else
213*0e9a2605SKonstantin Belousov 					for (; *p > ' '; ++p)
214*0e9a2605SKonstantin Belousov 						continue;
215*0e9a2605SKonstantin Belousov 			}
216*0e9a2605SKonstantin Belousov 			if (tmp)
217*0e9a2605SKonstantin Belousov 				PCHAR('>');
218*0e9a2605SKonstantin Belousov 			break;
219*0e9a2605SKonstantin Belousov 		case 'c':
220*0e9a2605SKonstantin Belousov 			PCHAR(va_arg(ap, int));
221*0e9a2605SKonstantin Belousov 			break;
222*0e9a2605SKonstantin Belousov 		case 'D':
223*0e9a2605SKonstantin Belousov 			up = va_arg(ap, u_char *);
224*0e9a2605SKonstantin Belousov 			p = va_arg(ap, char *);
225*0e9a2605SKonstantin Belousov 			if (!width)
226*0e9a2605SKonstantin Belousov 				width = 16;
227*0e9a2605SKonstantin Belousov 			while(width--) {
228*0e9a2605SKonstantin Belousov 				PCHAR(hex2ascii(*up >> 4));
229*0e9a2605SKonstantin Belousov 				PCHAR(hex2ascii(*up & 0x0f));
230*0e9a2605SKonstantin Belousov 				up++;
231*0e9a2605SKonstantin Belousov 				if (width)
232*0e9a2605SKonstantin Belousov 					for (q=p;*q;q++)
233*0e9a2605SKonstantin Belousov 						PCHAR(*q);
234*0e9a2605SKonstantin Belousov 			}
235*0e9a2605SKonstantin Belousov 			break;
236*0e9a2605SKonstantin Belousov 		case 'd':
237*0e9a2605SKonstantin Belousov 		case 'i':
238*0e9a2605SKonstantin Belousov 			base = 10;
239*0e9a2605SKonstantin Belousov 			sign = 1;
240*0e9a2605SKonstantin Belousov 			goto handle_sign;
241*0e9a2605SKonstantin Belousov 		case 'h':
242*0e9a2605SKonstantin Belousov 			if (hflag) {
243*0e9a2605SKonstantin Belousov 				hflag = 0;
244*0e9a2605SKonstantin Belousov 				cflag = 1;
245*0e9a2605SKonstantin Belousov 			} else
246*0e9a2605SKonstantin Belousov 				hflag = 1;
247*0e9a2605SKonstantin Belousov 			goto reswitch;
248*0e9a2605SKonstantin Belousov 		case 'j':
249*0e9a2605SKonstantin Belousov 			jflag = 1;
250*0e9a2605SKonstantin Belousov 			goto reswitch;
251*0e9a2605SKonstantin Belousov 		case 'l':
252*0e9a2605SKonstantin Belousov 			if (lflag) {
253*0e9a2605SKonstantin Belousov 				lflag = 0;
254*0e9a2605SKonstantin Belousov 				qflag = 1;
255*0e9a2605SKonstantin Belousov 			} else
256*0e9a2605SKonstantin Belousov 				lflag = 1;
257*0e9a2605SKonstantin Belousov 			goto reswitch;
258*0e9a2605SKonstantin Belousov 		case 'n':
259*0e9a2605SKonstantin Belousov 			if (jflag)
260*0e9a2605SKonstantin Belousov 				*(va_arg(ap, intmax_t *)) = retval;
261*0e9a2605SKonstantin Belousov 			else if (qflag)
262*0e9a2605SKonstantin Belousov 				*(va_arg(ap, quad_t *)) = retval;
263*0e9a2605SKonstantin Belousov 			else if (lflag)
264*0e9a2605SKonstantin Belousov 				*(va_arg(ap, long *)) = retval;
265*0e9a2605SKonstantin Belousov 			else if (zflag)
266*0e9a2605SKonstantin Belousov 				*(va_arg(ap, size_t *)) = retval;
267*0e9a2605SKonstantin Belousov 			else if (hflag)
268*0e9a2605SKonstantin Belousov 				*(va_arg(ap, short *)) = retval;
269*0e9a2605SKonstantin Belousov 			else if (cflag)
270*0e9a2605SKonstantin Belousov 				*(va_arg(ap, char *)) = retval;
271*0e9a2605SKonstantin Belousov 			else
272*0e9a2605SKonstantin Belousov 				*(va_arg(ap, int *)) = retval;
273*0e9a2605SKonstantin Belousov 			break;
274*0e9a2605SKonstantin Belousov 		case 'o':
275*0e9a2605SKonstantin Belousov 			base = 8;
276*0e9a2605SKonstantin Belousov 			goto handle_nosign;
277*0e9a2605SKonstantin Belousov 		case 'p':
278*0e9a2605SKonstantin Belousov 			base = 16;
279*0e9a2605SKonstantin Belousov 			sharpflag = (width == 0);
280*0e9a2605SKonstantin Belousov 			sign = 0;
281*0e9a2605SKonstantin Belousov 			num = (uintptr_t)va_arg(ap, void *);
282*0e9a2605SKonstantin Belousov 			goto number;
283*0e9a2605SKonstantin Belousov 		case 'q':
284*0e9a2605SKonstantin Belousov 			qflag = 1;
285*0e9a2605SKonstantin Belousov 			goto reswitch;
286*0e9a2605SKonstantin Belousov 		case 'r':
287*0e9a2605SKonstantin Belousov 			base = radix;
288*0e9a2605SKonstantin Belousov 			if (sign)
289*0e9a2605SKonstantin Belousov 				goto handle_sign;
290*0e9a2605SKonstantin Belousov 			goto handle_nosign;
291*0e9a2605SKonstantin Belousov 		case 's':
292*0e9a2605SKonstantin Belousov 			p = va_arg(ap, char *);
293*0e9a2605SKonstantin Belousov 			if (p == NULL)
294*0e9a2605SKonstantin Belousov 				p = "(null)";
295*0e9a2605SKonstantin Belousov 			if (!dot)
296*0e9a2605SKonstantin Belousov 				n = strlen (p);
297*0e9a2605SKonstantin Belousov 			else
298*0e9a2605SKonstantin Belousov 				for (n = 0; n < dwidth && p[n]; n++)
299*0e9a2605SKonstantin Belousov 					continue;
300*0e9a2605SKonstantin Belousov 
301*0e9a2605SKonstantin Belousov 			width -= n;
302*0e9a2605SKonstantin Belousov 
303*0e9a2605SKonstantin Belousov 			if (!ladjust && width > 0)
304*0e9a2605SKonstantin Belousov 				while (width--)
305*0e9a2605SKonstantin Belousov 					PCHAR(padc);
306*0e9a2605SKonstantin Belousov 			while (n--)
307*0e9a2605SKonstantin Belousov 				PCHAR(*p++);
308*0e9a2605SKonstantin Belousov 			if (ladjust && width > 0)
309*0e9a2605SKonstantin Belousov 				while (width--)
310*0e9a2605SKonstantin Belousov 					PCHAR(padc);
311*0e9a2605SKonstantin Belousov 			break;
312*0e9a2605SKonstantin Belousov 		case 't':
313*0e9a2605SKonstantin Belousov 			tflag = 1;
314*0e9a2605SKonstantin Belousov 			goto reswitch;
315*0e9a2605SKonstantin Belousov 		case 'u':
316*0e9a2605SKonstantin Belousov 			base = 10;
317*0e9a2605SKonstantin Belousov 			goto handle_nosign;
318*0e9a2605SKonstantin Belousov 		case 'X':
319*0e9a2605SKonstantin Belousov 			upper = 1;
320*0e9a2605SKonstantin Belousov 		case 'x':
321*0e9a2605SKonstantin Belousov 			base = 16;
322*0e9a2605SKonstantin Belousov 			goto handle_nosign;
323*0e9a2605SKonstantin Belousov 		case 'y':
324*0e9a2605SKonstantin Belousov 			base = 16;
325*0e9a2605SKonstantin Belousov 			sign = 1;
326*0e9a2605SKonstantin Belousov 			goto handle_sign;
327*0e9a2605SKonstantin Belousov 		case 'z':
328*0e9a2605SKonstantin Belousov 			zflag = 1;
329*0e9a2605SKonstantin Belousov 			goto reswitch;
330*0e9a2605SKonstantin Belousov handle_nosign:
331*0e9a2605SKonstantin Belousov 			sign = 0;
332*0e9a2605SKonstantin Belousov 			if (jflag)
333*0e9a2605SKonstantin Belousov 				num = va_arg(ap, uintmax_t);
334*0e9a2605SKonstantin Belousov 			else if (qflag)
335*0e9a2605SKonstantin Belousov 				num = va_arg(ap, u_quad_t);
336*0e9a2605SKonstantin Belousov 			else if (tflag)
337*0e9a2605SKonstantin Belousov 				num = va_arg(ap, ptrdiff_t);
338*0e9a2605SKonstantin Belousov 			else if (lflag)
339*0e9a2605SKonstantin Belousov 				num = va_arg(ap, u_long);
340*0e9a2605SKonstantin Belousov 			else if (zflag)
341*0e9a2605SKonstantin Belousov 				num = va_arg(ap, size_t);
342*0e9a2605SKonstantin Belousov 			else if (hflag)
343*0e9a2605SKonstantin Belousov 				num = (u_short)va_arg(ap, int);
344*0e9a2605SKonstantin Belousov 			else if (cflag)
345*0e9a2605SKonstantin Belousov 				num = (u_char)va_arg(ap, int);
346*0e9a2605SKonstantin Belousov 			else
347*0e9a2605SKonstantin Belousov 				num = va_arg(ap, u_int);
348*0e9a2605SKonstantin Belousov 			goto number;
349*0e9a2605SKonstantin Belousov handle_sign:
350*0e9a2605SKonstantin Belousov 			if (jflag)
351*0e9a2605SKonstantin Belousov 				num = va_arg(ap, intmax_t);
352*0e9a2605SKonstantin Belousov 			else if (qflag)
353*0e9a2605SKonstantin Belousov 				num = va_arg(ap, quad_t);
354*0e9a2605SKonstantin Belousov 			else if (tflag)
355*0e9a2605SKonstantin Belousov 				num = va_arg(ap, ptrdiff_t);
356*0e9a2605SKonstantin Belousov 			else if (lflag)
357*0e9a2605SKonstantin Belousov 				num = va_arg(ap, long);
358*0e9a2605SKonstantin Belousov 			else if (zflag)
359*0e9a2605SKonstantin Belousov 				num = va_arg(ap, ssize_t);
360*0e9a2605SKonstantin Belousov 			else if (hflag)
361*0e9a2605SKonstantin Belousov 				num = (short)va_arg(ap, int);
362*0e9a2605SKonstantin Belousov 			else if (cflag)
363*0e9a2605SKonstantin Belousov 				num = (char)va_arg(ap, int);
364*0e9a2605SKonstantin Belousov 			else
365*0e9a2605SKonstantin Belousov 				num = va_arg(ap, int);
366*0e9a2605SKonstantin Belousov number:
367*0e9a2605SKonstantin Belousov 			if (sign && (intmax_t)num < 0) {
368*0e9a2605SKonstantin Belousov 				neg = 1;
369*0e9a2605SKonstantin Belousov 				num = -(intmax_t)num;
370*0e9a2605SKonstantin Belousov 			}
371*0e9a2605SKonstantin Belousov 			p = ksprintn(nbuf, num, base, &n, upper);
372*0e9a2605SKonstantin Belousov 			tmp = 0;
373*0e9a2605SKonstantin Belousov 			if (sharpflag && num != 0) {
374*0e9a2605SKonstantin Belousov 				if (base == 8)
375*0e9a2605SKonstantin Belousov 					tmp++;
376*0e9a2605SKonstantin Belousov 				else if (base == 16)
377*0e9a2605SKonstantin Belousov 					tmp += 2;
378*0e9a2605SKonstantin Belousov 			}
379*0e9a2605SKonstantin Belousov 			if (neg)
380*0e9a2605SKonstantin Belousov 				tmp++;
381*0e9a2605SKonstantin Belousov 
382*0e9a2605SKonstantin Belousov 			if (!ladjust && padc == '0')
383*0e9a2605SKonstantin Belousov 				dwidth = width - tmp;
384*0e9a2605SKonstantin Belousov 			width -= tmp + imax(dwidth, n);
385*0e9a2605SKonstantin Belousov 			dwidth -= n;
386*0e9a2605SKonstantin Belousov 			if (!ladjust)
387*0e9a2605SKonstantin Belousov 				while (width-- > 0)
388*0e9a2605SKonstantin Belousov 					PCHAR(' ');
389*0e9a2605SKonstantin Belousov 			if (neg)
390*0e9a2605SKonstantin Belousov 				PCHAR('-');
391*0e9a2605SKonstantin Belousov 			if (sharpflag && num != 0) {
392*0e9a2605SKonstantin Belousov 				if (base == 8) {
393*0e9a2605SKonstantin Belousov 					PCHAR('0');
394*0e9a2605SKonstantin Belousov 				} else if (base == 16) {
395*0e9a2605SKonstantin Belousov 					PCHAR('0');
396*0e9a2605SKonstantin Belousov 					PCHAR('x');
397*0e9a2605SKonstantin Belousov 				}
398*0e9a2605SKonstantin Belousov 			}
399*0e9a2605SKonstantin Belousov 			while (dwidth-- > 0)
400*0e9a2605SKonstantin Belousov 				PCHAR('0');
401*0e9a2605SKonstantin Belousov 
402*0e9a2605SKonstantin Belousov 			while (*p)
403*0e9a2605SKonstantin Belousov 				PCHAR(*p--);
404*0e9a2605SKonstantin Belousov 
405*0e9a2605SKonstantin Belousov 			if (ladjust)
406*0e9a2605SKonstantin Belousov 				while (width-- > 0)
407*0e9a2605SKonstantin Belousov 					PCHAR(' ');
408*0e9a2605SKonstantin Belousov 
409*0e9a2605SKonstantin Belousov 			break;
410*0e9a2605SKonstantin Belousov 		default:
411*0e9a2605SKonstantin Belousov 			while (percent < fmt)
412*0e9a2605SKonstantin Belousov 				PCHAR(*percent++);
413*0e9a2605SKonstantin Belousov 			/*
414*0e9a2605SKonstantin Belousov 			 * Since we ignore an formatting argument it is no
415*0e9a2605SKonstantin Belousov 			 * longer safe to obey the remaining formatting
416*0e9a2605SKonstantin Belousov 			 * arguments as the arguments will no longer match
417*0e9a2605SKonstantin Belousov 			 * the format specs.
418*0e9a2605SKonstantin Belousov 			 */
419*0e9a2605SKonstantin Belousov 			stop = 1;
420*0e9a2605SKonstantin Belousov 			break;
421*0e9a2605SKonstantin Belousov 		}
422*0e9a2605SKonstantin Belousov 	}
423*0e9a2605SKonstantin Belousov #undef PCHAR
424*0e9a2605SKonstantin Belousov }
425*0e9a2605SKonstantin Belousov 
426*0e9a2605SKonstantin Belousov int
427*0e9a2605SKonstantin Belousov rtld_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap)
428*0e9a2605SKonstantin Belousov {
429*0e9a2605SKonstantin Belousov 	struct snprintf_arg info;
430*0e9a2605SKonstantin Belousov 	int retval;
431*0e9a2605SKonstantin Belousov 
432*0e9a2605SKonstantin Belousov 	info.buf = info.str = buf;
433*0e9a2605SKonstantin Belousov 	info.buf_total = info.remain = bufsize;
434*0e9a2605SKonstantin Belousov 	info.fd = -1;
435*0e9a2605SKonstantin Belousov 	retval = kvprintf(fmt, snprintf_func, &info, 10, ap);
436*0e9a2605SKonstantin Belousov 	if (info.remain >= 1)
437*0e9a2605SKonstantin Belousov 		*info.str++ = '\0';
438*0e9a2605SKonstantin Belousov 	return (retval);
439*0e9a2605SKonstantin Belousov }
440*0e9a2605SKonstantin Belousov 
441*0e9a2605SKonstantin Belousov int
442*0e9a2605SKonstantin Belousov rtld_vfdprintf(int fd, const char *fmt, va_list ap)
443*0e9a2605SKonstantin Belousov {
444*0e9a2605SKonstantin Belousov 	char buf[512];
445*0e9a2605SKonstantin Belousov 	struct snprintf_arg info;
446*0e9a2605SKonstantin Belousov 	int retval;
447*0e9a2605SKonstantin Belousov 
448*0e9a2605SKonstantin Belousov 	info.buf = info.str = buf;
449*0e9a2605SKonstantin Belousov 	info.buf_total = info.remain = sizeof(buf);
450*0e9a2605SKonstantin Belousov 	info.fd = fd;
451*0e9a2605SKonstantin Belousov 	retval = kvprintf(fmt, printf_func, &info, 10, ap);
452*0e9a2605SKonstantin Belousov 	printf_out(&info);
453*0e9a2605SKonstantin Belousov 	return (retval);
454*0e9a2605SKonstantin Belousov }
455*0e9a2605SKonstantin Belousov 
456*0e9a2605SKonstantin Belousov int
457*0e9a2605SKonstantin Belousov rtld_fdprintf(int fd, const char *fmt, ...)
458*0e9a2605SKonstantin Belousov {
459*0e9a2605SKonstantin Belousov 	va_list ap;
460*0e9a2605SKonstantin Belousov 	int retval;
461*0e9a2605SKonstantin Belousov 
462*0e9a2605SKonstantin Belousov 	va_start(ap, fmt);
463*0e9a2605SKonstantin Belousov 	retval = rtld_vfdprintf(fd, fmt, ap);
464*0e9a2605SKonstantin Belousov 	va_end(ap);
465*0e9a2605SKonstantin Belousov 	return (retval);
466*0e9a2605SKonstantin Belousov }
467*0e9a2605SKonstantin Belousov 
468*0e9a2605SKonstantin Belousov void
469*0e9a2605SKonstantin Belousov rtld_fdputstr(int fd, const char *str)
470*0e9a2605SKonstantin Belousov {
471*0e9a2605SKonstantin Belousov 
472*0e9a2605SKonstantin Belousov 	write(fd, str, strlen(str));
473*0e9a2605SKonstantin Belousov }
474*0e9a2605SKonstantin Belousov 
475*0e9a2605SKonstantin Belousov void
476*0e9a2605SKonstantin Belousov rtld_fdputchar(int fd, int c)
477*0e9a2605SKonstantin Belousov {
478*0e9a2605SKonstantin Belousov 	char c1;
479*0e9a2605SKonstantin Belousov 
480*0e9a2605SKonstantin Belousov 	c1 = c;
481*0e9a2605SKonstantin Belousov 	write(fd, &c1, 1);
482*0e9a2605SKonstantin Belousov }
483