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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 39 * $FreeBSD$ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/kernel.h> 45 #include <sys/msgbuf.h> 46 #include <sys/malloc.h> 47 #include <sys/proc.h> 48 #include <sys/tty.h> 49 #include <sys/tprintf.h> 50 #include <sys/syslog.h> 51 #include <sys/cons.h> 52 53 /* 54 * Note that stdarg.h and the ANSI style va_start macro is used for both 55 * ANSI and traditional C compilers. 56 */ 57 #include <machine/stdarg.h> 58 59 #define TOCONS 0x01 60 #define TOTTY 0x02 61 #define TOLOG 0x04 62 63 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 64 #define MAXNBUF (sizeof(quad_t) * NBBY + 1) 65 66 struct putchar_arg { 67 int flags; 68 struct tty *tty; 69 }; 70 71 struct snprintf_arg { 72 char *str; 73 size_t remain; 74 }; 75 76 struct tty *constty; /* pointer to console "window" tty */ 77 78 static void (*v_putc)(int) = cnputc; /* routine to putc on virtual console */ 79 static void logpri __P((int level)); 80 static void msglogchar(int c, void *dummyarg); 81 static void putchar __P((int ch, void *arg)); 82 static char *ksprintn __P((char *nbuf, u_long num, int base, int *len)); 83 static char *ksprintqn __P((char *nbuf, u_quad_t num, int base, int *len)); 84 static void snprintf_func __P((int ch, void *arg)); 85 86 static int consintr = 1; /* Ok to handle console interrupts? */ 87 static int msgbufmapped; /* Set when safe to use msgbuf */ 88 89 /* 90 * Warn that a system table is full. 91 */ 92 void 93 tablefull(tab) 94 const char *tab; 95 { 96 97 log(LOG_ERR, "%s: table is full\n", tab); 98 } 99 100 /* 101 * Uprintf prints to the controlling terminal for the current process. 102 * It may block if the tty queue is overfull. No message is printed if 103 * the queue does not clear in a reasonable time. 104 */ 105 int 106 uprintf(const char *fmt, ...) 107 { 108 struct proc *p = curproc; 109 va_list ap; 110 struct putchar_arg pca; 111 int retval = 0; 112 113 if (p && p != idleproc && p->p_flag & P_CONTROLT && 114 p->p_session->s_ttyvp) { 115 va_start(ap, fmt); 116 pca.tty = p->p_session->s_ttyp; 117 pca.flags = TOTTY; 118 retval = kvprintf(fmt, putchar, &pca, 10, ap); 119 va_end(ap); 120 } 121 return retval; 122 } 123 124 tpr_t 125 tprintf_open(p) 126 register struct proc *p; 127 { 128 129 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 130 SESSHOLD(p->p_session); 131 return ((tpr_t) p->p_session); 132 } 133 return ((tpr_t) NULL); 134 } 135 136 void 137 tprintf_close(sess) 138 tpr_t sess; 139 { 140 141 if (sess) 142 SESSRELE((struct session *) sess); 143 } 144 145 /* 146 * tprintf prints on the controlling terminal associated 147 * with the given session. 148 */ 149 int 150 tprintf(tpr_t tpr, const char *fmt, ...) 151 { 152 register struct session *sess = (struct session *)tpr; 153 struct tty *tp = NULL; 154 int flags = TOLOG; 155 va_list ap; 156 struct putchar_arg pca; 157 int retval; 158 159 logpri(LOG_INFO); 160 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 161 flags |= TOTTY; 162 tp = sess->s_ttyp; 163 } 164 va_start(ap, fmt); 165 pca.tty = tp; 166 pca.flags = flags; 167 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 */ 178 int 179 ttyprintf(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 193 extern 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 */ 200 int 201 log(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 227 static void 228 logpri(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 240 int 241 addlog(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 264 int 265 printf(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 285 int 286 vprintf(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 */ 308 static void 309 putchar(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 */ 332 int 333 sprintf(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 */ 348 int 349 vsprintf(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 */ 361 int 362 snprintf(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 */ 376 int 377 vsnprintf(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 390 static void 391 snprintf_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 */ 407 static char * 408 ksprintn(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. */ 425 static char * 426 ksprintqn(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 */ 469 int 470 kvprintf(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; 507 reswitch: 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 case 'X': 669 if (qflag) 670 uq = va_arg(ap, u_quad_t); 671 else if (lflag) 672 ul = va_arg(ap, u_long); 673 else 674 ul = va_arg(ap, u_int); 675 base = 16; 676 goto nosign; 677 case 'z': 678 if (qflag) 679 uq = va_arg(ap, u_quad_t); 680 else if (lflag) 681 ul = va_arg(ap, u_long); 682 else 683 ul = sign ? 684 (u_long)va_arg(ap, int) : va_arg(ap, u_int); 685 base = 16; 686 goto number; 687 nosign: sign = 0; 688 number: 689 if (qflag) { 690 if (sign && (quad_t)uq < 0) { 691 neg = 1; 692 uq = -(quad_t)uq; 693 } 694 p = ksprintqn(nbuf, uq, base, &tmp); 695 } else { 696 if (sign && (long)ul < 0) { 697 neg = 1; 698 ul = -(long)ul; 699 } 700 p = ksprintn(nbuf, ul, base, &tmp); 701 } 702 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 703 if (base == 8) 704 tmp++; 705 else if (base == 16) 706 tmp += 2; 707 } 708 if (neg) 709 tmp++; 710 711 if (!ladjust && width && (width -= tmp) > 0) 712 while (width--) 713 PCHAR(padc); 714 if (neg) 715 PCHAR('-'); 716 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 717 if (base == 8) { 718 PCHAR('0'); 719 } else if (base == 16) { 720 PCHAR('0'); 721 PCHAR('x'); 722 } 723 } 724 725 while (*p) 726 PCHAR(*p--); 727 728 if (ladjust && width && (width -= tmp) > 0) 729 while (width--) 730 PCHAR(padc); 731 732 break; 733 default: 734 PCHAR('%'); 735 if (lflag) 736 PCHAR('l'); 737 PCHAR(ch); 738 break; 739 } 740 } 741 #undef PCHAR 742 } 743 744 /* 745 * Put character in log buffer. 746 */ 747 static void 748 msglogchar(int c, void *dummyarg) 749 { 750 struct msgbuf *mbp; 751 752 if (c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 753 mbp = msgbufp; 754 mbp->msg_ptr[mbp->msg_bufx++] = c; 755 if (mbp->msg_bufx >= mbp->msg_size) 756 mbp->msg_bufx = 0; 757 /* If the buffer is full, keep the most recent data. */ 758 if (mbp->msg_bufr == mbp->msg_bufx) { 759 if (++mbp->msg_bufr >= mbp->msg_size) 760 mbp->msg_bufr = 0; 761 } 762 } 763 } 764 765 static void 766 msgbufcopy(struct msgbuf *oldp) 767 { 768 int pos; 769 770 pos = oldp->msg_bufr; 771 while (pos != oldp->msg_bufx) { 772 msglogchar(oldp->msg_ptr[pos], NULL); 773 if (++pos >= oldp->msg_size) 774 pos = 0; 775 } 776 } 777 778 void 779 msgbufinit(void *ptr, size_t size) 780 { 781 char *cp; 782 static struct msgbuf *oldp = NULL; 783 784 cp = (char *)ptr; 785 msgbufp = (struct msgbuf *) (cp + size - sizeof(*msgbufp)); 786 if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp) { 787 bzero(cp, size); 788 msgbufp->msg_magic = MSG_MAGIC; 789 msgbufp->msg_size = (char *)msgbufp - cp; 790 msgbufp->msg_ptr = cp; 791 } 792 if (msgbufmapped && oldp != msgbufp) 793 msgbufcopy(oldp); 794 msgbufmapped = 1; 795 oldp = msgbufp; 796 } 797 798 #include "opt_ddb.h" 799 #ifdef DDB 800 #include <ddb/ddb.h> 801 802 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 803 { 804 int i, j; 805 806 if (!msgbufmapped) { 807 db_printf("msgbuf not mapped yet\n"); 808 return; 809 } 810 db_printf("msgbufp = %p\n", msgbufp); 811 db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n", 812 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, 813 msgbufp->msg_bufx, msgbufp->msg_ptr); 814 for (i = 0; i < msgbufp->msg_size; i++) { 815 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; 816 db_printf("%c", msgbufp->msg_ptr[j]); 817 } 818 db_printf("\n"); 819 } 820 821 #endif /* DDB */ 822