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