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