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: src/sys/kern/subr_prf.c,v 1.61.2.5 2002/08/31 18:22:08 dwmalone Exp $ 40 * $DragonFly: src/sys/kern/subr_prf.c,v 1.10 2005/11/21 21:56:14 dillon Exp $ 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/msgbuf.h> 47 #include <sys/malloc.h> 48 #include <sys/proc.h> 49 #include <sys/tty.h> 50 #include <sys/tprintf.h> 51 #include <sys/syslog.h> 52 #include <sys/cons.h> 53 #include <sys/uio.h> 54 #include <sys/sysctl.h> 55 #include <sys/lock.h> 56 57 /* 58 * Note that stdarg.h and the ANSI style va_start macro is used for both 59 * ANSI and traditional C compilers. We use the __ machine version to stay 60 * within the kernel header file set. 61 */ 62 #include <machine/stdarg.h> 63 64 #define TOCONS 0x01 65 #define TOTTY 0x02 66 #define TOLOG 0x04 67 68 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 69 #define MAXNBUF (sizeof(quad_t) * NBBY + 1) 70 71 struct putchar_arg { 72 int flags; 73 int pri; 74 struct tty *tty; 75 }; 76 77 struct snprintf_arg { 78 char *str; 79 size_t remain; 80 }; 81 82 extern int log_open; 83 84 struct tty *constty; /* pointer to console "window" tty */ 85 86 static void (*v_putc)(int) = cnputc; /* routine to putc on virtual console */ 87 static void msglogchar(int c, int pri); 88 static void msgaddchar(int c, void *dummy); 89 static void putchar (int ch, void *arg); 90 static char *ksprintn (char *nbuf, u_long num, int base, int *len); 91 static char *ksprintqn (char *nbuf, u_quad_t num, int base, int *len); 92 static void snprintf_func (int ch, void *arg); 93 94 static int consintr = 1; /* Ok to handle console interrupts? */ 95 static int msgbufmapped; /* Set when safe to use msgbuf */ 96 int msgbuftrigger; 97 98 static int log_console_output = 1; 99 TUNABLE_INT("kern.log_console_output", &log_console_output); 100 SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW, 101 &log_console_output, 0, ""); 102 103 static int unprivileged_read_msgbuf = 1; 104 SYSCTL_INT(_kern, OID_AUTO, unprivileged_read_msgbuf, CTLFLAG_RW, 105 &unprivileged_read_msgbuf, 0, 106 "Unprivileged processes may read the kernel message buffer"); 107 108 /* 109 * Warn that a system table is full. 110 */ 111 void 112 tablefull(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 */ 123 int 124 uprintf(const char *fmt, ...) 125 { 126 struct proc *p = curproc; 127 __va_list ap; 128 struct putchar_arg pca; 129 int retval = 0; 130 131 if (p && p->p_flag & P_CONTROLT && 132 p->p_session->s_ttyvp) { 133 __va_start(ap, fmt); 134 pca.tty = p->p_session->s_ttyp; 135 pca.flags = TOTTY; 136 137 retval = kvprintf(fmt, putchar, &pca, 10, ap); 138 __va_end(ap); 139 } 140 return retval; 141 } 142 143 tpr_t 144 tprintf_open(struct proc *p) 145 { 146 147 if ((p->p_flag & P_CONTROLT) && p->p_session->s_ttyvp) { 148 sess_hold(p->p_session); 149 return ((tpr_t) p->p_session); 150 } 151 return ((tpr_t) NULL); 152 } 153 154 void 155 tprintf_close(tpr_t sess) 156 { 157 if (sess) 158 sess_rele((struct session *) sess); 159 } 160 161 /* 162 * tprintf prints on the controlling terminal associated 163 * with the given session. 164 */ 165 int 166 tprintf(tpr_t tpr, const char *fmt, ...) 167 { 168 struct session *sess = (struct session *)tpr; 169 struct tty *tp = NULL; 170 int flags = TOLOG; 171 __va_list ap; 172 struct putchar_arg pca; 173 int retval; 174 175 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 176 flags |= TOTTY; 177 tp = sess->s_ttyp; 178 } 179 __va_start(ap, fmt); 180 pca.tty = tp; 181 pca.flags = flags; 182 pca.pri = LOG_INFO; 183 retval = kvprintf(fmt, putchar, &pca, 10, ap); 184 __va_end(ap); 185 msgbuftrigger = 1; 186 return retval; 187 } 188 189 /* 190 * Ttyprintf displays a message on a tty; it should be used only by 191 * the tty driver, or anything that knows the underlying tty will not 192 * be revoke(2)'d away. Other callers should use tprintf. 193 */ 194 int 195 ttyprintf(struct tty *tp, const char *fmt, ...) 196 { 197 __va_list ap; 198 struct putchar_arg pca; 199 int retval; 200 201 __va_start(ap, fmt); 202 pca.tty = tp; 203 pca.flags = TOTTY; 204 retval = kvprintf(fmt, putchar, &pca, 10, ap); 205 __va_end(ap); 206 return retval; 207 } 208 209 /* 210 * Log writes to the log buffer, and guarantees not to sleep (so can be 211 * called by interrupt routines). If there is no process reading the 212 * log yet, it writes to the console also. 213 */ 214 int 215 log(int level, const char *fmt, ...) 216 { 217 __va_list ap; 218 int retval; 219 struct putchar_arg pca; 220 221 pca.tty = NULL; 222 pca.pri = level; 223 pca.flags = log_open ? TOLOG : TOCONS; 224 225 __va_start(ap, fmt); 226 retval = kvprintf(fmt, putchar, &pca, 10, ap); 227 __va_end(ap); 228 229 msgbuftrigger = 1; 230 return (retval); 231 } 232 233 int 234 addlog(const char *fmt, ...) 235 { 236 __va_list ap; 237 int retval; 238 struct putchar_arg pca; 239 240 pca.tty = NULL; 241 pca.pri = -1; 242 pca.flags = log_open ? TOLOG : TOCONS; 243 244 __va_start(ap, fmt); 245 retval = kvprintf(fmt, putchar, &pca, 10, ap); 246 __va_end(ap); 247 248 msgbuftrigger = 1; 249 return (retval); 250 } 251 252 #define CONSCHUNK 128 253 254 void 255 log_console(struct uio *uio) 256 { 257 int c, i, error, iovlen, nl; 258 struct uio muio; 259 struct iovec *miov = NULL; 260 char *consbuffer; 261 int pri; 262 263 if (!log_console_output) 264 return; 265 266 pri = LOG_INFO | LOG_CONSOLE; 267 muio = *uio; 268 iovlen = uio->uio_iovcnt * sizeof (struct iovec); 269 MALLOC(miov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 270 MALLOC(consbuffer, char *, CONSCHUNK, M_TEMP, M_WAITOK); 271 bcopy((caddr_t)muio.uio_iov, (caddr_t)miov, iovlen); 272 muio.uio_iov = miov; 273 uio = &muio; 274 275 nl = 0; 276 while (uio->uio_resid > 0) { 277 c = imin(uio->uio_resid, CONSCHUNK); 278 error = uiomove(consbuffer, c, uio); 279 if (error != 0) 280 return; 281 for (i = 0; i < c; i++) { 282 msglogchar(consbuffer[i], pri); 283 if (consbuffer[i] == '\n') 284 nl = 1; 285 else 286 nl = 0; 287 } 288 } 289 if (!nl) 290 msglogchar('\n', pri); 291 msgbuftrigger = 1; 292 FREE(miov, M_TEMP); 293 FREE(consbuffer, M_TEMP); 294 return; 295 } 296 297 /* 298 * Output to the console. 299 * 300 * NOT YET ENTIRELY MPSAFE 301 */ 302 int 303 printf(const char *fmt, ...) 304 { 305 __va_list ap; 306 int savintr; 307 struct putchar_arg pca; 308 int retval; 309 310 savintr = consintr; /* disable interrupts */ 311 consintr = 0; 312 __va_start(ap, fmt); 313 pca.tty = NULL; 314 pca.flags = TOCONS | TOLOG; 315 pca.pri = -1; 316 cons_lock(); 317 retval = kvprintf(fmt, putchar, &pca, 10, ap); 318 cons_unlock(); 319 __va_end(ap); 320 if (!panicstr) 321 msgbuftrigger = 1; 322 consintr = savintr; /* reenable interrupts */ 323 return retval; 324 } 325 326 int 327 vprintf(const char *fmt, __va_list ap) 328 { 329 int savintr; 330 struct putchar_arg pca; 331 int retval; 332 333 savintr = consintr; /* disable interrupts */ 334 consintr = 0; 335 pca.tty = NULL; 336 pca.flags = TOCONS | TOLOG; 337 pca.pri = -1; 338 cons_lock(); 339 retval = kvprintf(fmt, putchar, &pca, 10, ap); 340 cons_unlock(); 341 if (!panicstr) 342 msgbuftrigger = 1; 343 consintr = savintr; /* reenable interrupts */ 344 return retval; 345 } 346 347 /* 348 * Print a character on console or users terminal. If destination is 349 * the console then the last bunch of characters are saved in msgbuf for 350 * inspection later. 351 * 352 * NOT YET ENTIRELY MPSAFE, EVEN WHEN LOGGING JUST TO THE SYSCONSOLE. 353 */ 354 static void 355 putchar(int c, void *arg) 356 { 357 struct putchar_arg *ap = (struct putchar_arg*) arg; 358 int flags = ap->flags; 359 struct tty *tp = ap->tty; 360 if (panicstr) 361 constty = NULL; 362 if ((flags & TOCONS) && tp == NULL && constty) { 363 tp = constty; 364 flags |= TOTTY; 365 } 366 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 367 (flags & TOCONS) && tp == constty) 368 constty = NULL; 369 if ((flags & TOLOG)) 370 msglogchar(c, ap->pri); 371 if ((flags & TOCONS) && constty == NULL && c != '\0') 372 (*v_putc)(c); 373 } 374 375 /* 376 * Scaled down version of sprintf(3). 377 */ 378 int 379 sprintf(char *buf, const char *cfmt, ...) 380 { 381 int retval; 382 __va_list ap; 383 384 __va_start(ap, cfmt); 385 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 386 buf[retval] = '\0'; 387 __va_end(ap); 388 return retval; 389 } 390 391 /* 392 * Scaled down version of vsprintf(3). 393 */ 394 int 395 vsprintf(char *buf, const char *cfmt, __va_list ap) 396 { 397 int retval; 398 399 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 400 buf[retval] = '\0'; 401 return retval; 402 } 403 404 /* 405 * Scaled down version of snprintf(3). 406 */ 407 int 408 snprintf(char *str, size_t size, const char *format, ...) 409 { 410 int retval; 411 __va_list ap; 412 413 __va_start(ap, format); 414 retval = vsnprintf(str, size, format, ap); 415 __va_end(ap); 416 return(retval); 417 } 418 419 /* 420 * Scaled down version of vsnprintf(3). 421 */ 422 int 423 vsnprintf(char *str, size_t size, const char *format, __va_list ap) 424 { 425 struct snprintf_arg info; 426 int retval; 427 428 info.str = str; 429 info.remain = size; 430 retval = kvprintf(format, snprintf_func, &info, 10, ap); 431 if (info.remain >= 1) 432 *info.str++ = '\0'; 433 return retval; 434 } 435 436 static void 437 snprintf_func(int ch, void *arg) 438 { 439 struct snprintf_arg *const info = arg; 440 441 if (info->remain >= 2) { 442 *info->str++ = ch; 443 info->remain--; 444 } 445 } 446 447 /* 448 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 449 * order; return an optional length and a pointer to the last character 450 * written in the buffer (i.e., the first character of the string). 451 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 452 */ 453 static char * 454 ksprintn(nbuf, ul, base, lenp) 455 char *nbuf; 456 u_long ul; 457 int base, *lenp; 458 { 459 char *p; 460 461 p = nbuf; 462 *p = '\0'; 463 do { 464 *++p = hex2ascii(ul % base); 465 } while (ul /= base); 466 if (lenp) 467 *lenp = p - nbuf; 468 return (p); 469 } 470 /* ksprintn, but for a quad_t. */ 471 static char * 472 ksprintqn(nbuf, uq, base, lenp) 473 char *nbuf; 474 u_quad_t uq; 475 int base, *lenp; 476 { 477 char *p; 478 479 p = nbuf; 480 *p = '\0'; 481 do { 482 *++p = hex2ascii(uq % base); 483 } while (uq /= base); 484 if (lenp) 485 *lenp = p - nbuf; 486 return (p); 487 } 488 489 /* 490 * Scaled down version of printf(3). 491 * 492 * Two additional formats: 493 * 494 * The format %b is supported to decode error registers. 495 * Its usage is: 496 * 497 * printf("reg=%b\n", regval, "<base><arg>*"); 498 * 499 * where <base> is the output base expressed as a control character, e.g. 500 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 501 * the first of which gives the bit number to be inspected (origin 1), and 502 * the next characters (up to a control character, i.e. a character <= 32), 503 * give the name of the register. Thus: 504 * 505 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 506 * 507 * would produce output: 508 * 509 * reg=3<BITTWO,BITONE> 510 * 511 * XXX: %D -- Hexdump, takes pointer and separator string: 512 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 513 * ("%*D", len, ptr, " " -> XX XX XX XX ... 514 */ 515 int 516 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, __va_list ap) 517 { 518 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 519 char nbuf[MAXNBUF]; 520 char *p, *q, *d; 521 u_char *up; 522 int ch, n; 523 u_long ul; 524 u_quad_t uq; 525 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 526 int dwidth; 527 char padc; 528 int retval = 0; 529 530 ul = 0; 531 uq = 0; 532 if (!func) 533 d = (char *) arg; 534 else 535 d = NULL; 536 537 if (fmt == NULL) 538 fmt = "(fmt null)\n"; 539 540 if (radix < 2 || radix > 36) 541 radix = 10; 542 543 for (;;) { 544 padc = ' '; 545 width = 0; 546 while ((ch = (u_char)*fmt++) != '%') { 547 if (ch == '\0') 548 return retval; 549 PCHAR(ch); 550 } 551 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 552 sign = 0; dot = 0; dwidth = 0; 553 reswitch: switch (ch = (u_char)*fmt++) { 554 case '.': 555 dot = 1; 556 goto reswitch; 557 case '#': 558 sharpflag = 1; 559 goto reswitch; 560 case '+': 561 sign = 1; 562 goto reswitch; 563 case '-': 564 ladjust = 1; 565 goto reswitch; 566 case '%': 567 PCHAR(ch); 568 break; 569 case '*': 570 if (!dot) { 571 width = __va_arg(ap, int); 572 if (width < 0) { 573 ladjust = !ladjust; 574 width = -width; 575 } 576 } else { 577 dwidth = __va_arg(ap, int); 578 } 579 goto reswitch; 580 case '0': 581 if (!dot) { 582 padc = '0'; 583 goto reswitch; 584 } 585 case '1': case '2': case '3': case '4': 586 case '5': case '6': case '7': case '8': case '9': 587 for (n = 0;; ++fmt) { 588 n = n * 10 + ch - '0'; 589 ch = *fmt; 590 if (ch < '0' || ch > '9') 591 break; 592 } 593 if (dot) 594 dwidth = n; 595 else 596 width = n; 597 goto reswitch; 598 case 'b': 599 ul = __va_arg(ap, int); 600 p = __va_arg(ap, char *); 601 for (q = ksprintn(nbuf, ul, *p++, NULL); *q;) 602 PCHAR(*q--); 603 604 if (!ul) 605 break; 606 607 for (tmp = 0; *p;) { 608 n = *p++; 609 if (ul & (1 << (n - 1))) { 610 PCHAR(tmp ? ',' : '<'); 611 for (; (n = *p) > ' '; ++p) 612 PCHAR(n); 613 tmp = 1; 614 } else 615 for (; *p > ' '; ++p) 616 continue; 617 } 618 if (tmp) 619 PCHAR('>'); 620 break; 621 case 'c': 622 PCHAR(__va_arg(ap, int)); 623 break; 624 case 'D': 625 up = __va_arg(ap, u_char *); 626 p = __va_arg(ap, char *); 627 if (!width) 628 width = 16; 629 while(width--) { 630 PCHAR(hex2ascii(*up >> 4)); 631 PCHAR(hex2ascii(*up & 0x0f)); 632 up++; 633 if (width) 634 for (q=p;*q;q++) 635 PCHAR(*q); 636 } 637 break; 638 case 'd': 639 if (qflag) 640 uq = __va_arg(ap, quad_t); 641 else if (lflag) 642 ul = __va_arg(ap, long); 643 else 644 ul = __va_arg(ap, int); 645 sign = 1; 646 base = 10; 647 goto number; 648 case 'l': 649 if (lflag) { 650 lflag = 0; 651 qflag = 1; 652 } else 653 lflag = 1; 654 goto reswitch; 655 case 'o': 656 if (qflag) 657 uq = __va_arg(ap, u_quad_t); 658 else if (lflag) 659 ul = __va_arg(ap, u_long); 660 else 661 ul = __va_arg(ap, u_int); 662 base = 8; 663 goto nosign; 664 case 'p': 665 ul = (uintptr_t)__va_arg(ap, void *); 666 base = 16; 667 sharpflag = (width == 0); 668 goto nosign; 669 case 'q': 670 qflag = 1; 671 goto reswitch; 672 case 'n': 673 case 'r': 674 if (qflag) 675 uq = __va_arg(ap, u_quad_t); 676 else if (lflag) 677 ul = __va_arg(ap, u_long); 678 else 679 ul = sign ? 680 (u_long)__va_arg(ap, int) : __va_arg(ap, u_int); 681 base = radix; 682 goto number; 683 case 's': 684 p = __va_arg(ap, char *); 685 if (p == NULL) 686 p = "(null)"; 687 if (!dot) 688 n = strlen (p); 689 else 690 for (n = 0; n < dwidth && p[n]; n++) 691 continue; 692 693 width -= n; 694 695 if (!ladjust && width > 0) 696 while (width--) 697 PCHAR(padc); 698 while (n--) 699 PCHAR(*p++); 700 if (ladjust && width > 0) 701 while (width--) 702 PCHAR(padc); 703 break; 704 case 'u': 705 if (qflag) 706 uq = __va_arg(ap, u_quad_t); 707 else if (lflag) 708 ul = __va_arg(ap, u_long); 709 else 710 ul = __va_arg(ap, u_int); 711 base = 10; 712 goto nosign; 713 case 'x': 714 case 'X': 715 if (qflag) 716 uq = __va_arg(ap, u_quad_t); 717 else if (lflag) 718 ul = __va_arg(ap, u_long); 719 else 720 ul = __va_arg(ap, u_int); 721 base = 16; 722 goto nosign; 723 case 'z': 724 if (qflag) 725 uq = __va_arg(ap, u_quad_t); 726 else if (lflag) 727 ul = __va_arg(ap, u_long); 728 else 729 ul = sign ? 730 (u_long)__va_arg(ap, int) : __va_arg(ap, u_int); 731 base = 16; 732 goto number; 733 nosign: sign = 0; 734 number: 735 if (qflag) { 736 if (sign && (quad_t)uq < 0) { 737 neg = 1; 738 uq = -(quad_t)uq; 739 } 740 p = ksprintqn(nbuf, uq, base, &tmp); 741 } else { 742 if (sign && (long)ul < 0) { 743 neg = 1; 744 ul = -(long)ul; 745 } 746 p = ksprintn(nbuf, ul, base, &tmp); 747 } 748 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 749 if (base == 8) 750 tmp++; 751 else if (base == 16) 752 tmp += 2; 753 } 754 if (neg) 755 tmp++; 756 757 if (!ladjust && width && (width -= tmp) > 0) 758 while (width--) 759 PCHAR(padc); 760 if (neg) 761 PCHAR('-'); 762 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 763 if (base == 8) { 764 PCHAR('0'); 765 } else if (base == 16) { 766 PCHAR('0'); 767 PCHAR('x'); 768 } 769 } 770 771 while (*p) 772 PCHAR(*p--); 773 774 if (ladjust && width && (width -= tmp) > 0) 775 while (width--) 776 PCHAR(padc); 777 778 break; 779 default: 780 PCHAR('%'); 781 if (lflag) 782 PCHAR('l'); 783 PCHAR(ch); 784 break; 785 } 786 } 787 #undef PCHAR 788 } 789 790 /* 791 * Put character in log buffer with a particular priority. 792 * 793 * MPSAFE 794 */ 795 static void 796 msglogchar(int c, int pri) 797 { 798 static int lastpri = -1; 799 static int dangling; 800 char nbuf[MAXNBUF]; 801 char *p; 802 803 if (!msgbufmapped) 804 return; 805 if (c == '\0' || c == '\r') 806 return; 807 if (pri != -1 && pri != lastpri) { 808 if (dangling) { 809 msgaddchar('\n', NULL); 810 dangling = 0; 811 } 812 msgaddchar('<', NULL); 813 for (p = ksprintn(nbuf, (u_long)pri, 10, NULL); *p;) 814 msgaddchar(*p--, NULL); 815 msgaddchar('>', NULL); 816 lastpri = pri; 817 } 818 msgaddchar(c, NULL); 819 if (c == '\n') { 820 dangling = 0; 821 lastpri = -1; 822 } else { 823 dangling = 1; 824 } 825 } 826 827 /* 828 * Put char in log buffer. Make sure nothing blows up beyond repair if 829 * we have an MP race. 830 * 831 * MPSAFE. 832 */ 833 static void 834 msgaddchar(int c, void *dummy) 835 { 836 struct msgbuf *mbp; 837 int rindex; 838 int windex; 839 840 if (!msgbufmapped) 841 return; 842 mbp = msgbufp; 843 windex = mbp->msg_bufx; 844 mbp->msg_ptr[windex] = c; 845 if (++windex >= mbp->msg_size) 846 windex = 0; 847 rindex = mbp->msg_bufr; 848 if (windex == rindex) { 849 rindex += 32; 850 if (rindex >= mbp->msg_size) 851 rindex -= mbp->msg_size; 852 mbp->msg_bufr = rindex; 853 } 854 mbp->msg_bufx = windex; 855 } 856 857 static void 858 msgbufcopy(struct msgbuf *oldp) 859 { 860 int pos; 861 862 pos = oldp->msg_bufr; 863 while (pos != oldp->msg_bufx) { 864 msglogchar(oldp->msg_ptr[pos], -1); 865 if (++pos >= oldp->msg_size) 866 pos = 0; 867 } 868 } 869 870 void 871 msgbufinit(void *ptr, size_t size) 872 { 873 char *cp; 874 static struct msgbuf *oldp = NULL; 875 876 size -= sizeof(*msgbufp); 877 cp = (char *)ptr; 878 msgbufp = (struct msgbuf *) (cp + size); 879 if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_size != size || 880 msgbufp->msg_bufx >= size || msgbufp->msg_bufr >= size) { 881 bzero(cp, size); 882 bzero(msgbufp, sizeof(*msgbufp)); 883 msgbufp->msg_magic = MSG_MAGIC; 884 msgbufp->msg_size = (char *)msgbufp - cp; 885 } 886 msgbufp->msg_ptr = cp; 887 if (msgbufmapped && oldp != msgbufp) 888 msgbufcopy(oldp); 889 msgbufmapped = 1; 890 oldp = msgbufp; 891 } 892 893 /* Sysctls for accessing/clearing the msgbuf */ 894 895 static int 896 sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 897 { 898 struct ucred *cred; 899 int error; 900 901 /* 902 * Only wheel or root can access the message log. 903 */ 904 if (unprivileged_read_msgbuf == 0) { 905 KKASSERT(req->td->td_proc); 906 cred = req->td->td_proc->p_ucred; 907 908 if ((cred->cr_prison || groupmember(0, cred) == 0) && 909 suser(req->td) != 0 910 ) { 911 return (EPERM); 912 } 913 } 914 915 /* 916 * Unwind the buffer, so that it's linear (possibly starting with 917 * some initial nulls). 918 */ 919 error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr + msgbufp->msg_bufx, 920 msgbufp->msg_size - msgbufp->msg_bufx, req); 921 if (error) 922 return (error); 923 if (msgbufp->msg_bufx > 0) { 924 error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr, 925 msgbufp->msg_bufx, req); 926 } 927 return (error); 928 } 929 930 SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD, 931 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 932 933 static int msgbuf_clear; 934 935 static int 936 sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 937 { 938 int error; 939 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 940 if (!error && req->newptr) { 941 /* Clear the buffer and reset write pointer */ 942 bzero(msgbufp->msg_ptr, msgbufp->msg_size); 943 msgbufp->msg_bufr = msgbufp->msg_bufx = 0; 944 msgbuf_clear = 0; 945 } 946 return (error); 947 } 948 949 SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 950 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clear, 0, 951 sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer"); 952 953 #include "opt_ddb.h" 954 #ifdef DDB 955 #include <ddb/ddb.h> 956 957 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 958 { 959 int i, j; 960 961 if (!msgbufmapped) { 962 db_printf("msgbuf not mapped yet\n"); 963 return; 964 } 965 db_printf("msgbufp = %p\n", msgbufp); 966 db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n", 967 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, 968 msgbufp->msg_bufx, msgbufp->msg_ptr); 969 for (i = 0; i < msgbufp->msg_size; i++) { 970 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; 971 db_printf("%c", msgbufp->msg_ptr[j]); 972 } 973 db_printf("\n"); 974 } 975 976 #endif /* DDB */ 977