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