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