hexdump.c revision 65557
1109998Smarkm/*- 2280304Sjkim * Copyright (c) 1986, 1988, 1991, 1993 3280304Sjkim * The Regents of the University of California. All rights reserved. 4280304Sjkim * (c) UNIX System Laboratories, Inc. 5109998Smarkm * All or some portions of this file are derived from material licensed 6109998Smarkm * to the University of California by American Telephone and Telegraph 7109998Smarkm * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8109998Smarkm * the permission of UNIX System Laboratories, Inc. 9109998Smarkm * 10109998Smarkm * Redistribution and use in source and binary forms, with or without 11109998Smarkm * modification, are permitted provided that the following conditions 12109998Smarkm * are met: 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14280304Sjkim * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 16109998Smarkm * notice, this list of conditions and the following disclaimer in the 17109998Smarkm * documentation and/or other materials provided with the distribution. 18109998Smarkm * 3. All advertising materials mentioning features or use of this software 19109998Smarkm * must display the following acknowledgement: 20109998Smarkm * This product includes software developed by the University of 21109998Smarkm * California, Berkeley and its contributors. 22109998Smarkm * 4. Neither the name of the University nor the names of its contributors 23109998Smarkm * may be used to endorse or promote products derived from this software 24109998Smarkm * without specific prior written permission. 25109998Smarkm * 26109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27109998Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29109998Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30109998Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31109998Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32109998Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34109998Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35109998Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36109998Smarkm * SUCH DAMAGE. 37109998Smarkm * 38109998Smarkm * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 39109998Smarkm * $FreeBSD: head/sys/kern/subr_prf.c 65557 2000-09-07 01:33:02Z jasone $ 40109998Smarkm */ 41109998Smarkm 42109998Smarkm#include <sys/param.h> 43109998Smarkm#include <sys/systm.h> 44109998Smarkm#include <sys/kernel.h> 45109998Smarkm#include <sys/msgbuf.h> 46109998Smarkm#include <sys/malloc.h> 47109998Smarkm#include <sys/proc.h> 48109998Smarkm#include <sys/tty.h> 49109998Smarkm#include <sys/tprintf.h> 50109998Smarkm#include <sys/syslog.h> 51109998Smarkm#include <sys/cons.h> 52109998Smarkm 53109998Smarkm/* 54109998Smarkm * Note that stdarg.h and the ANSI style va_start macro is used for both 55109998Smarkm * ANSI and traditional C compilers. 56109998Smarkm */ 57109998Smarkm#include <machine/stdarg.h> 58109998Smarkm 59109998Smarkm#define TOCONS 0x01 60109998Smarkm#define TOTTY 0x02 61109998Smarkm#define TOLOG 0x04 62109998Smarkm 63109998Smarkm/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 64109998Smarkm#define MAXNBUF (sizeof(quad_t) * NBBY + 1) 65109998Smarkm 66109998Smarkmstruct putchar_arg { 67109998Smarkm int flags; 68280304Sjkim struct tty *tty; 69280304Sjkim}; 70280304Sjkim 71280304Sjkimstruct snprintf_arg { 72280304Sjkim char *str; 73280304Sjkim size_t remain; 74280304Sjkim}; 75280304Sjkim 76280304Sjkimstruct tty *constty; /* pointer to console "window" tty */ 77109998Smarkm 78109998Smarkmstatic void (*v_putc)(int) = cnputc; /* routine to putc on virtual console */ 79280304Sjkimstatic void logpri __P((int level)); 80280304Sjkimstatic void msglogchar(int c, void *dummyarg); 81280304Sjkimstatic void putchar __P((int ch, void *arg)); 82280304Sjkimstatic char *ksprintn __P((char *nbuf, u_long num, int base, int *len)); 83280304Sjkimstatic char *ksprintqn __P((char *nbuf, u_quad_t num, int base, int *len)); 84109998Smarkmstatic void snprintf_func __P((int ch, void *arg)); 85238405Sjkim 86280304Sjkimstatic int consintr = 1; /* Ok to handle console interrupts? */ 87280304Sjkimstatic int msgbufmapped; /* Set when safe to use msgbuf */ 88109998Smarkm 89280304Sjkim/* 90280304Sjkim * Warn that a system table is full. 91280304Sjkim */ 92280304Sjkimvoid 93280304Sjkimtablefull(tab) 94280304Sjkim const char *tab; 95280304Sjkim{ 96280304Sjkim 97280304Sjkim log(LOG_ERR, "%s: table is full\n", tab); 98280304Sjkim} 99280304Sjkim 100280304Sjkim/* 101109998Smarkm * Uprintf prints to the controlling terminal for the current process. 102238405Sjkim * It may block if the tty queue is overfull. No message is printed if 103280304Sjkim * the queue does not clear in a reasonable time. 104280304Sjkim */ 105109998Smarkmint 106280304Sjkimuprintf(const char *fmt, ...) 107280304Sjkim{ 108280304Sjkim struct proc *p = curproc; 109280304Sjkim va_list ap; 110280304Sjkim struct putchar_arg pca; 111280304Sjkim int retval = 0; 112280304Sjkim 113280304Sjkim if (p && p != idleproc && p->p_flag & P_CONTROLT && 114280304Sjkim p->p_session->s_ttyvp) { 115280304Sjkim va_start(ap, fmt); 116280304Sjkim pca.tty = p->p_session->s_ttyp; 117280304Sjkim pca.flags = TOTTY; 118109998Smarkm retval = kvprintf(fmt, putchar, &pca, 10, ap); 119109998Smarkm va_end(ap); 120280304Sjkim } 121280304Sjkim return retval; 122280304Sjkim} 123280304Sjkim 124280304Sjkimtpr_t 125280304Sjkimtprintf_open(p) 126280304Sjkim register struct proc *p; 127280304Sjkim{ 128280304Sjkim 129280304Sjkim if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 130280304Sjkim SESSHOLD(p->p_session); 131280304Sjkim return ((tpr_t) p->p_session); 132280304Sjkim } 133280304Sjkim return ((tpr_t) NULL); 134109998Smarkm} 135109998Smarkm 136280304Sjkimvoid 137280304Sjkimtprintf_close(sess) 138109998Smarkm tpr_t sess; 139280304Sjkim{ 140280304Sjkim 141280304Sjkim if (sess) 142280304Sjkim SESSRELE((struct session *) sess); 143280304Sjkim} 144280304Sjkim 145280304Sjkim/* 146280304Sjkim * tprintf prints on the controlling terminal associated 147280304Sjkim * with the given session. 148280304Sjkim */ 149280304Sjkimint 150280304Sjkimtprintf(tpr_t tpr, const char *fmt, ...) 151109998Smarkm{ 152109998Smarkm register struct session *sess = (struct session *)tpr; 153280304Sjkim struct tty *tp = NULL; 154280304Sjkim int flags = TOLOG; 155109998Smarkm va_list ap; 156280304Sjkim struct putchar_arg pca; 157280304Sjkim int retval; 158280304Sjkim 159280304Sjkim logpri(LOG_INFO); 160280304Sjkim if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 161280304Sjkim flags |= TOTTY; 162280304Sjkim tp = sess->s_ttyp; 163280304Sjkim } 164280304Sjkim va_start(ap, fmt); 165280304Sjkim pca.tty = tp; 166280304Sjkim pca.flags = flags; 167280304Sjkim retval = kvprintf(fmt, putchar, &pca, 10, ap); 168 va_end(ap); 169 logwakeup(); 170 return retval; 171} 172 173/* 174 * Ttyprintf displays a message on a tty; it should be used only by 175 * the tty driver, or anything that knows the underlying tty will not 176 * be revoke(2)'d away. Other callers should use tprintf. 177 */ 178int 179ttyprintf(struct tty *tp, const char *fmt, ...) 180{ 181 va_list ap; 182 struct putchar_arg pca; 183 int retval; 184 185 va_start(ap, fmt); 186 pca.tty = tp; 187 pca.flags = TOTTY; 188 retval = kvprintf(fmt, putchar, &pca, 10, ap); 189 va_end(ap); 190 return retval; 191} 192 193extern int log_open; 194 195/* 196 * Log writes to the log buffer, and guarantees not to sleep (so can be 197 * called by interrupt routines). If there is no process reading the 198 * log yet, it writes to the console also. 199 */ 200int 201log(int level, const char *fmt, ...) 202{ 203 register int s; 204 va_list ap; 205 int retval; 206 207 s = splhigh(); 208 logpri(level); 209 va_start(ap, fmt); 210 211 retval = kvprintf(fmt, msglogchar, NULL, 10, ap); 212 va_end(ap); 213 214 splx(s); 215 if (!log_open) { 216 struct putchar_arg pca; 217 va_start(ap, fmt); 218 pca.tty = NULL; 219 pca.flags = TOCONS; 220 retval += kvprintf(fmt, putchar, &pca, 10, ap); 221 va_end(ap); 222 } 223 logwakeup(); 224 return retval; 225} 226 227static void 228logpri(level) 229 int level; 230{ 231 char nbuf[MAXNBUF]; 232 register char *p; 233 234 msglogchar('<', NULL); 235 for (p = ksprintn(nbuf, (u_long)level, 10, NULL); *p;) 236 msglogchar(*p--, NULL); 237 msglogchar('>', NULL); 238} 239 240int 241addlog(const char *fmt, ...) 242{ 243 register int s; 244 va_list ap; 245 int retval; 246 247 s = splhigh(); 248 va_start(ap, fmt); 249 retval = kvprintf(fmt, msglogchar, NULL, 10, ap); 250 splx(s); 251 va_end(ap); 252 if (!log_open) { 253 struct putchar_arg pca; 254 va_start(ap, fmt); 255 pca.tty = NULL; 256 pca.flags = TOCONS; 257 retval += kvprintf(fmt, putchar, &pca, 10, ap); 258 va_end(ap); 259 } 260 logwakeup(); 261 return (retval); 262} 263 264int 265printf(const char *fmt, ...) 266{ 267 va_list ap; 268 register int savintr; 269 struct putchar_arg pca; 270 int retval; 271 272 savintr = consintr; /* disable interrupts */ 273 consintr = 0; 274 va_start(ap, fmt); 275 pca.tty = NULL; 276 pca.flags = TOCONS | TOLOG; 277 retval = kvprintf(fmt, putchar, &pca, 10, ap); 278 va_end(ap); 279 if (!panicstr) 280 logwakeup(); 281 consintr = savintr; /* reenable interrupts */ 282 return retval; 283} 284 285int 286vprintf(const char *fmt, va_list ap) 287{ 288 register int savintr; 289 struct putchar_arg pca; 290 int retval; 291 292 savintr = consintr; /* disable interrupts */ 293 consintr = 0; 294 pca.tty = NULL; 295 pca.flags = TOCONS | TOLOG; 296 retval = kvprintf(fmt, putchar, &pca, 10, ap); 297 if (!panicstr) 298 logwakeup(); 299 consintr = savintr; /* reenable interrupts */ 300 return retval; 301} 302 303/* 304 * Print a character on console or users terminal. If destination is 305 * the console then the last bunch of characters are saved in msgbuf for 306 * inspection later. 307 */ 308static void 309putchar(int c, void *arg) 310{ 311 struct putchar_arg *ap = (struct putchar_arg*) arg; 312 int flags = ap->flags; 313 struct tty *tp = ap->tty; 314 if (panicstr) 315 constty = NULL; 316 if ((flags & TOCONS) && tp == NULL && constty) { 317 tp = constty; 318 flags |= TOTTY; 319 } 320 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 321 (flags & TOCONS) && tp == constty) 322 constty = NULL; 323 if ((flags & TOLOG)) 324 msglogchar(c, NULL); 325 if ((flags & TOCONS) && constty == NULL && c != '\0') 326 (*v_putc)(c); 327} 328 329/* 330 * Scaled down version of sprintf(3). 331 */ 332int 333sprintf(char *buf, const char *cfmt, ...) 334{ 335 int retval; 336 va_list ap; 337 338 va_start(ap, cfmt); 339 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 340 buf[retval] = '\0'; 341 va_end(ap); 342 return retval; 343} 344 345/* 346 * Scaled down version of vsprintf(3). 347 */ 348int 349vsprintf(char *buf, const char *cfmt, va_list ap) 350{ 351 int retval; 352 353 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 354 buf[retval] = '\0'; 355 return retval; 356} 357 358/* 359 * Scaled down version of snprintf(3). 360 */ 361int 362snprintf(char *str, size_t size, const char *format, ...) 363{ 364 int retval; 365 va_list ap; 366 367 va_start(ap, format); 368 retval = vsnprintf(str, size, format, ap); 369 va_end(ap); 370 return(retval); 371} 372 373/* 374 * Scaled down version of vsnprintf(3). 375 */ 376int 377vsnprintf(char *str, size_t size, const char *format, va_list ap) 378{ 379 struct snprintf_arg info; 380 int retval; 381 382 info.str = str; 383 info.remain = size; 384 retval = kvprintf(format, snprintf_func, &info, 10, ap); 385 if (info.remain >= 1) 386 *info.str++ = '\0'; 387 return retval; 388} 389 390static void 391snprintf_func(int ch, void *arg) 392{ 393 struct snprintf_arg *const info = arg; 394 395 if (info->remain >= 2) { 396 *info->str++ = ch; 397 info->remain--; 398 } 399} 400 401/* 402 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 403 * order; return an optional length and a pointer to the last character 404 * written in the buffer (i.e., the first character of the string). 405 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 406 */ 407static char * 408ksprintn(nbuf, ul, base, lenp) 409 char *nbuf; 410 register u_long ul; 411 register int base, *lenp; 412{ 413 register char *p; 414 415 p = nbuf; 416 *p = '\0'; 417 do { 418 *++p = hex2ascii(ul % base); 419 } while (ul /= base); 420 if (lenp) 421 *lenp = p - nbuf; 422 return (p); 423} 424/* ksprintn, but for a quad_t. */ 425static char * 426ksprintqn(nbuf, uq, base, lenp) 427 char *nbuf; 428 register u_quad_t uq; 429 register int base, *lenp; 430{ 431 register char *p; 432 433 p = nbuf; 434 *p = '\0'; 435 do { 436 *++p = hex2ascii(uq % base); 437 } while (uq /= base); 438 if (lenp) 439 *lenp = p - nbuf; 440 return (p); 441} 442 443/* 444 * Scaled down version of printf(3). 445 * 446 * Two additional formats: 447 * 448 * The format %b is supported to decode error registers. 449 * Its usage is: 450 * 451 * printf("reg=%b\n", regval, "<base><arg>*"); 452 * 453 * where <base> is the output base expressed as a control character, e.g. 454 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 455 * the first of which gives the bit number to be inspected (origin 1), and 456 * the next characters (up to a control character, i.e. a character <= 32), 457 * give the name of the register. Thus: 458 * 459 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 460 * 461 * would produce output: 462 * 463 * reg=3<BITTWO,BITONE> 464 * 465 * XXX: %D -- Hexdump, takes pointer and separator string: 466 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 467 * ("%*D", len, ptr, " " -> XX XX XX XX ... 468 */ 469int 470kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 471{ 472#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 473 char nbuf[MAXNBUF]; 474 char *p, *q, *d; 475 u_char *up; 476 int ch, n; 477 u_long ul; 478 u_quad_t uq; 479 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 480 int dwidth; 481 char padc; 482 int retval = 0; 483 484 ul = 0; 485 uq = 0; 486 if (!func) 487 d = (char *) arg; 488 else 489 d = NULL; 490 491 if (fmt == NULL) 492 fmt = "(fmt null)\n"; 493 494 if (radix < 2 || radix > 36) 495 radix = 10; 496 497 for (;;) { 498 padc = ' '; 499 width = 0; 500 while ((ch = (u_char)*fmt++) != '%') { 501 if (ch == '\0') 502 return retval; 503 PCHAR(ch); 504 } 505 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 506 sign = 0; dot = 0; dwidth = 0; 507reswitch: switch (ch = (u_char)*fmt++) { 508 case '.': 509 dot = 1; 510 goto reswitch; 511 case '#': 512 sharpflag = 1; 513 goto reswitch; 514 case '+': 515 sign = 1; 516 goto reswitch; 517 case '-': 518 ladjust = 1; 519 goto reswitch; 520 case '%': 521 PCHAR(ch); 522 break; 523 case '*': 524 if (!dot) { 525 width = va_arg(ap, int); 526 if (width < 0) { 527 ladjust = !ladjust; 528 width = -width; 529 } 530 } else { 531 dwidth = va_arg(ap, int); 532 } 533 goto reswitch; 534 case '0': 535 if (!dot) { 536 padc = '0'; 537 goto reswitch; 538 } 539 case '1': case '2': case '3': case '4': 540 case '5': case '6': case '7': case '8': case '9': 541 for (n = 0;; ++fmt) { 542 n = n * 10 + ch - '0'; 543 ch = *fmt; 544 if (ch < '0' || ch > '9') 545 break; 546 } 547 if (dot) 548 dwidth = n; 549 else 550 width = n; 551 goto reswitch; 552 case 'b': 553 ul = va_arg(ap, int); 554 p = va_arg(ap, char *); 555 for (q = ksprintn(nbuf, ul, *p++, NULL); *q;) 556 PCHAR(*q--); 557 558 if (!ul) 559 break; 560 561 for (tmp = 0; *p;) { 562 n = *p++; 563 if (ul & (1 << (n - 1))) { 564 PCHAR(tmp ? ',' : '<'); 565 for (; (n = *p) > ' '; ++p) 566 PCHAR(n); 567 tmp = 1; 568 } else 569 for (; *p > ' '; ++p) 570 continue; 571 } 572 if (tmp) 573 PCHAR('>'); 574 break; 575 case 'c': 576 PCHAR(va_arg(ap, int)); 577 break; 578 case 'D': 579 up = va_arg(ap, u_char *); 580 p = va_arg(ap, char *); 581 if (!width) 582 width = 16; 583 while(width--) { 584 PCHAR(hex2ascii(*up >> 4)); 585 PCHAR(hex2ascii(*up & 0x0f)); 586 up++; 587 if (width) 588 for (q=p;*q;q++) 589 PCHAR(*q); 590 } 591 break; 592 case 'd': 593 if (qflag) 594 uq = va_arg(ap, quad_t); 595 else if (lflag) 596 ul = va_arg(ap, long); 597 else 598 ul = va_arg(ap, int); 599 sign = 1; 600 base = 10; 601 goto number; 602 case 'l': 603 if (lflag) { 604 lflag = 0; 605 qflag = 1; 606 } else 607 lflag = 1; 608 goto reswitch; 609 case 'o': 610 if (qflag) 611 uq = va_arg(ap, u_quad_t); 612 else if (lflag) 613 ul = va_arg(ap, u_long); 614 else 615 ul = va_arg(ap, u_int); 616 base = 8; 617 goto nosign; 618 case 'p': 619 ul = (uintptr_t)va_arg(ap, void *); 620 base = 16; 621 sharpflag = (width == 0); 622 goto nosign; 623 case 'q': 624 qflag = 1; 625 goto reswitch; 626 case 'n': 627 case 'r': 628 if (qflag) 629 uq = va_arg(ap, u_quad_t); 630 else if (lflag) 631 ul = va_arg(ap, u_long); 632 else 633 ul = sign ? 634 (u_long)va_arg(ap, int) : va_arg(ap, u_int); 635 base = radix; 636 goto number; 637 case 's': 638 p = va_arg(ap, char *); 639 if (p == NULL) 640 p = "(null)"; 641 if (!dot) 642 n = strlen (p); 643 else 644 for (n = 0; n < dwidth && p[n]; n++) 645 continue; 646 647 width -= n; 648 649 if (!ladjust && width > 0) 650 while (width--) 651 PCHAR(padc); 652 while (n--) 653 PCHAR(*p++); 654 if (ladjust && width > 0) 655 while (width--) 656 PCHAR(padc); 657 break; 658 case 'u': 659 if (qflag) 660 uq = va_arg(ap, u_quad_t); 661 else if (lflag) 662 ul = va_arg(ap, u_long); 663 else 664 ul = va_arg(ap, u_int); 665 base = 10; 666 goto nosign; 667 case 'x': 668 if (qflag) 669 uq = va_arg(ap, u_quad_t); 670 else if (lflag) 671 ul = va_arg(ap, u_long); 672 else 673 ul = va_arg(ap, u_int); 674 base = 16; 675 goto nosign; 676 case 'z': 677 if (qflag) 678 uq = va_arg(ap, u_quad_t); 679 else if (lflag) 680 ul = va_arg(ap, u_long); 681 else 682 ul = sign ? 683 (u_long)va_arg(ap, int) : va_arg(ap, u_int); 684 base = 16; 685 goto number; 686nosign: sign = 0; 687number: 688 if (qflag) { 689 if (sign && (quad_t)uq < 0) { 690 neg = 1; 691 uq = -(quad_t)uq; 692 } 693 p = ksprintqn(nbuf, uq, base, &tmp); 694 } else { 695 if (sign && (long)ul < 0) { 696 neg = 1; 697 ul = -(long)ul; 698 } 699 p = ksprintn(nbuf, ul, base, &tmp); 700 } 701 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 702 if (base == 8) 703 tmp++; 704 else if (base == 16) 705 tmp += 2; 706 } 707 if (neg) 708 tmp++; 709 710 if (!ladjust && width && (width -= tmp) > 0) 711 while (width--) 712 PCHAR(padc); 713 if (neg) 714 PCHAR('-'); 715 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 716 if (base == 8) { 717 PCHAR('0'); 718 } else if (base == 16) { 719 PCHAR('0'); 720 PCHAR('x'); 721 } 722 } 723 724 while (*p) 725 PCHAR(*p--); 726 727 if (ladjust && width && (width -= tmp) > 0) 728 while (width--) 729 PCHAR(padc); 730 731 break; 732 default: 733 PCHAR('%'); 734 if (lflag) 735 PCHAR('l'); 736 PCHAR(ch); 737 break; 738 } 739 } 740#undef PCHAR 741} 742 743/* 744 * Put character in log buffer. 745 */ 746static void 747msglogchar(int c, void *dummyarg) 748{ 749 struct msgbuf *mbp; 750 751 if (c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 752 mbp = msgbufp; 753 mbp->msg_ptr[mbp->msg_bufx++] = c; 754 if (mbp->msg_bufx >= mbp->msg_size) 755 mbp->msg_bufx = 0; 756 /* If the buffer is full, keep the most recent data. */ 757 if (mbp->msg_bufr == mbp->msg_bufx) { 758 if (++mbp->msg_bufr >= mbp->msg_size) 759 mbp->msg_bufr = 0; 760 } 761 } 762} 763 764static void 765msgbufcopy(struct msgbuf *oldp) 766{ 767 int pos; 768 769 pos = oldp->msg_bufr; 770 while (pos != oldp->msg_bufx) { 771 msglogchar(oldp->msg_ptr[pos], NULL); 772 if (++pos >= oldp->msg_size) 773 pos = 0; 774 } 775} 776 777void 778msgbufinit(void *ptr, size_t size) 779{ 780 char *cp; 781 static struct msgbuf *oldp = NULL; 782 783 cp = (char *)ptr; 784 msgbufp = (struct msgbuf *) (cp + size - sizeof(*msgbufp)); 785 if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp) { 786 bzero(cp, size); 787 msgbufp->msg_magic = MSG_MAGIC; 788 msgbufp->msg_size = (char *)msgbufp - cp; 789 msgbufp->msg_ptr = cp; 790 } 791 if (msgbufmapped && oldp != msgbufp) 792 msgbufcopy(oldp); 793 msgbufmapped = 1; 794 oldp = msgbufp; 795} 796 797#include "opt_ddb.h" 798#ifdef DDB 799#include <ddb/ddb.h> 800 801DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 802{ 803 int i, j; 804 805 if (!msgbufmapped) { 806 db_printf("msgbuf not mapped yet\n"); 807 return; 808 } 809 db_printf("msgbufp = %p\n", msgbufp); 810 db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n", 811 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, 812 msgbufp->msg_bufx, msgbufp->msg_ptr); 813 for (i = 0; i < msgbufp->msg_size; i++) { 814 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; 815 db_printf("%c", msgbufp->msg_ptr[j]); 816 } 817 db_printf("\n"); 818} 819 820#endif /* DDB */ 821