1 /*- 2 * Copyright (c) 1986, 1988, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)subr_prf.c 7.32 (Berkeley) 11/01/91 8 */ 9 10 #include <sys/param.h> 11 #include <sys/systm.h> 12 #include <sys/buf.h> 13 #include <sys/conf.h> 14 #include <sys/reboot.h> 15 #include <sys/msgbuf.h> 16 #include <sys/proc.h> 17 #include <sys/ioctl.h> 18 #include <sys/vnode.h> 19 #include <sys/file.h> 20 #include <sys/tty.h> 21 #include <sys/tprintf.h> 22 #include <sys/syslog.h> 23 #include <sys/malloc.h> 24 25 /* 26 * Note that stdarg.h and the ANSI style va_start macro is used for both 27 * ANSI and traditional C compilers. 28 */ 29 #include <machine/stdarg.h> 30 31 #ifdef KADB 32 #include "machine/kdbparam.h" 33 #endif 34 35 #define TOCONS 0x01 36 #define TOTTY 0x02 37 #define TOLOG 0x04 38 39 struct tty *constty; /* pointer to console "window" tty */ 40 41 #ifdef KADB 42 extern cngetc(); /* standard console getc */ 43 int (*v_getc)() = cngetc; /* "" getc from virtual console */ 44 extern cnpoll(); 45 int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */ 46 #endif 47 extern cnputc(); /* standard console putc */ 48 int (*v_putc)() = cnputc; /* routine to putc on virtual console */ 49 50 void logpri __P((int level)); 51 static void putchar __P((int ch, int flags, struct tty *tp)); 52 static char *ksprintn __P((u_long num, int base, int *len)); 53 void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list ap, ...)); 54 55 int consintr = 1; /* Ok to handle console interrupts? */ 56 57 /* 58 * Variable panicstr contains argument to first call to panic; used as flag 59 * to indicate that the kernel has already called panic. 60 */ 61 const char *panicstr; 62 63 /* 64 * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 65 * and then reboots. If we are called twice, then we avoid trying to sync 66 * the disks as this often leads to recursive panics. 67 */ 68 void 69 #ifdef __STDC__ 70 panic(const char *fmt, ...) 71 #else 72 panic(fmt /*, va_alist */) 73 char *fmt; 74 #endif 75 { 76 int bootopt, savintr; 77 va_list ap; 78 79 bootopt = RB_AUTOBOOT | RB_DUMP; 80 if (panicstr) 81 bootopt |= RB_NOSYNC; 82 else 83 panicstr = fmt; 84 85 savintr = consintr; /* disable interrupts */ 86 consintr = 0; 87 88 va_start(ap, fmt); 89 kprintf("panic: ", TOCONS | TOLOG, NULL, ap); 90 kprintf(fmt, TOCONS | TOLOG, NULL, ap); 91 va_end(ap); 92 93 consintr = savintr; /* reenable interrupts */ 94 95 #ifdef KGDB 96 kgdb_panic(); 97 #endif 98 #ifdef KADB 99 if (boothowto & RB_KDB) { 100 int s; 101 102 s = splnet(); /* below kdb pri */ 103 setsoftkdb(); 104 splx(s); 105 } 106 #endif 107 boot(bootopt); 108 } 109 110 /* 111 * Warn that a system table is full. 112 */ 113 void 114 tablefull(tab) 115 char *tab; 116 { 117 118 log(LOG_ERR, "%s: table is full\n", tab); 119 } 120 121 /* 122 * Uprintf prints to the controlling terminal for the current process. 123 * It may block if the tty queue is overfull. No message is printed if 124 * the queue does not clear in a reasonable time. 125 */ 126 void 127 #ifdef __STDC__ 128 uprintf(const char *fmt, ...) 129 #else 130 uprintf(fmt /*, va_alist */) 131 char *fmt; 132 #endif 133 { 134 register struct proc *p = curproc; 135 va_list ap; 136 137 if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 138 va_start(ap, fmt); 139 kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); 140 va_end(ap); 141 } 142 } 143 144 tpr_t 145 tprintf_open(p) 146 register struct proc *p; 147 { 148 149 if (p->p_flag & SCTTY && p->p_session->s_ttyvp) { 150 SESSHOLD(p->p_session); 151 return ((tpr_t) p->p_session); 152 } 153 return ((tpr_t) NULL); 154 } 155 156 void 157 tprintf_close(sess) 158 tpr_t sess; 159 { 160 161 if (sess) 162 SESSRELE((struct session *) sess); 163 } 164 165 /* 166 * tprintf prints on the controlling terminal associated 167 * with the given session. 168 */ 169 void 170 #ifdef __STDC__ 171 tprintf(tpr_t tpr, const char *fmt, ...) 172 #else 173 tprintf(tpr, fmt /*, va_alist */) 174 tpr_t tpr; 175 char *fmt; 176 #endif 177 { 178 register struct session *sess = (struct session *)tpr; 179 struct tty *tp = NULL; 180 int flags = TOLOG; 181 va_list ap; 182 183 logpri(LOG_INFO); 184 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 185 flags |= TOTTY; 186 tp = sess->s_ttyp; 187 } 188 va_start(ap, fmt); 189 kprintf(fmt, flags, tp, ap); 190 va_end(ap); 191 logwakeup(); 192 } 193 194 /* 195 * Ttyprintf displays a message on a tty; it should be used only by 196 * the tty driver, or anything that knows the underlying tty will not 197 * be revoke(2)'d away. Other callers should use tprintf. 198 */ 199 void 200 #ifdef __STDC__ 201 ttyprintf(struct tty *tp, const char *fmt, ...) 202 #else 203 ttyprintf(tp, fmt /*, va_alist */) 204 struct tty *tp; 205 char *fmt; 206 #endif 207 { 208 va_list ap; 209 210 va_start(ap, fmt); 211 kprintf(fmt, TOTTY, tp, ap); 212 va_end(ap); 213 } 214 215 extern int log_open; 216 217 /* 218 * Log writes to the log buffer, and guarantees not to sleep (so can be 219 * called by interrupt routines). If there is no process reading the 220 * log yet, it writes to the console also. 221 */ 222 void 223 #ifdef __STDC__ 224 log(int level, const char *fmt, ...) 225 #else 226 log(level, fmt /*, va_alist */) 227 int level; 228 char *fmt; 229 #endif 230 { 231 register int s; 232 va_list ap; 233 234 s = splhigh(); 235 logpri(level); 236 va_start(ap, fmt); 237 kprintf(fmt, TOLOG, NULL, ap); 238 splx(s); 239 va_end(ap); 240 if (!log_open) { 241 va_start(ap, fmt); 242 kprintf(fmt, TOCONS, NULL, ap); 243 va_end(ap); 244 } 245 logwakeup(); 246 } 247 248 void 249 logpri(level) 250 int level; 251 { 252 register int ch; 253 register char *p; 254 255 putchar('<', TOLOG, NULL); 256 for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;) 257 putchar(ch, TOLOG, NULL); 258 putchar('>', TOLOG, NULL); 259 } 260 261 void 262 #ifdef __STDC__ 263 addlog(const char *fmt, ...) 264 #else 265 addlog(fmt /*, va_alist */) 266 char *fmt; 267 #endif 268 { 269 register int s; 270 va_list ap; 271 272 s = splhigh(); 273 va_start(ap, fmt); 274 kprintf(fmt, TOLOG, NULL, ap); 275 splx(s); 276 va_end(ap); 277 if (!log_open) { 278 va_start(ap, fmt); 279 kprintf(fmt, TOCONS, NULL, ap); 280 va_end(ap); 281 } 282 logwakeup(); 283 } 284 285 void 286 #ifdef __STDC__ 287 printf(const char *fmt, ...) 288 #else 289 printf(fmt /*, va_alist */) 290 char *fmt; 291 #endif 292 { 293 va_list ap; 294 register int savintr; 295 296 savintr = consintr; /* disable interrupts */ 297 consintr = 0; 298 va_start(ap, fmt); 299 kprintf(fmt, TOCONS | TOLOG, NULL, ap); 300 va_end(ap); 301 if (!panicstr) 302 logwakeup(); 303 consintr = savintr; /* reenable interrupts */ 304 } 305 306 /* 307 * Scaled down version of printf(3). 308 * 309 * Two additional formats: 310 * 311 * The format %b is supported to decode error registers. 312 * Its usage is: 313 * 314 * kprintf("reg=%b\n", regval, "<base><arg>*"); 315 * 316 * where <base> is the output base expressed as a control character, e.g. 317 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 318 * the first of which gives the bit number to be inspected (origin 1), and 319 * the next characters (up to a control character, i.e. a character <= 32), 320 * give the name of the register. Thus: 321 * 322 * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 323 * 324 * would produce output: 325 * 326 * reg=3<BITTWO,BITONE> 327 * 328 * The format %r passes an additional format string and argument list 329 * recursively. Its usage is: 330 * 331 * fn(char *fmt, ...) 332 * { 333 * va_list ap; 334 * va_start(ap, fmt); 335 * kprintf("prefix: %r: suffix\n", flags, tp, fmt, ap); 336 * va_end(ap); 337 * } 338 * 339 * Space or zero padding and a field width are supported for the numeric 340 * formats only. 341 */ 342 void 343 #ifdef __STDC__ 344 kprintf(const char *fmt, int flags, struct tty *tp, va_list ap, ...) 345 #else 346 kprintf(fmt, flags, tp) 347 register const char *fmt; 348 int flags; 349 struct tty *tp; 350 va_list ap; 351 #endif 352 { 353 register char *p; 354 register int ch, n; 355 u_long ul; 356 int base, lflag, tmp, width; 357 char padc; 358 359 for (;;) { 360 padc = ' '; 361 width = 0; 362 while ((ch = *(u_char *)fmt++) != '%') { 363 if (ch == '\0') 364 return; 365 putchar(ch, flags, tp); 366 } 367 lflag = 0; 368 reswitch: switch (ch = *(u_char *)fmt++) { 369 case '0': 370 padc = '0'; 371 goto reswitch; 372 case '1': case '2': case '3': case '4': 373 case '5': case '6': case '7': case '8': case '9': 374 for (width = 0;; ++fmt) { 375 width = width * 10 + ch - '0'; 376 ch = *fmt; 377 if (ch < '0' || ch > '9') 378 break; 379 } 380 goto reswitch; 381 case 'l': 382 lflag = 1; 383 goto reswitch; 384 case 'b': 385 ul = va_arg(ap, int); 386 p = va_arg(ap, char *); 387 for (p = ksprintn(ul, *p++, NULL); ch = *p--;) 388 putchar(ch, flags, tp); 389 390 if (!ul) 391 break; 392 393 for (tmp = 0; n = *p++;) { 394 if (ul & (1 << (n - 1))) { 395 putchar(tmp ? ',' : '<', flags, tp); 396 for (; (n = *p) > ' '; ++p) 397 putchar(n, flags, tp); 398 tmp = 1; 399 } else 400 for (; *p > ' '; ++p); 401 } 402 if (tmp) 403 putchar('>', flags, tp); 404 break; 405 case 'c': 406 putchar(va_arg(ap, int), flags, tp); 407 break; 408 case 'r': 409 p = va_arg(ap, char *); 410 kprintf(p, flags, tp, va_arg(ap, va_list)); 411 break; 412 case 's': 413 p = va_arg(ap, char *); 414 while (ch = *p++) 415 putchar(ch, flags, tp); 416 break; 417 case 'd': 418 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 419 if ((long)ul < 0) { 420 putchar('-', flags, tp); 421 ul = -(long)ul; 422 } 423 base = 10; 424 goto number; 425 case 'o': 426 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 427 base = 8; 428 goto number; 429 case 'u': 430 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 431 base = 10; 432 goto number; 433 case 'x': 434 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 435 base = 16; 436 number: p = ksprintn(ul, base, &tmp); 437 if (width && (width -= tmp) > 0) 438 while (width--) 439 putchar(padc, flags, tp); 440 while (ch = *p--) 441 putchar(ch, flags, tp); 442 break; 443 default: 444 putchar('%', flags, tp); 445 if (lflag) 446 putchar('l', flags, tp); 447 /* FALLTHROUGH */ 448 case '%': 449 putchar(ch, flags, tp); 450 } 451 } 452 } 453 454 /* 455 * Print a character on console or users terminal. If destination is 456 * the console then the last MSGBUFS characters are saved in msgbuf for 457 * inspection later. 458 */ 459 static void 460 putchar(c, flags, tp) 461 register int c; 462 int flags; 463 struct tty *tp; 464 { 465 extern int msgbufmapped; 466 register struct msgbuf *mbp; 467 468 if (panicstr) 469 constty = NULL; 470 if ((flags & TOCONS) && tp == NULL && constty) { 471 tp = constty; 472 flags |= TOTTY; 473 } 474 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 475 (flags & TOCONS) && tp == constty) 476 constty = NULL; 477 if ((flags & TOLOG) && 478 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 479 mbp = msgbufp; 480 if (mbp->msg_magic != MSG_MAGIC) { 481 bzero((caddr_t)mbp, sizeof(*mbp)); 482 mbp->msg_magic = MSG_MAGIC; 483 } 484 mbp->msg_bufc[mbp->msg_bufx++] = c; 485 if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 486 mbp->msg_bufx = 0; 487 } 488 if ((flags & TOCONS) && constty == NULL && c != '\0') 489 (*v_putc)(c); 490 } 491 492 /* 493 * Scaled down version of sprintf(3). 494 */ 495 #ifdef __STDC__ 496 sprintf(char *buf, const char *cfmt, ...) 497 #else 498 sprintf(buf, cfmt /*, va_alist */) 499 char *buf, *cfmt; 500 #endif 501 { 502 register const char *fmt = cfmt; 503 register char *p, *bp; 504 register int ch, base; 505 u_long ul; 506 int lflag; 507 va_list ap; 508 509 va_start(ap, cfmt); 510 for (bp = buf; ; ) { 511 while ((ch = *(u_char *)fmt++) != '%') 512 if ((*bp++ = ch) == '\0') 513 return ((bp - buf) - 1); 514 515 lflag = 0; 516 reswitch: switch (ch = *(u_char *)fmt++) { 517 case 'l': 518 lflag = 1; 519 goto reswitch; 520 case 'c': 521 *bp++ = va_arg(ap, int); 522 break; 523 case 's': 524 p = va_arg(ap, char *); 525 while (*bp++ = *p++) 526 ; 527 --bp; 528 break; 529 case 'd': 530 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 531 if ((long)ul < 0) { 532 *bp++ = '-'; 533 ul = -(long)ul; 534 } 535 base = 10; 536 goto number; 537 break; 538 case 'o': 539 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 540 base = 8; 541 goto number; 542 break; 543 case 'u': 544 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 545 base = 10; 546 goto number; 547 break; 548 case 'x': 549 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 550 base = 16; 551 number: for (p = ksprintn(ul, base, NULL); ch = *p--;) 552 *bp++ = ch; 553 break; 554 default: 555 *bp++ = '%'; 556 if (lflag) 557 *bp++ = 'l'; 558 /* FALLTHROUGH */ 559 case '%': 560 *bp++ = ch; 561 } 562 } 563 va_end(ap); 564 } 565 566 /* 567 * Put a number (base <= 16) in a buffer in reverse order; return an 568 * optional length and a pointer to the NULL terminated (preceded?) 569 * buffer. 570 */ 571 static char * 572 ksprintn(ul, base, lenp) 573 register u_long ul; 574 register int base, *lenp; 575 { /* A long in base 8, plus NULL. */ 576 static char buf[sizeof(long) * NBBY / 3 + 2]; 577 register char *p; 578 579 p = buf; 580 do { 581 *++p = "0123456789abcdef"[ul % base]; 582 } while (ul /= base); 583 if (lenp) 584 *lenp = p - buf; 585 return (p); 586 } 587