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