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