1 /* $NetBSD: subr_prf.c,v 1.37 1996/11/13 06:06:05 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1986, 1988, 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/buf.h> 46 #include <sys/conf.h> 47 #include <sys/reboot.h> 48 #include <sys/msgbuf.h> 49 #include <sys/proc.h> 50 #include <sys/ioctl.h> 51 #include <sys/vnode.h> 52 #include <sys/file.h> 53 #include <sys/tty.h> 54 #include <sys/tprintf.h> 55 #include <sys/syslog.h> 56 #include <sys/malloc.h> 57 58 #include <dev/cons.h> 59 60 /* 61 * Note that stdarg.h and the ANSI style va_start macro is used for both 62 * ANSI and traditional C compilers. 63 * XXX: This requires that stdarg.h defines: va_alist, va_dcl 64 */ 65 #include <machine/stdarg.h> 66 67 #include "ipkdb.h" 68 69 #ifdef KADB 70 #include <machine/kdbparam.h> 71 #endif 72 #ifdef KGDB 73 #include <machine/cpu.h> 74 #endif 75 76 #define TOCONS 0x01 77 #define TOTTY 0x02 78 #define TOLOG 0x04 79 80 /* 81 * This is the size of the buffer that should be passed to ksnprintn(). 82 * It's the length of a long in base 8, plus NULL. 83 */ 84 #define KSNPRINTN_BUFSIZE (sizeof(long) * NBBY / 3 + 2) 85 86 struct tty *constty; /* pointer to console "window" tty */ 87 88 void (*v_putc) __P((int)) = cnputc; /* routine to putc on virtual console */ 89 90 static void putchar __P((int, int, struct tty *)); 91 static char *ksnprintn __P((u_long, int, int *, char *, size_t)); 92 void kprintf __P((const char *, int, struct tty *, va_list)); 93 94 int consintr = 1; /* Ok to handle console interrupts? */ 95 96 /* 97 * Variable panicstr contains argument to first call to panic; used as flag 98 * to indicate that the kernel has already called panic. 99 */ 100 const char *panicstr; 101 102 /* 103 * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 104 * and then reboots. If we are called twice, then we avoid trying to sync 105 * the disks as this often leads to recursive panics. 106 */ 107 void 108 #ifdef __STDC__ 109 panic(const char *fmt, ...) 110 #else 111 panic(fmt, va_alist) 112 char *fmt; 113 va_dcl 114 #endif 115 { 116 int bootopt; 117 va_list ap; 118 119 bootopt = RB_AUTOBOOT | RB_DUMP; 120 if (panicstr) 121 bootopt |= RB_NOSYNC; 122 else 123 panicstr = fmt; 124 125 va_start(ap, fmt); 126 printf("panic: %:\n", fmt, ap); 127 va_end(ap); 128 129 #if NIPKDB > 0 130 ipkdb_panic(); 131 #endif 132 #ifdef KGDB 133 kgdb_panic(); 134 #endif 135 #ifdef KADB 136 if (boothowto & RB_KDB) 137 kdbpanic(); 138 #endif 139 #ifdef DDB 140 Debugger(); 141 #endif 142 boot(bootopt, NULL); 143 } 144 145 /* 146 * Warn that a system table is full. 147 */ 148 void 149 tablefull(tab) 150 const char *tab; 151 { 152 153 log(LOG_ERR, "%s: table is full\n", tab); 154 } 155 156 /* 157 * Uprintf prints to the controlling terminal for the current process. 158 * It may block if the tty queue is overfull. No message is printed if 159 * the queue does not clear in a reasonable time. 160 */ 161 void 162 #ifdef __STDC__ 163 uprintf(const char *fmt, ...) 164 #else 165 uprintf(fmt, va_alist) 166 char *fmt; 167 va_dcl 168 #endif 169 { 170 register struct proc *p = curproc; 171 va_list ap; 172 173 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 174 va_start(ap, fmt); 175 kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); 176 va_end(ap); 177 } 178 } 179 180 tpr_t 181 tprintf_open(p) 182 register struct proc *p; 183 { 184 185 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 186 SESSHOLD(p->p_session); 187 return ((tpr_t) p->p_session); 188 } 189 return ((tpr_t) NULL); 190 } 191 192 void 193 tprintf_close(sess) 194 tpr_t sess; 195 { 196 197 if (sess) 198 SESSRELE((struct session *) sess); 199 } 200 201 /* 202 * tprintf prints on the controlling terminal associated 203 * with the given session. 204 */ 205 void 206 #ifdef __STDC__ 207 tprintf(tpr_t tpr, const char *fmt, ...) 208 #else 209 tprintf(tpr, fmt, va_alist) 210 tpr_t tpr; 211 char *fmt; 212 va_dcl 213 #endif 214 { 215 register struct session *sess = (struct session *)tpr; 216 struct tty *tp = NULL; 217 int flags = TOLOG; 218 va_list ap; 219 220 logpri(LOG_INFO); 221 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 222 flags |= TOTTY; 223 tp = sess->s_ttyp; 224 } 225 va_start(ap, fmt); 226 kprintf(fmt, flags, tp, ap); 227 va_end(ap); 228 logwakeup(); 229 } 230 231 /* 232 * Ttyprintf displays a message on a tty; it should be used only by 233 * the tty driver, or anything that knows the underlying tty will not 234 * be revoke(2)'d away. Other callers should use tprintf. 235 */ 236 void 237 #ifdef __STDC__ 238 ttyprintf(struct tty *tp, const char *fmt, ...) 239 #else 240 ttyprintf(tp, fmt, va_alist) 241 struct tty *tp; 242 char *fmt; 243 va_dcl 244 #endif 245 { 246 va_list ap; 247 248 va_start(ap, fmt); 249 kprintf(fmt, TOTTY, tp, ap); 250 va_end(ap); 251 } 252 253 extern int log_open; 254 255 /* 256 * Log writes to the log buffer, and guarantees not to sleep (so can be 257 * called by interrupt routines). If there is no process reading the 258 * log yet, it writes to the console also. 259 */ 260 void 261 #ifdef __STDC__ 262 log(int level, const char *fmt, ...) 263 #else 264 log(level, fmt, va_alist) 265 int level; 266 char *fmt; 267 va_dcl 268 #endif 269 { 270 register int s; 271 va_list ap; 272 273 s = splhigh(); 274 logpri(level); 275 va_start(ap, fmt); 276 kprintf(fmt, TOLOG, NULL, ap); 277 splx(s); 278 va_end(ap); 279 if (!log_open) { 280 va_start(ap, fmt); 281 kprintf(fmt, TOCONS, NULL, ap); 282 va_end(ap); 283 } 284 logwakeup(); 285 } 286 287 void 288 logpri(level) 289 int level; 290 { 291 register int ch; 292 register char *p; 293 char snbuf[KSNPRINTN_BUFSIZE]; 294 295 putchar('<', TOLOG, NULL); 296 for (p = ksnprintn((u_long)level, 10, NULL, snbuf, sizeof(snbuf)); 297 (ch = *p--) != 0;) 298 putchar(ch, TOLOG, NULL); 299 putchar('>', TOLOG, NULL); 300 } 301 302 void 303 #ifdef __STDC__ 304 addlog(const char *fmt, ...) 305 #else 306 addlog(fmt, va_alist) 307 char *fmt; 308 va_dcl 309 #endif 310 { 311 register int s; 312 va_list ap; 313 314 s = splhigh(); 315 va_start(ap, fmt); 316 kprintf(fmt, TOLOG, NULL, ap); 317 splx(s); 318 va_end(ap); 319 if (!log_open) { 320 va_start(ap, fmt); 321 kprintf(fmt, TOCONS, NULL, ap); 322 va_end(ap); 323 } 324 logwakeup(); 325 } 326 327 void 328 #ifdef __STDC__ 329 printf(const char *fmt, ...) 330 #else 331 printf(fmt, va_alist) 332 char *fmt; 333 va_dcl 334 #endif 335 { 336 va_list ap; 337 register int savintr; 338 339 savintr = consintr; /* disable interrupts */ 340 consintr = 0; 341 va_start(ap, fmt); 342 kprintf(fmt, TOCONS | TOLOG, NULL, ap); 343 va_end(ap); 344 if (!panicstr) 345 logwakeup(); 346 consintr = savintr; /* reenable interrupts */ 347 } 348 349 /* 350 * Scaled down version of printf(3). 351 * 352 * Two additional formats: 353 * 354 * The format %b is supported to decode error registers. 355 * Its usage is: 356 * 357 * printf("reg=%b\n", regval, "<base><arg>*"); 358 * 359 * where <base> is the output base expressed as a control character, e.g. 360 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 361 * the first of which gives the bit number to be inspected (origin 1), and 362 * the next characters (up to a control character, i.e. a character <= 32), 363 * give the name of the register. Thus: 364 * 365 * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 366 * 367 * would produce output: 368 * 369 * reg=3<BITTWO,BITONE> 370 * 371 * The format %: passes an additional format string and argument list 372 * recursively. Its usage is: 373 * 374 * fn(char *fmt, ...) 375 * { 376 * va_list ap; 377 * va_start(ap, fmt); 378 * printf("prefix: %: suffix\n", fmt, ap); 379 * va_end(ap); 380 * } 381 * 382 * Space or zero padding and a field width are supported for the numeric 383 * formats only. 384 */ 385 void 386 kprintf(fmt, flags, tp, ap) 387 register const char *fmt; 388 int flags; 389 struct tty *tp; 390 va_list ap; 391 { 392 register char *p, *q; 393 register int ch, n; 394 u_long ul; 395 int base, lflag, tmp, width; 396 char padc, snbuf[KSNPRINTN_BUFSIZE]; 397 398 for (;;) { 399 padc = ' '; 400 width = 0; 401 while ((ch = *(const u_char *)fmt++) != '%') { 402 if (ch == '\0') 403 return; 404 putchar(ch, flags, tp); 405 } 406 lflag = 0; 407 reswitch: switch (ch = *(const u_char *)fmt++) { 408 case '0': 409 case '.': 410 padc = '0'; 411 goto reswitch; 412 case '1': case '2': case '3': case '4': 413 case '5': case '6': case '7': case '8': case '9': 414 for (width = 0;; ++fmt) { 415 width = width * 10 + ch - '0'; 416 ch = *fmt; 417 if (ch < '0' || ch > '9') 418 break; 419 } 420 goto reswitch; 421 case 'l': 422 lflag = 1; 423 goto reswitch; 424 case 'b': 425 ul = va_arg(ap, int); 426 p = va_arg(ap, char *); 427 for (q = ksnprintn(ul, *p++, NULL, snbuf, 428 sizeof(snbuf)); (ch = *q--) != 0;) 429 putchar(ch, flags, tp); 430 431 if (!ul) 432 break; 433 434 for (tmp = 0; (n = *p++) != 0;) { 435 if (ul & (1 << (n - 1))) { 436 putchar(tmp ? ',' : '<', flags, tp); 437 for (; (n = *p) > ' '; ++p) 438 putchar(n, flags, tp); 439 tmp = 1; 440 } else 441 for (; *p > ' '; ++p) 442 continue; 443 } 444 if (tmp) 445 putchar('>', flags, tp); 446 break; 447 case 'c': 448 putchar(va_arg(ap, int), flags, tp); 449 break; 450 case ':': 451 p = va_arg(ap, char *); 452 kprintf(p, flags, tp, va_arg(ap, va_list)); 453 break; 454 case 's': 455 if ((p = va_arg(ap, char *)) == NULL) 456 p = "(null)"; 457 while ((ch = *p++) != 0) 458 putchar(ch, flags, tp); 459 break; 460 case 'd': 461 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 462 if ((long)ul < 0) { 463 putchar('-', flags, tp); 464 ul = -(long)ul; 465 } 466 base = 10; 467 goto number; 468 case 'o': 469 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 470 base = 8; 471 goto number; 472 case 'u': 473 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 474 base = 10; 475 goto number; 476 case 'p': 477 putchar('0', flags, tp); 478 putchar('x', flags, tp); 479 ul = (u_long)va_arg(ap, void *); 480 base = 16; 481 goto number; 482 case 'x': 483 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 484 base = 16; 485 number: p = ksnprintn(ul, base, &tmp, snbuf, sizeof(snbuf)); 486 if (width && (width -= tmp) > 0) 487 while (width--) 488 putchar(padc, flags, tp); 489 while ((ch = *p--) != 0) 490 putchar(ch, flags, tp); 491 break; 492 default: 493 putchar('%', flags, tp); 494 if (lflag) 495 putchar('l', flags, tp); 496 /* FALLTHROUGH */ 497 case '%': 498 putchar(ch, flags, tp); 499 } 500 } 501 } 502 503 /* 504 * Print a character on console or users terminal. If destination is 505 * the console then the last MSGBUFS characters are saved in msgbuf for 506 * inspection later. 507 */ 508 static void 509 putchar(c, flags, tp) 510 register int c; 511 int flags; 512 struct tty *tp; 513 { 514 extern int msgbufmapped; 515 register struct msgbuf *mbp; 516 517 if (panicstr) 518 constty = NULL; 519 if ((flags & TOCONS) && tp == NULL && constty) { 520 tp = constty; 521 flags |= TOTTY; 522 } 523 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 524 (flags & TOCONS) && tp == constty) 525 constty = NULL; 526 if ((flags & TOLOG) && 527 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 528 mbp = msgbufp; 529 if (mbp->msg_magic != MSG_MAGIC) { 530 bzero((caddr_t)mbp, sizeof(*mbp)); 531 mbp->msg_magic = MSG_MAGIC; 532 } 533 mbp->msg_bufc[mbp->msg_bufx++] = c; 534 if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 535 mbp->msg_bufx = 0; 536 } 537 if ((flags & TOCONS) && constty == NULL && c != '\0') 538 (*v_putc)(c); 539 } 540 541 /* 542 * Scaled down version of sprintf(3). 543 */ 544 int 545 #ifdef __STDC__ 546 sprintf(char *buf, const char *cfmt, ...) 547 #else 548 sprintf(buf, cfmt, va_alist) 549 char *buf; 550 const char *cfmt; 551 va_dcl 552 #endif 553 { 554 register const char *fmt = cfmt; 555 register char *p, *bp; 556 register int ch, base; 557 u_long ul; 558 int lflag, tmp, width; 559 va_list ap; 560 char padc, snbuf[KSNPRINTN_BUFSIZE]; 561 562 va_start(ap, cfmt); 563 for (bp = buf; ; ) { 564 padc = ' '; 565 width = 0; 566 while ((ch = *(const u_char *)fmt++) != '%') 567 if ((*bp++ = ch) == '\0') 568 return ((bp - buf) - 1); 569 570 lflag = 0; 571 reswitch: switch (ch = *(const u_char *)fmt++) { 572 case '0': 573 padc = '0'; 574 goto reswitch; 575 case '1': case '2': case '3': case '4': 576 case '5': case '6': case '7': case '8': case '9': 577 for (width = 0;; ++fmt) { 578 width = width * 10 + ch - '0'; 579 ch = *fmt; 580 if (ch < '0' || ch > '9') 581 break; 582 } 583 goto reswitch; 584 case 'l': 585 lflag = 1; 586 goto reswitch; 587 /* case 'b': ... break; XXX */ 588 case 'c': 589 *bp++ = va_arg(ap, int); 590 break; 591 /* case 'r': ... break; XXX */ 592 case 's': 593 p = va_arg(ap, char *); 594 while ((*bp++ = *p++) != 0) 595 continue; 596 --bp; 597 break; 598 case 'd': 599 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 600 if ((long)ul < 0) { 601 *bp++ = '-'; 602 ul = -(long)ul; 603 } 604 base = 10; 605 goto number; 606 break; 607 case 'o': 608 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 609 base = 8; 610 goto number; 611 break; 612 case 'u': 613 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 614 base = 10; 615 goto number; 616 break; 617 case 'p': 618 *bp++ = '0'; 619 *bp++ = 'x'; 620 ul = (u_long)va_arg(ap, void *); 621 base = 16; 622 goto number; 623 case 'x': 624 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 625 base = 16; 626 number: p = ksnprintn(ul, base, &tmp, snbuf, sizeof(snbuf)); 627 if (width && (width -= tmp) > 0) 628 while (width--) 629 *bp++ = padc; 630 while ((ch = *p--) != 0) 631 *bp++ = ch; 632 break; 633 default: 634 *bp++ = '%'; 635 if (lflag) 636 *bp++ = 'l'; 637 /* FALLTHROUGH */ 638 case '%': 639 *bp++ = ch; 640 } 641 } 642 va_end(ap); 643 } 644 645 /* 646 * Put a number (base <= 16) in a buffer in reverse order; return an 647 * optional length and a pointer to the NULL terminated (preceded?) 648 * buffer. 649 */ 650 static char * 651 ksnprintn(ul, base, lenp, buf, buflen) 652 register u_long ul; 653 register int base, *lenp; 654 char *buf; 655 size_t buflen; 656 { 657 register char *p; 658 659 p = buf; 660 *p = '\0'; /* ensure NULL `termination' */ 661 662 /* 663 * Don't even bother of the buffer's not big enough. No 664 * value at all is better than a wrong value, and we 665 * have a lot of control over the buffer that's passed 666 * to this function, since it's not exported. 667 */ 668 if (buflen < KSNPRINTN_BUFSIZE) 669 return (p); 670 671 do { 672 *++p = "0123456789abcdef"[ul % base]; 673 } while (ul /= base); 674 if (lenp) 675 *lenp = p - buf; 676 return (p); 677 } 678 679 /* 680 * Print a bitmask into the provided buffer, and return a pointer 681 * to that buffer. 682 */ 683 char * 684 bitmask_snprintf(ul, p, buf, buflen) 685 u_long ul; 686 const char *p; 687 char *buf; 688 size_t buflen; 689 { 690 char *bp, *q; 691 size_t left; 692 register int n; 693 int ch, tmp; 694 char snbuf[KSNPRINTN_BUFSIZE]; 695 696 bp = buf; 697 bzero(buf, buflen); 698 699 /* 700 * Always leave room for the trailing NULL. 701 */ 702 left = buflen - 1; 703 704 /* 705 * Print the value into the buffer. Abort if there's not 706 * enough room. 707 */ 708 if (buflen < KSNPRINTN_BUFSIZE) 709 return (buf); 710 711 for (q = ksnprintn(ul, *p++, NULL, snbuf, sizeof(snbuf)); 712 (ch = *q--) != 0;) { 713 *bp++ = ch; 714 left--; 715 } 716 717 /* 718 * If the value we printed was 0, or if we don't have room for 719 * "<x>", we're done. 720 */ 721 if (ul == 0 || left < 3) 722 return (buf); 723 724 #define PUTBYTE(b, c, l) \ 725 *(b)++ = (c); \ 726 if (--(l) == 0) \ 727 goto out; 728 729 for (tmp = 0; (n = *p++) != 0;) { 730 if (ul & (1 << (n - 1))) { 731 PUTBYTE(bp, tmp ? ',' : '<', left); 732 for (; (n = *p) > ' '; ++p) { 733 PUTBYTE(bp, n, left); 734 } 735 tmp = 1; 736 } else 737 for (; *p > ' '; ++p) 738 continue; 739 } 740 if (tmp) 741 *bp = '>'; 742 743 #undef PUTBYTE 744 745 out: 746 return (buf); 747 } 748