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