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: stable/11/sys/kern/subr_prf.c 339446 2018-10-20 16:20:36Z jamie $"); 39 40#ifdef _KERNEL 41#include "opt_ddb.h" 42#include "opt_printf.h" 43#endif /* _KERNEL */ 44 45#include <sys/param.h> 46#ifdef _KERNEL 47#include <sys/systm.h> 48#include <sys/lock.h> 49#include <sys/kdb.h> 50#include <sys/mutex.h> 51#include <sys/sx.h> 52#include <sys/kernel.h> 53#include <sys/msgbuf.h> 54#include <sys/malloc.h> 55#include <sys/priv.h> 56#include <sys/proc.h> 57#include <sys/stddef.h> 58#include <sys/sysctl.h> 59#include <sys/tty.h> 60#include <sys/syslog.h> 61#include <sys/cons.h> 62#include <sys/uio.h> 63#endif 64#include <sys/ctype.h> 65#include <sys/sbuf.h> 66 67#ifdef DDB 68#include <ddb/ddb.h> 69#endif 70 71/* 72 * Note that stdarg.h and the ANSI style va_start macro is used for both 73 * ANSI and traditional C compilers. 74 */ 75#ifdef _KERNEL 76#include <machine/stdarg.h> 77#else 78#include <stdarg.h> 79#endif 80 81/* 82 * This is needed for sbuf_putbuf() when compiled into userland. Due to the 83 * shared nature of this file, it's the only place to put it. 84 */ 85#ifndef _KERNEL 86#include <stdio.h> 87#endif 88 89#ifdef _KERNEL 90 91#define TOCONS 0x01 92#define TOTTY 0x02 93#define TOLOG 0x04 94 95/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 96#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 97 98struct putchar_arg { 99 int flags; 100 int pri; 101 struct tty *tty; 102 char *p_bufr; 103 size_t n_bufr; 104 char *p_next; 105 size_t remain; 106}; 107 108struct snprintf_arg { 109 char *str; 110 size_t remain; 111}; 112 113extern int log_open; 114 115static void msglogchar(int c, int pri); 116static void msglogstr(char *str, int pri, int filter_cr); 117static void putchar(int ch, void *arg); 118static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper); 119static void snprintf_func(int ch, void *arg); 120 121static bool msgbufmapped; /* Set when safe to use msgbuf */ 122int msgbuftrigger; 123 124#ifndef BOOT_TAG_SZ 125#define BOOT_TAG_SZ 32 126#endif 127#ifndef BOOT_TAG 128/* Tag used to mark the start of a boot in dmesg */ 129#define BOOT_TAG "" 130#endif 131 132static char current_boot_tag[BOOT_TAG_SZ + 1] = BOOT_TAG; 133SYSCTL_STRING(_kern, OID_AUTO, boot_tag, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, 134 current_boot_tag, 0, "Tag added to dmesg at start of boot"); 135 136static int log_console_output = 1; 137SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN, 138 &log_console_output, 0, "Duplicate console output to the syslog"); 139 140/* 141 * See the comment in log_console() below for more explanation of this. 142 */ 143static int log_console_add_linefeed; 144SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RWTUN, 145 &log_console_add_linefeed, 0, "log_console() adds extra newlines"); 146 147static int always_console_output; 148SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RWTUN, 149 &always_console_output, 0, "Always output to console despite TIOCCONS"); 150 151/* 152 * Warn that a system table is full. 153 */ 154void 155tablefull(const char *tab) 156{ 157 158 log(LOG_ERR, "%s: table is full\n", tab); 159} 160 161/* 162 * Uprintf prints to the controlling terminal for the current process. 163 */ 164int 165uprintf(const char *fmt, ...) 166{ 167 va_list ap; 168 struct putchar_arg pca; 169 struct proc *p; 170 struct thread *td; 171 int retval; 172 173 td = curthread; 174 if (TD_IS_IDLETHREAD(td)) 175 return (0); 176 177 sx_slock(&proctree_lock); 178 p = td->td_proc; 179 PROC_LOCK(p); 180 if ((p->p_flag & P_CONTROLT) == 0) { 181 PROC_UNLOCK(p); 182 sx_sunlock(&proctree_lock); 183 return (0); 184 } 185 SESS_LOCK(p->p_session); 186 pca.tty = p->p_session->s_ttyp; 187 SESS_UNLOCK(p->p_session); 188 PROC_UNLOCK(p); 189 if (pca.tty == NULL) { 190 sx_sunlock(&proctree_lock); 191 return (0); 192 } 193 pca.flags = TOTTY; 194 pca.p_bufr = NULL; 195 va_start(ap, fmt); 196 tty_lock(pca.tty); 197 sx_sunlock(&proctree_lock); 198 retval = kvprintf(fmt, putchar, &pca, 10, ap); 199 tty_unlock(pca.tty); 200 va_end(ap); 201 return (retval); 202} 203 204/* 205 * tprintf and vtprintf print on the controlling terminal associated with the 206 * given session, possibly to the log as well. 207 */ 208void 209tprintf(struct proc *p, int pri, const char *fmt, ...) 210{ 211 va_list ap; 212 213 va_start(ap, fmt); 214 vtprintf(p, pri, fmt, ap); 215 va_end(ap); 216} 217 218void 219vtprintf(struct proc *p, int pri, const char *fmt, va_list ap) 220{ 221 struct tty *tp = NULL; 222 int flags = 0; 223 struct putchar_arg pca; 224 struct session *sess = NULL; 225 226 sx_slock(&proctree_lock); 227 if (pri != -1) 228 flags |= TOLOG; 229 if (p != NULL) { 230 PROC_LOCK(p); 231 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 232 sess = p->p_session; 233 sess_hold(sess); 234 PROC_UNLOCK(p); 235 tp = sess->s_ttyp; 236 if (tp != NULL && tty_checkoutq(tp)) 237 flags |= TOTTY; 238 else 239 tp = NULL; 240 } else 241 PROC_UNLOCK(p); 242 } 243 pca.pri = pri; 244 pca.tty = tp; 245 pca.flags = flags; 246 pca.p_bufr = NULL; 247 if (pca.tty != NULL) 248 tty_lock(pca.tty); 249 sx_sunlock(&proctree_lock); 250 kvprintf(fmt, putchar, &pca, 10, ap); 251 if (pca.tty != NULL) 252 tty_unlock(pca.tty); 253 if (sess != NULL) 254 sess_release(sess); 255 msgbuftrigger = 1; 256} 257 258/* 259 * Ttyprintf displays a message on a tty; it should be used only by 260 * the tty driver, or anything that knows the underlying tty will not 261 * be revoke(2)'d away. Other callers should use tprintf. 262 */ 263int 264ttyprintf(struct tty *tp, const char *fmt, ...) 265{ 266 va_list ap; 267 struct putchar_arg pca; 268 int retval; 269 270 va_start(ap, fmt); 271 pca.tty = tp; 272 pca.flags = TOTTY; 273 pca.p_bufr = NULL; 274 retval = kvprintf(fmt, putchar, &pca, 10, ap); 275 va_end(ap); 276 return (retval); 277} 278 279static int 280_vprintf(int level, int flags, const char *fmt, va_list ap) 281{ 282 struct putchar_arg pca; 283 int retval; 284#ifdef PRINTF_BUFR_SIZE 285 char bufr[PRINTF_BUFR_SIZE]; 286#endif 287 288 pca.tty = NULL; 289 pca.pri = level; 290 pca.flags = flags; 291#ifdef PRINTF_BUFR_SIZE 292 pca.p_bufr = bufr; 293 pca.p_next = pca.p_bufr; 294 pca.n_bufr = sizeof(bufr); 295 pca.remain = sizeof(bufr); 296 *pca.p_next = '\0'; 297#else 298 /* Don't buffer console output. */ 299 pca.p_bufr = NULL; 300#endif 301 302 retval = kvprintf(fmt, putchar, &pca, 10, ap); 303 304#ifdef PRINTF_BUFR_SIZE 305 /* Write any buffered console/log output: */ 306 if (*pca.p_bufr != '\0') { 307 if (pca.flags & TOLOG) 308 msglogstr(pca.p_bufr, level, /*filter_cr*/1); 309 310 if (pca.flags & TOCONS) 311 cnputs(pca.p_bufr); 312 } 313#endif 314 315 return (retval); 316} 317 318/* 319 * Log writes to the log buffer, and guarantees not to sleep (so can be 320 * called by interrupt routines). If there is no process reading the 321 * log yet, it writes to the console also. 322 */ 323void 324log(int level, const char *fmt, ...) 325{ 326 va_list ap; 327 328 va_start(ap, fmt); 329 vlog(level, fmt, ap); 330 va_end(ap); 331} 332 333void 334vlog(int level, const char *fmt, va_list ap) 335{ 336 337 (void)_vprintf(level, log_open ? TOLOG : TOCONS | TOLOG, fmt, ap); 338 msgbuftrigger = 1; 339} 340 341#define CONSCHUNK 128 342 343void 344log_console(struct uio *uio) 345{ 346 int c, error, nl; 347 char *consbuffer; 348 int pri; 349 350 if (!log_console_output) 351 return; 352 353 pri = LOG_INFO | LOG_CONSOLE; 354 uio = cloneuio(uio); 355 consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK); 356 357 nl = 0; 358 while (uio->uio_resid > 0) { 359 c = imin(uio->uio_resid, CONSCHUNK - 1); 360 error = uiomove(consbuffer, c, uio); 361 if (error != 0) 362 break; 363 /* Make sure we're NUL-terminated */ 364 consbuffer[c] = '\0'; 365 if (consbuffer[c - 1] == '\n') 366 nl = 1; 367 else 368 nl = 0; 369 msglogstr(consbuffer, pri, /*filter_cr*/ 1); 370 } 371 /* 372 * The previous behavior in log_console() is preserved when 373 * log_console_add_linefeed is non-zero. For that behavior, if an 374 * individual console write came in that was not terminated with a 375 * line feed, it would add a line feed. 376 * 377 * This results in different data in the message buffer than 378 * appears on the system console (which doesn't add extra line feed 379 * characters). 380 * 381 * A number of programs and rc scripts write a line feed, or a period 382 * and a line feed when they have completed their operation. On 383 * the console, this looks seamless, but when displayed with 384 * 'dmesg -a', you wind up with output that looks like this: 385 * 386 * Updating motd: 387 * . 388 * 389 * On the console, it looks like this: 390 * Updating motd:. 391 * 392 * We could add logic to detect that situation, or just not insert 393 * the extra newlines. Set the kern.log_console_add_linefeed 394 * sysctl/tunable variable to get the old behavior. 395 */ 396 if (!nl && log_console_add_linefeed) { 397 consbuffer[0] = '\n'; 398 consbuffer[1] = '\0'; 399 msglogstr(consbuffer, pri, /*filter_cr*/ 1); 400 } 401 msgbuftrigger = 1; 402 free(uio, M_IOV); 403 free(consbuffer, M_TEMP); 404} 405 406int 407printf(const char *fmt, ...) 408{ 409 va_list ap; 410 int retval; 411 412 va_start(ap, fmt); 413 retval = vprintf(fmt, ap); 414 va_end(ap); 415 416 return (retval); 417} 418 419int 420vprintf(const char *fmt, va_list ap) 421{ 422 int retval; 423 424 retval = _vprintf(-1, TOCONS | TOLOG, fmt, ap); 425 426 if (!panicstr) 427 msgbuftrigger = 1; 428 429 return (retval); 430} 431 432static void 433prf_putbuf(char *bufr, int flags, int pri) 434{ 435 436 if (flags & TOLOG) 437 msglogstr(bufr, pri, /*filter_cr*/1); 438 439 if (flags & TOCONS) { 440 if ((panicstr == NULL) && (constty != NULL)) 441 msgbuf_addstr(&consmsgbuf, -1, 442 bufr, /*filter_cr*/ 0); 443 444 if ((constty == NULL) ||(always_console_output)) 445 cnputs(bufr); 446 } 447} 448 449static void 450putbuf(int c, struct putchar_arg *ap) 451{ 452 /* Check if no console output buffer was provided. */ 453 if (ap->p_bufr == NULL) { 454 /* Output direct to the console. */ 455 if (ap->flags & TOCONS) 456 cnputc(c); 457 458 if (ap->flags & TOLOG) 459 msglogchar(c, ap->pri); 460 } else { 461 /* Buffer the character: */ 462 *ap->p_next++ = c; 463 ap->remain--; 464 465 /* Always leave the buffer zero terminated. */ 466 *ap->p_next = '\0'; 467 468 /* Check if the buffer needs to be flushed. */ 469 if (ap->remain == 2 || c == '\n') { 470 prf_putbuf(ap->p_bufr, ap->flags, ap->pri); 471 472 ap->p_next = ap->p_bufr; 473 ap->remain = ap->n_bufr; 474 *ap->p_next = '\0'; 475 } 476 477 /* 478 * Since we fill the buffer up one character at a time, 479 * this should not happen. We should always catch it when 480 * ap->remain == 2 (if not sooner due to a newline), flush 481 * the buffer and move on. One way this could happen is 482 * if someone sets PRINTF_BUFR_SIZE to 1 or something 483 * similarly silly. 484 */ 485 KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd", 486 ap->remain)); 487 } 488} 489 490/* 491 * Print a character on console or users terminal. If destination is 492 * the console then the last bunch of characters are saved in msgbuf for 493 * inspection later. 494 */ 495static void 496putchar(int c, void *arg) 497{ 498 struct putchar_arg *ap = (struct putchar_arg*) arg; 499 struct tty *tp = ap->tty; 500 int flags = ap->flags; 501 502 /* Don't use the tty code after a panic or while in ddb. */ 503 if (kdb_active) { 504 if (c != '\0') 505 cnputc(c); 506 return; 507 } 508 509 if ((flags & TOTTY) && tp != NULL && panicstr == NULL) 510 tty_putchar(tp, c); 511 512 if ((flags & (TOCONS | TOLOG)) && c != '\0') 513 putbuf(c, ap); 514} 515 516/* 517 * Scaled down version of sprintf(3). 518 */ 519int 520sprintf(char *buf, const char *cfmt, ...) 521{ 522 int retval; 523 va_list ap; 524 525 va_start(ap, cfmt); 526 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 527 buf[retval] = '\0'; 528 va_end(ap); 529 return (retval); 530} 531 532/* 533 * Scaled down version of vsprintf(3). 534 */ 535int 536vsprintf(char *buf, const char *cfmt, va_list ap) 537{ 538 int retval; 539 540 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 541 buf[retval] = '\0'; 542 return (retval); 543} 544 545/* 546 * Scaled down version of snprintf(3). 547 */ 548int 549snprintf(char *str, size_t size, const char *format, ...) 550{ 551 int retval; 552 va_list ap; 553 554 va_start(ap, format); 555 retval = vsnprintf(str, size, format, ap); 556 va_end(ap); 557 return(retval); 558} 559 560/* 561 * Scaled down version of vsnprintf(3). 562 */ 563int 564vsnprintf(char *str, size_t size, const char *format, va_list ap) 565{ 566 struct snprintf_arg info; 567 int retval; 568 569 info.str = str; 570 info.remain = size; 571 retval = kvprintf(format, snprintf_func, &info, 10, ap); 572 if (info.remain >= 1) 573 *info.str++ = '\0'; 574 return (retval); 575} 576 577/* 578 * Kernel version which takes radix argument vsnprintf(3). 579 */ 580int 581vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap) 582{ 583 struct snprintf_arg info; 584 int retval; 585 586 info.str = str; 587 info.remain = size; 588 retval = kvprintf(format, snprintf_func, &info, radix, ap); 589 if (info.remain >= 1) 590 *info.str++ = '\0'; 591 return (retval); 592} 593 594static void 595snprintf_func(int ch, void *arg) 596{ 597 struct snprintf_arg *const info = arg; 598 599 if (info->remain >= 2) { 600 *info->str++ = ch; 601 info->remain--; 602 } 603} 604 605/* 606 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 607 * order; return an optional length and a pointer to the last character 608 * written in the buffer (i.e., the first character of the string). 609 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 610 */ 611static char * 612ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 613{ 614 char *p, c; 615 616 p = nbuf; 617 *p = '\0'; 618 do { 619 c = hex2ascii(num % base); 620 *++p = upper ? toupper(c) : c; 621 } while (num /= base); 622 if (lenp) 623 *lenp = p - nbuf; 624 return (p); 625} 626 627/* 628 * Scaled down version of printf(3). 629 * 630 * Two additional formats: 631 * 632 * The format %b is supported to decode error registers. 633 * Its usage is: 634 * 635 * printf("reg=%b\n", regval, "<base><arg>*"); 636 * 637 * where <base> is the output base expressed as a control character, e.g. 638 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 639 * the first of which gives the bit number to be inspected (origin 1), and 640 * the next characters (up to a control character, i.e. a character <= 32), 641 * give the name of the register. Thus: 642 * 643 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE"); 644 * 645 * would produce output: 646 * 647 * reg=3<BITTWO,BITONE> 648 * 649 * XXX: %D -- Hexdump, takes pointer and separator string: 650 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 651 * ("%*D", len, ptr, " " -> XX XX XX XX ... 652 */ 653int 654kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 655{ 656#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 657 char nbuf[MAXNBUF]; 658 char *d; 659 const char *p, *percent, *q; 660 u_char *up; 661 int ch, n; 662 uintmax_t num; 663 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 664 int cflag, hflag, jflag, tflag, zflag; 665 int dwidth, upper; 666 char padc; 667 int stop = 0, retval = 0; 668 669 num = 0; 670 if (!func) 671 d = (char *) arg; 672 else 673 d = NULL; 674 675 if (fmt == NULL) 676 fmt = "(fmt null)\n"; 677 678 if (radix < 2 || radix > 36) 679 radix = 10; 680 681 for (;;) { 682 padc = ' '; 683 width = 0; 684 while ((ch = (u_char)*fmt++) != '%' || stop) { 685 if (ch == '\0') 686 return (retval); 687 PCHAR(ch); 688 } 689 percent = fmt - 1; 690 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 691 sign = 0; dot = 0; dwidth = 0; upper = 0; 692 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 693reswitch: switch (ch = (u_char)*fmt++) { 694 case '.': 695 dot = 1; 696 goto reswitch; 697 case '#': 698 sharpflag = 1; 699 goto reswitch; 700 case '+': 701 sign = 1; 702 goto reswitch; 703 case '-': 704 ladjust = 1; 705 goto reswitch; 706 case '%': 707 PCHAR(ch); 708 break; 709 case '*': 710 if (!dot) { 711 width = va_arg(ap, int); 712 if (width < 0) { 713 ladjust = !ladjust; 714 width = -width; 715 } 716 } else { 717 dwidth = va_arg(ap, int); 718 } 719 goto reswitch; 720 case '0': 721 if (!dot) { 722 padc = '0'; 723 goto reswitch; 724 } 725 /* FALLTHROUGH */ 726 case '1': case '2': case '3': case '4': 727 case '5': case '6': case '7': case '8': case '9': 728 for (n = 0;; ++fmt) { 729 n = n * 10 + ch - '0'; 730 ch = *fmt; 731 if (ch < '0' || ch > '9') 732 break; 733 } 734 if (dot) 735 dwidth = n; 736 else 737 width = n; 738 goto reswitch; 739 case 'b': 740 num = (u_int)va_arg(ap, int); 741 p = va_arg(ap, char *); 742 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 743 PCHAR(*q--); 744 745 if (num == 0) 746 break; 747 748 for (tmp = 0; *p;) { 749 n = *p++; 750 if (num & (1 << (n - 1))) { 751 PCHAR(tmp ? ',' : '<'); 752 for (; (n = *p) > ' '; ++p) 753 PCHAR(n); 754 tmp = 1; 755 } else 756 for (; *p > ' '; ++p) 757 continue; 758 } 759 if (tmp) 760 PCHAR('>'); 761 break; 762 case 'c': 763 width -= 1; 764 765 if (!ladjust && width > 0) 766 while (width--) 767 PCHAR(padc); 768 PCHAR(va_arg(ap, int)); 769 if (ladjust && width > 0) 770 while (width--) 771 PCHAR(padc); 772 break; 773 case 'D': 774 up = va_arg(ap, u_char *); 775 p = va_arg(ap, char *); 776 if (!width) 777 width = 16; 778 while(width--) { 779 PCHAR(hex2ascii(*up >> 4)); 780 PCHAR(hex2ascii(*up & 0x0f)); 781 up++; 782 if (width) 783 for (q=p;*q;q++) 784 PCHAR(*q); 785 } 786 break; 787 case 'd': 788 case 'i': 789 base = 10; 790 sign = 1; 791 goto handle_sign; 792 case 'h': 793 if (hflag) { 794 hflag = 0; 795 cflag = 1; 796 } else 797 hflag = 1; 798 goto reswitch; 799 case 'j': 800 jflag = 1; 801 goto reswitch; 802 case 'l': 803 if (lflag) { 804 lflag = 0; 805 qflag = 1; 806 } else 807 lflag = 1; 808 goto reswitch; 809 case 'n': 810 if (jflag) 811 *(va_arg(ap, intmax_t *)) = retval; 812 else if (qflag) 813 *(va_arg(ap, quad_t *)) = retval; 814 else if (lflag) 815 *(va_arg(ap, long *)) = retval; 816 else if (zflag) 817 *(va_arg(ap, size_t *)) = retval; 818 else if (hflag) 819 *(va_arg(ap, short *)) = retval; 820 else if (cflag) 821 *(va_arg(ap, char *)) = retval; 822 else 823 *(va_arg(ap, int *)) = retval; 824 break; 825 case 'o': 826 base = 8; 827 goto handle_nosign; 828 case 'p': 829 base = 16; 830 sharpflag = (width == 0); 831 sign = 0; 832 num = (uintptr_t)va_arg(ap, void *); 833 goto number; 834 case 'q': 835 qflag = 1; 836 goto reswitch; 837 case 'r': 838 base = radix; 839 if (sign) 840 goto handle_sign; 841 goto handle_nosign; 842 case 's': 843 p = va_arg(ap, char *); 844 if (p == NULL) 845 p = "(null)"; 846 if (!dot) 847 n = strlen (p); 848 else 849 for (n = 0; n < dwidth && p[n]; n++) 850 continue; 851 852 width -= n; 853 854 if (!ladjust && width > 0) 855 while (width--) 856 PCHAR(padc); 857 while (n--) 858 PCHAR(*p++); 859 if (ladjust && width > 0) 860 while (width--) 861 PCHAR(padc); 862 break; 863 case 't': 864 tflag = 1; 865 goto reswitch; 866 case 'u': 867 base = 10; 868 goto handle_nosign; 869 case 'X': 870 upper = 1; 871 case 'x': 872 base = 16; 873 goto handle_nosign; 874 case 'y': 875 base = 16; 876 sign = 1; 877 goto handle_sign; 878 case 'z': 879 zflag = 1; 880 goto reswitch; 881handle_nosign: 882 sign = 0; 883 if (jflag) 884 num = va_arg(ap, uintmax_t); 885 else if (qflag) 886 num = va_arg(ap, u_quad_t); 887 else if (tflag) 888 num = va_arg(ap, ptrdiff_t); 889 else if (lflag) 890 num = va_arg(ap, u_long); 891 else if (zflag) 892 num = va_arg(ap, size_t); 893 else if (hflag) 894 num = (u_short)va_arg(ap, int); 895 else if (cflag) 896 num = (u_char)va_arg(ap, int); 897 else 898 num = va_arg(ap, u_int); 899 goto number; 900handle_sign: 901 if (jflag) 902 num = va_arg(ap, intmax_t); 903 else if (qflag) 904 num = va_arg(ap, quad_t); 905 else if (tflag) 906 num = va_arg(ap, ptrdiff_t); 907 else if (lflag) 908 num = va_arg(ap, long); 909 else if (zflag) 910 num = va_arg(ap, ssize_t); 911 else if (hflag) 912 num = (short)va_arg(ap, int); 913 else if (cflag) 914 num = (char)va_arg(ap, int); 915 else 916 num = va_arg(ap, int); 917number: 918 if (sign && (intmax_t)num < 0) { 919 neg = 1; 920 num = -(intmax_t)num; 921 } 922 p = ksprintn(nbuf, num, base, &n, upper); 923 tmp = 0; 924 if (sharpflag && num != 0) { 925 if (base == 8) 926 tmp++; 927 else if (base == 16) 928 tmp += 2; 929 } 930 if (neg) 931 tmp++; 932 933 if (!ladjust && padc == '0') 934 dwidth = width - tmp; 935 width -= tmp + imax(dwidth, n); 936 dwidth -= n; 937 if (!ladjust) 938 while (width-- > 0) 939 PCHAR(' '); 940 if (neg) 941 PCHAR('-'); 942 if (sharpflag && num != 0) { 943 if (base == 8) { 944 PCHAR('0'); 945 } else if (base == 16) { 946 PCHAR('0'); 947 PCHAR('x'); 948 } 949 } 950 while (dwidth-- > 0) 951 PCHAR('0'); 952 953 while (*p) 954 PCHAR(*p--); 955 956 if (ladjust) 957 while (width-- > 0) 958 PCHAR(' '); 959 960 break; 961 default: 962 while (percent < fmt) 963 PCHAR(*percent++); 964 /* 965 * Since we ignore a formatting argument it is no 966 * longer safe to obey the remaining formatting 967 * arguments as the arguments will no longer match 968 * the format specs. 969 */ 970 stop = 1; 971 break; 972 } 973 } 974#undef PCHAR 975} 976 977/* 978 * Put character in log buffer with a particular priority. 979 */ 980static void 981msglogchar(int c, int pri) 982{ 983 static int lastpri = -1; 984 static int dangling; 985 char nbuf[MAXNBUF]; 986 char *p; 987 988 if (!msgbufmapped) 989 return; 990 if (c == '\0' || c == '\r') 991 return; 992 if (pri != -1 && pri != lastpri) { 993 if (dangling) { 994 msgbuf_addchar(msgbufp, '\n'); 995 dangling = 0; 996 } 997 msgbuf_addchar(msgbufp, '<'); 998 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;) 999 msgbuf_addchar(msgbufp, *p--); 1000 msgbuf_addchar(msgbufp, '>'); 1001 lastpri = pri; 1002 } 1003 msgbuf_addchar(msgbufp, c); 1004 if (c == '\n') { 1005 dangling = 0; 1006 lastpri = -1; 1007 } else { 1008 dangling = 1; 1009 } 1010} 1011 1012static void 1013msglogstr(char *str, int pri, int filter_cr) 1014{ 1015 if (!msgbufmapped) 1016 return; 1017 1018 msgbuf_addstr(msgbufp, pri, str, filter_cr); 1019} 1020 1021void 1022msgbufinit(void *ptr, int size) 1023{ 1024 char *cp; 1025 static struct msgbuf *oldp = NULL; 1026 bool print_boot_tag; 1027 1028 size -= sizeof(*msgbufp); 1029 cp = (char *)ptr; 1030 print_boot_tag = !msgbufmapped; 1031 /* Attempt to fetch kern.boot_tag tunable on first mapping */ 1032 if (!msgbufmapped) 1033 TUNABLE_STR_FETCH("kern.boot_tag", current_boot_tag, 1034 sizeof(current_boot_tag)); 1035 msgbufp = (struct msgbuf *)(cp + size); 1036 msgbuf_reinit(msgbufp, cp, size); 1037 if (msgbufmapped && oldp != msgbufp) 1038 msgbuf_copy(oldp, msgbufp); 1039 msgbufmapped = true; 1040 if (print_boot_tag && *current_boot_tag != '\0') 1041 printf("%s\n", current_boot_tag); 1042 oldp = msgbufp; 1043} 1044 1045/* Sysctls for accessing/clearing the msgbuf */ 1046static int 1047sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 1048{ 1049 char buf[128]; 1050 u_int seq; 1051 int error, len; 1052 1053 error = priv_check(req->td, PRIV_MSGBUF); 1054 if (error) 1055 return (error); 1056 1057 /* Read the whole buffer, one chunk at a time. */ 1058 mtx_lock(&msgbuf_lock); 1059 msgbuf_peekbytes(msgbufp, NULL, 0, &seq); 1060 for (;;) { 1061 len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq); 1062 mtx_unlock(&msgbuf_lock); 1063 if (len == 0) 1064 return (SYSCTL_OUT(req, "", 1)); /* add nulterm */ 1065 1066 error = sysctl_handle_opaque(oidp, buf, len, req); 1067 if (error) 1068 return (error); 1069 1070 mtx_lock(&msgbuf_lock); 1071 } 1072} 1073 1074SYSCTL_PROC(_kern, OID_AUTO, msgbuf, 1075 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 1076 NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 1077 1078static int msgbuf_clearflag; 1079 1080static int 1081sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 1082{ 1083 int error; 1084 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 1085 if (!error && req->newptr) { 1086 mtx_lock(&msgbuf_lock); 1087 msgbuf_clear(msgbufp); 1088 mtx_unlock(&msgbuf_lock); 1089 msgbuf_clearflag = 0; 1090 } 1091 return (error); 1092} 1093 1094SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 1095 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE, 1096 &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I", 1097 "Clear kernel message buffer"); 1098 1099#ifdef DDB 1100 1101DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 1102{ 1103 int i, j; 1104 1105 if (!msgbufmapped) { 1106 db_printf("msgbuf not mapped yet\n"); 1107 return; 1108 } 1109 db_printf("msgbufp = %p\n", msgbufp); 1110 db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n", 1111 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq, 1112 msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum); 1113 for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) { 1114 j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq); 1115 db_printf("%c", msgbufp->msg_ptr[j]); 1116 } 1117 db_printf("\n"); 1118} 1119 1120#endif /* DDB */ 1121 1122void 1123hexdump(const void *ptr, int length, const char *hdr, int flags) 1124{ 1125 int i, j, k; 1126 int cols; 1127 const unsigned char *cp; 1128 char delim; 1129 1130 if ((flags & HD_DELIM_MASK) != 0) 1131 delim = (flags & HD_DELIM_MASK) >> 8; 1132 else 1133 delim = ' '; 1134 1135 if ((flags & HD_COLUMN_MASK) != 0) 1136 cols = flags & HD_COLUMN_MASK; 1137 else 1138 cols = 16; 1139 1140 cp = ptr; 1141 for (i = 0; i < length; i+= cols) { 1142 if (hdr != NULL) 1143 printf("%s", hdr); 1144 1145 if ((flags & HD_OMIT_COUNT) == 0) 1146 printf("%04x ", i); 1147 1148 if ((flags & HD_OMIT_HEX) == 0) { 1149 for (j = 0; j < cols; j++) { 1150 k = i + j; 1151 if (k < length) 1152 printf("%c%02x", delim, cp[k]); 1153 else 1154 printf(" "); 1155 } 1156 } 1157 1158 if ((flags & HD_OMIT_CHARS) == 0) { 1159 printf(" |"); 1160 for (j = 0; j < cols; j++) { 1161 k = i + j; 1162 if (k >= length) 1163 printf(" "); 1164 else if (cp[k] >= ' ' && cp[k] <= '~') 1165 printf("%c", cp[k]); 1166 else 1167 printf("."); 1168 } 1169 printf("|"); 1170 } 1171 printf("\n"); 1172 } 1173} 1174#endif /* _KERNEL */ 1175 1176void 1177sbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr, 1178 int flags) 1179{ 1180 int i, j, k; 1181 int cols; 1182 const unsigned char *cp; 1183 char delim; 1184 1185 if ((flags & HD_DELIM_MASK) != 0) 1186 delim = (flags & HD_DELIM_MASK) >> 8; 1187 else 1188 delim = ' '; 1189 1190 if ((flags & HD_COLUMN_MASK) != 0) 1191 cols = flags & HD_COLUMN_MASK; 1192 else 1193 cols = 16; 1194 1195 cp = ptr; 1196 for (i = 0; i < length; i+= cols) { 1197 if (hdr != NULL) 1198 sbuf_printf(sb, "%s", hdr); 1199 1200 if ((flags & HD_OMIT_COUNT) == 0) 1201 sbuf_printf(sb, "%04x ", i); 1202 1203 if ((flags & HD_OMIT_HEX) == 0) { 1204 for (j = 0; j < cols; j++) { 1205 k = i + j; 1206 if (k < length) 1207 sbuf_printf(sb, "%c%02x", delim, cp[k]); 1208 else 1209 sbuf_printf(sb, " "); 1210 } 1211 } 1212 1213 if ((flags & HD_OMIT_CHARS) == 0) { 1214 sbuf_printf(sb, " |"); 1215 for (j = 0; j < cols; j++) { 1216 k = i + j; 1217 if (k >= length) 1218 sbuf_printf(sb, " "); 1219 else if (cp[k] >= ' ' && cp[k] <= '~') 1220 sbuf_printf(sb, "%c", cp[k]); 1221 else 1222 sbuf_printf(sb, "."); 1223 } 1224 sbuf_printf(sb, "|"); 1225 } 1226 sbuf_printf(sb, "\n"); 1227 } 1228} 1229 1230#ifdef _KERNEL 1231void 1232counted_warning(unsigned *counter, const char *msg) 1233{ 1234 struct thread *td; 1235 unsigned c; 1236 1237 for (;;) { 1238 c = *counter; 1239 if (c == 0) 1240 break; 1241 if (atomic_cmpset_int(counter, c, c - 1)) { 1242 td = curthread; 1243 log(LOG_INFO, "pid %d (%s) %s%s\n", 1244 td->td_proc->p_pid, td->td_name, msg, 1245 c > 1 ? "" : " - not logging anymore"); 1246 break; 1247 } 1248 } 1249} 1250#endif 1251 1252#ifdef _KERNEL 1253void 1254sbuf_putbuf(struct sbuf *sb) 1255{ 1256 1257 prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1); 1258} 1259#else 1260void 1261sbuf_putbuf(struct sbuf *sb) 1262{ 1263 1264 printf("%s", sbuf_data(sb)); 1265} 1266#endif 1267