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 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_ddb.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/lock.h> 45 #include <sys/kdb.h> 46 #include <sys/mutex.h> 47 #include <sys/sx.h> 48 #include <sys/kernel.h> 49 #include <sys/msgbuf.h> 50 #include <sys/malloc.h> 51 #include <sys/proc.h> 52 #include <sys/stddef.h> 53 #include <sys/sysctl.h> 54 #include <sys/tty.h> 55 #include <sys/syslog.h> 56 #include <sys/cons.h> 57 #include <sys/uio.h> 58 59 #ifdef DDB 60 #include <ddb/ddb.h> 61 #endif 62 63 /* 64 * Note that stdarg.h and the ANSI style va_start macro is used for both 65 * ANSI and traditional C compilers. 66 */ 67 #include <machine/stdarg.h> 68 69 #define TOCONS 0x01 70 #define TOTTY 0x02 71 #define TOLOG 0x04 72 73 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 74 #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 75 76 struct putchar_arg { 77 int flags; 78 int pri; 79 struct tty *tty; 80 }; 81 82 struct snprintf_arg { 83 char *str; 84 size_t remain; 85 }; 86 87 extern int log_open; 88 89 static void msglogchar(int c, int pri); 90 static void putchar(int ch, void *arg); 91 static char *ksprintn(char *nbuf, uintmax_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, "Duplicate console output to the syslog."); 102 103 static int always_console_output = 0; 104 TUNABLE_INT("kern.always_console_output", &always_console_output); 105 SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW, 106 &always_console_output, 0, "Always output to console despite TIOCCONS."); 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 thread *td = curthread; 127 struct proc *p = td->td_proc; 128 va_list ap; 129 struct putchar_arg pca; 130 int retval; 131 132 if (td == NULL || td == PCPU_GET(idlethread)) 133 return (0); 134 135 p = td->td_proc; 136 PROC_LOCK(p); 137 if ((p->p_flag & P_CONTROLT) == 0) { 138 PROC_UNLOCK(p); 139 return (0); 140 } 141 SESS_LOCK(p->p_session); 142 pca.tty = p->p_session->s_ttyp; 143 SESS_UNLOCK(p->p_session); 144 PROC_UNLOCK(p); 145 if (pca.tty == NULL) 146 return (0); 147 pca.flags = TOTTY; 148 va_start(ap, fmt); 149 retval = kvprintf(fmt, putchar, &pca, 10, ap); 150 va_end(ap); 151 152 return (retval); 153 } 154 155 /* 156 * tprintf prints on the controlling terminal associated 157 * with the given session, possibly to the log as well. 158 */ 159 void 160 tprintf(struct proc *p, int pri, const char *fmt, ...) 161 { 162 struct tty *tp = NULL; 163 int flags = 0; 164 va_list ap; 165 struct putchar_arg pca; 166 struct session *sess = NULL; 167 168 if (pri != -1) 169 flags |= TOLOG; 170 if (p != NULL) { 171 PROC_LOCK(p); 172 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 173 sess = p->p_session; 174 SESS_LOCK(sess); 175 PROC_UNLOCK(p); 176 SESSHOLD(sess); 177 tp = sess->s_ttyp; 178 SESS_UNLOCK(sess); 179 if (ttycheckoutq(tp, 0)) 180 flags |= TOTTY; 181 else 182 tp = NULL; 183 } else 184 PROC_UNLOCK(p); 185 } 186 pca.pri = pri; 187 pca.tty = tp; 188 pca.flags = flags; 189 va_start(ap, fmt); 190 kvprintf(fmt, putchar, &pca, 10, ap); 191 va_end(ap); 192 if (sess != NULL) { 193 SESS_LOCK(sess); 194 SESSRELE(sess); 195 SESS_UNLOCK(sess); 196 } 197 msgbuftrigger = 1; 198 } 199 200 /* 201 * Ttyprintf displays a message on a tty; it should be used only by 202 * the tty driver, or anything that knows the underlying tty will not 203 * be revoke(2)'d away. Other callers should use tprintf. 204 */ 205 int 206 ttyprintf(struct tty *tp, const char *fmt, ...) 207 { 208 va_list ap; 209 struct putchar_arg pca; 210 int retval; 211 212 va_start(ap, fmt); 213 pca.tty = tp; 214 pca.flags = TOTTY; 215 retval = kvprintf(fmt, putchar, &pca, 10, ap); 216 va_end(ap); 217 return (retval); 218 } 219 220 /* 221 * Log writes to the log buffer, and guarantees not to sleep (so can be 222 * called by interrupt routines). If there is no process reading the 223 * log yet, it writes to the console also. 224 */ 225 void 226 log(int level, const char *fmt, ...) 227 { 228 va_list ap; 229 struct putchar_arg pca; 230 231 pca.tty = NULL; 232 pca.pri = level; 233 pca.flags = log_open ? TOLOG : TOCONS; 234 235 va_start(ap, fmt); 236 kvprintf(fmt, putchar, &pca, 10, ap); 237 va_end(ap); 238 239 msgbuftrigger = 1; 240 } 241 242 #define CONSCHUNK 128 243 244 void 245 log_console(struct uio *uio) 246 { 247 int c, i, error, nl; 248 char *consbuffer; 249 int pri; 250 251 if (!log_console_output) 252 return; 253 254 pri = LOG_INFO | LOG_CONSOLE; 255 uio = cloneuio(uio); 256 consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK); 257 258 nl = 0; 259 while (uio->uio_resid > 0) { 260 c = imin(uio->uio_resid, CONSCHUNK); 261 error = uiomove(consbuffer, c, uio); 262 if (error != 0) 263 break; 264 for (i = 0; i < c; i++) { 265 msglogchar(consbuffer[i], pri); 266 if (consbuffer[i] == '\n') 267 nl = 1; 268 else 269 nl = 0; 270 } 271 } 272 if (!nl) 273 msglogchar('\n', pri); 274 msgbuftrigger = 1; 275 free(uio, M_IOV); 276 free(consbuffer, M_TEMP); 277 return; 278 } 279 280 int 281 printf(const char *fmt, ...) 282 { 283 va_list ap; 284 int savintr; 285 struct putchar_arg pca; 286 int retval; 287 288 savintr = consintr; /* disable interrupts */ 289 consintr = 0; 290 va_start(ap, fmt); 291 pca.tty = NULL; 292 pca.flags = TOCONS | TOLOG; 293 pca.pri = -1; 294 retval = kvprintf(fmt, putchar, &pca, 10, ap); 295 va_end(ap); 296 if (!panicstr) 297 msgbuftrigger = 1; 298 consintr = savintr; /* reenable interrupts */ 299 return (retval); 300 } 301 302 int 303 vprintf(const char *fmt, va_list ap) 304 { 305 int savintr; 306 struct putchar_arg pca; 307 int retval; 308 309 savintr = consintr; /* disable interrupts */ 310 consintr = 0; 311 pca.tty = NULL; 312 pca.flags = TOCONS | TOLOG; 313 pca.pri = -1; 314 retval = kvprintf(fmt, putchar, &pca, 10, ap); 315 if (!panicstr) 316 msgbuftrigger = 1; 317 consintr = savintr; /* reenable interrupts */ 318 return (retval); 319 } 320 321 /* 322 * Print a character on console or users terminal. If destination is 323 * the console then the last bunch of characters are saved in msgbuf for 324 * inspection later. 325 */ 326 static void 327 putchar(int c, void *arg) 328 { 329 struct putchar_arg *ap = (struct putchar_arg*) arg; 330 struct tty *tp = ap->tty; 331 int consdirect, flags = ap->flags; 332 333 consdirect = ((flags & TOCONS) && constty == NULL); 334 /* Don't use the tty code after a panic or while in ddb. */ 335 if (panicstr) 336 consdirect = 1; 337 if (kdb_active) 338 consdirect = 1; 339 if (consdirect) { 340 if (c != '\0') 341 cnputc(c); 342 } else { 343 if ((flags & TOTTY) && tp != NULL) 344 tputchar(c, tp); 345 if (flags & TOCONS) { 346 if (constty != NULL) 347 msgbuf_addchar(&consmsgbuf, c); 348 if (always_console_output && c != '\0') 349 cnputc(c); 350 } 351 } 352 if ((flags & TOLOG)) 353 msglogchar(c, ap->pri); 354 } 355 356 /* 357 * Scaled down version of sprintf(3). 358 */ 359 int 360 sprintf(char *buf, const char *cfmt, ...) 361 { 362 int retval; 363 va_list ap; 364 365 va_start(ap, cfmt); 366 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 367 buf[retval] = '\0'; 368 va_end(ap); 369 return (retval); 370 } 371 372 /* 373 * Scaled down version of vsprintf(3). 374 */ 375 int 376 vsprintf(char *buf, const char *cfmt, va_list ap) 377 { 378 int retval; 379 380 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 381 buf[retval] = '\0'; 382 return (retval); 383 } 384 385 /* 386 * Scaled down version of snprintf(3). 387 */ 388 int 389 snprintf(char *str, size_t size, const char *format, ...) 390 { 391 int retval; 392 va_list ap; 393 394 va_start(ap, format); 395 retval = vsnprintf(str, size, format, ap); 396 va_end(ap); 397 return(retval); 398 } 399 400 /* 401 * Scaled down version of vsnprintf(3). 402 */ 403 int 404 vsnprintf(char *str, size_t size, const char *format, va_list ap) 405 { 406 struct snprintf_arg info; 407 int retval; 408 409 info.str = str; 410 info.remain = size; 411 retval = kvprintf(format, snprintf_func, &info, 10, ap); 412 if (info.remain >= 1) 413 *info.str++ = '\0'; 414 return (retval); 415 } 416 417 /* 418 * Kernel version which takes radix argument vsnprintf(3). 419 */ 420 int 421 vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap) 422 { 423 struct snprintf_arg info; 424 int retval; 425 426 info.str = str; 427 info.remain = size; 428 retval = kvprintf(format, snprintf_func, &info, radix, ap); 429 if (info.remain >= 1) 430 *info.str++ = '\0'; 431 return (retval); 432 } 433 434 static void 435 snprintf_func(int ch, void *arg) 436 { 437 struct snprintf_arg *const info = arg; 438 439 if (info->remain >= 2) { 440 *info->str++ = ch; 441 info->remain--; 442 } 443 } 444 445 /* 446 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 447 * order; return an optional length and a pointer to the last character 448 * written in the buffer (i.e., the first character of the string). 449 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 450 */ 451 static char * 452 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp) 453 { 454 char *p; 455 456 p = nbuf; 457 *p = '\0'; 458 do { 459 *++p = hex2ascii(num % base); 460 } while (num /= base); 461 if (lenp) 462 *lenp = p - nbuf; 463 return (p); 464 } 465 466 /* 467 * Scaled down version of printf(3). 468 * 469 * Two additional formats: 470 * 471 * The format %b is supported to decode error registers. 472 * Its usage is: 473 * 474 * printf("reg=%b\n", regval, "<base><arg>*"); 475 * 476 * where <base> is the output base expressed as a control character, e.g. 477 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 478 * the first of which gives the bit number to be inspected (origin 1), and 479 * the next characters (up to a control character, i.e. a character <= 32), 480 * give the name of the register. Thus: 481 * 482 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 483 * 484 * would produce output: 485 * 486 * reg=3<BITTWO,BITONE> 487 * 488 * XXX: %D -- Hexdump, takes pointer and separator string: 489 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 490 * ("%*D", len, ptr, " " -> XX XX XX XX ... 491 */ 492 int 493 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 494 { 495 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 496 char nbuf[MAXNBUF]; 497 char *d; 498 const char *p, *percent, *q; 499 u_char *up; 500 int ch, n; 501 uintmax_t num; 502 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 503 int cflag, hflag, jflag, tflag, zflag; 504 int dwidth; 505 char padc; 506 int retval = 0; 507 508 num = 0; 509 if (!func) 510 d = (char *) arg; 511 else 512 d = NULL; 513 514 if (fmt == NULL) 515 fmt = "(fmt null)\n"; 516 517 if (radix < 2 || radix > 36) 518 radix = 10; 519 520 for (;;) { 521 padc = ' '; 522 width = 0; 523 while ((ch = (u_char)*fmt++) != '%') { 524 if (ch == '\0') 525 return (retval); 526 PCHAR(ch); 527 } 528 percent = fmt - 1; 529 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 530 sign = 0; dot = 0; dwidth = 0; 531 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 532 reswitch: switch (ch = (u_char)*fmt++) { 533 case '.': 534 dot = 1; 535 goto reswitch; 536 case '#': 537 sharpflag = 1; 538 goto reswitch; 539 case '+': 540 sign = 1; 541 goto reswitch; 542 case '-': 543 ladjust = 1; 544 goto reswitch; 545 case '%': 546 PCHAR(ch); 547 break; 548 case '*': 549 if (!dot) { 550 width = va_arg(ap, int); 551 if (width < 0) { 552 ladjust = !ladjust; 553 width = -width; 554 } 555 } else { 556 dwidth = va_arg(ap, int); 557 } 558 goto reswitch; 559 case '0': 560 if (!dot) { 561 padc = '0'; 562 goto reswitch; 563 } 564 case '1': case '2': case '3': case '4': 565 case '5': case '6': case '7': case '8': case '9': 566 for (n = 0;; ++fmt) { 567 n = n * 10 + ch - '0'; 568 ch = *fmt; 569 if (ch < '0' || ch > '9') 570 break; 571 } 572 if (dot) 573 dwidth = n; 574 else 575 width = n; 576 goto reswitch; 577 case 'b': 578 num = (u_int)va_arg(ap, int); 579 p = va_arg(ap, char *); 580 for (q = ksprintn(nbuf, num, *p++, NULL); *q;) 581 PCHAR(*q--); 582 583 if (num == 0) 584 break; 585 586 for (tmp = 0; *p;) { 587 n = *p++; 588 if (num & (1 << (n - 1))) { 589 PCHAR(tmp ? ',' : '<'); 590 for (; (n = *p) > ' '; ++p) 591 PCHAR(n); 592 tmp = 1; 593 } else 594 for (; *p > ' '; ++p) 595 continue; 596 } 597 if (tmp) 598 PCHAR('>'); 599 break; 600 case 'c': 601 PCHAR(va_arg(ap, int)); 602 break; 603 case 'D': 604 up = va_arg(ap, u_char *); 605 p = va_arg(ap, char *); 606 if (!width) 607 width = 16; 608 while(width--) { 609 PCHAR(hex2ascii(*up >> 4)); 610 PCHAR(hex2ascii(*up & 0x0f)); 611 up++; 612 if (width) 613 for (q=p;*q;q++) 614 PCHAR(*q); 615 } 616 break; 617 case 'd': 618 case 'i': 619 base = 10; 620 sign = 1; 621 goto handle_sign; 622 case 'h': 623 if (hflag) { 624 hflag = 0; 625 cflag = 1; 626 } else 627 hflag = 1; 628 goto reswitch; 629 case 'j': 630 jflag = 1; 631 goto reswitch; 632 case 'l': 633 if (lflag) { 634 lflag = 0; 635 qflag = 1; 636 } else 637 lflag = 1; 638 goto reswitch; 639 case 'n': 640 if (jflag) 641 *(va_arg(ap, intmax_t *)) = retval; 642 else if (qflag) 643 *(va_arg(ap, quad_t *)) = retval; 644 else if (lflag) 645 *(va_arg(ap, long *)) = retval; 646 else if (zflag) 647 *(va_arg(ap, size_t *)) = retval; 648 else if (hflag) 649 *(va_arg(ap, short *)) = retval; 650 else if (cflag) 651 *(va_arg(ap, char *)) = retval; 652 else 653 *(va_arg(ap, int *)) = retval; 654 break; 655 case 'o': 656 base = 8; 657 goto handle_nosign; 658 case 'p': 659 base = 16; 660 sharpflag = (width == 0); 661 sign = 0; 662 num = (uintptr_t)va_arg(ap, void *); 663 goto number; 664 case 'q': 665 qflag = 1; 666 goto reswitch; 667 case 'r': 668 base = radix; 669 if (sign) 670 goto handle_sign; 671 goto handle_nosign; 672 case 's': 673 p = va_arg(ap, char *); 674 if (p == NULL) 675 p = "(null)"; 676 if (!dot) 677 n = strlen (p); 678 else 679 for (n = 0; n < dwidth && p[n]; n++) 680 continue; 681 682 width -= n; 683 684 if (!ladjust && width > 0) 685 while (width--) 686 PCHAR(padc); 687 while (n--) 688 PCHAR(*p++); 689 if (ladjust && width > 0) 690 while (width--) 691 PCHAR(padc); 692 break; 693 case 't': 694 tflag = 1; 695 goto reswitch; 696 case 'u': 697 base = 10; 698 goto handle_nosign; 699 case 'x': 700 case 'X': 701 base = 16; 702 goto handle_nosign; 703 case 'y': 704 base = 16; 705 sign = 1; 706 goto handle_sign; 707 case 'z': 708 zflag = 1; 709 goto reswitch; 710 handle_nosign: 711 sign = 0; 712 if (jflag) 713 num = va_arg(ap, uintmax_t); 714 else if (qflag) 715 num = va_arg(ap, u_quad_t); 716 else if (tflag) 717 num = va_arg(ap, ptrdiff_t); 718 else if (lflag) 719 num = va_arg(ap, u_long); 720 else if (zflag) 721 num = va_arg(ap, size_t); 722 else if (hflag) 723 num = (u_short)va_arg(ap, int); 724 else if (cflag) 725 num = (u_char)va_arg(ap, int); 726 else 727 num = va_arg(ap, u_int); 728 goto number; 729 handle_sign: 730 if (jflag) 731 num = va_arg(ap, intmax_t); 732 else if (qflag) 733 num = va_arg(ap, quad_t); 734 else if (tflag) 735 num = va_arg(ap, ptrdiff_t); 736 else if (lflag) 737 num = va_arg(ap, long); 738 else if (zflag) 739 num = va_arg(ap, size_t); 740 else if (hflag) 741 num = (short)va_arg(ap, int); 742 else if (cflag) 743 num = (char)va_arg(ap, int); 744 else 745 num = va_arg(ap, int); 746 number: 747 if (sign && (intmax_t)num < 0) { 748 neg = 1; 749 num = -(intmax_t)num; 750 } 751 p = ksprintn(nbuf, num, base, &tmp); 752 if (sharpflag && num != 0) { 753 if (base == 8) 754 tmp++; 755 else if (base == 16) 756 tmp += 2; 757 } 758 if (neg) 759 tmp++; 760 761 if (!ladjust && width && (width -= tmp) > 0) 762 while (width--) 763 PCHAR(padc); 764 if (neg) 765 PCHAR('-'); 766 if (sharpflag && num != 0) { 767 if (base == 8) { 768 PCHAR('0'); 769 } else if (base == 16) { 770 PCHAR('0'); 771 PCHAR('x'); 772 } 773 } 774 775 while (*p) 776 PCHAR(*p--); 777 778 if (ladjust && width && (width -= tmp) > 0) 779 while (width--) 780 PCHAR(padc); 781 782 break; 783 default: 784 while (percent < fmt) 785 PCHAR(*percent++); 786 break; 787 } 788 } 789 #undef PCHAR 790 } 791 792 /* 793 * Put character in log buffer with a particular priority. 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 msgbuf_addchar(msgbufp, '\n'); 810 dangling = 0; 811 } 812 msgbuf_addchar(msgbufp, '<'); 813 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL); *p;) 814 msgbuf_addchar(msgbufp, *p--); 815 msgbuf_addchar(msgbufp, '>'); 816 lastpri = pri; 817 } 818 msgbuf_addchar(msgbufp, c); 819 if (c == '\n') { 820 dangling = 0; 821 lastpri = -1; 822 } else { 823 dangling = 1; 824 } 825 } 826 827 void 828 msgbufinit(void *ptr, int size) 829 { 830 char *cp; 831 static struct msgbuf *oldp = NULL; 832 833 size -= sizeof(*msgbufp); 834 cp = (char *)ptr; 835 msgbufp = (struct msgbuf *)(cp + size); 836 msgbuf_reinit(msgbufp, cp, size); 837 if (msgbufmapped && oldp != msgbufp) 838 msgbuf_copy(oldp, msgbufp); 839 msgbufmapped = 1; 840 oldp = msgbufp; 841 } 842 843 SYSCTL_DECL(_security_bsd); 844 845 static int unprivileged_read_msgbuf = 1; 846 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf, 847 CTLFLAG_RW, &unprivileged_read_msgbuf, 0, 848 "Unprivileged processes may read the kernel message buffer"); 849 850 /* Sysctls for accessing/clearing the msgbuf */ 851 static int 852 sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 853 { 854 char buf[128]; 855 u_int seq; 856 int error, len; 857 858 if (!unprivileged_read_msgbuf) { 859 error = suser(req->td); 860 if (error) 861 return (error); 862 } 863 864 /* Read the whole buffer, one chunk at a time. */ 865 msgbuf_peekbytes(msgbufp, NULL, 0, &seq); 866 while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) { 867 error = sysctl_handle_opaque(oidp, buf, len, req); 868 if (error) 869 return (error); 870 } 871 return (0); 872 } 873 874 SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD, 875 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 876 877 static int msgbuf_clearflag; 878 879 static int 880 sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 881 { 882 int error; 883 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 884 if (!error && req->newptr) { 885 msgbuf_clear(msgbufp); 886 msgbuf_clearflag = 0; 887 } 888 return (error); 889 } 890 891 SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 892 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0, 893 sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer"); 894 895 #ifdef DDB 896 897 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 898 { 899 int i, j; 900 901 if (!msgbufmapped) { 902 db_printf("msgbuf not mapped yet\n"); 903 return; 904 } 905 db_printf("msgbufp = %p\n", msgbufp); 906 db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n", 907 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq, 908 msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum); 909 for (i = 0; i < msgbufp->msg_size; i++) { 910 j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq); 911 db_printf("%c", msgbufp->msg_ptr[j]); 912 } 913 db_printf("\n"); 914 } 915 916 #endif /* DDB */ 917 918 void 919 hexdump(void *ptr, int length, const char *hdr, int flags) 920 { 921 int i, j, k; 922 int cols; 923 unsigned char *cp; 924 char delim; 925 926 if ((flags & HD_DELIM_MASK) != 0) 927 delim = (flags & HD_DELIM_MASK) >> 8; 928 else 929 delim = ' '; 930 931 if ((flags & HD_COLUMN_MASK) != 0) 932 cols = flags & HD_COLUMN_MASK; 933 else 934 cols = 16; 935 936 cp = ptr; 937 for (i = 0; i < length; i+= cols) { 938 if (hdr != NULL) 939 printf("%s", hdr); 940 941 if ((flags & HD_OMIT_COUNT) == 0) 942 printf("%04x ", i); 943 944 if ((flags & HD_OMIT_HEX) == 0) { 945 for (j = 0; j < cols; j++) { 946 k = i + j; 947 if (k < length) 948 printf("%c%02x", delim, cp[k]); 949 else 950 printf(" "); 951 } 952 } 953 954 if ((flags & HD_OMIT_CHARS) == 0) { 955 printf(" |"); 956 for (j = 0; j < cols; j++) { 957 k = i + j; 958 if (k >= length) 959 printf(" "); 960 else if (cp[k] >= ' ' && cp[k] <= '~') 961 printf("%c", cp[k]); 962 else 963 printf("."); 964 } 965 printf("|\n"); 966 } 967 } 968 } 969 970