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_flag & P_CONTROLT && p->p_session->s_ttyvp) { 114 va_start(ap, fmt); 115 pca.tty = p->p_session->s_ttyp; 116 pca.flags = TOTTY; 117 retval = kvprintf(fmt, putchar, &pca, 10, ap); 118 va_end(ap); 119 } 120 return retval; 121 } 122 123 tpr_t 124 tprintf_open(p) 125 register struct proc *p; 126 { 127 128 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 129 SESSHOLD(p->p_session); 130 return ((tpr_t) p->p_session); 131 } 132 return ((tpr_t) NULL); 133 } 134 135 void 136 tprintf_close(sess) 137 tpr_t sess; 138 { 139 140 if (sess) 141 SESSRELE((struct session *) sess); 142 } 143 144 /* 145 * tprintf prints on the controlling terminal associated 146 * with the given session. 147 */ 148 int 149 tprintf(tpr_t tpr, const char *fmt, ...) 150 { 151 register struct session *sess = (struct session *)tpr; 152 struct tty *tp = NULL; 153 int flags = TOLOG; 154 va_list ap; 155 struct putchar_arg pca; 156 int retval; 157 158 logpri(LOG_INFO); 159 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 160 flags |= TOTTY; 161 tp = sess->s_ttyp; 162 } 163 va_start(ap, fmt); 164 pca.tty = tp; 165 pca.flags = flags; 166 retval = kvprintf(fmt, putchar, &pca, 10, ap); 167 va_end(ap); 168 logwakeup(); 169 return retval; 170 } 171 172 /* 173 * Ttyprintf displays a message on a tty; it should be used only by 174 * the tty driver, or anything that knows the underlying tty will not 175 * be revoke(2)'d away. Other callers should use tprintf. 176 */ 177 int 178 ttyprintf(struct tty *tp, const char *fmt, ...) 179 { 180 va_list ap; 181 struct putchar_arg pca; 182 int retval; 183 184 va_start(ap, fmt); 185 pca.tty = tp; 186 pca.flags = TOTTY; 187 retval = kvprintf(fmt, putchar, &pca, 10, ap); 188 va_end(ap); 189 return retval; 190 } 191 192 extern int log_open; 193 194 /* 195 * Log writes to the log buffer, and guarantees not to sleep (so can be 196 * called by interrupt routines). If there is no process reading the 197 * log yet, it writes to the console also. 198 */ 199 int 200 log(int level, const char *fmt, ...) 201 { 202 register int s; 203 va_list ap; 204 int retval; 205 206 s = splhigh(); 207 logpri(level); 208 va_start(ap, fmt); 209 210 retval = kvprintf(fmt, msglogchar, NULL, 10, ap); 211 va_end(ap); 212 213 splx(s); 214 if (!log_open) { 215 struct putchar_arg pca; 216 va_start(ap, fmt); 217 pca.tty = NULL; 218 pca.flags = TOCONS; 219 retval += kvprintf(fmt, putchar, &pca, 10, ap); 220 va_end(ap); 221 } 222 logwakeup(); 223 return retval; 224 } 225 226 static void 227 logpri(level) 228 int level; 229 { 230 char nbuf[MAXNBUF]; 231 register char *p; 232 233 msglogchar('<', NULL); 234 for (p = ksprintn(nbuf, (u_long)level, 10, NULL); *p;) 235 msglogchar(*p--, NULL); 236 msglogchar('>', NULL); 237 } 238 239 int 240 addlog(const char *fmt, ...) 241 { 242 register int s; 243 va_list ap; 244 int retval; 245 246 s = splhigh(); 247 va_start(ap, fmt); 248 retval = kvprintf(fmt, msglogchar, NULL, 10, ap); 249 splx(s); 250 va_end(ap); 251 if (!log_open) { 252 struct putchar_arg pca; 253 va_start(ap, fmt); 254 pca.tty = NULL; 255 pca.flags = TOCONS; 256 retval += kvprintf(fmt, putchar, &pca, 10, ap); 257 va_end(ap); 258 } 259 logwakeup(); 260 return (retval); 261 } 262 263 int 264 printf(const char *fmt, ...) 265 { 266 va_list ap; 267 register int savintr; 268 struct putchar_arg pca; 269 int retval; 270 271 savintr = consintr; /* disable interrupts */ 272 consintr = 0; 273 va_start(ap, fmt); 274 pca.tty = NULL; 275 pca.flags = TOCONS | TOLOG; 276 retval = kvprintf(fmt, putchar, &pca, 10, ap); 277 va_end(ap); 278 if (!panicstr) 279 logwakeup(); 280 consintr = savintr; /* reenable interrupts */ 281 return retval; 282 } 283 284 int 285 vprintf(const char *fmt, va_list ap) 286 { 287 register int savintr; 288 struct putchar_arg pca; 289 int retval; 290 291 savintr = consintr; /* disable interrupts */ 292 consintr = 0; 293 pca.tty = NULL; 294 pca.flags = TOCONS | TOLOG; 295 retval = kvprintf(fmt, putchar, &pca, 10, ap); 296 if (!panicstr) 297 logwakeup(); 298 consintr = savintr; /* reenable interrupts */ 299 return retval; 300 } 301 302 /* 303 * Print a character on console or users terminal. If destination is 304 * the console then the last bunch of characters are saved in msgbuf for 305 * inspection later. 306 */ 307 static void 308 putchar(int c, void *arg) 309 { 310 struct putchar_arg *ap = (struct putchar_arg*) arg; 311 int flags = ap->flags; 312 struct tty *tp = ap->tty; 313 if (panicstr) 314 constty = NULL; 315 if ((flags & TOCONS) && tp == NULL && constty) { 316 tp = constty; 317 flags |= TOTTY; 318 } 319 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 320 (flags & TOCONS) && tp == constty) 321 constty = NULL; 322 if ((flags & TOLOG)) 323 msglogchar(c, NULL); 324 if ((flags & TOCONS) && constty == NULL && c != '\0') 325 (*v_putc)(c); 326 } 327 328 /* 329 * Scaled down version of sprintf(3). 330 */ 331 int 332 sprintf(char *buf, const char *cfmt, ...) 333 { 334 int retval; 335 va_list ap; 336 337 va_start(ap, cfmt); 338 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 339 buf[retval] = '\0'; 340 va_end(ap); 341 return retval; 342 } 343 344 /* 345 * Scaled down version of vsprintf(3). 346 */ 347 int 348 vsprintf(char *buf, const char *cfmt, va_list ap) 349 { 350 int retval; 351 352 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 353 buf[retval] = '\0'; 354 return retval; 355 } 356 357 /* 358 * Scaled down version of snprintf(3). 359 */ 360 int 361 snprintf(char *str, size_t size, const char *format, ...) 362 { 363 int retval; 364 va_list ap; 365 366 va_start(ap, format); 367 retval = vsnprintf(str, size, format, ap); 368 va_end(ap); 369 return(retval); 370 } 371 372 /* 373 * Scaled down version of vsnprintf(3). 374 */ 375 int 376 vsnprintf(char *str, size_t size, const char *format, va_list ap) 377 { 378 struct snprintf_arg info; 379 int retval; 380 381 info.str = str; 382 info.remain = size; 383 retval = kvprintf(format, snprintf_func, &info, 10, ap); 384 if (info.remain >= 1) 385 *info.str++ = '\0'; 386 return retval; 387 } 388 389 static void 390 snprintf_func(int ch, void *arg) 391 { 392 struct snprintf_arg *const info = arg; 393 394 if (info->remain >= 2) { 395 *info->str++ = ch; 396 info->remain--; 397 } 398 } 399 400 /* 401 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 402 * order; return an optional length and a pointer to the last character 403 * written in the buffer (i.e., the first character of the string). 404 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 405 */ 406 static char * 407 ksprintn(nbuf, ul, base, lenp) 408 char *nbuf; 409 register u_long ul; 410 register int base, *lenp; 411 { 412 register char *p; 413 414 p = nbuf; 415 *p = '\0'; 416 do { 417 *++p = hex2ascii(ul % base); 418 } while (ul /= base); 419 if (lenp) 420 *lenp = p - nbuf; 421 return (p); 422 } 423 /* ksprintn, but for a quad_t. */ 424 static char * 425 ksprintqn(nbuf, uq, base, lenp) 426 char *nbuf; 427 register u_quad_t uq; 428 register int base, *lenp; 429 { 430 register char *p; 431 432 p = nbuf; 433 *p = '\0'; 434 do { 435 *++p = hex2ascii(uq % base); 436 } while (uq /= base); 437 if (lenp) 438 *lenp = p - nbuf; 439 return (p); 440 } 441 442 /* 443 * Scaled down version of printf(3). 444 * 445 * Two additional formats: 446 * 447 * The format %b is supported to decode error registers. 448 * Its usage is: 449 * 450 * printf("reg=%b\n", regval, "<base><arg>*"); 451 * 452 * where <base> is the output base expressed as a control character, e.g. 453 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 454 * the first of which gives the bit number to be inspected (origin 1), and 455 * the next characters (up to a control character, i.e. a character <= 32), 456 * give the name of the register. Thus: 457 * 458 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 459 * 460 * would produce output: 461 * 462 * reg=3<BITTWO,BITONE> 463 * 464 * XXX: %D -- Hexdump, takes pointer and separator string: 465 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 466 * ("%*D", len, ptr, " " -> XX XX XX XX ... 467 */ 468 int 469 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 470 { 471 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 472 char nbuf[MAXNBUF]; 473 char *p, *q, *d; 474 u_char *up; 475 int ch, n; 476 u_long ul; 477 u_quad_t uq; 478 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 479 int dwidth; 480 char padc; 481 int retval = 0; 482 483 ul = 0; 484 uq = 0; 485 if (!func) 486 d = (char *) arg; 487 else 488 d = NULL; 489 490 if (fmt == NULL) 491 fmt = "(fmt null)\n"; 492 493 if (radix < 2 || radix > 36) 494 radix = 10; 495 496 for (;;) { 497 padc = ' '; 498 width = 0; 499 while ((ch = (u_char)*fmt++) != '%') { 500 if (ch == '\0') 501 return retval; 502 PCHAR(ch); 503 } 504 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 505 sign = 0; dot = 0; dwidth = 0; 506 reswitch: switch (ch = (u_char)*fmt++) { 507 case '.': 508 dot = 1; 509 goto reswitch; 510 case '#': 511 sharpflag = 1; 512 goto reswitch; 513 case '+': 514 sign = 1; 515 goto reswitch; 516 case '-': 517 ladjust = 1; 518 goto reswitch; 519 case '%': 520 PCHAR(ch); 521 break; 522 case '*': 523 if (!dot) { 524 width = va_arg(ap, int); 525 if (width < 0) { 526 ladjust = !ladjust; 527 width = -width; 528 } 529 } else { 530 dwidth = va_arg(ap, int); 531 } 532 goto reswitch; 533 case '0': 534 if (!dot) { 535 padc = '0'; 536 goto reswitch; 537 } 538 case '1': case '2': case '3': case '4': 539 case '5': case '6': case '7': case '8': case '9': 540 for (n = 0;; ++fmt) { 541 n = n * 10 + ch - '0'; 542 ch = *fmt; 543 if (ch < '0' || ch > '9') 544 break; 545 } 546 if (dot) 547 dwidth = n; 548 else 549 width = n; 550 goto reswitch; 551 case 'b': 552 ul = va_arg(ap, int); 553 p = va_arg(ap, char *); 554 for (q = ksprintn(nbuf, ul, *p++, NULL); *q;) 555 PCHAR(*q--); 556 557 if (!ul) 558 break; 559 560 for (tmp = 0; *p;) { 561 n = *p++; 562 if (ul & (1 << (n - 1))) { 563 PCHAR(tmp ? ',' : '<'); 564 for (; (n = *p) > ' '; ++p) 565 PCHAR(n); 566 tmp = 1; 567 } else 568 for (; *p > ' '; ++p) 569 continue; 570 } 571 if (tmp) 572 PCHAR('>'); 573 break; 574 case 'c': 575 PCHAR(va_arg(ap, int)); 576 break; 577 case 'D': 578 up = va_arg(ap, u_char *); 579 p = va_arg(ap, char *); 580 if (!width) 581 width = 16; 582 while(width--) { 583 PCHAR(hex2ascii(*up >> 4)); 584 PCHAR(hex2ascii(*up & 0x0f)); 585 up++; 586 if (width) 587 for (q=p;*q;q++) 588 PCHAR(*q); 589 } 590 break; 591 case 'd': 592 if (qflag) 593 uq = va_arg(ap, quad_t); 594 else if (lflag) 595 ul = va_arg(ap, long); 596 else 597 ul = va_arg(ap, int); 598 sign = 1; 599 base = 10; 600 goto number; 601 case 'l': 602 if (lflag) { 603 lflag = 0; 604 qflag = 1; 605 } else 606 lflag = 1; 607 goto reswitch; 608 case 'o': 609 if (qflag) 610 uq = va_arg(ap, u_quad_t); 611 else if (lflag) 612 ul = va_arg(ap, u_long); 613 else 614 ul = va_arg(ap, u_int); 615 base = 8; 616 goto nosign; 617 case 'p': 618 ul = (uintptr_t)va_arg(ap, void *); 619 base = 16; 620 sharpflag = (width == 0); 621 goto nosign; 622 case 'q': 623 qflag = 1; 624 goto reswitch; 625 case 'n': 626 case 'r': 627 if (qflag) 628 uq = va_arg(ap, u_quad_t); 629 else if (lflag) 630 ul = va_arg(ap, u_long); 631 else 632 ul = sign ? 633 (u_long)va_arg(ap, int) : va_arg(ap, u_int); 634 base = radix; 635 goto number; 636 case 's': 637 p = va_arg(ap, char *); 638 if (p == NULL) 639 p = "(null)"; 640 if (!dot) 641 n = strlen (p); 642 else 643 for (n = 0; n < dwidth && p[n]; n++) 644 continue; 645 646 width -= n; 647 648 if (!ladjust && width > 0) 649 while (width--) 650 PCHAR(padc); 651 while (n--) 652 PCHAR(*p++); 653 if (ladjust && width > 0) 654 while (width--) 655 PCHAR(padc); 656 break; 657 case 'u': 658 if (qflag) 659 uq = va_arg(ap, u_quad_t); 660 else if (lflag) 661 ul = va_arg(ap, u_long); 662 else 663 ul = va_arg(ap, u_int); 664 base = 10; 665 goto nosign; 666 case 'x': 667 if (qflag) 668 uq = va_arg(ap, u_quad_t); 669 else if (lflag) 670 ul = va_arg(ap, u_long); 671 else 672 ul = va_arg(ap, u_int); 673 base = 16; 674 goto nosign; 675 case 'z': 676 if (qflag) 677 uq = va_arg(ap, u_quad_t); 678 else if (lflag) 679 ul = va_arg(ap, u_long); 680 else 681 ul = sign ? 682 (u_long)va_arg(ap, int) : va_arg(ap, u_int); 683 base = 16; 684 goto number; 685 nosign: sign = 0; 686 number: 687 if (qflag) { 688 if (sign && (quad_t)uq < 0) { 689 neg = 1; 690 uq = -(quad_t)uq; 691 } 692 p = ksprintqn(nbuf, uq, base, &tmp); 693 } else { 694 if (sign && (long)ul < 0) { 695 neg = 1; 696 ul = -(long)ul; 697 } 698 p = ksprintn(nbuf, ul, base, &tmp); 699 } 700 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 701 if (base == 8) 702 tmp++; 703 else if (base == 16) 704 tmp += 2; 705 } 706 if (neg) 707 tmp++; 708 709 if (!ladjust && width && (width -= tmp) > 0) 710 while (width--) 711 PCHAR(padc); 712 if (neg) 713 PCHAR('-'); 714 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 715 if (base == 8) { 716 PCHAR('0'); 717 } else if (base == 16) { 718 PCHAR('0'); 719 PCHAR('x'); 720 } 721 } 722 723 while (*p) 724 PCHAR(*p--); 725 726 if (ladjust && width && (width -= tmp) > 0) 727 while (width--) 728 PCHAR(padc); 729 730 break; 731 default: 732 PCHAR('%'); 733 if (lflag) 734 PCHAR('l'); 735 PCHAR(ch); 736 break; 737 } 738 } 739 #undef PCHAR 740 } 741 742 /* 743 * Put character in log buffer. 744 */ 745 static void 746 msglogchar(int c, void *dummyarg) 747 { 748 struct msgbuf *mbp; 749 750 if (c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 751 mbp = msgbufp; 752 mbp->msg_ptr[mbp->msg_bufx++] = c; 753 if (mbp->msg_bufx >= mbp->msg_size) 754 mbp->msg_bufx = 0; 755 /* If the buffer is full, keep the most recent data. */ 756 if (mbp->msg_bufr == mbp->msg_bufx) { 757 if (++mbp->msg_bufr >= mbp->msg_size) 758 mbp->msg_bufr = 0; 759 } 760 } 761 } 762 763 static void 764 msgbufcopy(struct msgbuf *oldp) 765 { 766 int pos; 767 768 pos = oldp->msg_bufr; 769 while (pos != oldp->msg_bufx) { 770 msglogchar(oldp->msg_ptr[pos], NULL); 771 if (++pos >= oldp->msg_size) 772 pos = 0; 773 } 774 } 775 776 void 777 msgbufinit(void *ptr, size_t size) 778 { 779 char *cp; 780 static struct msgbuf *oldp = NULL; 781 782 cp = (char *)ptr; 783 msgbufp = (struct msgbuf *) (cp + size - sizeof(*msgbufp)); 784 if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp) { 785 bzero(cp, size); 786 msgbufp->msg_magic = MSG_MAGIC; 787 msgbufp->msg_size = (char *)msgbufp - cp; 788 msgbufp->msg_ptr = cp; 789 } 790 if (msgbufmapped && oldp != msgbufp) 791 msgbufcopy(oldp); 792 msgbufmapped = 1; 793 oldp = msgbufp; 794 } 795 796 #include "opt_ddb.h" 797 #ifdef DDB 798 #include <ddb/ddb.h> 799 800 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 801 { 802 int i, j; 803 804 if (!msgbufmapped) { 805 db_printf("msgbuf not mapped yet\n"); 806 return; 807 } 808 db_printf("msgbufp = %p\n", msgbufp); 809 db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n", 810 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, 811 msgbufp->msg_bufx, msgbufp->msg_ptr); 812 for (i = 0; i < msgbufp->msg_size; i++) { 813 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; 814 db_printf("%c", msgbufp->msg_ptr[j]); 815 } 816 db_printf("\n"); 817 } 818 819 #endif /* DDB */ 820