subr_prf.c revision 1.41 1 /* $NetBSD: subr_prf.c,v 1.41 1997/06/16 15:02:27 drochner 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(quad_t) * 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_quad_t, 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 #ifdef __powerpc__ /* XXX */
127 printf("panic: "); /* XXX */
128 vprintf(fmt, ap); /* XXX */
129 printf("\n"); /* XXX */
130 #else /* XXX */
131 printf("panic: %:\n", fmt, ap); /* XXX */
132 #endif /* XXX */
133 va_end(ap);
134
135 #if NIPKDB > 0
136 ipkdb_panic();
137 #endif
138 #ifdef KGDB
139 kgdb_panic();
140 #endif
141 #ifdef KADB
142 if (boothowto & RB_KDB)
143 kdbpanic();
144 #endif
145 #ifdef DDB
146 if (db_onpanic)
147 Debugger();
148 #endif
149 cpu_reboot(bootopt, NULL);
150 }
151
152 /*
153 * Warn that a system table is full.
154 */
155 void
156 tablefull(tab)
157 const char *tab;
158 {
159
160 log(LOG_ERR, "%s: table is full\n", tab);
161 }
162
163 /*
164 * Uprintf prints to the controlling terminal for the current process.
165 * It may block if the tty queue is overfull. No message is printed if
166 * the queue does not clear in a reasonable time.
167 */
168 void
169 #ifdef __STDC__
170 uprintf(const char *fmt, ...)
171 #else
172 uprintf(fmt, va_alist)
173 char *fmt;
174 va_dcl
175 #endif
176 {
177 register struct proc *p = curproc;
178 va_list ap;
179
180 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
181 va_start(ap, fmt);
182 kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
183 va_end(ap);
184 }
185 }
186
187 tpr_t
188 tprintf_open(p)
189 register struct proc *p;
190 {
191
192 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
193 SESSHOLD(p->p_session);
194 return ((tpr_t) p->p_session);
195 }
196 return ((tpr_t) NULL);
197 }
198
199 void
200 tprintf_close(sess)
201 tpr_t sess;
202 {
203
204 if (sess)
205 SESSRELE((struct session *) sess);
206 }
207
208 /*
209 * tprintf prints on the controlling terminal associated
210 * with the given session.
211 */
212 void
213 #ifdef __STDC__
214 tprintf(tpr_t tpr, const char *fmt, ...)
215 #else
216 tprintf(tpr, fmt, va_alist)
217 tpr_t tpr;
218 char *fmt;
219 va_dcl
220 #endif
221 {
222 register struct session *sess = (struct session *)tpr;
223 struct tty *tp = NULL;
224 int flags = TOLOG;
225 va_list ap;
226
227 logpri(LOG_INFO);
228 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
229 flags |= TOTTY;
230 tp = sess->s_ttyp;
231 }
232 va_start(ap, fmt);
233 kprintf(fmt, flags, tp, ap);
234 va_end(ap);
235 logwakeup();
236 }
237
238 /*
239 * Ttyprintf displays a message on a tty; it should be used only by
240 * the tty driver, or anything that knows the underlying tty will not
241 * be revoke(2)'d away. Other callers should use tprintf.
242 */
243 void
244 #ifdef __STDC__
245 ttyprintf(struct tty *tp, const char *fmt, ...)
246 #else
247 ttyprintf(tp, fmt, va_alist)
248 struct tty *tp;
249 char *fmt;
250 va_dcl
251 #endif
252 {
253 va_list ap;
254
255 va_start(ap, fmt);
256 kprintf(fmt, TOTTY, tp, ap);
257 va_end(ap);
258 }
259
260 extern int log_open;
261
262 /*
263 * Log writes to the log buffer, and guarantees not to sleep (so can be
264 * called by interrupt routines). If there is no process reading the
265 * log yet, it writes to the console also.
266 */
267 void
268 #ifdef __STDC__
269 log(int level, const char *fmt, ...)
270 #else
271 log(level, fmt, va_alist)
272 int level;
273 char *fmt;
274 va_dcl
275 #endif
276 {
277 register int s;
278 va_list ap;
279
280 s = splhigh();
281 logpri(level);
282 va_start(ap, fmt);
283 kprintf(fmt, TOLOG, NULL, ap);
284 splx(s);
285 va_end(ap);
286 if (!log_open) {
287 va_start(ap, fmt);
288 kprintf(fmt, TOCONS, NULL, ap);
289 va_end(ap);
290 }
291 logwakeup();
292 }
293
294 void
295 logpri(level)
296 int level;
297 {
298 register int ch;
299 register char *p;
300 char snbuf[KSNPRINTN_BUFSIZE];
301
302 putchar('<', TOLOG, NULL);
303 for (p = ksnprintn((u_long)level, 10, NULL, snbuf, sizeof(snbuf));
304 (ch = *p--) != 0;)
305 putchar(ch, TOLOG, NULL);
306 putchar('>', TOLOG, NULL);
307 }
308
309 void
310 #ifdef __STDC__
311 addlog(const char *fmt, ...)
312 #else
313 addlog(fmt, va_alist)
314 char *fmt;
315 va_dcl
316 #endif
317 {
318 register int s;
319 va_list ap;
320
321 s = splhigh();
322 va_start(ap, fmt);
323 kprintf(fmt, TOLOG, NULL, ap);
324 splx(s);
325 va_end(ap);
326 if (!log_open) {
327 va_start(ap, fmt);
328 kprintf(fmt, TOCONS, NULL, ap);
329 va_end(ap);
330 }
331 logwakeup();
332 }
333
334 void
335 #ifdef __STDC__
336 printf(const char *fmt, ...)
337 #else
338 printf(fmt, va_alist)
339 char *fmt;
340 va_dcl
341 #endif
342 {
343 va_list ap;
344 register int savintr;
345
346 savintr = consintr; /* disable interrupts */
347 consintr = 0;
348 va_start(ap, fmt);
349 kprintf(fmt, TOCONS | TOLOG, NULL, ap);
350 va_end(ap);
351 if (!panicstr)
352 logwakeup();
353 consintr = savintr; /* reenable interrupts */
354 }
355
356 #ifdef __powerpc__ /* XXX XXX XXX */
357 void
358 vprintf(fmt, ap)
359 const char *fmt;
360 va_list ap;
361 {
362 register int savintr;
363
364 savintr = consintr; /* disable interrupts */
365 consintr = 0;
366 kprintf(fmt, TOCONS | TOLOG, NULL, ap);
367 if (!panicstr)
368 logwakeup();
369 consintr = savintr; /* reenable interrupts */
370 }
371 #endif /* __powerpc__ */ /* XXX XXX XXX */
372
373 /*
374 * Scaled down version of printf(3).
375 *
376 * Two additional formats:
377 *
378 * The format %b is supported to decode error registers.
379 * Its usage is:
380 *
381 * printf("reg=%b\n", regval, "<base><arg>*");
382 *
383 * where <base> is the output base expressed as a control character, e.g.
384 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
385 * the first of which gives the bit number to be inspected (origin 1), and
386 * the next characters (up to a control character, i.e. a character <= 32),
387 * give the name of the register. Thus:
388 *
389 * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
390 *
391 * would produce output:
392 *
393 * reg=3<BITTWO,BITONE>
394 *
395 * The format %: passes an additional format string and argument list
396 * recursively. Its usage is:
397 *
398 * fn(char *fmt, ...)
399 * {
400 * va_list ap;
401 * va_start(ap, fmt);
402 * printf("prefix: %: suffix\n", fmt, ap);
403 * va_end(ap);
404 * }
405 *
406 * Space or zero padding and a field width are supported for the numeric
407 * formats only.
408 */
409 #define LONGINT 0x010 /* long integer */
410 #define QUADINT 0x020 /* quad integer */
411 #define SARG() \
412 (flags&QUADINT ? va_arg(ap, quad_t) : \
413 flags&LONGINT ? va_arg(ap, long) : \
414 (long)va_arg(ap, int))
415 #define UARG() \
416 (flags&QUADINT ? va_arg(ap, u_quad_t) : \
417 flags&LONGINT ? va_arg(ap, u_long) : \
418 (u_long)va_arg(ap, u_int))
419 void
420 kprintf(fmt, oflags, tp, ap)
421 register const char *fmt;
422 int oflags;
423 struct tty *tp;
424 va_list ap;
425 {
426 register char *p, *q;
427 register int ch, n;
428 u_quad_t ul;
429 int base, flags, tmp, width;
430 char padc, snbuf[KSNPRINTN_BUFSIZE];
431
432 for (;;) {
433 padc = ' ';
434 width = 0;
435 while ((ch = *(const u_char *)fmt++) != '%') {
436 if (ch == '\0')
437 return;
438 putchar(ch, oflags, tp);
439 }
440 flags = 0;
441 reswitch: switch (ch = *(const u_char *)fmt++) {
442 case '0':
443 case '.':
444 padc = '0';
445 goto reswitch;
446 case '1': case '2': case '3': case '4':
447 case '5': case '6': case '7': case '8': case '9':
448 for (width = 0;; ++fmt) {
449 width = width * 10 + ch - '0';
450 ch = *fmt;
451 if (ch < '0' || ch > '9')
452 break;
453 }
454 goto reswitch;
455 case 'l':
456 flags |= LONGINT;
457 goto reswitch;
458 case 'q':
459 flags |= QUADINT;
460 goto reswitch;
461 case 'b':
462 ul = va_arg(ap, int);
463 p = va_arg(ap, char *);
464 for (q = ksnprintn(ul, *p++, NULL, snbuf,
465 sizeof(snbuf)); (ch = *q--) != 0;)
466 putchar(ch, oflags, tp);
467
468 if (!ul)
469 break;
470
471 for (tmp = 0; (n = *p++) != 0;) {
472 if (ul & (1 << (n - 1))) {
473 putchar(tmp ? ',' : '<', oflags, tp);
474 for (; (n = *p) > ' '; ++p)
475 putchar(n, oflags, tp);
476 tmp = 1;
477 } else
478 for (; *p > ' '; ++p)
479 continue;
480 }
481 if (tmp)
482 putchar('>', oflags, tp);
483 break;
484 case 'c':
485 putchar(va_arg(ap, int), oflags, tp);
486 break;
487 #ifndef __powerpc__ /* XXX XXX XXX */
488 case ':':
489 p = va_arg(ap, char *);
490 kprintf(p, oflags, tp, va_arg(ap, va_list));
491 break;
492 #endif /* __powerpc__ */ /* XXX XXX XXX */
493 case 's':
494 if ((p = va_arg(ap, char *)) == NULL)
495 p = "(null)";
496 while ((ch = *p++) != 0)
497 putchar(ch, oflags, tp);
498 break;
499 case 'd':
500 ul = SARG();
501 if ((quad_t)ul < 0) {
502 putchar('-', oflags, tp);
503 ul = -ul;
504 }
505 base = 10;
506 goto number;
507 case 'o':
508 ul = UARG();
509 base = 8;
510 goto number;
511 case 'u':
512 ul = UARG();
513 base = 10;
514 goto number;
515 case 'p':
516 putchar('0', oflags, tp);
517 putchar('x', oflags, tp);
518 ul = (u_long)va_arg(ap, void *);
519 base = 16;
520 goto number;
521 case 'x':
522 ul = UARG();
523 base = 16;
524 number: p = ksnprintn(ul, base, &tmp, snbuf, sizeof(snbuf));
525 if (width && (width -= tmp) > 0)
526 while (width--)
527 putchar(padc, oflags, tp);
528 while ((ch = *p--) != 0)
529 putchar(ch, oflags, tp);
530 break;
531 default:
532 putchar('%', oflags, tp);
533 /* flags??? */
534 /* FALLTHROUGH */
535 case '%':
536 putchar(ch, oflags, tp);
537 }
538 }
539 }
540
541 /*
542 * Print a character on console or users terminal. If destination is
543 * the console then the last MSGBUFS characters are saved in msgbuf for
544 * inspection later.
545 */
546 static void
547 putchar(c, flags, tp)
548 register int c;
549 int flags;
550 struct tty *tp;
551 {
552 extern int msgbufmapped;
553 register struct msgbuf *mbp;
554
555 if (panicstr)
556 constty = NULL;
557 if ((flags & TOCONS) && tp == NULL && constty) {
558 tp = constty;
559 flags |= TOTTY;
560 }
561 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
562 (flags & TOCONS) && tp == constty)
563 constty = NULL;
564 if ((flags & TOLOG) &&
565 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
566 mbp = msgbufp;
567 if (mbp->msg_magic != MSG_MAGIC) {
568 bzero((caddr_t)mbp, sizeof(*mbp));
569 mbp->msg_magic = MSG_MAGIC;
570 }
571 mbp->msg_bufc[mbp->msg_bufx++] = c;
572 if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
573 mbp->msg_bufx = 0;
574 }
575 if ((flags & TOCONS) && constty == NULL && c != '\0')
576 (*v_putc)(c);
577 }
578
579 /*
580 * Scaled down version of sprintf(3).
581 */
582 int
583 #ifdef __STDC__
584 sprintf(char *buf, const char *cfmt, ...)
585 #else
586 sprintf(buf, cfmt, va_alist)
587 char *buf;
588 const char *cfmt;
589 va_dcl
590 #endif
591 {
592 register const char *fmt = cfmt;
593 register char *p, *bp;
594 register int ch, base;
595 u_quad_t ul;
596 int flags, tmp, width;
597 va_list ap;
598 char padc, snbuf[KSNPRINTN_BUFSIZE];
599
600 va_start(ap, cfmt);
601 for (bp = buf; ; ) {
602 padc = ' ';
603 width = 0;
604 while ((ch = *(const u_char *)fmt++) != '%')
605 if ((*bp++ = ch) == '\0')
606 return ((bp - buf) - 1);
607
608 flags = 0;
609 reswitch: switch (ch = *(const u_char *)fmt++) {
610 case '0':
611 padc = '0';
612 goto reswitch;
613 case '1': case '2': case '3': case '4':
614 case '5': case '6': case '7': case '8': case '9':
615 for (width = 0;; ++fmt) {
616 width = width * 10 + ch - '0';
617 ch = *fmt;
618 if (ch < '0' || ch > '9')
619 break;
620 }
621 goto reswitch;
622 case 'l':
623 flags |= LONGINT;
624 goto reswitch;
625 case 'q':
626 flags |= QUADINT;
627 goto reswitch;
628 /* case 'b': ... break; XXX */
629 case 'c':
630 *bp++ = va_arg(ap, int);
631 break;
632 /* case 'r': ... break; XXX */
633 case 's':
634 p = va_arg(ap, char *);
635 while ((*bp++ = *p++) != 0)
636 continue;
637 --bp;
638 break;
639 case 'd':
640 ul = SARG();
641 if ((quad_t)ul < 0) {
642 *bp++ = '-';
643 ul = -ul;
644 }
645 base = 10;
646 goto number;
647 case 'o':
648 ul = UARG();
649 base = 8;
650 goto number;
651 case 'u':
652 ul = UARG();
653 base = 10;
654 goto number;
655 case 'p':
656 *bp++ = '0';
657 *bp++ = 'x';
658 ul = (u_long)va_arg(ap, void *);
659 base = 16;
660 goto number;
661 case 'x':
662 ul = UARG();
663 base = 16;
664 number: p = ksnprintn(ul, base, &tmp, snbuf, sizeof(snbuf));
665 if (width && (width -= tmp) > 0)
666 while (width--)
667 *bp++ = padc;
668 while ((ch = *p--) != 0)
669 *bp++ = ch;
670 break;
671 default:
672 *bp++ = '%';
673 /* flags??? */
674 /* FALLTHROUGH */
675 case '%':
676 *bp++ = ch;
677 }
678 }
679 va_end(ap);
680 }
681
682 /*
683 * Put a number (base <= 16) in a buffer in reverse order; return an
684 * optional length and a pointer to the NULL terminated (preceded?)
685 * buffer.
686 */
687 static char *
688 ksnprintn(ul, base, lenp, buf, buflen)
689 register u_quad_t ul;
690 register int base, *lenp;
691 char *buf;
692 size_t buflen;
693 {
694 register char *p;
695
696 p = buf;
697 *p = '\0'; /* ensure NULL `termination' */
698
699 /*
700 * Don't even bother of the buffer's not big enough. No
701 * value at all is better than a wrong value, and we
702 * have a lot of control over the buffer that's passed
703 * to this function, since it's not exported.
704 */
705 if (buflen < KSNPRINTN_BUFSIZE)
706 return (p);
707
708 do {
709 *++p = "0123456789abcdef"[ul % base];
710 } while (ul /= base);
711 if (lenp)
712 *lenp = p - buf;
713 return (p);
714 }
715
716 /*
717 * Print a bitmask into the provided buffer, and return a pointer
718 * to that buffer.
719 */
720 char *
721 bitmask_snprintf(ul, p, buf, buflen)
722 u_long ul;
723 const char *p;
724 char *buf;
725 size_t buflen;
726 {
727 char *bp, *q;
728 size_t left;
729 register int n;
730 int ch, tmp;
731 char snbuf[KSNPRINTN_BUFSIZE];
732
733 bp = buf;
734 bzero(buf, buflen);
735
736 /*
737 * Always leave room for the trailing NULL.
738 */
739 left = buflen - 1;
740
741 /*
742 * Print the value into the buffer. Abort if there's not
743 * enough room.
744 */
745 if (buflen < KSNPRINTN_BUFSIZE)
746 return (buf);
747
748 for (q = ksnprintn(ul, *p++, NULL, snbuf, sizeof(snbuf));
749 (ch = *q--) != 0;) {
750 *bp++ = ch;
751 left--;
752 }
753
754 /*
755 * If the value we printed was 0, or if we don't have room for
756 * "<x>", we're done.
757 */
758 if (ul == 0 || left < 3)
759 return (buf);
760
761 #define PUTBYTE(b, c, l) \
762 *(b)++ = (c); \
763 if (--(l) == 0) \
764 goto out;
765
766 for (tmp = 0; (n = *p++) != 0;) {
767 if (ul & (1 << (n - 1))) {
768 PUTBYTE(bp, tmp ? ',' : '<', left);
769 for (; (n = *p) > ' '; ++p) {
770 PUTBYTE(bp, n, left);
771 }
772 tmp = 1;
773 } else
774 for (; *p > ' '; ++p)
775 continue;
776 }
777 if (tmp)
778 *bp = '>';
779
780 #undef PUTBYTE
781
782 out:
783 return (buf);
784 }
785