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