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.14 2006/12/20 18:14:41 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 kputchar (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 = kvcprintf(fmt, kputchar, &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 = kvcprintf(fmt, kputchar, &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 = kvcprintf(fmt, kputchar, &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 = kvcprintf(fmt, kputchar, &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 = kvcprintf(fmt, kputchar, &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 kprintf(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 = kvcprintf(fmt, kputchar, &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 /* 327 * Output to the console. (TO BE REMOVED) 328 * 329 * NOT YET ENTIRELY MPSAFE 330 */ 331 int 332 printf(const char *fmt, ...) 333 { 334 __va_list ap; 335 int savintr; 336 struct putchar_arg pca; 337 int retval; 338 339 savintr = consintr; /* disable interrupts */ 340 consintr = 0; 341 __va_start(ap, fmt); 342 pca.tty = NULL; 343 pca.flags = TOCONS | TOLOG; 344 pca.pri = -1; 345 cons_lock(); 346 retval = kvcprintf(fmt, kputchar, &pca, 10, ap); 347 cons_unlock(); 348 __va_end(ap); 349 if (!panicstr) 350 msgbuftrigger = 1; 351 consintr = savintr; /* reenable interrupts */ 352 return retval; 353 } 354 355 int 356 kvprintf(const char *fmt, __va_list ap) 357 { 358 int savintr; 359 struct putchar_arg pca; 360 int retval; 361 362 savintr = consintr; /* disable interrupts */ 363 consintr = 0; 364 pca.tty = NULL; 365 pca.flags = TOCONS | TOLOG; 366 pca.pri = -1; 367 cons_lock(); 368 retval = kvcprintf(fmt, kputchar, &pca, 10, ap); 369 cons_unlock(); 370 if (!panicstr) 371 msgbuftrigger = 1; 372 consintr = savintr; /* reenable interrupts */ 373 return retval; 374 } 375 376 /* 377 * Print a character on console or users terminal. If destination is 378 * the console then the last bunch of characters are saved in msgbuf for 379 * inspection later. 380 * 381 * NOT YET ENTIRELY MPSAFE, EVEN WHEN LOGGING JUST TO THE SYSCONSOLE. 382 */ 383 static void 384 kputchar(int c, void *arg) 385 { 386 struct putchar_arg *ap = (struct putchar_arg*) arg; 387 int flags = ap->flags; 388 struct tty *tp = ap->tty; 389 if (panicstr) 390 constty = NULL; 391 if ((flags & TOCONS) && tp == NULL && constty) { 392 tp = constty; 393 flags |= TOTTY; 394 } 395 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 396 (flags & TOCONS) && tp == constty) 397 constty = NULL; 398 if ((flags & TOLOG)) 399 msglogchar(c, ap->pri); 400 if ((flags & TOCONS) && constty == NULL && c != '\0') 401 (*v_putc)(c); 402 } 403 404 /* 405 * Scaled down version of sprintf(3). 406 */ 407 int 408 ksprintf(char *buf, const char *cfmt, ...) 409 { 410 int retval; 411 __va_list ap; 412 413 __va_start(ap, cfmt); 414 retval = kvcprintf(cfmt, NULL, (void *)buf, 10, ap); 415 buf[retval] = '\0'; 416 __va_end(ap); 417 return retval; 418 } 419 420 /* 421 * Scaled down version of vsprintf(3). 422 */ 423 int 424 kvsprintf(char *buf, const char *cfmt, __va_list ap) 425 { 426 int retval; 427 428 retval = kvcprintf(cfmt, NULL, (void *)buf, 10, ap); 429 buf[retval] = '\0'; 430 return retval; 431 } 432 433 /* 434 * Scaled down version of snprintf(3). 435 */ 436 int 437 ksnprintf(char *str, size_t size, const char *format, ...) 438 { 439 int retval; 440 __va_list ap; 441 442 __va_start(ap, format); 443 retval = kvsnprintf(str, size, format, ap); 444 __va_end(ap); 445 return(retval); 446 } 447 448 /* 449 * Scaled down version of vsnprintf(3). 450 */ 451 int 452 kvsnprintf(char *str, size_t size, const char *format, __va_list ap) 453 { 454 struct snprintf_arg info; 455 int retval; 456 457 info.str = str; 458 info.remain = size; 459 retval = kvcprintf(format, snprintf_func, &info, 10, ap); 460 if (info.remain >= 1) 461 *info.str++ = '\0'; 462 return retval; 463 } 464 465 static void 466 snprintf_func(int ch, void *arg) 467 { 468 struct snprintf_arg *const info = arg; 469 470 if (info->remain >= 2) { 471 *info->str++ = ch; 472 info->remain--; 473 } 474 } 475 476 /* 477 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 478 * order; return an optional length and a pointer to the last character 479 * written in the buffer (i.e., the first character of the string). 480 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 481 */ 482 static char * 483 ksprintn(nbuf, ul, base, lenp) 484 char *nbuf; 485 u_long ul; 486 int base, *lenp; 487 { 488 char *p; 489 490 p = nbuf; 491 *p = '\0'; 492 do { 493 *++p = hex2ascii(ul % base); 494 } while (ul /= base); 495 if (lenp) 496 *lenp = p - nbuf; 497 return (p); 498 } 499 /* ksprintn, but for a quad_t. */ 500 static char * 501 ksprintqn(nbuf, uq, base, lenp) 502 char *nbuf; 503 u_quad_t uq; 504 int base, *lenp; 505 { 506 char *p; 507 508 p = nbuf; 509 *p = '\0'; 510 do { 511 *++p = hex2ascii(uq % base); 512 } while (uq /= base); 513 if (lenp) 514 *lenp = p - nbuf; 515 return (p); 516 } 517 518 /* 519 * Scaled down version of printf(3). 520 * 521 * Two additional formats: 522 * 523 * The format %b is supported to decode error registers. 524 * Its usage is: 525 * 526 * printf("reg=%b\n", regval, "<base><arg>*"); 527 * 528 * where <base> is the output base expressed as a control character, e.g. 529 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 530 * the first of which gives the bit number to be inspected (origin 1), and 531 * the next characters (up to a control character, i.e. a character <= 32), 532 * give the name of the register. Thus: 533 * 534 * kvcprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 535 * 536 * would produce output: 537 * 538 * reg=3<BITTWO,BITONE> 539 * 540 * XXX: %D -- Hexdump, takes pointer and separator string: 541 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 542 * ("%*D", len, ptr, " " -> XX XX XX XX ... 543 */ 544 int 545 kvcprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, __va_list ap) 546 { 547 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 548 char nbuf[MAXNBUF]; 549 char *p, *q, *d; 550 u_char *up; 551 int ch, n; 552 u_long ul; 553 u_quad_t uq; 554 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 555 int dwidth; 556 char padc; 557 int retval = 0; 558 559 ul = 0; 560 uq = 0; 561 if (!func) 562 d = (char *) arg; 563 else 564 d = NULL; 565 566 if (fmt == NULL) 567 fmt = "(fmt null)\n"; 568 569 if (radix < 2 || radix > 36) 570 radix = 10; 571 572 for (;;) { 573 padc = ' '; 574 width = 0; 575 while ((ch = (u_char)*fmt++) != '%') { 576 if (ch == '\0') 577 return retval; 578 PCHAR(ch); 579 } 580 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 581 sign = 0; dot = 0; dwidth = 0; 582 reswitch: switch (ch = (u_char)*fmt++) { 583 case '.': 584 dot = 1; 585 goto reswitch; 586 case '#': 587 sharpflag = 1; 588 goto reswitch; 589 case '+': 590 sign = 1; 591 goto reswitch; 592 case '-': 593 ladjust = 1; 594 goto reswitch; 595 case '%': 596 PCHAR(ch); 597 break; 598 case '*': 599 if (!dot) { 600 width = __va_arg(ap, int); 601 if (width < 0) { 602 ladjust = !ladjust; 603 width = -width; 604 } 605 } else { 606 dwidth = __va_arg(ap, int); 607 } 608 goto reswitch; 609 case '0': 610 if (!dot) { 611 padc = '0'; 612 goto reswitch; 613 } 614 case '1': case '2': case '3': case '4': 615 case '5': case '6': case '7': case '8': case '9': 616 for (n = 0;; ++fmt) { 617 n = n * 10 + ch - '0'; 618 ch = *fmt; 619 if (ch < '0' || ch > '9') 620 break; 621 } 622 if (dot) 623 dwidth = n; 624 else 625 width = n; 626 goto reswitch; 627 case 'b': 628 ul = __va_arg(ap, int); 629 p = __va_arg(ap, char *); 630 for (q = ksprintn(nbuf, ul, *p++, NULL); *q;) 631 PCHAR(*q--); 632 633 if (!ul) 634 break; 635 636 for (tmp = 0; *p;) { 637 n = *p++; 638 if (ul & (1 << (n - 1))) { 639 PCHAR(tmp ? ',' : '<'); 640 for (; (n = *p) > ' '; ++p) 641 PCHAR(n); 642 tmp = 1; 643 } else 644 for (; *p > ' '; ++p) 645 continue; 646 } 647 if (tmp) 648 PCHAR('>'); 649 break; 650 case 'c': 651 PCHAR(__va_arg(ap, int)); 652 break; 653 case 'D': 654 up = __va_arg(ap, u_char *); 655 p = __va_arg(ap, char *); 656 if (!width) 657 width = 16; 658 while(width--) { 659 PCHAR(hex2ascii(*up >> 4)); 660 PCHAR(hex2ascii(*up & 0x0f)); 661 up++; 662 if (width) 663 for (q=p;*q;q++) 664 PCHAR(*q); 665 } 666 break; 667 case 'd': 668 if (qflag) 669 uq = __va_arg(ap, quad_t); 670 else if (lflag) 671 ul = __va_arg(ap, long); 672 else 673 ul = __va_arg(ap, int); 674 sign = 1; 675 base = 10; 676 goto number; 677 case 'l': 678 if (lflag) { 679 lflag = 0; 680 qflag = 1; 681 } else 682 lflag = 1; 683 goto reswitch; 684 case 'o': 685 if (qflag) 686 uq = __va_arg(ap, u_quad_t); 687 else if (lflag) 688 ul = __va_arg(ap, u_long); 689 else 690 ul = __va_arg(ap, u_int); 691 base = 8; 692 goto nosign; 693 case 'p': 694 ul = (uintptr_t)__va_arg(ap, void *); 695 base = 16; 696 sharpflag = (width == 0); 697 goto nosign; 698 case 'q': 699 qflag = 1; 700 goto reswitch; 701 case 'n': 702 case 'r': 703 if (qflag) 704 uq = __va_arg(ap, u_quad_t); 705 else if (lflag) 706 ul = __va_arg(ap, u_long); 707 else 708 ul = sign ? 709 (u_long)__va_arg(ap, int) : __va_arg(ap, u_int); 710 base = radix; 711 goto number; 712 case 's': 713 p = __va_arg(ap, char *); 714 if (p == NULL) 715 p = "(null)"; 716 if (!dot) 717 n = strlen (p); 718 else 719 for (n = 0; n < dwidth && p[n]; n++) 720 continue; 721 722 width -= n; 723 724 if (!ladjust && width > 0) 725 while (width--) 726 PCHAR(padc); 727 while (n--) 728 PCHAR(*p++); 729 if (ladjust && width > 0) 730 while (width--) 731 PCHAR(padc); 732 break; 733 case 'u': 734 if (qflag) 735 uq = __va_arg(ap, u_quad_t); 736 else if (lflag) 737 ul = __va_arg(ap, u_long); 738 else 739 ul = __va_arg(ap, u_int); 740 base = 10; 741 goto nosign; 742 case 'x': 743 case 'X': 744 if (qflag) 745 uq = __va_arg(ap, u_quad_t); 746 else if (lflag) 747 ul = __va_arg(ap, u_long); 748 else 749 ul = __va_arg(ap, u_int); 750 base = 16; 751 goto nosign; 752 case 'z': 753 if (qflag) 754 uq = __va_arg(ap, u_quad_t); 755 else if (lflag) 756 ul = __va_arg(ap, u_long); 757 else 758 ul = sign ? 759 (u_long)__va_arg(ap, int) : __va_arg(ap, u_int); 760 base = 16; 761 goto number; 762 nosign: sign = 0; 763 number: 764 if (qflag) { 765 if (sign && (quad_t)uq < 0) { 766 neg = 1; 767 uq = -(quad_t)uq; 768 } 769 p = ksprintqn(nbuf, uq, base, &tmp); 770 } else { 771 if (sign && (long)ul < 0) { 772 neg = 1; 773 ul = -(long)ul; 774 } 775 p = ksprintn(nbuf, ul, base, &tmp); 776 } 777 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 778 if (base == 8) 779 tmp++; 780 else if (base == 16) 781 tmp += 2; 782 } 783 if (neg) 784 tmp++; 785 786 if (!ladjust && width && (width -= tmp) > 0) 787 while (width--) 788 PCHAR(padc); 789 if (neg) 790 PCHAR('-'); 791 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 792 if (base == 8) { 793 PCHAR('0'); 794 } else if (base == 16) { 795 PCHAR('0'); 796 PCHAR('x'); 797 } 798 } 799 800 while (*p) 801 PCHAR(*p--); 802 803 if (ladjust && width && (width -= tmp) > 0) 804 while (width--) 805 PCHAR(padc); 806 807 break; 808 default: 809 PCHAR('%'); 810 if (lflag) 811 PCHAR('l'); 812 PCHAR(ch); 813 break; 814 } 815 } 816 #undef PCHAR 817 } 818 819 /* 820 * Put character in log buffer with a particular priority. 821 * 822 * MPSAFE 823 */ 824 static void 825 msglogchar(int c, int pri) 826 { 827 static int lastpri = -1; 828 static int dangling; 829 char nbuf[MAXNBUF]; 830 char *p; 831 832 if (!msgbufmapped) 833 return; 834 if (c == '\0' || c == '\r') 835 return; 836 if (pri != -1 && pri != lastpri) { 837 if (dangling) { 838 msgaddchar('\n', NULL); 839 dangling = 0; 840 } 841 msgaddchar('<', NULL); 842 for (p = ksprintn(nbuf, (u_long)pri, 10, NULL); *p;) 843 msgaddchar(*p--, NULL); 844 msgaddchar('>', NULL); 845 lastpri = pri; 846 } 847 msgaddchar(c, NULL); 848 if (c == '\n') { 849 dangling = 0; 850 lastpri = -1; 851 } else { 852 dangling = 1; 853 } 854 } 855 856 /* 857 * Put char in log buffer. Make sure nothing blows up beyond repair if 858 * we have an MP race. 859 * 860 * MPSAFE. 861 */ 862 static void 863 msgaddchar(int c, void *dummy) 864 { 865 struct msgbuf *mbp; 866 int rindex; 867 int windex; 868 869 if (!msgbufmapped) 870 return; 871 mbp = msgbufp; 872 windex = mbp->msg_bufx; 873 mbp->msg_ptr[windex] = c; 874 if (++windex >= mbp->msg_size) 875 windex = 0; 876 rindex = mbp->msg_bufr; 877 if (windex == rindex) { 878 rindex += 32; 879 if (rindex >= mbp->msg_size) 880 rindex -= mbp->msg_size; 881 mbp->msg_bufr = rindex; 882 } 883 mbp->msg_bufx = windex; 884 } 885 886 static void 887 msgbufcopy(struct msgbuf *oldp) 888 { 889 int pos; 890 891 pos = oldp->msg_bufr; 892 while (pos != oldp->msg_bufx) { 893 msglogchar(oldp->msg_ptr[pos], -1); 894 if (++pos >= oldp->msg_size) 895 pos = 0; 896 } 897 } 898 899 void 900 msgbufinit(void *ptr, size_t size) 901 { 902 char *cp; 903 static struct msgbuf *oldp = NULL; 904 905 size -= sizeof(*msgbufp); 906 cp = (char *)ptr; 907 msgbufp = (struct msgbuf *) (cp + size); 908 if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_size != size || 909 msgbufp->msg_bufx >= size || msgbufp->msg_bufr >= size) { 910 bzero(cp, size); 911 bzero(msgbufp, sizeof(*msgbufp)); 912 msgbufp->msg_magic = MSG_MAGIC; 913 msgbufp->msg_size = (char *)msgbufp - cp; 914 } 915 msgbufp->msg_ptr = cp; 916 if (msgbufmapped && oldp != msgbufp) 917 msgbufcopy(oldp); 918 msgbufmapped = 1; 919 oldp = msgbufp; 920 } 921 922 /* Sysctls for accessing/clearing the msgbuf */ 923 924 static int 925 sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 926 { 927 struct ucred *cred; 928 int error; 929 930 /* 931 * Only wheel or root can access the message log. 932 */ 933 if (unprivileged_read_msgbuf == 0) { 934 KKASSERT(req->td->td_proc); 935 cred = req->td->td_proc->p_ucred; 936 937 if ((cred->cr_prison || groupmember(0, cred) == 0) && 938 suser(req->td) != 0 939 ) { 940 return (EPERM); 941 } 942 } 943 944 /* 945 * Unwind the buffer, so that it's linear (possibly starting with 946 * some initial nulls). 947 */ 948 error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr + msgbufp->msg_bufx, 949 msgbufp->msg_size - msgbufp->msg_bufx, req); 950 if (error) 951 return (error); 952 if (msgbufp->msg_bufx > 0) { 953 error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr, 954 msgbufp->msg_bufx, req); 955 } 956 return (error); 957 } 958 959 SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD, 960 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 961 962 static int msgbuf_clear; 963 964 static int 965 sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 966 { 967 int error; 968 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 969 if (!error && req->newptr) { 970 /* Clear the buffer and reset write pointer */ 971 bzero(msgbufp->msg_ptr, msgbufp->msg_size); 972 msgbufp->msg_bufr = msgbufp->msg_bufx = 0; 973 msgbuf_clear = 0; 974 } 975 return (error); 976 } 977 978 SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 979 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clear, 0, 980 sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer"); 981 982 #include "opt_ddb.h" 983 #ifdef DDB 984 #include <ddb/ddb.h> 985 986 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 987 { 988 int i, j; 989 990 if (!msgbufmapped) { 991 db_printf("msgbuf not mapped yet\n"); 992 return; 993 } 994 db_printf("msgbufp = %p\n", msgbufp); 995 db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n", 996 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, 997 msgbufp->msg_bufx, msgbufp->msg_ptr); 998 for (i = 0; i < msgbufp->msg_size; i++) { 999 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; 1000 db_printf("%c", msgbufp->msg_ptr[j]); 1001 } 1002 db_printf("\n"); 1003 } 1004 1005 #endif /* DDB */ 1006