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