hexdump.c revision 147064
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 147064 2005-06-06 22:18:32Z dwhite $"); 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 * It may block if the tty queue is overfull. No message is printed if 121 * the queue does not clear in a reasonable time. 122 */ 123int 124uprintf(const char *fmt, ...) 125{ 126 struct thread *td = curthread; 127 struct proc *p = td->td_proc; 128 va_list ap; 129 struct putchar_arg pca; 130 int retval; 131 132 if (td == NULL || td == PCPU_GET(idlethread)) 133 return (0); 134 135 p = td->td_proc; 136 PROC_LOCK(p); 137 if ((p->p_flag & P_CONTROLT) == 0) { 138 PROC_UNLOCK(p); 139 return (0); 140 } 141 SESS_LOCK(p->p_session); 142 pca.tty = p->p_session->s_ttyp; 143 SESS_UNLOCK(p->p_session); 144 PROC_UNLOCK(p); 145 if (pca.tty == NULL) 146 return (0); 147 pca.flags = TOTTY; 148 va_start(ap, fmt); 149 retval = kvprintf(fmt, putchar, &pca, 10, ap); 150 va_end(ap); 151 152 return (retval); 153} 154 155/* 156 * tprintf prints on the controlling terminal associated 157 * with the given session, possibly to the log as well. 158 */ 159void 160tprintf(struct proc *p, int pri, const char *fmt, ...) 161{ 162 struct tty *tp = NULL; 163 int flags = 0; 164 va_list ap; 165 struct putchar_arg pca; 166 struct session *sess = NULL; 167 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 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++) != '%') { 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 && width && (width -= tmp) > 0) 759 while (width--) 760 PCHAR(padc); 761 if (neg) 762 PCHAR('-'); 763 if (sharpflag && num != 0) { 764 if (base == 8) { 765 PCHAR('0'); 766 } else if (base == 16) { 767 PCHAR('0'); 768 PCHAR('x'); 769 } 770 } 771 772 while (*p) 773 PCHAR(*p--); 774 775 if (ladjust && width && (width -= tmp) > 0) 776 while (width--) 777 PCHAR(padc); 778 779 break; 780 default: 781 while (percent < fmt) 782 PCHAR(*percent++); 783 break; 784 } 785 } 786#undef PCHAR 787} 788 789/* 790 * Put character in log buffer with a particular priority. 791 */ 792static void 793msglogchar(int c, int pri) 794{ 795 static int lastpri = -1; 796 static int dangling; 797 char nbuf[MAXNBUF]; 798 char *p; 799 800 if (!msgbufmapped) 801 return; 802 if (c == '\0' || c == '\r') 803 return; 804 if (pri != -1 && pri != lastpri) { 805 if (dangling) { 806 msgbuf_addchar(msgbufp, '\n'); 807 dangling = 0; 808 } 809 msgbuf_addchar(msgbufp, '<'); 810 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL); *p;) 811 msgbuf_addchar(msgbufp, *p--); 812 msgbuf_addchar(msgbufp, '>'); 813 lastpri = pri; 814 } 815 msgbuf_addchar(msgbufp, c); 816 if (c == '\n') { 817 dangling = 0; 818 lastpri = -1; 819 } else { 820 dangling = 1; 821 } 822} 823 824void 825msgbufinit(void *ptr, int size) 826{ 827 char *cp; 828 static struct msgbuf *oldp = NULL; 829 830 size -= sizeof(*msgbufp); 831 cp = (char *)ptr; 832 msgbufp = (struct msgbuf *)(cp + size); 833 msgbuf_reinit(msgbufp, cp, size); 834 if (msgbufmapped && oldp != msgbufp) 835 msgbuf_copy(oldp, msgbufp); 836 msgbufmapped = 1; 837 oldp = msgbufp; 838} 839 840SYSCTL_DECL(_security_bsd); 841 842static int unprivileged_read_msgbuf = 1; 843SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf, 844 CTLFLAG_RW, &unprivileged_read_msgbuf, 0, 845 "Unprivileged processes may read the kernel message buffer"); 846 847/* Sysctls for accessing/clearing the msgbuf */ 848static int 849sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 850{ 851 char buf[128]; 852 u_int seq; 853 int error, len; 854 855 if (!unprivileged_read_msgbuf) { 856 error = suser(req->td); 857 if (error) 858 return (error); 859 } 860 861 /* Read the whole buffer, one chunk at a time. */ 862 msgbuf_peekbytes(msgbufp, NULL, 0, &seq); 863 while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) { 864 error = sysctl_handle_opaque(oidp, buf, len, req); 865 if (error) 866 return (error); 867 } 868 return (0); 869} 870 871SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD, 872 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 873 874static int msgbuf_clearflag; 875 876static int 877sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 878{ 879 int error; 880 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 881 if (!error && req->newptr) { 882 msgbuf_clear(msgbufp); 883 msgbuf_clearflag = 0; 884 } 885 return (error); 886} 887 888SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 889 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0, 890 sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer"); 891 892#ifdef DDB 893 894DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 895{ 896 int i, j, quit; 897 898 quit = 0; 899 900 if (!msgbufmapped) { 901 db_printf("msgbuf not mapped yet\n"); 902 return; 903 } 904 db_setup_paging(db_simple_pager, &quit, db_lines_per_page); 905 db_printf("msgbufp = %p\n", msgbufp); 906 db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n", 907 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq, 908 msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum); 909 for (i = 0; i < msgbufp->msg_size && !quit; i++) { 910 j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq); 911 db_printf("%c", msgbufp->msg_ptr[j]); 912 } 913 db_printf("\n"); 914} 915 916#endif /* DDB */ 917 918void 919hexdump(const void *ptr, int length, const char *hdr, int flags) 920{ 921 int i, j, k; 922 int cols; 923 const unsigned char *cp; 924 char delim; 925 926 if ((flags & HD_DELIM_MASK) != 0) 927 delim = (flags & HD_DELIM_MASK) >> 8; 928 else 929 delim = ' '; 930 931 if ((flags & HD_COLUMN_MASK) != 0) 932 cols = flags & HD_COLUMN_MASK; 933 else 934 cols = 16; 935 936 cp = ptr; 937 for (i = 0; i < length; i+= cols) { 938 if (hdr != NULL) 939 printf("%s", hdr); 940 941 if ((flags & HD_OMIT_COUNT) == 0) 942 printf("%04x ", i); 943 944 if ((flags & HD_OMIT_HEX) == 0) { 945 for (j = 0; j < cols; j++) { 946 k = i + j; 947 if (k < length) 948 printf("%c%02x", delim, cp[k]); 949 else 950 printf(" "); 951 } 952 } 953 954 if ((flags & HD_OMIT_CHARS) == 0) { 955 printf(" |"); 956 for (j = 0; j < cols; j++) { 957 k = i + j; 958 if (k >= length) 959 printf(" "); 960 else if (cp[k] >= ' ' && cp[k] <= '~') 961 printf("%c", cp[k]); 962 else 963 printf("."); 964 } 965 printf("|\n"); 966 } 967 } 968} 969 970