subr_prf.c revision 1.13 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.13 1994/05/12 10:26:19 mycroft 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 putchar __P((int ch, int flags, struct tty *tp));
85 static char *ksprintn __P((u_long num, int base, int *len));
86 void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list));
87 volatile void boot(int bootopt);
88
89 /*
90 * Variable panicstr contains argument to first call to panic; used
91 * as flag to indicate that the kernel has already called panic.
92 */
93 const char *panicstr;
94
95 /*
96 * Message buffer
97 */
98 struct msgbuf *msgbufp;
99 int msgbufmapped;
100
101 /*
102 * Panic is called on unresolvable fatal errors. It prints "panic: mesg",
103 * and then reboots. If we are called twice, then we avoid trying to sync
104 * the disks as this often leads to recursive panics.
105 */
106 #ifdef __STDC__
107 volatile void
108 panic(const char *fmt, ...)
109 #else
110 void
111 panic(fmt)
112 char *fmt;
113 #endif
114 {
115 va_list ap;
116 int bootopt = RB_AUTOBOOT | RB_DUMP;
117 char buf[256];
118
119 if (panicstr)
120 bootopt |= RB_NOSYNC;
121 else
122 panicstr = fmt;
123
124 va_start(ap, fmt);
125 sprintf(buf, "panic: %s\n", fmt);
126 kprintf(buf, TOCONS | TOLOG, NULL, ap);
127 va_end(ap);
128
129 #ifdef KGDB
130 kgdb_panic();
131 #endif
132 #ifdef KADB
133 if (boothowto & RB_KDB) {
134 int s;
135
136 s = splnet(); /* below kdb pri */
137 setsoftkdb();
138 splx(s);
139 }
140 #endif
141 #ifdef DDB
142 Debugger();
143 #else
144 #ifdef PANICWAIT
145 printf("hit any key to boot/dump...\n>");
146 cngetc();
147 #endif
148 #endif
149 boot(bootopt);
150 }
151
152 /*
153 * Warn that a system table is full.
154 */
155 void
156 tablefull(tab)
157 const char *tab;
158 {
159
160 log(LOG_ERR, "%s: table is full\n", tab);
161 }
162
163 /*
164 * Uprintf prints to the controlling terminal for the current process.
165 * It may block if the tty queue is overfull. No message is printed if
166 * the queue does not clear in a reasonable time.
167 */
168 void
169 #ifdef __STDC__
170 uprintf(const char *fmt, ...)
171 #else
172 uprintf(fmt /*, va_alist */)
173 char *fmt;
174 #endif
175 {
176 register struct proc *p = curproc;
177 va_list ap;
178
179 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
180 va_start(ap, fmt);
181 kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
182 va_end(ap);
183 }
184 }
185
186 tpr_t
187 tprintf_open(p)
188 register struct proc *p;
189 {
190
191 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
192 SESSHOLD(p->p_session);
193 return ((tpr_t) p->p_session);
194 }
195 return ((tpr_t) NULL);
196 }
197
198 void
199 tprintf_close(sess)
200 tpr_t sess;
201 {
202
203 if (sess)
204 SESSRELE((struct session *) sess);
205 }
206
207 /*
208 * tprintf prints on the controlling terminal associated
209 * with the given session.
210 */
211 void
212 #ifdef __STDC__
213 tprintf(tpr_t tpr, const char *fmt, ...)
214 #else
215 tprintf(tpr, fmt /*, va_alist */)
216 tpr_t tpr;
217 char *fmt;
218 #endif
219 {
220 register struct session *sess = (struct session *)tpr;
221 struct tty *tp = NULL;
222 int flags = TOLOG;
223 va_list ap;
224
225 logpri(LOG_INFO);
226 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
227 flags |= TOTTY;
228 tp = sess->s_ttyp;
229 }
230 va_start(ap, fmt);
231 kprintf(fmt, flags, tp, ap);
232 va_end(ap);
233 logwakeup();
234 }
235
236 /*
237 * Ttyprintf displays a message on a tty; it should be used only by
238 * the tty driver, or anything that knows the underlying tty will not
239 * be revoke(2)'d away. Other callers should use tprintf.
240 */
241 void
242 #ifdef __STDC__
243 ttyprintf(struct tty *tp, const char *fmt, ...)
244 #else
245 ttyprintf(tp, fmt /*, va_alist */)
246 struct tty *tp;
247 char *fmt;
248 #endif
249 {
250 va_list ap;
251
252 va_start(ap, fmt);
253 kprintf(fmt, TOTTY, tp, ap);
254 va_end(ap);
255 }
256
257 extern int log_open;
258
259 /*
260 * Log writes to the log buffer, and guarantees not to sleep (so can be
261 * called by interrupt routines). If there is no process reading the
262 * log yet, it writes to the console also.
263 */
264 void
265 #ifdef __STDC__
266 log(int level, const char *fmt, ...)
267 #else
268 log(level, fmt /*, va_alist */)
269 int level;
270 char *fmt;
271 #endif
272 {
273 register int s;
274 va_list ap;
275
276 s = splhigh();
277 logpri(level);
278 va_start(ap, fmt);
279 kprintf(fmt, TOLOG, NULL, ap);
280 splx(s);
281 va_end(ap);
282 if (!log_open) {
283 va_start(ap, fmt);
284 kprintf(fmt, TOCONS, NULL, ap);
285 va_end(ap);
286 }
287 logwakeup();
288 }
289
290 void
291 logpri(level)
292 int level;
293 {
294 register int ch;
295 register char *p;
296
297 putchar('<', TOLOG, NULL);
298 for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;)
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 #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 int consintr = 1; /* ok to handle console interrupts? */
328
329 void
330 #ifdef __STDC__
331 printf(const char *fmt, ...)
332 #else
333 printf(fmt, va_alist)
334 char *fmt;
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 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
367 *
368 * would produce output:
369 *
370 * reg=3<BITTWO,BITONE>
371 *
372 * The format %r is supposed to pass an additional format string and argument
373 * list recursively.
374 * Its usage is:
375 *
376 * fn(otherstuff, char *fmt, ...)
377 * {
378 * va_list ap;
379 * va_start(ap, fmt);
380 * printf("prefix: %r, other stuff\n", fmt, ap);
381 * va_end(ap);
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, *p2;
394 register int ch, n;
395 u_long ul;
396 int base, lflag, tmp, width;
397 char padc;
398
399 for (;;) {
400 padc = ' ';
401 width = 0;
402 while ((ch = *(u_char *)fmt++) != '%') {
403 if (ch == '\0')
404 return;
405 putchar(ch, flags, tp);
406 }
407 lflag = 0;
408 reswitch: switch (ch = *(u_char *)fmt++) {
409 case '0':
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 (p2 = ksprintn(ul, *p++, NULL); ch = *p2--;)
428 putchar(ch, flags, tp);
429
430 if (!ul)
431 break;
432
433 for (tmp = 0; n = *p++;) {
434 if (ul & (1 << (n - 1))) {
435 putchar(tmp ? ',' : '<', flags, tp);
436 for (; (n = *p) > ' '; ++p)
437 putchar(n, flags, tp);
438 tmp = 1;
439 } else
440 for (; *p > ' '; ++p);
441 }
442 if (tmp)
443 putchar('>', flags, tp);
444 break;
445 case 'c':
446 putchar(va_arg(ap, int), flags, tp);
447 break;
448 case 'r':
449 p = va_arg(ap, char *);
450 kprintf(p, flags, tp, va_arg(ap, va_list));
451 break;
452 case 's':
453 p = va_arg(ap, char *);
454 while (ch = *p++)
455 putchar(ch, flags, tp);
456 break;
457 case 'd':
458 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
459 if ((long)ul < 0) {
460 putchar('-', flags, tp);
461 ul = -(long)ul;
462 }
463 base = 10;
464 goto number;
465 case 'o':
466 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
467 base = 8;
468 goto number;
469 case 'u':
470 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
471 base = 10;
472 goto number;
473 case 'x':
474 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
475 base = 16;
476 number: p = ksprintn(ul, base, &tmp);
477 if (width && (width -= tmp) > 0)
478 while (width--)
479 putchar(padc, flags, tp);
480 while (ch = *p--)
481 putchar(ch, flags, tp);
482 break;
483 default:
484 putchar('%', flags, tp);
485 if (lflag)
486 putchar('l', flags, tp);
487 /* FALLTHROUGH */
488 case '%':
489 putchar(ch, flags, tp);
490 }
491 }
492 }
493
494 /*
495 * Print a character on console or users terminal. If destination is
496 * the console then the last MSGBUFS characters are saved in msgbuf for
497 * inspection later.
498 */
499 static void
500 putchar(c, flags, tp)
501 register int c;
502 int flags;
503 struct tty *tp;
504 {
505 register struct msgbuf *mbp;
506
507 if (panicstr)
508 constty = NULL;
509 if ((flags & TOCONS) && tp == NULL && constty) {
510 tp = constty;
511 flags |= TOTTY;
512 }
513 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
514 (flags & TOCONS) && tp == constty)
515 constty = NULL;
516 if ((flags & TOLOG) &&
517 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
518 mbp = msgbufp;
519 if (mbp->msg_magic != MSG_MAGIC) {
520 bzero((caddr_t)mbp, sizeof(*mbp));
521 mbp->msg_magic = MSG_MAGIC;
522 }
523 mbp->msg_bufc[mbp->msg_bufx++] = c;
524 if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
525 mbp->msg_bufx = 0;
526 }
527 if ((flags & TOCONS) && constty == NULL && c != '\0')
528 (*v_putc)(c);
529 }
530
531 /*
532 * Scaled down version of sprintf(3).
533 */
534 #ifdef __STDC__
535 int
536 sprintf(char *buf, const char *cfmt, ...)
537 #else
538 int
539 sprintf(buf, cfmt /*, va_alist */)
540 char *buf, *cfmt;
541 #endif
542 {
543 register const char *fmt = cfmt;
544 register char *p, *bp;
545 register int ch, base;
546 u_long ul;
547 int lflag;
548 va_list ap;
549
550 va_start(ap, cfmt);
551 for (bp = buf; ; ) {
552 while ((ch = *(u_char *)fmt++) != '%')
553 if ((*bp++ = ch) == '\0')
554 return ((bp - buf) - 1);
555
556 lflag = 0;
557 reswitch: switch (ch = *(u_char *)fmt++) {
558 case 'l':
559 lflag = 1;
560 goto reswitch;
561 case 'c':
562 *bp++ = va_arg(ap, int);
563 break;
564 case 's':
565 p = va_arg(ap, char *);
566 while (*bp++ = *p++)
567 ;
568 --bp;
569 break;
570 case 'd':
571 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
572 if ((long)ul < 0) {
573 *bp++ = '-';
574 ul = -(long)ul;
575 }
576 base = 10;
577 goto number;
578 break;
579 case 'o':
580 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
581 base = 8;
582 goto number;
583 break;
584 case 'u':
585 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
586 base = 10;
587 goto number;
588 break;
589 case 'x':
590 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
591 base = 16;
592 number: for (p = ksprintn(ul, base, NULL); ch = *p--;)
593 *bp++ = ch;
594 break;
595 default:
596 *bp++ = '%';
597 if (lflag)
598 *bp++ = 'l';
599 /* FALLTHROUGH */
600 case '%':
601 *bp++ = ch;
602 }
603 }
604 va_end(ap);
605 }
606
607 /*
608 * Put a number (base <= 16) in a buffer in reverse order; return an
609 * optional length and a pointer to the NULL terminated (preceded?)
610 * buffer.
611 */
612 static char *
613 ksprintn(ul, base, lenp)
614 register u_long ul;
615 register int base, *lenp;
616 { /* A long in base 8, plus NULL. */
617 static char buf[sizeof(long) * NBBY / 3 + 2];
618 register char *p;
619
620 p = buf;
621 do {
622 *++p = "0123456789abcdef"[ul % base];
623 } while (ul /= base);
624 if (lenp)
625 *lenp = p - buf;
626 return (p);
627 }
628