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 * $FreeBSD$ 380e9a2605SKonstantin Belousov */ 390e9a2605SKonstantin Belousov 400e9a2605SKonstantin Belousov #include <sys/param.h> 410e9a2605SKonstantin Belousov #include <inttypes.h> 420e9a2605SKonstantin Belousov #include <stdarg.h> 430e9a2605SKonstantin Belousov #include <stddef.h> 440e9a2605SKonstantin Belousov #include <string.h> 450e9a2605SKonstantin Belousov #include <unistd.h> 460e9a2605SKonstantin Belousov #include "rtld_printf.h" 47b54a59f3SAlex Richardson #include "rtld_libc.h" 480e9a2605SKonstantin Belousov 490e9a2605SKonstantin Belousov #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 500e9a2605SKonstantin Belousov 51b2367317SKonstantin Belousov #define PRINT_METHOD_SNPRINTF 1 52b2367317SKonstantin Belousov #define PRINT_METHOD_WRITE 2 53b2367317SKonstantin Belousov 540e9a2605SKonstantin Belousov struct snprintf_arg { 55b2367317SKonstantin Belousov int method; 560e9a2605SKonstantin Belousov char *str; 570e9a2605SKonstantin Belousov char *buf; 580e9a2605SKonstantin Belousov size_t remain; 590e9a2605SKonstantin Belousov size_t buf_total; 600e9a2605SKonstantin Belousov int fd; 610e9a2605SKonstantin Belousov }; 620e9a2605SKonstantin Belousov 630e9a2605SKonstantin Belousov static void 640e9a2605SKonstantin Belousov printf_out(struct snprintf_arg *info) 650e9a2605SKonstantin Belousov { 660e9a2605SKonstantin Belousov 670e9a2605SKonstantin Belousov if (info->remain == info->buf_total) 680e9a2605SKonstantin Belousov return; 690e9a2605SKonstantin Belousov write(info->fd, info->buf, info->buf_total - info->remain); 700e9a2605SKonstantin Belousov info->str = info->buf; 710e9a2605SKonstantin Belousov info->remain = info->buf_total; 720e9a2605SKonstantin Belousov } 730e9a2605SKonstantin Belousov 740e9a2605SKonstantin Belousov static void 75b2367317SKonstantin Belousov snprintf_func(int ch, struct snprintf_arg *const info) 760e9a2605SKonstantin Belousov { 770e9a2605SKonstantin Belousov 78b2367317SKonstantin Belousov switch (info->method) { 79b2367317SKonstantin Belousov case PRINT_METHOD_SNPRINTF: 80b2367317SKonstantin Belousov if (info->remain >= 2) { 81b2367317SKonstantin Belousov *info->str++ = ch; 82b2367317SKonstantin Belousov info->remain--; 83b2367317SKonstantin Belousov } 84b2367317SKonstantin Belousov break; 85b2367317SKonstantin Belousov case PRINT_METHOD_WRITE: 860e9a2605SKonstantin Belousov if (info->remain > 0) { 870e9a2605SKonstantin Belousov *info->str++ = ch; 880e9a2605SKonstantin Belousov info->remain--; 890e9a2605SKonstantin Belousov } else 900e9a2605SKonstantin Belousov printf_out(info); 91b2367317SKonstantin Belousov break; 92b2367317SKonstantin Belousov } 930e9a2605SKonstantin Belousov } 940e9a2605SKonstantin Belousov 955983b871SKonstantin Belousov static char const hex2ascii_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 965983b871SKonstantin Belousov static char const hex2ascii_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 975983b871SKonstantin Belousov #define hex2ascii(hex) (hex2ascii_lower[hex]) 985983b871SKonstantin Belousov #define hex2ascii_upper(hex) (hex2ascii_upper[hex]) 990e9a2605SKonstantin Belousov 1000e9a2605SKonstantin Belousov static __inline int 1010e9a2605SKonstantin Belousov imax(int a, int b) 1020e9a2605SKonstantin Belousov { 1030e9a2605SKonstantin Belousov 1040e9a2605SKonstantin Belousov return (a > b ? a : b); 1050e9a2605SKonstantin Belousov } 1060e9a2605SKonstantin Belousov 1070e9a2605SKonstantin Belousov static char * 1080e9a2605SKonstantin Belousov ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 1090e9a2605SKonstantin Belousov { 1100e9a2605SKonstantin Belousov char *p, c; 1110e9a2605SKonstantin Belousov 1120e9a2605SKonstantin Belousov p = nbuf; 1130e9a2605SKonstantin Belousov *p = '\0'; 1140e9a2605SKonstantin Belousov do { 1155983b871SKonstantin Belousov c = upper ? hex2ascii_upper(num % base) : 1165983b871SKonstantin Belousov hex2ascii(num % base); 1175983b871SKonstantin Belousov *++p = c; 1180e9a2605SKonstantin Belousov } while (num /= base); 1190e9a2605SKonstantin Belousov if (lenp) 1200e9a2605SKonstantin Belousov *lenp = p - nbuf; 1210e9a2605SKonstantin Belousov return (p); 1220e9a2605SKonstantin Belousov } 1230e9a2605SKonstantin Belousov 1240e9a2605SKonstantin Belousov static int 125b2367317SKonstantin Belousov kvprintf(char const *fmt, struct snprintf_arg *arg, int radix, va_list ap) 1260e9a2605SKonstantin Belousov { 127b2367317SKonstantin Belousov #define PCHAR(c) snprintf_func((c), arg) 1280e9a2605SKonstantin Belousov char nbuf[MAXNBUF]; 1290e9a2605SKonstantin Belousov const char *p, *percent, *q; 1300e9a2605SKonstantin Belousov u_char *up; 1310e9a2605SKonstantin Belousov int ch, n; 1320e9a2605SKonstantin Belousov uintmax_t num; 1330e9a2605SKonstantin Belousov int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 1340e9a2605SKonstantin Belousov int cflag, hflag, jflag, tflag, zflag; 1350e9a2605SKonstantin Belousov int dwidth, upper; 1360e9a2605SKonstantin Belousov char padc; 1370e9a2605SKonstantin Belousov int stop = 0, retval = 0; 1380e9a2605SKonstantin Belousov 1390e9a2605SKonstantin Belousov num = 0; 1400e9a2605SKonstantin Belousov 1410e9a2605SKonstantin Belousov if (fmt == NULL) 1420e9a2605SKonstantin Belousov fmt = "(fmt null)\n"; 1430e9a2605SKonstantin Belousov 1440e9a2605SKonstantin Belousov if (radix < 2 || radix > 36) 1450e9a2605SKonstantin Belousov radix = 10; 1460e9a2605SKonstantin Belousov 1470e9a2605SKonstantin Belousov for (;;) { 1480e9a2605SKonstantin Belousov padc = ' '; 1490e9a2605SKonstantin Belousov width = 0; 1500e9a2605SKonstantin Belousov while ((ch = (u_char)*fmt++) != '%' || stop) { 1510e9a2605SKonstantin Belousov if (ch == '\0') 1520e9a2605SKonstantin Belousov return (retval); 1530e9a2605SKonstantin Belousov PCHAR(ch); 1540e9a2605SKonstantin Belousov } 1550e9a2605SKonstantin Belousov percent = fmt - 1; 1560e9a2605SKonstantin Belousov qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 1570e9a2605SKonstantin Belousov sign = 0; dot = 0; dwidth = 0; upper = 0; 1580e9a2605SKonstantin Belousov cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 1590e9a2605SKonstantin Belousov reswitch: switch (ch = (u_char)*fmt++) { 1600e9a2605SKonstantin Belousov case '.': 1610e9a2605SKonstantin Belousov dot = 1; 1620e9a2605SKonstantin Belousov goto reswitch; 1630e9a2605SKonstantin Belousov case '#': 1640e9a2605SKonstantin Belousov sharpflag = 1; 1650e9a2605SKonstantin Belousov goto reswitch; 1660e9a2605SKonstantin Belousov case '+': 1670e9a2605SKonstantin Belousov sign = 1; 1680e9a2605SKonstantin Belousov goto reswitch; 1690e9a2605SKonstantin Belousov case '-': 1700e9a2605SKonstantin Belousov ladjust = 1; 1710e9a2605SKonstantin Belousov goto reswitch; 1720e9a2605SKonstantin Belousov case '%': 1730e9a2605SKonstantin Belousov PCHAR(ch); 1740e9a2605SKonstantin Belousov break; 1750e9a2605SKonstantin Belousov case '*': 1760e9a2605SKonstantin Belousov if (!dot) { 1770e9a2605SKonstantin Belousov width = va_arg(ap, int); 1780e9a2605SKonstantin Belousov if (width < 0) { 1790e9a2605SKonstantin Belousov ladjust = !ladjust; 1800e9a2605SKonstantin Belousov width = -width; 1810e9a2605SKonstantin Belousov } 1820e9a2605SKonstantin Belousov } else { 1830e9a2605SKonstantin Belousov dwidth = va_arg(ap, int); 1840e9a2605SKonstantin Belousov } 1850e9a2605SKonstantin Belousov goto reswitch; 1860e9a2605SKonstantin Belousov case '0': 1870e9a2605SKonstantin Belousov if (!dot) { 1880e9a2605SKonstantin Belousov padc = '0'; 1890e9a2605SKonstantin Belousov goto reswitch; 1900e9a2605SKonstantin Belousov } 1913ab5b6bdSAlex Richardson /* FALLTHROUGH */ 1920e9a2605SKonstantin Belousov case '1': case '2': case '3': case '4': 1930e9a2605SKonstantin Belousov case '5': case '6': case '7': case '8': case '9': 1940e9a2605SKonstantin Belousov for (n = 0;; ++fmt) { 1950e9a2605SKonstantin Belousov n = n * 10 + ch - '0'; 1960e9a2605SKonstantin Belousov ch = *fmt; 1970e9a2605SKonstantin Belousov if (ch < '0' || ch > '9') 1980e9a2605SKonstantin Belousov break; 1990e9a2605SKonstantin Belousov } 2000e9a2605SKonstantin Belousov if (dot) 2010e9a2605SKonstantin Belousov dwidth = n; 2020e9a2605SKonstantin Belousov else 2030e9a2605SKonstantin Belousov width = n; 2040e9a2605SKonstantin Belousov goto reswitch; 2050e9a2605SKonstantin Belousov case 'b': 2060e9a2605SKonstantin Belousov num = (u_int)va_arg(ap, int); 2070e9a2605SKonstantin Belousov p = va_arg(ap, char *); 2080e9a2605SKonstantin Belousov for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 2090e9a2605SKonstantin Belousov PCHAR(*q--); 2100e9a2605SKonstantin Belousov 2110e9a2605SKonstantin Belousov if (num == 0) 2120e9a2605SKonstantin Belousov break; 2130e9a2605SKonstantin Belousov 2140e9a2605SKonstantin Belousov for (tmp = 0; *p;) { 2150e9a2605SKonstantin Belousov n = *p++; 2160e9a2605SKonstantin Belousov if (num & (1 << (n - 1))) { 2170e9a2605SKonstantin Belousov PCHAR(tmp ? ',' : '<'); 2180e9a2605SKonstantin Belousov for (; (n = *p) > ' '; ++p) 2190e9a2605SKonstantin Belousov PCHAR(n); 2200e9a2605SKonstantin Belousov tmp = 1; 2210e9a2605SKonstantin Belousov } else 2220e9a2605SKonstantin Belousov for (; *p > ' '; ++p) 2230e9a2605SKonstantin Belousov continue; 2240e9a2605SKonstantin Belousov } 2250e9a2605SKonstantin Belousov if (tmp) 2260e9a2605SKonstantin Belousov PCHAR('>'); 2270e9a2605SKonstantin Belousov break; 2280e9a2605SKonstantin Belousov case 'c': 2290e9a2605SKonstantin Belousov PCHAR(va_arg(ap, int)); 2300e9a2605SKonstantin Belousov break; 2310e9a2605SKonstantin Belousov case 'D': 2320e9a2605SKonstantin Belousov up = va_arg(ap, u_char *); 2330e9a2605SKonstantin Belousov p = va_arg(ap, char *); 2340e9a2605SKonstantin Belousov if (!width) 2350e9a2605SKonstantin Belousov width = 16; 2360e9a2605SKonstantin Belousov while(width--) { 2370e9a2605SKonstantin Belousov PCHAR(hex2ascii(*up >> 4)); 2380e9a2605SKonstantin Belousov PCHAR(hex2ascii(*up & 0x0f)); 2390e9a2605SKonstantin Belousov up++; 2400e9a2605SKonstantin Belousov if (width) 2410e9a2605SKonstantin Belousov for (q=p;*q;q++) 2420e9a2605SKonstantin Belousov PCHAR(*q); 2430e9a2605SKonstantin Belousov } 2440e9a2605SKonstantin Belousov break; 2450e9a2605SKonstantin Belousov case 'd': 2460e9a2605SKonstantin Belousov case 'i': 2470e9a2605SKonstantin Belousov base = 10; 2480e9a2605SKonstantin Belousov sign = 1; 2490e9a2605SKonstantin Belousov goto handle_sign; 2500e9a2605SKonstantin Belousov case 'h': 2510e9a2605SKonstantin Belousov if (hflag) { 2520e9a2605SKonstantin Belousov hflag = 0; 2530e9a2605SKonstantin Belousov cflag = 1; 2540e9a2605SKonstantin Belousov } else 2550e9a2605SKonstantin Belousov hflag = 1; 2560e9a2605SKonstantin Belousov goto reswitch; 2570e9a2605SKonstantin Belousov case 'j': 2580e9a2605SKonstantin Belousov jflag = 1; 2590e9a2605SKonstantin Belousov goto reswitch; 2600e9a2605SKonstantin Belousov case 'l': 2610e9a2605SKonstantin Belousov if (lflag) { 2620e9a2605SKonstantin Belousov lflag = 0; 2630e9a2605SKonstantin Belousov qflag = 1; 2640e9a2605SKonstantin Belousov } else 2650e9a2605SKonstantin Belousov lflag = 1; 2660e9a2605SKonstantin Belousov goto reswitch; 2670e9a2605SKonstantin Belousov case 'n': 2680e9a2605SKonstantin Belousov if (jflag) 2690e9a2605SKonstantin Belousov *(va_arg(ap, intmax_t *)) = retval; 2700e9a2605SKonstantin Belousov else if (qflag) 2710e9a2605SKonstantin Belousov *(va_arg(ap, quad_t *)) = retval; 2720e9a2605SKonstantin Belousov else if (lflag) 2730e9a2605SKonstantin Belousov *(va_arg(ap, long *)) = retval; 2740e9a2605SKonstantin Belousov else if (zflag) 2750e9a2605SKonstantin Belousov *(va_arg(ap, size_t *)) = retval; 2760e9a2605SKonstantin Belousov else if (hflag) 2770e9a2605SKonstantin Belousov *(va_arg(ap, short *)) = retval; 2780e9a2605SKonstantin Belousov else if (cflag) 2790e9a2605SKonstantin Belousov *(va_arg(ap, char *)) = retval; 2800e9a2605SKonstantin Belousov else 2810e9a2605SKonstantin Belousov *(va_arg(ap, int *)) = retval; 2820e9a2605SKonstantin Belousov break; 2830e9a2605SKonstantin Belousov case 'o': 2840e9a2605SKonstantin Belousov base = 8; 2850e9a2605SKonstantin Belousov goto handle_nosign; 2860e9a2605SKonstantin Belousov case 'p': 2870e9a2605SKonstantin Belousov base = 16; 2880e9a2605SKonstantin Belousov sharpflag = (width == 0); 2890e9a2605SKonstantin Belousov sign = 0; 2900e9a2605SKonstantin Belousov num = (uintptr_t)va_arg(ap, void *); 2910e9a2605SKonstantin Belousov goto number; 2920e9a2605SKonstantin Belousov case 'q': 2930e9a2605SKonstantin Belousov qflag = 1; 2940e9a2605SKonstantin Belousov goto reswitch; 2950e9a2605SKonstantin Belousov case 'r': 2960e9a2605SKonstantin Belousov base = radix; 2970e9a2605SKonstantin Belousov if (sign) 2980e9a2605SKonstantin Belousov goto handle_sign; 2990e9a2605SKonstantin Belousov goto handle_nosign; 3000e9a2605SKonstantin Belousov case 's': 3010e9a2605SKonstantin Belousov p = va_arg(ap, char *); 3020e9a2605SKonstantin Belousov if (p == NULL) 3030e9a2605SKonstantin Belousov p = "(null)"; 3040e9a2605SKonstantin Belousov if (!dot) 3050e9a2605SKonstantin Belousov n = strlen (p); 3060e9a2605SKonstantin Belousov else 3070e9a2605SKonstantin Belousov for (n = 0; n < dwidth && p[n]; n++) 3080e9a2605SKonstantin Belousov continue; 3090e9a2605SKonstantin Belousov 3100e9a2605SKonstantin Belousov width -= n; 3110e9a2605SKonstantin Belousov 3120e9a2605SKonstantin Belousov if (!ladjust && width > 0) 3130e9a2605SKonstantin Belousov while (width--) 3140e9a2605SKonstantin Belousov PCHAR(padc); 3150e9a2605SKonstantin Belousov while (n--) 3160e9a2605SKonstantin Belousov PCHAR(*p++); 3170e9a2605SKonstantin Belousov if (ladjust && width > 0) 3180e9a2605SKonstantin Belousov while (width--) 3190e9a2605SKonstantin Belousov PCHAR(padc); 3200e9a2605SKonstantin Belousov break; 3210e9a2605SKonstantin Belousov case 't': 3220e9a2605SKonstantin Belousov tflag = 1; 3230e9a2605SKonstantin Belousov goto reswitch; 3240e9a2605SKonstantin Belousov case 'u': 3250e9a2605SKonstantin Belousov base = 10; 3260e9a2605SKonstantin Belousov goto handle_nosign; 3270e9a2605SKonstantin Belousov case 'X': 3280e9a2605SKonstantin Belousov upper = 1; 3293ab5b6bdSAlex Richardson /* FALLTHROUGH */ 3300e9a2605SKonstantin Belousov case 'x': 3310e9a2605SKonstantin Belousov base = 16; 3320e9a2605SKonstantin Belousov goto handle_nosign; 3330e9a2605SKonstantin Belousov case 'y': 3340e9a2605SKonstantin Belousov base = 16; 3350e9a2605SKonstantin Belousov sign = 1; 3360e9a2605SKonstantin Belousov goto handle_sign; 3370e9a2605SKonstantin Belousov case 'z': 3380e9a2605SKonstantin Belousov zflag = 1; 3390e9a2605SKonstantin Belousov goto reswitch; 3400e9a2605SKonstantin Belousov handle_nosign: 3410e9a2605SKonstantin Belousov sign = 0; 3420e9a2605SKonstantin Belousov if (jflag) 3430e9a2605SKonstantin Belousov num = va_arg(ap, uintmax_t); 3440e9a2605SKonstantin Belousov else if (qflag) 3450e9a2605SKonstantin Belousov num = va_arg(ap, u_quad_t); 3460e9a2605SKonstantin Belousov else if (tflag) 3470e9a2605SKonstantin Belousov num = va_arg(ap, ptrdiff_t); 3480e9a2605SKonstantin Belousov else if (lflag) 3490e9a2605SKonstantin Belousov num = va_arg(ap, u_long); 3500e9a2605SKonstantin Belousov else if (zflag) 3510e9a2605SKonstantin Belousov num = va_arg(ap, size_t); 3520e9a2605SKonstantin Belousov else if (hflag) 3530e9a2605SKonstantin Belousov num = (u_short)va_arg(ap, int); 3540e9a2605SKonstantin Belousov else if (cflag) 3550e9a2605SKonstantin Belousov num = (u_char)va_arg(ap, int); 3560e9a2605SKonstantin Belousov else 3570e9a2605SKonstantin Belousov num = va_arg(ap, u_int); 3580e9a2605SKonstantin Belousov goto number; 3590e9a2605SKonstantin Belousov handle_sign: 3600e9a2605SKonstantin Belousov if (jflag) 3610e9a2605SKonstantin Belousov num = va_arg(ap, intmax_t); 3620e9a2605SKonstantin Belousov else if (qflag) 3630e9a2605SKonstantin Belousov num = va_arg(ap, quad_t); 3640e9a2605SKonstantin Belousov else if (tflag) 3650e9a2605SKonstantin Belousov num = va_arg(ap, ptrdiff_t); 3660e9a2605SKonstantin Belousov else if (lflag) 3670e9a2605SKonstantin Belousov num = va_arg(ap, long); 3680e9a2605SKonstantin Belousov else if (zflag) 3690e9a2605SKonstantin Belousov num = va_arg(ap, ssize_t); 3700e9a2605SKonstantin Belousov else if (hflag) 3710e9a2605SKonstantin Belousov num = (short)va_arg(ap, int); 3720e9a2605SKonstantin Belousov else if (cflag) 3730e9a2605SKonstantin Belousov num = (char)va_arg(ap, int); 3740e9a2605SKonstantin Belousov else 3750e9a2605SKonstantin Belousov num = va_arg(ap, int); 3760e9a2605SKonstantin Belousov number: 3770e9a2605SKonstantin Belousov if (sign && (intmax_t)num < 0) { 3780e9a2605SKonstantin Belousov neg = 1; 3790e9a2605SKonstantin Belousov num = -(intmax_t)num; 3800e9a2605SKonstantin Belousov } 3810e9a2605SKonstantin Belousov p = ksprintn(nbuf, num, base, &n, upper); 3820e9a2605SKonstantin Belousov tmp = 0; 3830e9a2605SKonstantin Belousov if (sharpflag && num != 0) { 3840e9a2605SKonstantin Belousov if (base == 8) 3850e9a2605SKonstantin Belousov tmp++; 3860e9a2605SKonstantin Belousov else if (base == 16) 3870e9a2605SKonstantin Belousov tmp += 2; 3880e9a2605SKonstantin Belousov } 3890e9a2605SKonstantin Belousov if (neg) 3900e9a2605SKonstantin Belousov tmp++; 3910e9a2605SKonstantin Belousov 3920e9a2605SKonstantin Belousov if (!ladjust && padc == '0') 3930e9a2605SKonstantin Belousov dwidth = width - tmp; 3940e9a2605SKonstantin Belousov width -= tmp + imax(dwidth, n); 3950e9a2605SKonstantin Belousov dwidth -= n; 3960e9a2605SKonstantin Belousov if (!ladjust) 3970e9a2605SKonstantin Belousov while (width-- > 0) 3980e9a2605SKonstantin Belousov PCHAR(' '); 3990e9a2605SKonstantin Belousov if (neg) 4000e9a2605SKonstantin Belousov PCHAR('-'); 4010e9a2605SKonstantin Belousov if (sharpflag && num != 0) { 4020e9a2605SKonstantin Belousov if (base == 8) { 4030e9a2605SKonstantin Belousov PCHAR('0'); 4040e9a2605SKonstantin Belousov } else if (base == 16) { 4050e9a2605SKonstantin Belousov PCHAR('0'); 4060e9a2605SKonstantin Belousov PCHAR('x'); 4070e9a2605SKonstantin Belousov } 4080e9a2605SKonstantin Belousov } 4090e9a2605SKonstantin Belousov while (dwidth-- > 0) 4100e9a2605SKonstantin Belousov PCHAR('0'); 4110e9a2605SKonstantin Belousov 4120e9a2605SKonstantin Belousov while (*p) 4130e9a2605SKonstantin Belousov PCHAR(*p--); 4140e9a2605SKonstantin Belousov 4150e9a2605SKonstantin Belousov if (ladjust) 4160e9a2605SKonstantin Belousov while (width-- > 0) 4170e9a2605SKonstantin Belousov PCHAR(' '); 4180e9a2605SKonstantin Belousov 4190e9a2605SKonstantin Belousov break; 4200e9a2605SKonstantin Belousov default: 4210e9a2605SKonstantin Belousov while (percent < fmt) 4220e9a2605SKonstantin Belousov PCHAR(*percent++); 4230e9a2605SKonstantin Belousov /* 4240e9a2605SKonstantin Belousov * Since we ignore an formatting argument it is no 4250e9a2605SKonstantin Belousov * longer safe to obey the remaining formatting 4260e9a2605SKonstantin Belousov * arguments as the arguments will no longer match 4270e9a2605SKonstantin Belousov * the format specs. 4280e9a2605SKonstantin Belousov */ 4290e9a2605SKonstantin Belousov stop = 1; 4300e9a2605SKonstantin Belousov break; 4310e9a2605SKonstantin Belousov } 4320e9a2605SKonstantin Belousov } 4330e9a2605SKonstantin Belousov #undef PCHAR 4340e9a2605SKonstantin Belousov } 4350e9a2605SKonstantin Belousov 4360e9a2605SKonstantin Belousov int 43702d3b38eSJonathan Anderson rtld_snprintf(char *buf, size_t bufsize, const char *fmt, ...) 43802d3b38eSJonathan Anderson { 43902d3b38eSJonathan Anderson va_list ap; 44002d3b38eSJonathan Anderson int retval; 44102d3b38eSJonathan Anderson 44202d3b38eSJonathan Anderson va_start(ap, fmt); 44302d3b38eSJonathan Anderson retval = rtld_vsnprintf(buf, bufsize, fmt, ap); 44402d3b38eSJonathan Anderson va_end(ap); 44502d3b38eSJonathan Anderson return (retval); 44602d3b38eSJonathan Anderson } 44702d3b38eSJonathan Anderson 44802d3b38eSJonathan Anderson int 4490e9a2605SKonstantin Belousov rtld_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap) 4500e9a2605SKonstantin Belousov { 4510e9a2605SKonstantin Belousov struct snprintf_arg info; 4520e9a2605SKonstantin Belousov int retval; 4530e9a2605SKonstantin Belousov 454b2367317SKonstantin Belousov info.method = PRINT_METHOD_SNPRINTF; 4550e9a2605SKonstantin Belousov info.buf = info.str = buf; 4560e9a2605SKonstantin Belousov info.buf_total = info.remain = bufsize; 4570e9a2605SKonstantin Belousov info.fd = -1; 458b2367317SKonstantin Belousov retval = kvprintf(fmt, &info, 10, ap); 4590e9a2605SKonstantin Belousov if (info.remain >= 1) 4600e9a2605SKonstantin Belousov *info.str++ = '\0'; 4610e9a2605SKonstantin Belousov return (retval); 4620e9a2605SKonstantin Belousov } 4630e9a2605SKonstantin Belousov 4640e9a2605SKonstantin Belousov int 4650e9a2605SKonstantin Belousov rtld_vfdprintf(int fd, const char *fmt, va_list ap) 4660e9a2605SKonstantin Belousov { 4670e9a2605SKonstantin Belousov char buf[512]; 4680e9a2605SKonstantin Belousov struct snprintf_arg info; 4690e9a2605SKonstantin Belousov int retval; 4700e9a2605SKonstantin Belousov 471b2367317SKonstantin Belousov info.method = PRINT_METHOD_WRITE; 4720e9a2605SKonstantin Belousov info.buf = info.str = buf; 4730e9a2605SKonstantin Belousov info.buf_total = info.remain = sizeof(buf); 4740e9a2605SKonstantin Belousov info.fd = fd; 475b2367317SKonstantin Belousov retval = kvprintf(fmt, &info, 10, ap); 4760e9a2605SKonstantin Belousov printf_out(&info); 4770e9a2605SKonstantin Belousov return (retval); 4780e9a2605SKonstantin Belousov } 4790e9a2605SKonstantin Belousov 4800e9a2605SKonstantin Belousov int 4810e9a2605SKonstantin Belousov rtld_fdprintf(int fd, const char *fmt, ...) 4820e9a2605SKonstantin Belousov { 4830e9a2605SKonstantin Belousov va_list ap; 4840e9a2605SKonstantin Belousov int retval; 4850e9a2605SKonstantin Belousov 4860e9a2605SKonstantin Belousov va_start(ap, fmt); 4870e9a2605SKonstantin Belousov retval = rtld_vfdprintf(fd, fmt, ap); 4880e9a2605SKonstantin Belousov va_end(ap); 4890e9a2605SKonstantin Belousov return (retval); 4900e9a2605SKonstantin Belousov } 4910e9a2605SKonstantin Belousov 492*77c088abSKonstantin Belousov int 493*77c088abSKonstantin Belousov rtld_fdprintfx(int fd, const char *fmt, ...) 494*77c088abSKonstantin Belousov { 495*77c088abSKonstantin Belousov va_list ap; 496*77c088abSKonstantin Belousov int retval; 497*77c088abSKonstantin Belousov 498*77c088abSKonstantin Belousov va_start(ap, fmt); 499*77c088abSKonstantin Belousov retval = rtld_vfdprintf(fd, fmt, ap); 500*77c088abSKonstantin Belousov va_end(ap); 501*77c088abSKonstantin Belousov return (retval); 502*77c088abSKonstantin Belousov } 503*77c088abSKonstantin Belousov 5040e9a2605SKonstantin Belousov void 5050e9a2605SKonstantin Belousov rtld_fdputstr(int fd, const char *str) 5060e9a2605SKonstantin Belousov { 5070e9a2605SKonstantin Belousov 5080e9a2605SKonstantin Belousov write(fd, str, strlen(str)); 5090e9a2605SKonstantin Belousov } 5100e9a2605SKonstantin Belousov 5110e9a2605SKonstantin Belousov void 5120e9a2605SKonstantin Belousov rtld_fdputchar(int fd, int c) 5130e9a2605SKonstantin Belousov { 5140e9a2605SKonstantin Belousov char c1; 5150e9a2605SKonstantin Belousov 5160e9a2605SKonstantin Belousov c1 = c; 5170e9a2605SKonstantin Belousov write(fd, &c1, 1); 5180e9a2605SKonstantin Belousov } 519