xref: /netbsd-src/sys/kern/subr_prf.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
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