BSD 4_4_Lite1 release
[unix-history] / usr / src / sys / kern / subr_prf.c
CommitLineData
f324a387 1/*-
ad787160
C
2 * Copyright (c) 1986, 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
adb35f79
KB
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.
f324a387 9 *
ad787160
C
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.
da7c5cc6 25 *
ad787160
C
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 *
ed554bc5 38 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
da7c5cc6 39 */
8cbb423c 40
ed782152
KB
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>
96d38f03 55
f324a387
KB
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
f7f8b75f 62#ifdef KADB
38a01dbe 63#include <machine/kdbparam.h>
3eb8e016
MK
64#endif
65
f324a387
KB
66#define TOCONS 0x01
67#define TOTTY 0x02
68#define TOLOG 0x04
34ef3482 69
ed2d0915 70struct tty *constty; /* pointer to console "window" tty */
ae032917 71
f324a387 72extern cnputc(); /* standard console putc */
f26dc35a 73int (*v_putc)() = cnputc; /* routine to putc on virtual console */
f324a387 74
890fb5ad 75void logpri __P((int level));
d4339c84 76static void putchar __P((int ch, int flags, struct tty *tp));
d4339c84 77static char *ksprintn __P((u_long num, int base, int *len));
c77828a2 78void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list ap));
ed782152
KB
79
80int consintr = 1; /* Ok to handle console interrupts? */
ed2d0915 81
8cbb423c 82/*
ed782152
KB
83 * Variable panicstr contains argument to first call to panic; used as flag
84 * to indicate that the kernel has already called panic.
8cbb423c 85 */
ed782152 86const char *panicstr;
3e199d90 87
f324a387
KB
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 */
c77828a2 93#ifdef __GNUC__
ea95b3cd 94volatile void boot(int flags); /* boot() does not return */
c77828a2
MT
95volatile /* panic() does not return */
96#endif
f324a387 97void
ed782152
KB
98#ifdef __STDC__
99panic(const char *fmt, ...)
100#else
08901f4a 101panic(fmt, va_alist)
ed782152
KB
102 char *fmt;
103#endif
f324a387 104{
c77828a2 105 int bootopt;
ed782152 106 va_list ap;
fb1db32c 107
ed782152 108 bootopt = RB_AUTOBOOT | RB_DUMP;
f324a387
KB
109 if (panicstr)
110 bootopt |= RB_NOSYNC;
111 else
ed782152
KB
112 panicstr = fmt;
113
ed782152 114 va_start(ap, fmt);
c77828a2 115 printf("panic: %r\n", fmt, ap);
ed782152
KB
116 va_end(ap);
117
f324a387
KB
118#ifdef KGDB
119 kgdb_panic();
120#endif
121#ifdef KADB
08901f4a
RC
122 if (boothowto & RB_KDB)
123 kdbpanic();
f324a387
KB
124#endif
125 boot(bootopt);
126}
127
128/*
129 * Warn that a system table is full.
130 */
131void
132tablefull(tab)
ea95b3cd 133 const char *tab;
96d38f03
BJ
134{
135
f324a387 136 log(LOG_ERR, "%s: table is full\n", tab);
96d38f03
BJ
137}
138
843267b1 139/*
71e86b6c 140 * Uprintf prints to the controlling terminal for the current process.
f324a387
KB
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.
843267b1 143 */
f324a387
KB
144void
145#ifdef __STDC__
146uprintf(const char *fmt, ...)
147#else
6534ed0a 148uprintf(fmt, va_alist)
b725a0ca 149 char *fmt;
f324a387 150#endif
96d38f03 151{
8429d022 152 register struct proc *p = curproc;
f324a387 153 va_list ap;
96d38f03 154
cf5ef508 155 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
f26dc35a 156 va_start(ap, fmt);
f324a387 157 kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
f26dc35a
KB
158 va_end(ap);
159 }
35dc415e
MT
160}
161
162tpr_t
3e199d90
MK
163tprintf_open(p)
164 register struct proc *p;
35dc415e 165{
f26dc35a 166
cf5ef508 167 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
35dc415e 168 SESSHOLD(p->p_session);
3e199d90 169 return ((tpr_t) p->p_session);
f324a387
KB
170 }
171 return ((tpr_t) NULL);
35dc415e
MT
172}
173
3e199d90 174void
35dc415e
MT
175tprintf_close(sess)
176 tpr_t sess;
177{
f26dc35a 178
35dc415e 179 if (sess)
3e199d90 180 SESSRELE((struct session *) sess);
34ef3482
RC
181}
182
bd10af3f 183/*
35dc415e 184 * tprintf prints on the controlling terminal associated
f324a387 185 * with the given session.
bd10af3f 186 */
f324a387
KB
187void
188#ifdef __STDC__
189tprintf(tpr_t tpr, const char *fmt, ...)
190#else
6534ed0a 191tprintf(tpr, fmt, va_alist)
3e199d90 192 tpr_t tpr;
34ef3482 193 char *fmt;
f324a387 194#endif
34ef3482 195{
3e199d90
MK
196 register struct session *sess = (struct session *)tpr;
197 struct tty *tp = NULL;
35dc415e 198 int flags = TOLOG;
f324a387 199 va_list ap;
34ef3482 200
6f71a9f6 201 logpri(LOG_INFO);
3e199d90 202 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
35dc415e 203 flags |= TOTTY;
3e199d90
MK
204 tp = sess->s_ttyp;
205 }
f324a387
KB
206 va_start(ap, fmt);
207 kprintf(fmt, flags, tp, ap);
208 va_end(ap);
6f71a9f6 209 logwakeup();
34ef3482
RC
210}
211
f324a387
KB
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 */
217void
218#ifdef __STDC__
219ttyprintf(struct tty *tp, const char *fmt, ...)
220#else
6534ed0a 221ttyprintf(tp, fmt, va_alist)
f324a387
KB
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
3e199d90 233extern int log_open;
35dc415e 234
34ef3482 235/*
f324a387
KB
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.
34ef3482 239 */
f324a387
KB
240void
241#ifdef __STDC__
242log(int level, const char *fmt, ...)
243#else
6534ed0a 244log(level, fmt, va_alist)
f324a387 245 int level;
34ef3482 246 char *fmt;
f324a387 247#endif
34ef3482 248{
293eb5c9 249 register int s;
f324a387 250 va_list ap;
34ef3482 251
293eb5c9 252 s = splhigh();
6f71a9f6 253 logpri(level);
f324a387
KB
254 va_start(ap, fmt);
255 kprintf(fmt, TOLOG, NULL, ap);
34ef3482 256 splx(s);
f324a387 257 va_end(ap);
f26dc35a
KB
258 if (!log_open) {
259 va_start(ap, fmt);
260 kprintf(fmt, TOCONS, NULL, ap);
261 va_end(ap);
262 }
34ef3482 263 logwakeup();
96d38f03
BJ
264}
265
890fb5ad 266void
6f71a9f6
MK
267logpri(level)
268 int level;
269{
d4339c84
KB
270 register int ch;
271 register char *p;
6f71a9f6 272
f324a387 273 putchar('<', TOLOG, NULL);
d4339c84
KB
274 for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;)
275 putchar(ch, TOLOG, NULL);
f324a387 276 putchar('>', TOLOG, NULL);
6f71a9f6
MK
277}
278
f324a387
KB
279void
280#ifdef __STDC__
281addlog(const char *fmt, ...)
282#else
6534ed0a 283addlog(fmt, va_alist)
c55a3dd0 284 char *fmt;
f324a387 285#endif
c55a3dd0 286{
293eb5c9 287 register int s;
f324a387 288 va_list ap;
c55a3dd0 289
293eb5c9 290 s = splhigh();
f324a387
KB
291 va_start(ap, fmt);
292 kprintf(fmt, TOLOG, NULL, ap);
c55a3dd0 293 splx(s);
f324a387 294 va_end(ap);
f26dc35a
KB
295 if (!log_open) {
296 va_start(ap, fmt);
297 kprintf(fmt, TOCONS, NULL, ap);
298 va_end(ap);
299 }
c55a3dd0
MK
300 logwakeup();
301}
302
f324a387
KB
303void
304#ifdef __STDC__
305printf(const char *fmt, ...)
306#else
6534ed0a 307printf(fmt, va_alist)
f324a387
KB
308 char *fmt;
309#endif
8cbb423c 310{
f324a387 311 va_list ap;
f26dc35a 312 register int savintr;
8cbb423c 313
f324a387
KB
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 */
8cbb423c
BJ
322}
323
324/*
f324a387
KB
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 *
c77828a2 332 * printf("reg=%b\n", regval, "<base><arg>*");
f324a387
KB
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 *
ed782152 340 * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
f324a387
KB
341 *
342 * would produce output:
343 *
344 * reg=3<BITTWO,BITONE>
345 *
ed782152
KB
346 * The format %r passes an additional format string and argument list
347 * recursively. Its usage is:
f324a387 348 *
ed782152 349 * fn(char *fmt, ...)
f26dc35a
KB
350 * {
351 * va_list ap;
352 * va_start(ap, fmt);
c77828a2 353 * printf("prefix: %r: suffix\n", fmt, ap);
f26dc35a 354 * va_end(ap);
ed782152 355 * }
d4339c84
KB
356 *
357 * Space or zero padding and a field width are supported for the numeric
358 * formats only.
8cbb423c 359 */
106a3d16 360void
c77828a2 361kprintf(fmt, flags, tp, ap)
8345edbf 362 register const char *fmt;
f324a387 363 int flags;
8345edbf 364 struct tty *tp;
f324a387 365 va_list ap;
8cbb423c 366{
40a0752a 367 register char *p, *q;
f324a387 368 register int ch, n;
d4339c84
KB
369 u_long ul;
370 int base, lflag, tmp, width;
371 char padc;
f324a387
KB
372
373 for (;;) {
d4339c84
KB
374 padc = ' ';
375 width = 0;
8b22ea34 376 while ((ch = *(u_char *)fmt++) != '%') {
f324a387
KB
377 if (ch == '\0')
378 return;
8345edbf 379 putchar(ch, flags, tp);
f324a387
KB
380 }
381 lflag = 0;
8b22ea34 382reswitch: switch (ch = *(u_char *)fmt++) {
d4339c84
KB
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;
f324a387
KB
395 case 'l':
396 lflag = 1;
397 goto reswitch;
398 case 'b':
399 ul = va_arg(ap, int);
400 p = va_arg(ap, char *);
40a0752a 401 for (q = ksprintn(ul, *p++, NULL); ch = *q--;)
d4339c84 402 putchar(ch, flags, tp);
f324a387
KB
403
404 if (!ul)
405 break;
406
d4339c84 407 for (tmp = 0; n = *p++;) {
f324a387 408 if (ul & (1 << (n - 1))) {
d4339c84 409 putchar(tmp ? ',' : '<', flags, tp);
f324a387 410 for (; (n = *p) > ' '; ++p)
8345edbf 411 putchar(n, flags, tp);
d4339c84 412 tmp = 1;
f324a387 413 } else
a6e3920d
CT
414 for (; *p > ' '; ++p)
415 continue;
f324a387 416 }
d4339c84 417 if (tmp)
8345edbf 418 putchar('>', flags, tp);
f324a387
KB
419 break;
420 case 'c':
8345edbf 421 putchar(va_arg(ap, int), flags, tp);
f324a387
KB
422 break;
423 case 'r':
424 p = va_arg(ap, char *);
8345edbf 425 kprintf(p, flags, tp, va_arg(ap, va_list));
f324a387
KB
426 break;
427 case 's':
428 p = va_arg(ap, char *);
429 while (ch = *p++)
8345edbf 430 putchar(ch, flags, tp);
f324a387 431 break;
f324a387 432 case 'd':
d4339c84 433 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
f324a387 434 if ((long)ul < 0) {
8345edbf 435 putchar('-', flags, tp);
f324a387
KB
436 ul = -(long)ul;
437 }
d4339c84
KB
438 base = 10;
439 goto number;
f324a387 440 case 'o':
d4339c84
KB
441 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
442 base = 8;
f26dc35a 443 goto number;
f324a387 444 case 'u':
d4339c84
KB
445 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
446 base = 10;
447 goto number;
f324a387 448 case 'x':
d4339c84
KB
449 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
450 base = 16;
451number: 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);
f324a387
KB
457 break;
458 default:
8345edbf 459 putchar('%', flags, tp);
f324a387 460 if (lflag)
8345edbf 461 putchar('l', flags, tp);
d4339c84
KB
462 /* FALLTHROUGH */
463 case '%':
8345edbf 464 putchar(ch, flags, tp);
f324a387 465 }
3eb8e016 466 }
8cbb423c
BJ
467}
468
96d38f03 469/*
f324a387
KB
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.
96d38f03 473 */
f324a387 474static void
8345edbf 475putchar(c, flags, tp)
843267b1 476 register int c;
f324a387 477 int flags;
8345edbf 478 struct tty *tp;
96d38f03 479{
c55a3dd0 480 extern int msgbufmapped;
293eb5c9 481 register struct msgbuf *mbp;
96d38f03 482
ed2d0915 483 if (panicstr)
f324a387 484 constty = NULL;
8345edbf
KB
485 if ((flags & TOCONS) && tp == NULL && constty) {
486 tp = constty;
ed2d0915
MK
487 flags |= TOTTY;
488 }
8345edbf
KB
489 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
490 (flags & TOCONS) && tp == constty)
f324a387
KB
491 constty = NULL;
492 if ((flags & TOLOG) &&
493 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
293eb5c9 494 mbp = msgbufp;
9db58063 495 if (mbp->msg_magic != MSG_MAGIC) {
f26dc35a 496 bzero((caddr_t)mbp, sizeof(*mbp));
9db58063 497 mbp->msg_magic = MSG_MAGIC;
90f8d91f 498 }
9db58063
KM
499 mbp->msg_bufc[mbp->msg_bufx++] = c;
500 if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
501 mbp->msg_bufx = 0;
96d38f03 502 }
ad787160
C
503 if ((flags & TOCONS) && constty == NULL && c != '\0')
504 (*v_putc)(c);
8cbb423c
BJ
505}
506
fdd11a14 507/*
ad787160 508 * Scaled down version of sprintf(3).
fdd11a14 509 */
ad787160
C
510#ifdef __STDC__
511sprintf(char *buf, const char *cfmt, ...)
512#else
513sprintf(buf, cfmt, va_alist)
514 char *buf, *cfmt;
515#endif
fdd11a14 516{
ad787160
C
517 register const char *fmt = cfmt;
518 register char *p, *bp;
519 register int ch, base;
520 u_long ul;
521 int lflag;
522 va_list ap;
523
524 va_start(ap, cfmt);
525 for (bp = buf; ; ) {
526 while ((ch = *(u_char *)fmt++) != '%')
527 if ((*bp++ = ch) == '\0')
528 return ((bp - buf) - 1);
529
530 lflag = 0;
531reswitch: switch (ch = *(u_char *)fmt++) {
532 case 'l':
533 lflag = 1;
534 goto reswitch;
535 case 'c':
536 *bp++ = va_arg(ap, int);
537 break;
538 case 's':
539 p = va_arg(ap, char *);
540 while (*bp++ = *p++)
541 continue;
542 --bp;
543 break;
544 case 'd':
545 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
546 if ((long)ul < 0) {
547 *bp++ = '-';
548 ul = -(long)ul;
549 }
550 base = 10;
551 goto number;
552 break;
553 case 'o':
554 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
555 base = 8;
556 goto number;
557 break;
558 case 'u':
559 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
560 base = 10;
561 goto number;
562 break;
563 case 'x':
564 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
565 base = 16;
566number: for (p = ksprintn(ul, base, NULL); ch = *p--;)
567 *bp++ = ch;
568 break;
569 default:
570 *bp++ = '%';
571 if (lflag)
572 *bp++ = 'l';
573 /* FALLTHROUGH */
574 case '%':
575 *bp++ = ch;
576 }
577 }
578 va_end(ap);
fdd11a14
BJ
579}
580
96d38f03 581/*
ad787160
C
582 * Put a number (base <= 16) in a buffer in reverse order; return an
583 * optional length and a pointer to the NULL terminated (preceded?)
584 * buffer.
96d38f03 585 */
ad787160
C
586static char *
587ksprintn(ul, base, lenp)
588 register u_long ul;
589 register int base, *lenp;
590{ /* A long in base 8, plus NULL. */
591 static char buf[sizeof(long) * NBBY / 3 + 2];
592 register char *p;
593
594 p = buf;
595 do {
596 *++p = "0123456789abcdef"[ul % base];
597 } while (ul /= base);
598 if (lenp)
599 *lenp = p - buf;
600 return (p);
96d38f03 601}