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