xref: /freebsd/libexec/rtld-elf/rtld_printf.c (revision f5a8f6f71a6845ad2eb3d8db22789ba6b1fd3fd8)
10e9a2605SKonstantin Belousov /*-
28a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni  *
40e9a2605SKonstantin Belousov  * Copyright (c) 1986, 1988, 1991, 1993
50e9a2605SKonstantin Belousov  *	The Regents of the University of California.  All rights reserved.
60e9a2605SKonstantin Belousov  * (c) UNIX System Laboratories, Inc.
70e9a2605SKonstantin Belousov  * All or some portions of this file are derived from material licensed
80e9a2605SKonstantin Belousov  * to the University of California by American Telephone and Telegraph
90e9a2605SKonstantin Belousov  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
100e9a2605SKonstantin Belousov  * the permission of UNIX System Laboratories, Inc.
110e9a2605SKonstantin Belousov  * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
120e9a2605SKonstantin Belousov  *
130e9a2605SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
140e9a2605SKonstantin Belousov  * modification, are permitted provided that the following conditions
150e9a2605SKonstantin Belousov  * are met:
160e9a2605SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
170e9a2605SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
180e9a2605SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
190e9a2605SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
200e9a2605SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
21fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
220e9a2605SKonstantin Belousov  *    may be used to endorse or promote products derived from this software
230e9a2605SKonstantin Belousov  *    without specific prior written permission.
240e9a2605SKonstantin Belousov  *
250e9a2605SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
260e9a2605SKonstantin Belousov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
270e9a2605SKonstantin Belousov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
280e9a2605SKonstantin Belousov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
290e9a2605SKonstantin Belousov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
300e9a2605SKonstantin Belousov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
310e9a2605SKonstantin Belousov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
320e9a2605SKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
330e9a2605SKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
340e9a2605SKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
350e9a2605SKonstantin Belousov  * SUCH DAMAGE.
360e9a2605SKonstantin Belousov  */
370e9a2605SKonstantin Belousov 
380e9a2605SKonstantin Belousov #include <sys/param.h>
390e9a2605SKonstantin Belousov #include <inttypes.h>
400e9a2605SKonstantin Belousov #include <stdarg.h>
410e9a2605SKonstantin Belousov #include <stddef.h>
420e9a2605SKonstantin Belousov #include <string.h>
430e9a2605SKonstantin Belousov #include <unistd.h>
440e9a2605SKonstantin Belousov #include "rtld_printf.h"
45b54a59f3SAlex Richardson #include "rtld_libc.h"
460e9a2605SKonstantin Belousov 
470e9a2605SKonstantin Belousov #define MAXNBUF	(sizeof(intmax_t) * NBBY + 1)
480e9a2605SKonstantin Belousov 
49b2367317SKonstantin Belousov #define	PRINT_METHOD_SNPRINTF	1
50b2367317SKonstantin Belousov #define	PRINT_METHOD_WRITE	2
51b2367317SKonstantin Belousov 
520e9a2605SKonstantin Belousov struct snprintf_arg {
53b2367317SKonstantin Belousov 	int	method;
540e9a2605SKonstantin Belousov 	char	*str;
550e9a2605SKonstantin Belousov 	char	*buf;
560e9a2605SKonstantin Belousov 	size_t	remain;
570e9a2605SKonstantin Belousov 	size_t	buf_total;
580e9a2605SKonstantin Belousov 	int	fd;
590e9a2605SKonstantin Belousov };
600e9a2605SKonstantin Belousov 
610e9a2605SKonstantin Belousov static void
printf_out(struct snprintf_arg * info)620e9a2605SKonstantin Belousov printf_out(struct snprintf_arg *info)
630e9a2605SKonstantin Belousov {
640e9a2605SKonstantin Belousov 
650e9a2605SKonstantin Belousov 	if (info->remain == info->buf_total)
660e9a2605SKonstantin Belousov 		return;
670e9a2605SKonstantin Belousov 	write(info->fd, info->buf, info->buf_total - info->remain);
680e9a2605SKonstantin Belousov 	info->str = info->buf;
690e9a2605SKonstantin Belousov 	info->remain = info->buf_total;
700e9a2605SKonstantin Belousov }
710e9a2605SKonstantin Belousov 
720e9a2605SKonstantin Belousov static void
snprintf_func(int ch,struct snprintf_arg * const info)73b2367317SKonstantin Belousov snprintf_func(int ch, struct snprintf_arg *const info)
740e9a2605SKonstantin Belousov {
750e9a2605SKonstantin Belousov 
76b2367317SKonstantin Belousov 	switch (info->method) {
77b2367317SKonstantin Belousov 	case PRINT_METHOD_SNPRINTF:
78b2367317SKonstantin Belousov 		if (info->remain >= 2) {
79b2367317SKonstantin Belousov 			*info->str++ = ch;
80b2367317SKonstantin Belousov 			info->remain--;
81b2367317SKonstantin Belousov 		}
82b2367317SKonstantin Belousov 		break;
83b2367317SKonstantin Belousov 	case PRINT_METHOD_WRITE:
8456ee5fc4SKonstantin Belousov 		if (info->remain == 0)
8556ee5fc4SKonstantin Belousov 			printf_out(info);
860e9a2605SKonstantin Belousov 		*info->str++ = ch;
870e9a2605SKonstantin Belousov 		info->remain--;
88b2367317SKonstantin Belousov 		break;
89b2367317SKonstantin Belousov 	}
900e9a2605SKonstantin Belousov }
910e9a2605SKonstantin Belousov 
925983b871SKonstantin Belousov static char const hex2ascii_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
935983b871SKonstantin Belousov static char const hex2ascii_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
945983b871SKonstantin Belousov #define	hex2ascii(hex)	(hex2ascii_lower[hex])
955983b871SKonstantin Belousov #define	hex2ascii_upper(hex)	(hex2ascii_upper[hex])
960e9a2605SKonstantin Belousov 
970e9a2605SKonstantin Belousov static __inline int
imax(int a,int b)980e9a2605SKonstantin Belousov imax(int a, int b)
990e9a2605SKonstantin Belousov {
1000e9a2605SKonstantin Belousov 
1010e9a2605SKonstantin Belousov 	return (a > b ? a : b);
1020e9a2605SKonstantin Belousov }
1030e9a2605SKonstantin Belousov 
1040e9a2605SKonstantin Belousov static char *
ksprintn(char * nbuf,uintmax_t num,int base,int * lenp,int upper)1050e9a2605SKonstantin Belousov ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
1060e9a2605SKonstantin Belousov {
1070e9a2605SKonstantin Belousov 	char *p, c;
1080e9a2605SKonstantin Belousov 
1090e9a2605SKonstantin Belousov 	p = nbuf;
1100e9a2605SKonstantin Belousov 	*p = '\0';
1110e9a2605SKonstantin Belousov 	do {
1125983b871SKonstantin Belousov 		c = upper ? hex2ascii_upper(num % base) :
1135983b871SKonstantin Belousov 		    hex2ascii(num % base);
1145983b871SKonstantin Belousov 		*++p = c;
1150e9a2605SKonstantin Belousov 	} while (num /= base);
1160e9a2605SKonstantin Belousov 	if (lenp)
1170e9a2605SKonstantin Belousov 		*lenp = p - nbuf;
1180e9a2605SKonstantin Belousov 	return (p);
1190e9a2605SKonstantin Belousov }
1200e9a2605SKonstantin Belousov 
1210e9a2605SKonstantin Belousov static int
kvprintf(char const * fmt,struct snprintf_arg * arg,int radix,va_list ap)122b2367317SKonstantin Belousov kvprintf(char const *fmt, struct snprintf_arg *arg, int radix, va_list ap)
1230e9a2605SKonstantin Belousov {
124b2367317SKonstantin Belousov #define PCHAR(c) snprintf_func((c), arg)
1250e9a2605SKonstantin Belousov 	char nbuf[MAXNBUF];
1260e9a2605SKonstantin Belousov 	const char *p, *percent, *q;
1270e9a2605SKonstantin Belousov 	u_char *up;
128*f5a8f6f7SWarner Losh 	int ch, n, sign;
1290e9a2605SKonstantin Belousov 	uintmax_t num;
130*f5a8f6f7SWarner Losh 	int base, lflag, qflag, tmp, width, ladjust, sharpflag, dot;
1310e9a2605SKonstantin Belousov 	int cflag, hflag, jflag, tflag, zflag;
1320e9a2605SKonstantin Belousov 	int dwidth, upper;
1330e9a2605SKonstantin Belousov 	char padc;
1340e9a2605SKonstantin Belousov 	int stop = 0, retval = 0;
1350e9a2605SKonstantin Belousov 
1360e9a2605SKonstantin Belousov 	num = 0;
1370e9a2605SKonstantin Belousov 
1380e9a2605SKonstantin Belousov 	if (fmt == NULL)
1390e9a2605SKonstantin Belousov 		fmt = "(fmt null)\n";
1400e9a2605SKonstantin Belousov 
1410e9a2605SKonstantin Belousov 	if (radix < 2 || radix > 36)
1420e9a2605SKonstantin Belousov 		radix = 10;
1430e9a2605SKonstantin Belousov 
1440e9a2605SKonstantin Belousov 	for (;;) {
1450e9a2605SKonstantin Belousov 		padc = ' ';
1460e9a2605SKonstantin Belousov 		width = 0;
1470e9a2605SKonstantin Belousov 		while ((ch = (u_char)*fmt++) != '%' || stop) {
1480e9a2605SKonstantin Belousov 			if (ch == '\0')
1490e9a2605SKonstantin Belousov 				return (retval);
1500e9a2605SKonstantin Belousov 			PCHAR(ch);
1510e9a2605SKonstantin Belousov 		}
1520e9a2605SKonstantin Belousov 		percent = fmt - 1;
153*f5a8f6f7SWarner Losh 		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0;
1540e9a2605SKonstantin Belousov 		sign = 0; dot = 0; dwidth = 0; upper = 0;
1550e9a2605SKonstantin Belousov 		cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
1560e9a2605SKonstantin Belousov reswitch:	switch (ch = (u_char)*fmt++) {
1570e9a2605SKonstantin Belousov 		case '.':
1580e9a2605SKonstantin Belousov 			dot = 1;
1590e9a2605SKonstantin Belousov 			goto reswitch;
1600e9a2605SKonstantin Belousov 		case '#':
1610e9a2605SKonstantin Belousov 			sharpflag = 1;
1620e9a2605SKonstantin Belousov 			goto reswitch;
1630e9a2605SKonstantin Belousov 		case '+':
164*f5a8f6f7SWarner Losh 			sign = '+';
1650e9a2605SKonstantin Belousov 			goto reswitch;
1660e9a2605SKonstantin Belousov 		case '-':
1670e9a2605SKonstantin Belousov 			ladjust = 1;
1680e9a2605SKonstantin Belousov 			goto reswitch;
1690e9a2605SKonstantin Belousov 		case '%':
1700e9a2605SKonstantin Belousov 			PCHAR(ch);
1710e9a2605SKonstantin Belousov 			break;
1720e9a2605SKonstantin Belousov 		case '*':
1730e9a2605SKonstantin Belousov 			if (!dot) {
1740e9a2605SKonstantin Belousov 				width = va_arg(ap, int);
1750e9a2605SKonstantin Belousov 				if (width < 0) {
1760e9a2605SKonstantin Belousov 					ladjust = !ladjust;
1770e9a2605SKonstantin Belousov 					width = -width;
1780e9a2605SKonstantin Belousov 				}
1790e9a2605SKonstantin Belousov 			} else {
1800e9a2605SKonstantin Belousov 				dwidth = va_arg(ap, int);
1810e9a2605SKonstantin Belousov 			}
1820e9a2605SKonstantin Belousov 			goto reswitch;
1830e9a2605SKonstantin Belousov 		case '0':
1840e9a2605SKonstantin Belousov 			if (!dot) {
1850e9a2605SKonstantin Belousov 				padc = '0';
1860e9a2605SKonstantin Belousov 				goto reswitch;
1870e9a2605SKonstantin Belousov 			}
1883ab5b6bdSAlex Richardson 			/* FALLTHROUGH */
1890e9a2605SKonstantin Belousov 		case '1': case '2': case '3': case '4':
1900e9a2605SKonstantin Belousov 		case '5': case '6': case '7': case '8': case '9':
1910e9a2605SKonstantin Belousov 				for (n = 0;; ++fmt) {
1920e9a2605SKonstantin Belousov 					n = n * 10 + ch - '0';
1930e9a2605SKonstantin Belousov 					ch = *fmt;
1940e9a2605SKonstantin Belousov 					if (ch < '0' || ch > '9')
1950e9a2605SKonstantin Belousov 						break;
1960e9a2605SKonstantin Belousov 				}
1970e9a2605SKonstantin Belousov 			if (dot)
1980e9a2605SKonstantin Belousov 				dwidth = n;
1990e9a2605SKonstantin Belousov 			else
2000e9a2605SKonstantin Belousov 				width = n;
2010e9a2605SKonstantin Belousov 			goto reswitch;
2020e9a2605SKonstantin Belousov 		case 'b':
2030e9a2605SKonstantin Belousov 			num = (u_int)va_arg(ap, int);
2040e9a2605SKonstantin Belousov 			p = va_arg(ap, char *);
2050e9a2605SKonstantin Belousov 			for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
2060e9a2605SKonstantin Belousov 				PCHAR(*q--);
2070e9a2605SKonstantin Belousov 
2080e9a2605SKonstantin Belousov 			if (num == 0)
2090e9a2605SKonstantin Belousov 				break;
2100e9a2605SKonstantin Belousov 
2110e9a2605SKonstantin Belousov 			for (tmp = 0; *p;) {
2120e9a2605SKonstantin Belousov 				n = *p++;
2130e9a2605SKonstantin Belousov 				if (num & (1 << (n - 1))) {
2140e9a2605SKonstantin Belousov 					PCHAR(tmp ? ',' : '<');
2150e9a2605SKonstantin Belousov 					for (; (n = *p) > ' '; ++p)
2160e9a2605SKonstantin Belousov 						PCHAR(n);
2170e9a2605SKonstantin Belousov 					tmp = 1;
2180e9a2605SKonstantin Belousov 				} else
2190e9a2605SKonstantin Belousov 					for (; *p > ' '; ++p)
2200e9a2605SKonstantin Belousov 						continue;
2210e9a2605SKonstantin Belousov 			}
2220e9a2605SKonstantin Belousov 			if (tmp)
2230e9a2605SKonstantin Belousov 				PCHAR('>');
2240e9a2605SKonstantin Belousov 			break;
2250e9a2605SKonstantin Belousov 		case 'c':
2260e9a2605SKonstantin Belousov 			PCHAR(va_arg(ap, int));
2270e9a2605SKonstantin Belousov 			break;
2280e9a2605SKonstantin Belousov 		case 'D':
2290e9a2605SKonstantin Belousov 			up = va_arg(ap, u_char *);
2300e9a2605SKonstantin Belousov 			p = va_arg(ap, char *);
2310e9a2605SKonstantin Belousov 			if (!width)
2320e9a2605SKonstantin Belousov 				width = 16;
2330e9a2605SKonstantin Belousov 			while(width--) {
2340e9a2605SKonstantin Belousov 				PCHAR(hex2ascii(*up >> 4));
2350e9a2605SKonstantin Belousov 				PCHAR(hex2ascii(*up & 0x0f));
2360e9a2605SKonstantin Belousov 				up++;
2370e9a2605SKonstantin Belousov 				if (width)
2380e9a2605SKonstantin Belousov 					for (q=p;*q;q++)
2390e9a2605SKonstantin Belousov 						PCHAR(*q);
2400e9a2605SKonstantin Belousov 			}
2410e9a2605SKonstantin Belousov 			break;
2420e9a2605SKonstantin Belousov 		case 'd':
2430e9a2605SKonstantin Belousov 		case 'i':
2440e9a2605SKonstantin Belousov 			base = 10;
2450e9a2605SKonstantin Belousov 			goto handle_sign;
2460e9a2605SKonstantin Belousov 		case 'h':
2470e9a2605SKonstantin Belousov 			if (hflag) {
2480e9a2605SKonstantin Belousov 				hflag = 0;
2490e9a2605SKonstantin Belousov 				cflag = 1;
2500e9a2605SKonstantin Belousov 			} else
2510e9a2605SKonstantin Belousov 				hflag = 1;
2520e9a2605SKonstantin Belousov 			goto reswitch;
2530e9a2605SKonstantin Belousov 		case 'j':
2540e9a2605SKonstantin Belousov 			jflag = 1;
2550e9a2605SKonstantin Belousov 			goto reswitch;
2560e9a2605SKonstantin Belousov 		case 'l':
2570e9a2605SKonstantin Belousov 			if (lflag) {
2580e9a2605SKonstantin Belousov 				lflag = 0;
2590e9a2605SKonstantin Belousov 				qflag = 1;
2600e9a2605SKonstantin Belousov 			} else
2610e9a2605SKonstantin Belousov 				lflag = 1;
2620e9a2605SKonstantin Belousov 			goto reswitch;
2630e9a2605SKonstantin Belousov 		case 'n':
2640e9a2605SKonstantin Belousov 			if (jflag)
2650e9a2605SKonstantin Belousov 				*(va_arg(ap, intmax_t *)) = retval;
2660e9a2605SKonstantin Belousov 			else if (qflag)
2670e9a2605SKonstantin Belousov 				*(va_arg(ap, quad_t *)) = retval;
2680e9a2605SKonstantin Belousov 			else if (lflag)
2690e9a2605SKonstantin Belousov 				*(va_arg(ap, long *)) = retval;
2700e9a2605SKonstantin Belousov 			else if (zflag)
2710e9a2605SKonstantin Belousov 				*(va_arg(ap, size_t *)) = retval;
2720e9a2605SKonstantin Belousov 			else if (hflag)
2730e9a2605SKonstantin Belousov 				*(va_arg(ap, short *)) = retval;
2740e9a2605SKonstantin Belousov 			else if (cflag)
2750e9a2605SKonstantin Belousov 				*(va_arg(ap, char *)) = retval;
2760e9a2605SKonstantin Belousov 			else
2770e9a2605SKonstantin Belousov 				*(va_arg(ap, int *)) = retval;
2780e9a2605SKonstantin Belousov 			break;
2790e9a2605SKonstantin Belousov 		case 'o':
2800e9a2605SKonstantin Belousov 			base = 8;
2810e9a2605SKonstantin Belousov 			goto handle_nosign;
2820e9a2605SKonstantin Belousov 		case 'p':
2830e9a2605SKonstantin Belousov 			base = 16;
2840e9a2605SKonstantin Belousov 			sharpflag = (width == 0);
2850e9a2605SKonstantin Belousov 			sign = 0;
2860e9a2605SKonstantin Belousov 			num = (uintptr_t)va_arg(ap, void *);
2870e9a2605SKonstantin Belousov 			goto number;
2880e9a2605SKonstantin Belousov 		case 'q':
2890e9a2605SKonstantin Belousov 			qflag = 1;
2900e9a2605SKonstantin Belousov 			goto reswitch;
2910e9a2605SKonstantin Belousov 		case 'r':
2920e9a2605SKonstantin Belousov 			base = radix;
293*f5a8f6f7SWarner Losh 			if (sign) {
294*f5a8f6f7SWarner Losh 				sign = 0;
2950e9a2605SKonstantin Belousov 				goto handle_sign;
296*f5a8f6f7SWarner Losh 			}
2970e9a2605SKonstantin Belousov 			goto handle_nosign;
2980e9a2605SKonstantin Belousov 		case 's':
2990e9a2605SKonstantin Belousov 			p = va_arg(ap, char *);
3000e9a2605SKonstantin Belousov 			if (p == NULL)
3010e9a2605SKonstantin Belousov 				p = "(null)";
3020e9a2605SKonstantin Belousov 			if (!dot)
3030e9a2605SKonstantin Belousov 				n = strlen (p);
3040e9a2605SKonstantin Belousov 			else
3050e9a2605SKonstantin Belousov 				for (n = 0; n < dwidth && p[n]; n++)
3060e9a2605SKonstantin Belousov 					continue;
3070e9a2605SKonstantin Belousov 
3080e9a2605SKonstantin Belousov 			width -= n;
3090e9a2605SKonstantin Belousov 
3100e9a2605SKonstantin Belousov 			if (!ladjust && width > 0)
3110e9a2605SKonstantin Belousov 				while (width--)
3120e9a2605SKonstantin Belousov 					PCHAR(padc);
3130e9a2605SKonstantin Belousov 			while (n--)
3140e9a2605SKonstantin Belousov 				PCHAR(*p++);
3150e9a2605SKonstantin Belousov 			if (ladjust && width > 0)
3160e9a2605SKonstantin Belousov 				while (width--)
3170e9a2605SKonstantin Belousov 					PCHAR(padc);
3180e9a2605SKonstantin Belousov 			break;
3190e9a2605SKonstantin Belousov 		case 't':
3200e9a2605SKonstantin Belousov 			tflag = 1;
3210e9a2605SKonstantin Belousov 			goto reswitch;
3220e9a2605SKonstantin Belousov 		case 'u':
3230e9a2605SKonstantin Belousov 			base = 10;
3240e9a2605SKonstantin Belousov 			goto handle_nosign;
3250e9a2605SKonstantin Belousov 		case 'X':
3260e9a2605SKonstantin Belousov 			upper = 1;
3273ab5b6bdSAlex Richardson 			/* FALLTHROUGH */
3280e9a2605SKonstantin Belousov 		case 'x':
3290e9a2605SKonstantin Belousov 			base = 16;
3300e9a2605SKonstantin Belousov 			goto handle_nosign;
3310e9a2605SKonstantin Belousov 		case 'y':
3320e9a2605SKonstantin Belousov 			base = 16;
3330e9a2605SKonstantin Belousov 			goto handle_sign;
3340e9a2605SKonstantin Belousov 		case 'z':
3350e9a2605SKonstantin Belousov 			zflag = 1;
3360e9a2605SKonstantin Belousov 			goto reswitch;
3370e9a2605SKonstantin Belousov handle_nosign:
3380e9a2605SKonstantin Belousov 			if (jflag)
3390e9a2605SKonstantin Belousov 				num = va_arg(ap, uintmax_t);
3400e9a2605SKonstantin Belousov 			else if (qflag)
3410e9a2605SKonstantin Belousov 				num = va_arg(ap, u_quad_t);
3420e9a2605SKonstantin Belousov 			else if (tflag)
3430e9a2605SKonstantin Belousov 				num = va_arg(ap, ptrdiff_t);
3440e9a2605SKonstantin Belousov 			else if (lflag)
3450e9a2605SKonstantin Belousov 				num = va_arg(ap, u_long);
3460e9a2605SKonstantin Belousov 			else if (zflag)
3470e9a2605SKonstantin Belousov 				num = va_arg(ap, size_t);
3480e9a2605SKonstantin Belousov 			else if (hflag)
3490e9a2605SKonstantin Belousov 				num = (u_short)va_arg(ap, int);
3500e9a2605SKonstantin Belousov 			else if (cflag)
3510e9a2605SKonstantin Belousov 				num = (u_char)va_arg(ap, int);
3520e9a2605SKonstantin Belousov 			else
3530e9a2605SKonstantin Belousov 				num = va_arg(ap, u_int);
3540e9a2605SKonstantin Belousov 			goto number;
3550e9a2605SKonstantin Belousov handle_sign:
3560e9a2605SKonstantin Belousov 			if (jflag)
3570e9a2605SKonstantin Belousov 				num = va_arg(ap, intmax_t);
3580e9a2605SKonstantin Belousov 			else if (qflag)
3590e9a2605SKonstantin Belousov 				num = va_arg(ap, quad_t);
3600e9a2605SKonstantin Belousov 			else if (tflag)
3610e9a2605SKonstantin Belousov 				num = va_arg(ap, ptrdiff_t);
3620e9a2605SKonstantin Belousov 			else if (lflag)
3630e9a2605SKonstantin Belousov 				num = va_arg(ap, long);
3640e9a2605SKonstantin Belousov 			else if (zflag)
3650e9a2605SKonstantin Belousov 				num = va_arg(ap, ssize_t);
3660e9a2605SKonstantin Belousov 			else if (hflag)
3670e9a2605SKonstantin Belousov 				num = (short)va_arg(ap, int);
3680e9a2605SKonstantin Belousov 			else if (cflag)
36982dfbaf7SWarner Losh 				num = (signed char)va_arg(ap, int);
3700e9a2605SKonstantin Belousov 			else
3710e9a2605SKonstantin Belousov 				num = va_arg(ap, int);
372*f5a8f6f7SWarner Losh 			if ((intmax_t)num < 0) {
373*f5a8f6f7SWarner Losh 				sign = '-';
3740e9a2605SKonstantin Belousov 				num = -(intmax_t)num;
3750e9a2605SKonstantin Belousov 			}
376*f5a8f6f7SWarner Losh number:
3770e9a2605SKonstantin Belousov 			p = ksprintn(nbuf, num, base, &n, upper);
3780e9a2605SKonstantin Belousov 			tmp = 0;
3790e9a2605SKonstantin Belousov 			if (sharpflag && num != 0) {
3800e9a2605SKonstantin Belousov 				if (base == 8)
3810e9a2605SKonstantin Belousov 					tmp++;
3820e9a2605SKonstantin Belousov 				else if (base == 16)
3830e9a2605SKonstantin Belousov 					tmp += 2;
3840e9a2605SKonstantin Belousov 			}
385*f5a8f6f7SWarner Losh 			if (sign)
3860e9a2605SKonstantin Belousov 				tmp++;
3870e9a2605SKonstantin Belousov 
3880e9a2605SKonstantin Belousov 			if (!ladjust && padc == '0')
3890e9a2605SKonstantin Belousov 				dwidth = width - tmp;
3900e9a2605SKonstantin Belousov 			width -= tmp + imax(dwidth, n);
3910e9a2605SKonstantin Belousov 			dwidth -= n;
3920e9a2605SKonstantin Belousov 			if (!ladjust)
3930e9a2605SKonstantin Belousov 				while (width-- > 0)
3940e9a2605SKonstantin Belousov 					PCHAR(' ');
395*f5a8f6f7SWarner Losh 			if (sign)
396*f5a8f6f7SWarner Losh 				PCHAR(sign);
3970e9a2605SKonstantin Belousov 			if (sharpflag && num != 0) {
3980e9a2605SKonstantin Belousov 				if (base == 8) {
3990e9a2605SKonstantin Belousov 					PCHAR('0');
4000e9a2605SKonstantin Belousov 				} else if (base == 16) {
4010e9a2605SKonstantin Belousov 					PCHAR('0');
4020e9a2605SKonstantin Belousov 					PCHAR('x');
4030e9a2605SKonstantin Belousov 				}
4040e9a2605SKonstantin Belousov 			}
4050e9a2605SKonstantin Belousov 			while (dwidth-- > 0)
4060e9a2605SKonstantin Belousov 				PCHAR('0');
4070e9a2605SKonstantin Belousov 
4080e9a2605SKonstantin Belousov 			while (*p)
4090e9a2605SKonstantin Belousov 				PCHAR(*p--);
4100e9a2605SKonstantin Belousov 
4110e9a2605SKonstantin Belousov 			if (ladjust)
4120e9a2605SKonstantin Belousov 				while (width-- > 0)
4130e9a2605SKonstantin Belousov 					PCHAR(' ');
4140e9a2605SKonstantin Belousov 
4150e9a2605SKonstantin Belousov 			break;
4160e9a2605SKonstantin Belousov 		default:
4170e9a2605SKonstantin Belousov 			while (percent < fmt)
4180e9a2605SKonstantin Belousov 				PCHAR(*percent++);
4190e9a2605SKonstantin Belousov 			/*
4200e9a2605SKonstantin Belousov 			 * Since we ignore an formatting argument it is no
4210e9a2605SKonstantin Belousov 			 * longer safe to obey the remaining formatting
4220e9a2605SKonstantin Belousov 			 * arguments as the arguments will no longer match
4230e9a2605SKonstantin Belousov 			 * the format specs.
4240e9a2605SKonstantin Belousov 			 */
4250e9a2605SKonstantin Belousov 			stop = 1;
4260e9a2605SKonstantin Belousov 			break;
4270e9a2605SKonstantin Belousov 		}
4280e9a2605SKonstantin Belousov 	}
4290e9a2605SKonstantin Belousov #undef PCHAR
4300e9a2605SKonstantin Belousov }
4310e9a2605SKonstantin Belousov 
4320e9a2605SKonstantin Belousov int
rtld_snprintf(char * buf,size_t bufsize,const char * fmt,...)43302d3b38eSJonathan Anderson rtld_snprintf(char *buf, size_t bufsize, const char *fmt, ...)
43402d3b38eSJonathan Anderson {
43502d3b38eSJonathan Anderson 	va_list ap;
43602d3b38eSJonathan Anderson 	int retval;
43702d3b38eSJonathan Anderson 
43802d3b38eSJonathan Anderson 	va_start(ap, fmt);
43902d3b38eSJonathan Anderson 	retval = rtld_vsnprintf(buf, bufsize, fmt, ap);
44002d3b38eSJonathan Anderson 	va_end(ap);
44102d3b38eSJonathan Anderson 	return (retval);
44202d3b38eSJonathan Anderson }
44302d3b38eSJonathan Anderson 
44402d3b38eSJonathan Anderson int
rtld_vsnprintf(char * buf,size_t bufsize,const char * fmt,va_list ap)4450e9a2605SKonstantin Belousov rtld_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap)
4460e9a2605SKonstantin Belousov {
4470e9a2605SKonstantin Belousov 	struct snprintf_arg info;
4480e9a2605SKonstantin Belousov 	int retval;
4490e9a2605SKonstantin Belousov 
450b2367317SKonstantin Belousov 	info.method = PRINT_METHOD_SNPRINTF;
4510e9a2605SKonstantin Belousov 	info.buf = info.str = buf;
4520e9a2605SKonstantin Belousov 	info.buf_total = info.remain = bufsize;
4530e9a2605SKonstantin Belousov 	info.fd = -1;
454b2367317SKonstantin Belousov 	retval = kvprintf(fmt, &info, 10, ap);
4550e9a2605SKonstantin Belousov 	if (info.remain >= 1)
4560e9a2605SKonstantin Belousov 		*info.str++ = '\0';
4570e9a2605SKonstantin Belousov 	return (retval);
4580e9a2605SKonstantin Belousov }
4590e9a2605SKonstantin Belousov 
4600e9a2605SKonstantin Belousov int
rtld_vfdprintf(int fd,const char * fmt,va_list ap)4610e9a2605SKonstantin Belousov rtld_vfdprintf(int fd, const char *fmt, va_list ap)
4620e9a2605SKonstantin Belousov {
4630e9a2605SKonstantin Belousov 	char buf[512];
4640e9a2605SKonstantin Belousov 	struct snprintf_arg info;
4650e9a2605SKonstantin Belousov 	int retval;
4660e9a2605SKonstantin Belousov 
467b2367317SKonstantin Belousov 	info.method = PRINT_METHOD_WRITE;
4680e9a2605SKonstantin Belousov 	info.buf = info.str = buf;
4690e9a2605SKonstantin Belousov 	info.buf_total = info.remain = sizeof(buf);
4700e9a2605SKonstantin Belousov 	info.fd = fd;
471b2367317SKonstantin Belousov 	retval = kvprintf(fmt, &info, 10, ap);
4720e9a2605SKonstantin Belousov 	printf_out(&info);
4730e9a2605SKonstantin Belousov 	return (retval);
4740e9a2605SKonstantin Belousov }
4750e9a2605SKonstantin Belousov 
4760e9a2605SKonstantin Belousov int
rtld_fdprintf(int fd,const char * fmt,...)4770e9a2605SKonstantin Belousov rtld_fdprintf(int fd, const char *fmt, ...)
4780e9a2605SKonstantin Belousov {
4790e9a2605SKonstantin Belousov 	va_list ap;
4800e9a2605SKonstantin Belousov 	int retval;
4810e9a2605SKonstantin Belousov 
4820e9a2605SKonstantin Belousov 	va_start(ap, fmt);
4830e9a2605SKonstantin Belousov 	retval = rtld_vfdprintf(fd, fmt, ap);
4840e9a2605SKonstantin Belousov 	va_end(ap);
4850e9a2605SKonstantin Belousov 	return (retval);
4860e9a2605SKonstantin Belousov }
4870e9a2605SKonstantin Belousov 
48877c088abSKonstantin Belousov int
rtld_fdprintfx(int fd,const char * fmt,...)48977c088abSKonstantin Belousov rtld_fdprintfx(int fd, const char *fmt, ...)
49077c088abSKonstantin Belousov {
49177c088abSKonstantin Belousov 	va_list ap;
49277c088abSKonstantin Belousov 	int retval;
49377c088abSKonstantin Belousov 
49477c088abSKonstantin Belousov 	va_start(ap, fmt);
49577c088abSKonstantin Belousov 	retval = rtld_vfdprintf(fd, fmt, ap);
49677c088abSKonstantin Belousov 	va_end(ap);
49777c088abSKonstantin Belousov 	return (retval);
49877c088abSKonstantin Belousov }
49977c088abSKonstantin Belousov 
5000e9a2605SKonstantin Belousov void
rtld_fdputstr(int fd,const char * str)5010e9a2605SKonstantin Belousov rtld_fdputstr(int fd, const char *str)
5020e9a2605SKonstantin Belousov {
5030e9a2605SKonstantin Belousov 
5040e9a2605SKonstantin Belousov 	write(fd, str, strlen(str));
5050e9a2605SKonstantin Belousov }
5060e9a2605SKonstantin Belousov 
5070e9a2605SKonstantin Belousov void
rtld_fdputchar(int fd,int c)5080e9a2605SKonstantin Belousov rtld_fdputchar(int fd, int c)
5090e9a2605SKonstantin Belousov {
5100e9a2605SKonstantin Belousov 	char c1;
5110e9a2605SKonstantin Belousov 
5120e9a2605SKonstantin Belousov 	c1 = c;
5130e9a2605SKonstantin Belousov 	write(fd, &c1, 1);
5140e9a2605SKonstantin Belousov }
515