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