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 61 #ifdef DDB 62 #include <ddb/ddb.h> 63 #endif 64 65 /* 66 * Note that stdarg.h and the ANSI style va_start macro is used for both 67 * ANSI and traditional C compilers. 68 */ 69 #include <machine/stdarg.h> 70 71 #define TOCONS 0x01 72 #define TOTTY 0x02 73 #define TOLOG 0x04 74 75 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 76 #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 77 78 struct putchar_arg { 79 int flags; 80 int pri; 81 struct tty *tty; 82 char *p_bufr; 83 size_t n_bufr; 84 char *p_next; 85 size_t remain; 86 }; 87 88 struct snprintf_arg { 89 char *str; 90 size_t remain; 91 }; 92 93 extern int log_open; 94 95 static void msglogchar(int c, int pri); 96 static void putchar(int ch, void *arg); 97 static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper); 98 static void snprintf_func(int ch, void *arg); 99 100 static int msgbufmapped; /* Set when safe to use msgbuf */ 101 int msgbuftrigger; 102 103 static int log_console_output = 1; 104 TUNABLE_INT("kern.log_console_output", &log_console_output); 105 SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW, 106 &log_console_output, 0, "Duplicate console output to the syslog."); 107 108 static int always_console_output = 0; 109 TUNABLE_INT("kern.always_console_output", &always_console_output); 110 SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW, 111 &always_console_output, 0, "Always output to console despite TIOCCONS."); 112 113 /* 114 * Warn that a system table is full. 115 */ 116 void 117 tablefull(const char *tab) 118 { 119 120 log(LOG_ERR, "%s: table is full\n", tab); 121 } 122 123 /* 124 * Uprintf prints to the controlling terminal for the current process. 125 */ 126 int 127 uprintf(const char *fmt, ...) 128 { 129 struct thread *td = curthread; 130 struct proc *p = td->td_proc; 131 va_list ap; 132 struct putchar_arg pca; 133 int retval; 134 135 if (td == NULL || td == PCPU_GET(idlethread)) 136 return (0); 137 138 mtx_lock(&Giant); 139 p = td->td_proc; 140 PROC_LOCK(p); 141 if ((p->p_flag & P_CONTROLT) == 0) { 142 PROC_UNLOCK(p); 143 retval = 0; 144 goto out; 145 } 146 SESS_LOCK(p->p_session); 147 pca.tty = p->p_session->s_ttyp; 148 SESS_UNLOCK(p->p_session); 149 PROC_UNLOCK(p); 150 if (pca.tty == NULL) { 151 retval = 0; 152 goto out; 153 } 154 pca.flags = TOTTY; 155 va_start(ap, fmt); 156 retval = kvprintf(fmt, putchar, &pca, 10, ap); 157 va_end(ap); 158 out: 159 mtx_unlock(&Giant); 160 return (retval); 161 } 162 163 /* 164 * tprintf prints on the controlling terminal associated with the given 165 * session, possibly to the log as well. 166 */ 167 void 168 tprintf(struct proc *p, int pri, const char *fmt, ...) 169 { 170 struct tty *tp = NULL; 171 int flags = 0; 172 va_list ap; 173 struct putchar_arg pca; 174 struct session *sess = NULL; 175 176 mtx_lock(&Giant); 177 if (pri != -1) 178 flags |= TOLOG; 179 if (p != NULL) { 180 PROC_LOCK(p); 181 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 182 sess = p->p_session; 183 SESS_LOCK(sess); 184 PROC_UNLOCK(p); 185 SESSHOLD(sess); 186 tp = sess->s_ttyp; 187 SESS_UNLOCK(sess); 188 if (ttycheckoutq(tp, 0)) 189 flags |= TOTTY; 190 else 191 tp = NULL; 192 } else 193 PROC_UNLOCK(p); 194 } 195 pca.pri = pri; 196 pca.tty = tp; 197 pca.flags = flags; 198 va_start(ap, fmt); 199 kvprintf(fmt, putchar, &pca, 10, ap); 200 va_end(ap); 201 if (sess != NULL) 202 SESSRELE(sess); 203 msgbuftrigger = 1; 204 mtx_unlock(&Giant); 205 } 206 207 /* 208 * Ttyprintf displays a message on a tty; it should be used only by 209 * the tty driver, or anything that knows the underlying tty will not 210 * be revoke(2)'d away. Other callers should use tprintf. 211 */ 212 int 213 ttyprintf(struct tty *tp, const char *fmt, ...) 214 { 215 va_list ap; 216 struct putchar_arg pca; 217 int retval; 218 219 va_start(ap, fmt); 220 pca.tty = tp; 221 pca.flags = TOTTY; 222 retval = kvprintf(fmt, putchar, &pca, 10, ap); 223 va_end(ap); 224 return (retval); 225 } 226 227 /* 228 * Log writes to the log buffer, and guarantees not to sleep (so can be 229 * called by interrupt routines). If there is no process reading the 230 * log yet, it writes to the console also. 231 */ 232 void 233 log(int level, const char *fmt, ...) 234 { 235 va_list ap; 236 struct putchar_arg pca; 237 238 pca.tty = NULL; 239 pca.pri = level; 240 pca.flags = log_open ? TOLOG : TOCONS; 241 pca.p_bufr = NULL; 242 243 va_start(ap, fmt); 244 kvprintf(fmt, putchar, &pca, 10, ap); 245 va_end(ap); 246 247 msgbuftrigger = 1; 248 } 249 250 #define CONSCHUNK 128 251 252 void 253 log_console(struct uio *uio) 254 { 255 int c, i, error, nl; 256 char *consbuffer; 257 int pri; 258 259 if (!log_console_output) 260 return; 261 262 pri = LOG_INFO | LOG_CONSOLE; 263 uio = cloneuio(uio); 264 consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK); 265 266 nl = 0; 267 while (uio->uio_resid > 0) { 268 c = imin(uio->uio_resid, CONSCHUNK); 269 error = uiomove(consbuffer, c, uio); 270 if (error != 0) 271 break; 272 for (i = 0; i < c; i++) { 273 msglogchar(consbuffer[i], pri); 274 if (consbuffer[i] == '\n') 275 nl = 1; 276 else 277 nl = 0; 278 } 279 } 280 if (!nl) 281 msglogchar('\n', pri); 282 msgbuftrigger = 1; 283 free(uio, M_IOV); 284 free(consbuffer, M_TEMP); 285 return; 286 } 287 288 int 289 printf(const char *fmt, ...) 290 { 291 va_list ap; 292 struct putchar_arg pca; 293 int retval; 294 295 critical_enter(); 296 297 va_start(ap, fmt); 298 pca.tty = NULL; 299 pca.flags = TOCONS | TOLOG; 300 pca.pri = -1; 301 pca.p_bufr = (char *) PCPU_PTR(cons_bufr); 302 pca.p_next = pca.p_bufr; 303 pca.n_bufr = PCPU_CONS_BUFR; 304 pca.remain = PCPU_CONS_BUFR; 305 *pca.p_next = '\0'; 306 307 retval = kvprintf(fmt, putchar, &pca, 10, ap); 308 va_end(ap); 309 310 /* Write any buffered console output: */ 311 if (*pca.p_bufr != '\0') 312 cnputs(pca.p_bufr); 313 314 if (!panicstr) 315 msgbuftrigger = 1; 316 317 critical_exit(); 318 319 return (retval); 320 } 321 322 int 323 vprintf(const char *fmt, va_list ap) 324 { 325 struct putchar_arg pca; 326 int retval; 327 328 critical_enter(); 329 330 pca.tty = NULL; 331 pca.flags = TOCONS | TOLOG; 332 pca.pri = -1; 333 pca.p_bufr = (char *) PCPU_PTR(cons_bufr); 334 pca.p_next = pca.p_bufr; 335 pca.n_bufr = PCPU_CONS_BUFR; 336 pca.remain = PCPU_CONS_BUFR; 337 *pca.p_next = '\0'; 338 339 retval = kvprintf(fmt, putchar, &pca, 10, ap); 340 341 /* Write any buffered console output: */ 342 if (*pca.p_bufr != '\0') 343 cnputs(pca.p_bufr); 344 345 if (!panicstr) 346 msgbuftrigger = 1; 347 348 critical_exit(); 349 350 return (retval); 351 } 352 353 static void 354 putcons(int c, struct putchar_arg *ap) 355 { 356 /* Check if no console output buffer was provided. */ 357 if (ap->p_bufr == NULL) 358 /* Output direct to the console. */ 359 cnputc(c); 360 else { 361 /* Buffer the character: */ 362 if (c == '\n') { 363 *ap->p_next++ = '\r'; 364 ap->remain--; 365 } 366 *ap->p_next++ = c; 367 ap->remain--; 368 369 /* Always leave the buffer zero terminated. */ 370 *ap->p_next = '\0'; 371 372 /* Check if the buffer needs to be flushed. */ 373 if (ap->remain < 3 || c == '\n') { 374 cnputs(ap->p_bufr); 375 ap->p_next = ap->p_bufr; 376 ap->remain = ap->n_bufr; 377 *ap->p_next = '\0'; 378 } 379 } 380 } 381 382 /* 383 * Print a character on console or users terminal. If destination is 384 * the console then the last bunch of characters are saved in msgbuf for 385 * inspection later. 386 */ 387 static void 388 putchar(int c, void *arg) 389 { 390 struct putchar_arg *ap = (struct putchar_arg*) arg; 391 struct tty *tp = ap->tty; 392 int flags = ap->flags; 393 394 /* Don't use the tty code after a panic or while in ddb. */ 395 if (kdb_active) { 396 if (c != '\0') 397 cnputc(c); 398 } else if (panicstr || ((flags & TOCONS) && constty == NULL)) { 399 if (c != '\0') 400 putcons(c, ap); 401 } else { 402 if ((flags & TOTTY) && tp != NULL) 403 tputchar(c, tp); 404 if (flags & TOCONS) { 405 if (constty != NULL) 406 msgbuf_addchar(&consmsgbuf, c); 407 if (always_console_output && c != '\0') 408 putcons(c, ap); 409 } 410 } 411 if ((flags & TOLOG)) 412 msglogchar(c, ap->pri); 413 } 414 415 /* 416 * Scaled down version of sprintf(3). 417 */ 418 int 419 sprintf(char *buf, const char *cfmt, ...) 420 { 421 int retval; 422 va_list ap; 423 424 va_start(ap, cfmt); 425 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 426 buf[retval] = '\0'; 427 va_end(ap); 428 return (retval); 429 } 430 431 /* 432 * Scaled down version of vsprintf(3). 433 */ 434 int 435 vsprintf(char *buf, const char *cfmt, va_list ap) 436 { 437 int retval; 438 439 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 440 buf[retval] = '\0'; 441 return (retval); 442 } 443 444 /* 445 * Scaled down version of snprintf(3). 446 */ 447 int 448 snprintf(char *str, size_t size, const char *format, ...) 449 { 450 int retval; 451 va_list ap; 452 453 va_start(ap, format); 454 retval = vsnprintf(str, size, format, ap); 455 va_end(ap); 456 return(retval); 457 } 458 459 /* 460 * Scaled down version of vsnprintf(3). 461 */ 462 int 463 vsnprintf(char *str, size_t size, const char *format, va_list ap) 464 { 465 struct snprintf_arg info; 466 int retval; 467 468 info.str = str; 469 info.remain = size; 470 retval = kvprintf(format, snprintf_func, &info, 10, ap); 471 if (info.remain >= 1) 472 *info.str++ = '\0'; 473 return (retval); 474 } 475 476 /* 477 * Kernel version which takes radix argument vsnprintf(3). 478 */ 479 int 480 vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap) 481 { 482 struct snprintf_arg info; 483 int retval; 484 485 info.str = str; 486 info.remain = size; 487 retval = kvprintf(format, snprintf_func, &info, radix, ap); 488 if (info.remain >= 1) 489 *info.str++ = '\0'; 490 return (retval); 491 } 492 493 static void 494 snprintf_func(int ch, void *arg) 495 { 496 struct snprintf_arg *const info = arg; 497 498 if (info->remain >= 2) { 499 *info->str++ = ch; 500 info->remain--; 501 } 502 } 503 504 /* 505 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 506 * order; return an optional length and a pointer to the last character 507 * written in the buffer (i.e., the first character of the string). 508 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 509 */ 510 static char * 511 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 512 { 513 char *p, c; 514 515 p = nbuf; 516 *p = '\0'; 517 do { 518 c = hex2ascii(num % base); 519 *++p = upper ? toupper(c) : c; 520 } while (num /= base); 521 if (lenp) 522 *lenp = p - nbuf; 523 return (p); 524 } 525 526 /* 527 * Scaled down version of printf(3). 528 * 529 * Two additional formats: 530 * 531 * The format %b is supported to decode error registers. 532 * Its usage is: 533 * 534 * printf("reg=%b\n", regval, "<base><arg>*"); 535 * 536 * where <base> is the output base expressed as a control character, e.g. 537 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 538 * the first of which gives the bit number to be inspected (origin 1), and 539 * the next characters (up to a control character, i.e. a character <= 32), 540 * give the name of the register. Thus: 541 * 542 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 543 * 544 * would produce output: 545 * 546 * reg=3<BITTWO,BITONE> 547 * 548 * XXX: %D -- Hexdump, takes pointer and separator string: 549 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 550 * ("%*D", len, ptr, " " -> XX XX XX XX ... 551 */ 552 int 553 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 554 { 555 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 556 char nbuf[MAXNBUF]; 557 char *d; 558 const char *p, *percent, *q; 559 u_char *up; 560 int ch, n; 561 uintmax_t num; 562 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 563 int cflag, hflag, jflag, tflag, zflag; 564 int dwidth, upper; 565 char padc; 566 int stop = 0, retval = 0; 567 568 num = 0; 569 if (!func) 570 d = (char *) arg; 571 else 572 d = NULL; 573 574 if (fmt == NULL) 575 fmt = "(fmt null)\n"; 576 577 if (radix < 2 || radix > 36) 578 radix = 10; 579 580 for (;;) { 581 padc = ' '; 582 width = 0; 583 while ((ch = (u_char)*fmt++) != '%' || stop) { 584 if (ch == '\0') 585 return (retval); 586 PCHAR(ch); 587 } 588 percent = fmt - 1; 589 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 590 sign = 0; dot = 0; dwidth = 0; upper = 0; 591 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 592 reswitch: switch (ch = (u_char)*fmt++) { 593 case '.': 594 dot = 1; 595 goto reswitch; 596 case '#': 597 sharpflag = 1; 598 goto reswitch; 599 case '+': 600 sign = 1; 601 goto reswitch; 602 case '-': 603 ladjust = 1; 604 goto reswitch; 605 case '%': 606 PCHAR(ch); 607 break; 608 case '*': 609 if (!dot) { 610 width = va_arg(ap, int); 611 if (width < 0) { 612 ladjust = !ladjust; 613 width = -width; 614 } 615 } else { 616 dwidth = va_arg(ap, int); 617 } 618 goto reswitch; 619 case '0': 620 if (!dot) { 621 padc = '0'; 622 goto reswitch; 623 } 624 case '1': case '2': case '3': case '4': 625 case '5': case '6': case '7': case '8': case '9': 626 for (n = 0;; ++fmt) { 627 n = n * 10 + ch - '0'; 628 ch = *fmt; 629 if (ch < '0' || ch > '9') 630 break; 631 } 632 if (dot) 633 dwidth = n; 634 else 635 width = n; 636 goto reswitch; 637 case 'b': 638 num = (u_int)va_arg(ap, int); 639 p = va_arg(ap, char *); 640 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 641 PCHAR(*q--); 642 643 if (num == 0) 644 break; 645 646 for (tmp = 0; *p;) { 647 n = *p++; 648 if (num & (1 << (n - 1))) { 649 PCHAR(tmp ? ',' : '<'); 650 for (; (n = *p) > ' '; ++p) 651 PCHAR(n); 652 tmp = 1; 653 } else 654 for (; *p > ' '; ++p) 655 continue; 656 } 657 if (tmp) 658 PCHAR('>'); 659 break; 660 case 'c': 661 PCHAR(va_arg(ap, int)); 662 break; 663 case 'D': 664 up = va_arg(ap, u_char *); 665 p = va_arg(ap, char *); 666 if (!width) 667 width = 16; 668 while(width--) { 669 PCHAR(hex2ascii(*up >> 4)); 670 PCHAR(hex2ascii(*up & 0x0f)); 671 up++; 672 if (width) 673 for (q=p;*q;q++) 674 PCHAR(*q); 675 } 676 break; 677 case 'd': 678 case 'i': 679 base = 10; 680 sign = 1; 681 goto handle_sign; 682 case 'h': 683 if (hflag) { 684 hflag = 0; 685 cflag = 1; 686 } else 687 hflag = 1; 688 goto reswitch; 689 case 'j': 690 jflag = 1; 691 goto reswitch; 692 case 'l': 693 if (lflag) { 694 lflag = 0; 695 qflag = 1; 696 } else 697 lflag = 1; 698 goto reswitch; 699 case 'n': 700 if (jflag) 701 *(va_arg(ap, intmax_t *)) = retval; 702 else if (qflag) 703 *(va_arg(ap, quad_t *)) = retval; 704 else if (lflag) 705 *(va_arg(ap, long *)) = retval; 706 else if (zflag) 707 *(va_arg(ap, size_t *)) = retval; 708 else if (hflag) 709 *(va_arg(ap, short *)) = retval; 710 else if (cflag) 711 *(va_arg(ap, char *)) = retval; 712 else 713 *(va_arg(ap, int *)) = retval; 714 break; 715 case 'o': 716 base = 8; 717 goto handle_nosign; 718 case 'p': 719 base = 16; 720 sharpflag = (width == 0); 721 sign = 0; 722 num = (uintptr_t)va_arg(ap, void *); 723 goto number; 724 case 'q': 725 qflag = 1; 726 goto reswitch; 727 case 'r': 728 base = radix; 729 if (sign) 730 goto handle_sign; 731 goto handle_nosign; 732 case 's': 733 p = va_arg(ap, char *); 734 if (p == NULL) 735 p = "(null)"; 736 if (!dot) 737 n = strlen (p); 738 else 739 for (n = 0; n < dwidth && p[n]; n++) 740 continue; 741 742 width -= n; 743 744 if (!ladjust && width > 0) 745 while (width--) 746 PCHAR(padc); 747 while (n--) 748 PCHAR(*p++); 749 if (ladjust && width > 0) 750 while (width--) 751 PCHAR(padc); 752 break; 753 case 't': 754 tflag = 1; 755 goto reswitch; 756 case 'u': 757 base = 10; 758 goto handle_nosign; 759 case 'X': 760 upper = 1; 761 case 'x': 762 base = 16; 763 goto handle_nosign; 764 case 'y': 765 base = 16; 766 sign = 1; 767 goto handle_sign; 768 case 'z': 769 zflag = 1; 770 goto reswitch; 771 handle_nosign: 772 sign = 0; 773 if (jflag) 774 num = va_arg(ap, uintmax_t); 775 else if (qflag) 776 num = va_arg(ap, u_quad_t); 777 else if (tflag) 778 num = va_arg(ap, ptrdiff_t); 779 else if (lflag) 780 num = va_arg(ap, u_long); 781 else if (zflag) 782 num = va_arg(ap, size_t); 783 else if (hflag) 784 num = (u_short)va_arg(ap, int); 785 else if (cflag) 786 num = (u_char)va_arg(ap, int); 787 else 788 num = va_arg(ap, u_int); 789 goto number; 790 handle_sign: 791 if (jflag) 792 num = va_arg(ap, intmax_t); 793 else if (qflag) 794 num = va_arg(ap, quad_t); 795 else if (tflag) 796 num = va_arg(ap, ptrdiff_t); 797 else if (lflag) 798 num = va_arg(ap, long); 799 else if (zflag) 800 num = va_arg(ap, size_t); 801 else if (hflag) 802 num = (short)va_arg(ap, int); 803 else if (cflag) 804 num = (char)va_arg(ap, int); 805 else 806 num = va_arg(ap, int); 807 number: 808 if (sign && (intmax_t)num < 0) { 809 neg = 1; 810 num = -(intmax_t)num; 811 } 812 p = ksprintn(nbuf, num, base, &tmp, upper); 813 if (sharpflag && num != 0) { 814 if (base == 8) 815 tmp++; 816 else if (base == 16) 817 tmp += 2; 818 } 819 if (neg) 820 tmp++; 821 822 if (!ladjust && padc != '0' && width 823 && (width -= tmp) > 0) 824 while (width--) 825 PCHAR(padc); 826 if (neg) 827 PCHAR('-'); 828 if (sharpflag && num != 0) { 829 if (base == 8) { 830 PCHAR('0'); 831 } else if (base == 16) { 832 PCHAR('0'); 833 PCHAR('x'); 834 } 835 } 836 if (!ladjust && width && (width -= tmp) > 0) 837 while (width--) 838 PCHAR(padc); 839 840 while (*p) 841 PCHAR(*p--); 842 843 if (ladjust && width && (width -= tmp) > 0) 844 while (width--) 845 PCHAR(padc); 846 847 break; 848 default: 849 while (percent < fmt) 850 PCHAR(*percent++); 851 /* 852 * Since we ignore an formatting argument it is no 853 * longer safe to obey the remaining formatting 854 * arguments as the arguments will no longer match 855 * the format specs. 856 */ 857 stop = 1; 858 break; 859 } 860 } 861 #undef PCHAR 862 } 863 864 /* 865 * Put character in log buffer with a particular priority. 866 */ 867 static void 868 msglogchar(int c, int pri) 869 { 870 static int lastpri = -1; 871 static int dangling; 872 char nbuf[MAXNBUF]; 873 char *p; 874 875 if (!msgbufmapped) 876 return; 877 if (c == '\0' || c == '\r') 878 return; 879 if (pri != -1 && pri != lastpri) { 880 if (dangling) { 881 msgbuf_addchar(msgbufp, '\n'); 882 dangling = 0; 883 } 884 msgbuf_addchar(msgbufp, '<'); 885 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;) 886 msgbuf_addchar(msgbufp, *p--); 887 msgbuf_addchar(msgbufp, '>'); 888 lastpri = pri; 889 } 890 msgbuf_addchar(msgbufp, c); 891 if (c == '\n') { 892 dangling = 0; 893 lastpri = -1; 894 } else { 895 dangling = 1; 896 } 897 } 898 899 void 900 msgbufinit(void *ptr, int size) 901 { 902 char *cp; 903 static struct msgbuf *oldp = NULL; 904 905 size -= sizeof(*msgbufp); 906 cp = (char *)ptr; 907 msgbufp = (struct msgbuf *)(cp + size); 908 msgbuf_reinit(msgbufp, cp, size); 909 if (msgbufmapped && oldp != msgbufp) 910 msgbuf_copy(oldp, msgbufp); 911 msgbufmapped = 1; 912 oldp = msgbufp; 913 } 914 915 static int unprivileged_read_msgbuf = 1; 916 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf, 917 CTLFLAG_RW, &unprivileged_read_msgbuf, 0, 918 "Unprivileged processes may read the kernel message buffer"); 919 920 /* Sysctls for accessing/clearing the msgbuf */ 921 static int 922 sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 923 { 924 char buf[128]; 925 u_int seq; 926 int error, len; 927 928 if (!unprivileged_read_msgbuf) { 929 error = priv_check(req->td, PRIV_MSGBUF); 930 if (error) 931 return (error); 932 } 933 934 /* Read the whole buffer, one chunk at a time. */ 935 msgbuf_peekbytes(msgbufp, NULL, 0, &seq); 936 while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) { 937 error = sysctl_handle_opaque(oidp, buf, len, req); 938 if (error) 939 return (error); 940 } 941 return (0); 942 } 943 944 SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD, 945 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 946 947 static int msgbuf_clearflag; 948 949 static int 950 sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 951 { 952 int error; 953 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 954 if (!error && req->newptr) { 955 msgbuf_clear(msgbufp); 956 msgbuf_clearflag = 0; 957 } 958 return (error); 959 } 960 961 SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 962 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0, 963 sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer"); 964 965 #ifdef DDB 966 967 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 968 { 969 int i, j; 970 971 if (!msgbufmapped) { 972 db_printf("msgbuf not mapped yet\n"); 973 return; 974 } 975 db_printf("msgbufp = %p\n", msgbufp); 976 db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n", 977 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq, 978 msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum); 979 for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) { 980 j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq); 981 db_printf("%c", msgbufp->msg_ptr[j]); 982 } 983 db_printf("\n"); 984 } 985 986 #endif /* DDB */ 987 988 void 989 hexdump(const void *ptr, int length, const char *hdr, int flags) 990 { 991 int i, j, k; 992 int cols; 993 const unsigned char *cp; 994 char delim; 995 996 if ((flags & HD_DELIM_MASK) != 0) 997 delim = (flags & HD_DELIM_MASK) >> 8; 998 else 999 delim = ' '; 1000 1001 if ((flags & HD_COLUMN_MASK) != 0) 1002 cols = flags & HD_COLUMN_MASK; 1003 else 1004 cols = 16; 1005 1006 cp = ptr; 1007 for (i = 0; i < length; i+= cols) { 1008 if (hdr != NULL) 1009 printf("%s", hdr); 1010 1011 if ((flags & HD_OMIT_COUNT) == 0) 1012 printf("%04x ", i); 1013 1014 if ((flags & HD_OMIT_HEX) == 0) { 1015 for (j = 0; j < cols; j++) { 1016 k = i + j; 1017 if (k < length) 1018 printf("%c%02x", delim, cp[k]); 1019 else 1020 printf(" "); 1021 } 1022 } 1023 1024 if ((flags & HD_OMIT_CHARS) == 0) { 1025 printf(" |"); 1026 for (j = 0; j < cols; j++) { 1027 k = i + j; 1028 if (k >= length) 1029 printf(" "); 1030 else if (cp[k] >= ' ' && cp[k] <= '~') 1031 printf("%c", cp[k]); 1032 else 1033 printf("."); 1034 } 1035 printf("|"); 1036 } 1037 printf("\n"); 1038 } 1039 } 1040 1041