subr_prf.c revision 1.37 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