1 /*- 2 * Copyright (c) 1986, 1988, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_ddb.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/lock.h> 45 #include <sys/kdb.h> 46 #include <sys/mutex.h> 47 #include <sys/sx.h> 48 #include <sys/kernel.h> 49 #include <sys/msgbuf.h> 50 #include <sys/malloc.h> 51 #include <sys/priv.h> 52 #include <sys/proc.h> 53 #include <sys/stddef.h> 54 #include <sys/sysctl.h> 55 #include <sys/tty.h> 56 #include <sys/syslog.h> 57 #include <sys/cons.h> 58 #include <sys/uio.h> 59 #include <sys/ctype.h> 60 #include <sys/sbuf.h> 61 62 #ifdef DDB 63 #include <ddb/ddb.h> 64 #endif 65 66 /* 67 * Note that stdarg.h and the ANSI style va_start macro is used for both 68 * ANSI and traditional C compilers. 69 */ 70 #include <machine/stdarg.h> 71 72 #define TOCONS 0x01 73 #define TOTTY 0x02 74 #define TOLOG 0x04 75 76 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 77 #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 78 79 struct putchar_arg { 80 int flags; 81 int pri; 82 struct tty *tty; 83 char *p_bufr; 84 size_t n_bufr; 85 char *p_next; 86 size_t remain; 87 }; 88 89 struct snprintf_arg { 90 char *str; 91 size_t remain; 92 }; 93 94 int putchar(int c); 95 int puts(const char *str); 96 97 98 static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper); 99 100 /* 101 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 102 * order; return an optional length and a pointer to the last character 103 * written in the buffer (i.e., the first character of the string). 104 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 105 */ 106 static char * 107 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 108 { 109 char *p, c; 110 111 p = nbuf; 112 *p = '\0'; 113 do { 114 c = hex2ascii(num % base); 115 *++p = upper ? toupper(c) : c; 116 } while (num /= base); 117 if (lenp) 118 *lenp = p - nbuf; 119 return (p); 120 } 121 122 static void 123 putbuf(int c, struct putchar_arg *ap) 124 { 125 /* Check if no console output buffer was provided. */ 126 if (ap->p_bufr == NULL) { 127 /* Output direct to the console. */ 128 if (ap->flags & TOCONS) 129 putchar(c); 130 131 } else { 132 /* Buffer the character: */ 133 *ap->p_next++ = c; 134 ap->remain--; 135 136 /* Always leave the buffer zero terminated. */ 137 *ap->p_next = '\0'; 138 139 /* Check if the buffer needs to be flushed. */ 140 if (ap->remain == 2 || c == '\n') { 141 142 if (ap->flags & TOCONS) { 143 puts(ap->p_bufr); 144 } 145 146 ap->p_next = ap->p_bufr; 147 ap->remain = ap->n_bufr; 148 *ap->p_next = '\0'; 149 } 150 151 /* 152 * Since we fill the buffer up one character at a time, 153 * this should not happen. We should always catch it when 154 * ap->remain == 2 (if not sooner due to a newline), flush 155 * the buffer and move on. One way this could happen is 156 * if someone sets PRINTF_BUFR_SIZE to 1 or something 157 * similarly silly. 158 */ 159 KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd", 160 ap->remain)); 161 } 162 } 163 164 /* 165 * Print a character on console or users terminal. If destination is 166 * the console then the last bunch of characters are saved in msgbuf for 167 * inspection later. 168 */ 169 static void 170 kputchar(int c, void *arg) 171 { 172 struct putchar_arg *ap = (struct putchar_arg*) arg; 173 int flags = ap->flags; 174 int putbuf_done = 0; 175 176 if (flags & TOCONS) { 177 putbuf(c, ap); 178 putbuf_done = 1; 179 } 180 181 if ((flags & TOLOG) && (putbuf_done == 0)) { 182 if (c != '\0') 183 putbuf(c, ap); 184 } 185 } 186 187 /* 188 * Scaled down version of printf(3). 189 * 190 * Two additional formats: 191 * 192 * The format %b is supported to decode error registers. 193 * Its usage is: 194 * 195 * printf("reg=%b\n", regval, "<base><arg>*"); 196 * 197 * where <base> is the output base expressed as a control character, e.g. 198 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 199 * the first of which gives the bit number to be inspected (origin 1), and 200 * the next characters (up to a control character, i.e. a character <= 32), 201 * give the name of the register. Thus: 202 * 203 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 204 * 205 * would produce output: 206 * 207 * reg=3<BITTWO,BITONE> 208 * 209 * XXX: %D -- Hexdump, takes pointer and separator string: 210 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 211 * ("%*D", len, ptr, " " -> XX XX XX XX ... 212 */ 213 int 214 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 215 { 216 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 217 char nbuf[MAXNBUF]; 218 char *d; 219 const char *p, *percent, *q; 220 u_char *up; 221 int ch, n; 222 uintmax_t num; 223 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 224 int cflag, hflag, jflag, tflag, zflag; 225 int dwidth, upper; 226 char padc; 227 int stop = 0, retval = 0; 228 229 num = 0; 230 if (!func) 231 d = (char *) arg; 232 else 233 d = NULL; 234 235 if (fmt == NULL) 236 fmt = "(fmt null)\n"; 237 238 if (radix < 2 || radix > 36) 239 radix = 10; 240 241 for (;;) { 242 padc = ' '; 243 width = 0; 244 while ((ch = (u_char)*fmt++) != '%' || stop) { 245 if (ch == '\0') 246 return (retval); 247 PCHAR(ch); 248 } 249 percent = fmt - 1; 250 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 251 sign = 0; dot = 0; dwidth = 0; upper = 0; 252 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 253 reswitch: switch (ch = (u_char)*fmt++) { 254 case '.': 255 dot = 1; 256 goto reswitch; 257 case '#': 258 sharpflag = 1; 259 goto reswitch; 260 case '+': 261 sign = 1; 262 goto reswitch; 263 case '-': 264 ladjust = 1; 265 goto reswitch; 266 case '%': 267 PCHAR(ch); 268 break; 269 case '*': 270 if (!dot) { 271 width = va_arg(ap, int); 272 if (width < 0) { 273 ladjust = !ladjust; 274 width = -width; 275 } 276 } else { 277 dwidth = va_arg(ap, int); 278 } 279 goto reswitch; 280 case '0': 281 if (!dot) { 282 padc = '0'; 283 goto reswitch; 284 } 285 case '1': case '2': case '3': case '4': 286 case '5': case '6': case '7': case '8': case '9': 287 for (n = 0;; ++fmt) { 288 n = n * 10 + ch - '0'; 289 ch = *fmt; 290 if (ch < '0' || ch > '9') 291 break; 292 } 293 if (dot) 294 dwidth = n; 295 else 296 width = n; 297 goto reswitch; 298 case 'b': 299 num = (u_int)va_arg(ap, int); 300 p = va_arg(ap, char *); 301 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 302 PCHAR(*q--); 303 304 if (num == 0) 305 break; 306 307 for (tmp = 0; *p;) { 308 n = *p++; 309 if (num & (1 << (n - 1))) { 310 PCHAR(tmp ? ',' : '<'); 311 for (; (n = *p) > ' '; ++p) 312 PCHAR(n); 313 tmp = 1; 314 } else 315 for (; *p > ' '; ++p) 316 continue; 317 } 318 if (tmp) 319 PCHAR('>'); 320 break; 321 case 'c': 322 PCHAR(va_arg(ap, int)); 323 break; 324 case 'D': 325 up = va_arg(ap, u_char *); 326 p = va_arg(ap, char *); 327 if (!width) 328 width = 16; 329 while(width--) { 330 PCHAR(hex2ascii(*up >> 4)); 331 PCHAR(hex2ascii(*up & 0x0f)); 332 up++; 333 if (width) 334 for (q=p;*q;q++) 335 PCHAR(*q); 336 } 337 break; 338 case 'd': 339 case 'i': 340 base = 10; 341 sign = 1; 342 goto handle_sign; 343 case 'h': 344 if (hflag) { 345 hflag = 0; 346 cflag = 1; 347 } else 348 hflag = 1; 349 goto reswitch; 350 case 'j': 351 jflag = 1; 352 goto reswitch; 353 case 'l': 354 if (lflag) { 355 lflag = 0; 356 qflag = 1; 357 } else 358 lflag = 1; 359 goto reswitch; 360 case 'n': 361 if (jflag) 362 *(va_arg(ap, intmax_t *)) = retval; 363 else if (qflag) 364 *(va_arg(ap, quad_t *)) = retval; 365 else if (lflag) 366 *(va_arg(ap, long *)) = retval; 367 else if (zflag) 368 *(va_arg(ap, size_t *)) = retval; 369 else if (hflag) 370 *(va_arg(ap, short *)) = retval; 371 else if (cflag) 372 *(va_arg(ap, char *)) = retval; 373 else 374 *(va_arg(ap, int *)) = retval; 375 break; 376 case 'o': 377 base = 8; 378 goto handle_nosign; 379 case 'p': 380 base = 16; 381 sharpflag = (width == 0); 382 sign = 0; 383 num = (uintptr_t)va_arg(ap, void *); 384 goto number; 385 case 'q': 386 qflag = 1; 387 goto reswitch; 388 case 'r': 389 base = radix; 390 if (sign) 391 goto handle_sign; 392 goto handle_nosign; 393 case 's': 394 p = va_arg(ap, char *); 395 if (p == NULL) 396 p = "(null)"; 397 if (!dot) 398 n = strlen (p); 399 else 400 for (n = 0; n < dwidth && p[n]; n++) 401 continue; 402 403 width -= n; 404 405 if (!ladjust && width > 0) 406 while (width--) 407 PCHAR(padc); 408 while (n--) 409 PCHAR(*p++); 410 if (ladjust && width > 0) 411 while (width--) 412 PCHAR(padc); 413 break; 414 case 't': 415 tflag = 1; 416 goto reswitch; 417 case 'u': 418 base = 10; 419 goto handle_nosign; 420 case 'X': 421 upper = 1; 422 case 'x': 423 base = 16; 424 goto handle_nosign; 425 case 'y': 426 base = 16; 427 sign = 1; 428 goto handle_sign; 429 case 'z': 430 zflag = 1; 431 goto reswitch; 432 handle_nosign: 433 sign = 0; 434 if (jflag) 435 num = va_arg(ap, uintmax_t); 436 else if (qflag) 437 num = va_arg(ap, u_quad_t); 438 else if (tflag) 439 num = va_arg(ap, ptrdiff_t); 440 else if (lflag) 441 num = va_arg(ap, u_long); 442 else if (zflag) 443 num = va_arg(ap, size_t); 444 else if (hflag) 445 num = (u_short)va_arg(ap, int); 446 else if (cflag) 447 num = (u_char)va_arg(ap, int); 448 else 449 num = va_arg(ap, u_int); 450 goto number; 451 handle_sign: 452 if (jflag) 453 num = va_arg(ap, intmax_t); 454 else if (qflag) 455 num = va_arg(ap, quad_t); 456 else if (tflag) 457 num = va_arg(ap, ptrdiff_t); 458 else if (lflag) 459 num = va_arg(ap, long); 460 else if (zflag) 461 num = va_arg(ap, ssize_t); 462 else if (hflag) 463 num = (short)va_arg(ap, int); 464 else if (cflag) 465 num = (char)va_arg(ap, int); 466 else 467 num = va_arg(ap, int); 468 number: 469 if (sign && (intmax_t)num < 0) { 470 neg = 1; 471 num = -(intmax_t)num; 472 } 473 p = ksprintn(nbuf, num, base, &n, upper); 474 tmp = 0; 475 if (sharpflag && num != 0) { 476 if (base == 8) 477 tmp++; 478 else if (base == 16) 479 tmp += 2; 480 } 481 if (neg) 482 tmp++; 483 484 if (!ladjust && padc == '0') 485 dwidth = width - tmp; 486 width -= tmp + imax(dwidth, n); 487 dwidth -= n; 488 if (!ladjust) 489 while (width-- > 0) 490 PCHAR(' '); 491 if (neg) 492 PCHAR('-'); 493 if (sharpflag && num != 0) { 494 if (base == 8) { 495 PCHAR('0'); 496 } else if (base == 16) { 497 PCHAR('0'); 498 PCHAR('x'); 499 } 500 } 501 while (dwidth-- > 0) 502 PCHAR('0'); 503 504 while (*p) 505 PCHAR(*p--); 506 507 if (ladjust) 508 while (width-- > 0) 509 PCHAR(' '); 510 511 break; 512 default: 513 while (percent < fmt) 514 PCHAR(*percent++); 515 /* 516 * Since we ignore an formatting argument it is no 517 * longer safe to obey the remaining formatting 518 * arguments as the arguments will no longer match 519 * the format specs. 520 */ 521 stop = 1; 522 break; 523 } 524 } 525 #undef PCHAR 526 } 527 528 int 529 printf(const char *fmt, ...) 530 { 531 va_list ap; 532 int retval; 533 534 va_start(ap, fmt); 535 retval = vprintf(fmt, ap); 536 va_end(ap); 537 538 return (retval); 539 } 540 541 int 542 vprintf(const char *fmt, va_list ap) 543 { 544 struct putchar_arg pca; 545 int retval; 546 #ifdef PRINTF_BUFR_SIZE 547 char bufr[PRINTF_BUFR_SIZE]; 548 #endif 549 550 pca.tty = NULL; 551 pca.flags = TOCONS | TOLOG; 552 pca.pri = -1; 553 #ifdef PRINTF_BUFR_SIZE 554 pca.p_bufr = bufr; 555 pca.p_next = pca.p_bufr; 556 pca.n_bufr = sizeof(bufr); 557 pca.remain = sizeof(bufr); 558 *pca.p_next = '\0'; 559 #else 560 /* Don't buffer console output. */ 561 pca.p_bufr = NULL; 562 #endif 563 564 retval = kvprintf(fmt, kputchar, &pca, 10, ap); 565 566 #ifdef PRINTF_BUFR_SIZE 567 /* Write any buffered console/log output: */ 568 if (*pca.p_bufr != '\0') { 569 cnputs(pca.p_bufr); 570 msglogstr(pca.p_bufr, pca.pri, /*filter_cr*/ 1); 571 } 572 #endif 573 574 return (retval); 575 } 576 577 void 578 vlog(int level, const char *fmt, va_list ap) 579 { 580 (void)vprintf(fmt, ap); 581 } 582 583 int 584 sbuf_printf_drain(void *arg, const char *data, int len) 585 { 586 return 0; 587 } 588 589