subr_prf.c revision 1.12 1 /*-
2 * Copyright (c) 1986, 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)subr_prf.c 7.30 (Berkeley) 6/29/91
39 * $Id: subr_prf.c,v 1.12 1994/05/05 05:38:22 cgd Exp $
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/buf.h>
45 #include <sys/conf.h>
46 #include <sys/reboot.h>
47 #include <sys/msgbuf.h>
48 #include <sys/proc.h>
49 #include <sys/ioctl.h>
50 #include <sys/vnode.h>
51 #include <sys/file.h>
52 #include <sys/tty.h>
53 #include <sys/tprintf.h>
54 #include <sys/syslog.h>
55 #include <sys/malloc.h>
56
57 /*
58 * Note that stdarg.h and the ANSI style va_start macro is used for both
59 * ANSI and traditional C compilers.
60 */
61 #include <machine/stdarg.h>
62
63 #ifdef KADB
64 #include <machine/kdbparam.h>
65 #endif
66
67 #define TOCONS 0x01
68 #define TOTTY 0x02
69 #define TOLOG 0x04
70
71 struct tty *constty; /* pointer to console "window" tty */
72
73 #if defined(KADB) || defined(PANICWAIT)
74 extern cngetc(); /* standard console getc */
75 #endif
76 #ifdef KADB
77 int (*v_getc)() = cngetc; /* "" getc from virtual console */
78 extern cnpoll();
79 int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */
80 #endif
81 extern cnputc(); /* standard console putc */
82 int (*v_putc)() = cnputc; /* routine to putc on virtual console */
83
84 static void logpri __P((int level));
85 static void putchar __P((int ch, int flags, struct tty *tp));
86 static char *ksprintn __P((u_long num, int base, int *len));
87 void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list));
88 volatile void boot(int bootopt);
89
90 /*
91 * Variable panicstr contains argument to first call to panic; used
92 * as flag to indicate that the kernel has already called panic.
93 */
94 const char *panicstr;
95
96 /*
97 * Message buffer
98 */
99 struct msgbuf *msgbufp;
100 int msgbufmapped;
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 #ifdef __STDC__
108 volatile void
109 panic(const char *fmt, ...)
110 #else
111 void
112 panic(fmt)
113 char *fmt;
114 #endif
115 {
116 va_list ap;
117 int bootopt = RB_AUTOBOOT | RB_DUMP;
118 char buf[256];
119
120 if (panicstr)
121 bootopt |= RB_NOSYNC;
122 else
123 panicstr = fmt;
124
125 va_start(ap, fmt);
126 sprintf(buf, "panic: %s\n", fmt);
127 kprintf(buf, TOCONS | TOLOG, NULL, ap);
128 va_end(ap);
129
130 #ifdef KGDB
131 kgdb_panic();
132 #endif
133 #ifdef KADB
134 if (boothowto & RB_KDB) {
135 int s;
136
137 s = splnet(); /* below kdb pri */
138 setsoftkdb();
139 splx(s);
140 }
141 #endif
142 #ifdef DDB
143 Debugger();
144 #else
145 #ifdef PANICWAIT
146 printf("hit any key to boot/dump...\n>");
147 cngetc();
148 #endif
149 #endif
150 boot(bootopt);
151 }
152
153 /*
154 * Warn that a system table is full.
155 */
156 void
157 tablefull(tab)
158 const char *tab;
159 {
160
161 log(LOG_ERR, "%s: table is full\n", tab);
162 }
163
164 /*
165 * Uprintf prints to the controlling terminal for the current process.
166 * It may block if the tty queue is overfull. No message is printed if
167 * the queue does not clear in a reasonable time.
168 */
169 void
170 #ifdef __STDC__
171 uprintf(const char *fmt, ...)
172 #else
173 uprintf(fmt /*, va_alist */)
174 char *fmt;
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 #endif
220 {
221 register struct session *sess = (struct session *)tpr;
222 struct tty *tp = NULL;
223 int flags = TOLOG;
224 va_list ap;
225
226 logpri(LOG_INFO);
227 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
228 flags |= TOTTY;
229 tp = sess->s_ttyp;
230 }
231 va_start(ap, fmt);
232 kprintf(fmt, flags, tp, ap);
233 va_end(ap);
234 logwakeup();
235 }
236
237 /*
238 * Ttyprintf displays a message on a tty; it should be used only by
239 * the tty driver, or anything that knows the underlying tty will not
240 * be revoke(2)'d away. Other callers should use tprintf.
241 */
242 void
243 #ifdef __STDC__
244 ttyprintf(struct tty *tp, const char *fmt, ...)
245 #else
246 ttyprintf(tp, fmt /*, va_alist */)
247 struct tty *tp;
248 char *fmt;
249 #endif
250 {
251 va_list ap;
252
253 va_start(ap, fmt);
254 kprintf(fmt, TOTTY, tp, ap);
255 va_end(ap);
256 }
257
258 extern int log_open;
259
260 /*
261 * Log writes to the log buffer, and guarantees not to sleep (so can be
262 * called by interrupt routines). If there is no process reading the
263 * log yet, it writes to the console also.
264 */
265 void
266 #ifdef __STDC__
267 log(int level, const char *fmt, ...)
268 #else
269 log(level, fmt /*, va_alist */)
270 int level;
271 char *fmt;
272 #endif
273 {
274 register int s;
275 va_list ap;
276
277 s = splhigh();
278 logpri(level);
279 va_start(ap, fmt);
280 kprintf(fmt, TOLOG, NULL, ap);
281 splx(s);
282 va_end(ap);
283 if (!log_open) {
284 va_start(ap, fmt);
285 kprintf(fmt, TOCONS, NULL, ap);
286 va_end(ap);
287 }
288 logwakeup();
289 }
290
291 static void
292 logpri(level)
293 int level;
294 {
295 register int ch;
296 register char *p;
297
298 putchar('<', TOLOG, NULL);
299 for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;)
300 putchar(ch, TOLOG, NULL);
301 putchar('>', TOLOG, NULL);
302 }
303
304 void
305 #ifdef __STDC__
306 addlog(const char *fmt, ...)
307 #else
308 addlog(fmt /*, va_alist */)
309 char *fmt;
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 int consintr = 1; /* ok to handle console interrupts? */
329
330 void
331 #ifdef __STDC__
332 printf(const char *fmt, ...)
333 #else
334 printf(fmt, va_alist)
335 char *fmt;
336 #endif
337 {
338 va_list ap;
339 register int savintr;
340
341 savintr = consintr; /* disable interrupts */
342 consintr = 0;
343 va_start(ap, fmt);
344 kprintf(fmt, TOCONS | TOLOG, NULL, ap);
345 va_end(ap);
346 if (!panicstr)
347 logwakeup();
348 consintr = savintr; /* reenable interrupts */
349 }
350
351 /*
352 * Scaled down version of printf(3).
353 *
354 * Two additional formats:
355 *
356 * The format %b is supported to decode error registers.
357 * Its usage is:
358 *
359 * printf("reg=%b\n", regval, "<base><arg>*");
360 *
361 * where <base> is the output base expressed as a control character, e.g.
362 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
363 * the first of which gives the bit number to be inspected (origin 1), and
364 * the next characters (up to a control character, i.e. a character <= 32),
365 * give the name of the register. Thus:
366 *
367 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
368 *
369 * would produce output:
370 *
371 * reg=3<BITTWO,BITONE>
372 *
373 * The format %r is supposed to pass an additional format string and argument
374 * list recursively.
375 * Its usage is:
376 *
377 * fn(otherstuff, char *fmt, ...)
378 * {
379 * va_list ap;
380 * va_start(ap, fmt);
381 * printf("prefix: %r, other stuff\n", fmt, ap);
382 * va_end(ap);
383 *
384 * Space or zero padding and a field width are supported for the numeric
385 * formats only.
386 */
387 void
388 kprintf(fmt, flags, tp, ap)
389 register const char *fmt;
390 int flags;
391 struct tty *tp;
392 va_list ap;
393 {
394 register char *p, *p2;
395 register int ch, n;
396 u_long ul;
397 int base, lflag, tmp, width;
398 char padc;
399
400 for (;;) {
401 padc = ' ';
402 width = 0;
403 while ((ch = *(u_char *)fmt++) != '%') {
404 if (ch == '\0')
405 return;
406 putchar(ch, flags, tp);
407 }
408 lflag = 0;
409 reswitch: switch (ch = *(u_char *)fmt++) {
410 case '0':
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 (p2 = ksprintn(ul, *p++, NULL); ch = *p2--;)
429 putchar(ch, flags, tp);
430
431 if (!ul)
432 break;
433
434 for (tmp = 0; n = *p++;) {
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 }
443 if (tmp)
444 putchar('>', flags, tp);
445 break;
446 case 'c':
447 putchar(va_arg(ap, int), flags, tp);
448 break;
449 case 'r':
450 p = va_arg(ap, char *);
451 kprintf(p, flags, tp, va_arg(ap, va_list));
452 break;
453 case 's':
454 p = va_arg(ap, char *);
455 while (ch = *p++)
456 putchar(ch, flags, tp);
457 break;
458 case 'd':
459 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
460 if ((long)ul < 0) {
461 putchar('-', flags, tp);
462 ul = -(long)ul;
463 }
464 base = 10;
465 goto number;
466 case 'o':
467 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
468 base = 8;
469 goto number;
470 case 'u':
471 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
472 base = 10;
473 goto number;
474 case 'x':
475 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
476 base = 16;
477 number: p = ksprintn(ul, base, &tmp);
478 if (width && (width -= tmp) > 0)
479 while (width--)
480 putchar(padc, flags, tp);
481 while (ch = *p--)
482 putchar(ch, flags, tp);
483 break;
484 default:
485 putchar('%', flags, tp);
486 if (lflag)
487 putchar('l', flags, tp);
488 /* FALLTHROUGH */
489 case '%':
490 putchar(ch, flags, tp);
491 }
492 }
493 }
494
495 /*
496 * Print a character on console or users terminal. If destination is
497 * the console then the last MSGBUFS characters are saved in msgbuf for
498 * inspection later.
499 */
500 static void
501 putchar(c, flags, tp)
502 register int c;
503 int flags;
504 struct tty *tp;
505 {
506 register struct msgbuf *mbp;
507
508 if (panicstr)
509 constty = NULL;
510 if ((flags & TOCONS) && tp == NULL && constty) {
511 tp = constty;
512 flags |= TOTTY;
513 }
514 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
515 (flags & TOCONS) && tp == constty)
516 constty = NULL;
517 if ((flags & TOLOG) &&
518 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
519 mbp = msgbufp;
520 if (mbp->msg_magic != MSG_MAGIC) {
521 bzero((caddr_t)mbp, sizeof(*mbp));
522 mbp->msg_magic = MSG_MAGIC;
523 }
524 mbp->msg_bufc[mbp->msg_bufx++] = c;
525 if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
526 mbp->msg_bufx = 0;
527 }
528 if ((flags & TOCONS) && constty == NULL && c != '\0')
529 (*v_putc)(c);
530 }
531
532 /*
533 * Scaled down version of sprintf(3).
534 */
535 #ifdef __STDC__
536 int
537 sprintf(char *buf, const char *cfmt, ...)
538 #else
539 int
540 sprintf(buf, cfmt /*, va_alist */)
541 char *buf, *cfmt;
542 #endif
543 {
544 register const char *fmt = cfmt;
545 register char *p, *bp;
546 register int ch, base;
547 u_long ul;
548 int lflag;
549 va_list ap;
550
551 va_start(ap, cfmt);
552 for (bp = buf; ; ) {
553 while ((ch = *(u_char *)fmt++) != '%')
554 if ((*bp++ = ch) == '\0')
555 return ((bp - buf) - 1);
556
557 lflag = 0;
558 reswitch: switch (ch = *(u_char *)fmt++) {
559 case 'l':
560 lflag = 1;
561 goto reswitch;
562 case 'c':
563 *bp++ = va_arg(ap, int);
564 break;
565 case 's':
566 p = va_arg(ap, char *);
567 while (*bp++ = *p++)
568 ;
569 --bp;
570 break;
571 case 'd':
572 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
573 if ((long)ul < 0) {
574 *bp++ = '-';
575 ul = -(long)ul;
576 }
577 base = 10;
578 goto number;
579 break;
580 case 'o':
581 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
582 base = 8;
583 goto number;
584 break;
585 case 'u':
586 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
587 base = 10;
588 goto number;
589 break;
590 case 'x':
591 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
592 base = 16;
593 number: for (p = ksprintn(ul, base, NULL); ch = *p--;)
594 *bp++ = ch;
595 break;
596 default:
597 *bp++ = '%';
598 if (lflag)
599 *bp++ = 'l';
600 /* FALLTHROUGH */
601 case '%':
602 *bp++ = ch;
603 }
604 }
605 va_end(ap);
606 }
607
608 /*
609 * Put a number (base <= 16) in a buffer in reverse order; return an
610 * optional length and a pointer to the NULL terminated (preceded?)
611 * buffer.
612 */
613 static char *
614 ksprintn(ul, base, lenp)
615 register u_long ul;
616 register int base, *lenp;
617 { /* A long in base 8, plus NULL. */
618 static char buf[sizeof(long) * NBBY / 3 + 2];
619 register char *p;
620
621 p = buf;
622 do {
623 *++p = "0123456789abcdef"[ul % base];
624 } while (ul /= base);
625 if (lenp)
626 *lenp = p - buf;
627 return (p);
628 }
629