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