ch unused, t and f never assigned!
[unix-history] / usr / src / sys / kern / subr_prf.c
CommitLineData
f324a387
KB
1/*-
2 * Copyright (c) 1986, 1988, 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
da7c5cc6 6 *
8b22ea34 7 * @(#)subr_prf.c 7.28 (Berkeley) %G%
da7c5cc6 8 */
8cbb423c 9
94368568
JB
10#include "param.h"
11#include "systm.h"
94368568
JB
12#include "buf.h"
13#include "conf.h"
14#include "reboot.h"
94368568 15#include "msgbuf.h"
94368568 16#include "proc.h"
3358b36b 17#include "ioctl.h"
71e86b6c
MT
18#include "vnode.h"
19#include "file.h"
94368568 20#include "tty.h"
35dc415e 21#include "tprintf.h"
bd10af3f 22#include "syslog.h"
35dc415e 23#include "malloc.h"
96d38f03 24
f324a387
KB
25/*
26 * Note that stdarg.h and the ANSI style va_start macro is used for both
27 * ANSI and traditional C compilers.
28 */
29#include <machine/stdarg.h>
30
f7f8b75f 31#ifdef KADB
40ed2c45 32#include "machine/kdbparam.h"
3eb8e016
MK
33#endif
34
f324a387
KB
35#define TOCONS 0x01
36#define TOTTY 0x02
37#define TOLOG 0x04
34ef3482 38
ed2d0915 39struct tty *constty; /* pointer to console "window" tty */
ae032917
MT
40
41#ifdef KADB
42extern cngetc(); /* standard console getc */
ae032917 43int (*v_getc)() = cngetc; /* "" getc from virtual console */
f324a387 44extern cnpoll();
ae032917
MT
45int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */
46#endif
f324a387
KB
47extern cnputc(); /* standard console putc */
48int (*v_putc)() = cnputc; /* routine to putc on virtual console */
49
d4339c84
KB
50static void logpri __P((int level));
51static void putchar __P((int ch, int flags, struct tty *tp));
d4339c84 52static char *ksprintn __P((u_long num, int base, int *len));
106a3d16 53void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list));
ed2d0915 54
1d4b2ce4
MK
55extern cnputc(); /* standard console putc */
56extern struct tty cons; /* standard console tty */
57struct tty *constty; /* pointer to console "window" tty */
58int (*v_console)() = cnputc; /* routine to putc on virtual console */
59
8cbb423c 60/*
f324a387
KB
61 * Variable panicstr contains argument to first call to panic; used
62 * as flag to indicate that the kernel has already called panic.
8cbb423c 63 */
f324a387 64char *panicstr;
3e199d90 65
f324a387
KB
66/*
67 * Panic is called on unresolvable fatal errors. It prints "panic: mesg",
68 * and then reboots. If we are called twice, then we avoid trying to sync
69 * the disks as this often leads to recursive panics.
70 */
71void
72panic(msg)
73 char *msg;
74{
75 int bootopt = RB_AUTOBOOT | RB_DUMP;
76 int s;
fb1db32c 77
f324a387
KB
78 if (panicstr)
79 bootopt |= RB_NOSYNC;
80 else
81 panicstr = msg;
82 printf("panic: %s\n", msg);
83#ifdef KGDB
84 kgdb_panic();
85#endif
86#ifdef KADB
87 if (boothowto & RB_KDB) {
88 s = splnet(); /* below kdb pri */
89 setsoftkdb();
90 splx(s);
91 }
92#endif
93 boot(bootopt);
94}
95
96/*
97 * Warn that a system table is full.
98 */
99void
100tablefull(tab)
101 char *tab;
96d38f03
BJ
102{
103
f324a387 104 log(LOG_ERR, "%s: table is full\n", tab);
96d38f03
BJ
105}
106
843267b1 107/*
71e86b6c 108 * Uprintf prints to the controlling terminal for the current process.
f324a387
KB
109 * It may block if the tty queue is overfull. No message is printed if
110 * the queue does not clear in a reasonable time.
843267b1 111 */
f324a387
KB
112void
113#ifdef __STDC__
114uprintf(const char *fmt, ...)
115#else
116uprintf(fmt /*, va_alist */)
b725a0ca 117 char *fmt;
f324a387 118#endif
96d38f03 119{
8429d022 120 register struct proc *p = curproc;
f324a387 121 va_list ap;
96d38f03 122
f324a387 123 va_start(ap, fmt);
35dc415e 124 if (p->p_flag & SCTTY && p->p_session->s_ttyvp)
f324a387
KB
125 kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
126 va_end(ap);
35dc415e
MT
127}
128
129tpr_t
3e199d90
MK
130tprintf_open(p)
131 register struct proc *p;
35dc415e 132{
35dc415e
MT
133 if (p->p_flag & SCTTY && p->p_session->s_ttyvp) {
134 SESSHOLD(p->p_session);
3e199d90 135 return ((tpr_t) p->p_session);
f324a387
KB
136 }
137 return ((tpr_t) NULL);
35dc415e
MT
138}
139
3e199d90 140void
35dc415e
MT
141tprintf_close(sess)
142 tpr_t sess;
143{
144 if (sess)
3e199d90 145 SESSRELE((struct session *) sess);
34ef3482
RC
146}
147
bd10af3f 148/*
35dc415e 149 * tprintf prints on the controlling terminal associated
f324a387 150 * with the given session.
bd10af3f 151 */
f324a387
KB
152void
153#ifdef __STDC__
154tprintf(tpr_t tpr, const char *fmt, ...)
155#else
156tprintf(tpr, fmt /*, va_alist */)
3e199d90 157 tpr_t tpr;
34ef3482 158 char *fmt;
f324a387 159#endif
34ef3482 160{
3e199d90
MK
161 register struct session *sess = (struct session *)tpr;
162 struct tty *tp = NULL;
35dc415e 163 int flags = TOLOG;
f324a387 164 va_list ap;
34ef3482 165
6f71a9f6 166 logpri(LOG_INFO);
3e199d90 167 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
35dc415e 168 flags |= TOTTY;
3e199d90
MK
169 tp = sess->s_ttyp;
170 }
f324a387
KB
171 va_start(ap, fmt);
172 kprintf(fmt, flags, tp, ap);
173 va_end(ap);
6f71a9f6 174 logwakeup();
34ef3482
RC
175}
176
f324a387
KB
177/*
178 * Ttyprintf displays a message on a tty; it should be used only by
179 * the tty driver, or anything that knows the underlying tty will not
180 * be revoke(2)'d away. Other callers should use tprintf.
181 */
182void
183#ifdef __STDC__
184ttyprintf(struct tty *tp, const char *fmt, ...)
185#else
186ttyprintf(tp, fmt /*, va_alist */)
187 struct tty *tp;
188 char *fmt;
189#endif
190{
191 va_list ap;
192
193 va_start(ap, fmt);
194 kprintf(fmt, TOTTY, tp, ap);
195 va_end(ap);
196}
197
3e199d90 198extern int log_open;
35dc415e 199
34ef3482 200/*
f324a387
KB
201 * Log writes to the log buffer, and guarantees not to sleep (so can be
202 * called by interrupt routines). If there is no process reading the
203 * log yet, it writes to the console also.
34ef3482 204 */
f324a387
KB
205void
206#ifdef __STDC__
207log(int level, const char *fmt, ...)
208#else
209log(level, fmt /*, va_alist */)
210 int level;
34ef3482 211 char *fmt;
f324a387 212#endif
34ef3482
RC
213{
214 register s = splhigh();
f324a387 215 va_list ap;
34ef3482 216
6f71a9f6 217 logpri(level);
f324a387
KB
218 va_start(ap, fmt);
219 kprintf(fmt, TOLOG, NULL, ap);
34ef3482 220 splx(s);
bd10af3f 221 if (!log_open)
f324a387
KB
222 kprintf(fmt, TOCONS, NULL, ap);
223 va_end(ap);
34ef3482 224 logwakeup();
96d38f03
BJ
225}
226
f324a387 227static void
6f71a9f6
MK
228logpri(level)
229 int level;
230{
d4339c84
KB
231 register int ch;
232 register char *p;
6f71a9f6 233
f324a387 234 putchar('<', TOLOG, NULL);
d4339c84
KB
235 for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;)
236 putchar(ch, TOLOG, NULL);
f324a387 237 putchar('>', TOLOG, NULL);
6f71a9f6
MK
238}
239
f324a387
KB
240void
241#ifdef __STDC__
242addlog(const char *fmt, ...)
243#else
244addlog(fmt /*, va_alist */)
c55a3dd0 245 char *fmt;
f324a387 246#endif
c55a3dd0
MK
247{
248 register s = splhigh();
f324a387 249 va_list ap;
c55a3dd0 250
f324a387
KB
251 va_start(ap, fmt);
252 kprintf(fmt, TOLOG, NULL, ap);
c55a3dd0
MK
253 splx(s);
254 if (!log_open)
f324a387
KB
255 kprintf(fmt, TOCONS, NULL, ap);
256 va_end(ap);
c55a3dd0
MK
257 logwakeup();
258}
259
f324a387 260int consintr = 1; /* ok to handle console interrupts? */
8cbb423c 261
f324a387
KB
262void
263#ifdef __STDC__
264printf(const char *fmt, ...)
265#else
266printf(fmt /*, va_alist */)
267 char *fmt;
268#endif
8cbb423c 269{
f324a387
KB
270 register int savintr;
271 va_list ap;
8cbb423c 272
f324a387
KB
273 savintr = consintr; /* disable interrupts */
274 consintr = 0;
275 va_start(ap, fmt);
276 kprintf(fmt, TOCONS | TOLOG, NULL, ap);
277 va_end(ap);
278 if (!panicstr)
279 logwakeup();
280 consintr = savintr; /* reenable interrupts */
8cbb423c
BJ
281}
282
283/*
f324a387
KB
284 * Scaled down version of printf(3).
285 *
286 * Two additional formats:
287 *
288 * The format %b is supported to decode error registers.
289 * Its usage is:
290 *
d4339c84 291 * printf("reg=%b\n", regval, "<base><arg>*");
f324a387
KB
292 *
293 * where <base> is the output base expressed as a control character, e.g.
294 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
295 * the first of which gives the bit number to be inspected (origin 1), and
296 * the next characters (up to a control character, i.e. a character <= 32),
297 * give the name of the register. Thus:
298 *
d4339c84 299 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
f324a387
KB
300 *
301 * would produce output:
302 *
303 * reg=3<BITTWO,BITONE>
304 *
305 * The format %r is supposed to pass an additional format string and argument
306 * list recursively.
307 * Its usage is:
308 *
309 * fn(otherstuff, fmt [, arg1, ... ])
310 * char *fmt;
311 * u_int arg1, ...;
312 *
d4339c84
KB
313 * printf("prefix: %r, other stuff\n", fmt, ap);
314 *
315 * Space or zero padding and a field width are supported for the numeric
316 * formats only.
8cbb423c 317 */
106a3d16 318void
8345edbf
KB
319kprintf(fmt, flags, tp, ap)
320 register const char *fmt;
f324a387 321 int flags;
8345edbf 322 struct tty *tp;
f324a387 323 va_list ap;
8cbb423c 324{
f324a387
KB
325 register char *p;
326 register int ch, n;
d4339c84
KB
327 u_long ul;
328 int base, lflag, tmp, width;
329 char padc;
f324a387
KB
330
331 for (;;) {
d4339c84
KB
332 padc = ' ';
333 width = 0;
8b22ea34 334 while ((ch = *(u_char *)fmt++) != '%') {
f324a387
KB
335 if (ch == '\0')
336 return;
8345edbf 337 putchar(ch, flags, tp);
f324a387
KB
338 }
339 lflag = 0;
8b22ea34 340reswitch: switch (ch = *(u_char *)fmt++) {
d4339c84
KB
341 case '0':
342 padc = '0';
343 goto reswitch;
344 case '1': case '2': case '3': case '4':
345 case '5': case '6': case '7': case '8': case '9':
346 for (width = 0;; ++fmt) {
347 width = width * 10 + ch - '0';
348 ch = *fmt;
349 if (ch < '0' || ch > '9')
350 break;
351 }
352 goto reswitch;
f324a387
KB
353 case 'l':
354 lflag = 1;
355 goto reswitch;
356 case 'b':
357 ul = va_arg(ap, int);
358 p = va_arg(ap, char *);
d4339c84
KB
359 for (p = ksprintn(ul, *p++, NULL); ch = *p--;)
360 putchar(ch, flags, tp);
f324a387
KB
361
362 if (!ul)
363 break;
364
d4339c84 365 for (tmp = 0; n = *p++;) {
f324a387 366 if (ul & (1 << (n - 1))) {
d4339c84 367 putchar(tmp ? ',' : '<', flags, tp);
f324a387 368 for (; (n = *p) > ' '; ++p)
8345edbf 369 putchar(n, flags, tp);
d4339c84 370 tmp = 1;
f324a387
KB
371 } else
372 for (; *p > ' '; ++p);
373 }
d4339c84 374 if (tmp)
8345edbf 375 putchar('>', flags, tp);
f324a387
KB
376 break;
377 case 'c':
8345edbf 378 putchar(va_arg(ap, int), flags, tp);
f324a387
KB
379 break;
380 case 'r':
381 p = va_arg(ap, char *);
8345edbf 382 kprintf(p, flags, tp, va_arg(ap, va_list));
f324a387
KB
383 break;
384 case 's':
385 p = va_arg(ap, char *);
386 while (ch = *p++)
8345edbf 387 putchar(ch, flags, tp);
f324a387 388 break;
f324a387 389 case 'd':
d4339c84 390 ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
f324a387 391 if ((long)ul < 0) {
8345edbf 392 putchar('-', flags, tp);
f324a387
KB
393 ul = -(long)ul;
394 }
d4339c84
KB
395 base = 10;
396 goto number;
f324a387 397 case 'o':
d4339c84
KB
398 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
399 base = 8;
400 goto number;;
f324a387 401 case 'u':
d4339c84
KB
402 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
403 base = 10;
404 goto number;
f324a387 405 case 'x':
d4339c84
KB
406 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
407 base = 16;
408number: p = ksprintn(ul, base, &tmp);
409 if (width && (width -= tmp) > 0)
410 while (width--)
411 putchar(padc, flags, tp);
412 while (ch = *p--)
413 putchar(ch, flags, tp);
f324a387
KB
414 break;
415 default:
8345edbf 416 putchar('%', flags, tp);
f324a387 417 if (lflag)
8345edbf 418 putchar('l', flags, tp);
d4339c84
KB
419 /* FALLTHROUGH */
420 case '%':
8345edbf 421 putchar(ch, flags, tp);
f324a387 422 }
3eb8e016 423 }
8cbb423c
BJ
424}
425
96d38f03 426/*
f324a387
KB
427 * Print a character on console or users terminal. If destination is
428 * the console then the last MSGBUFS characters are saved in msgbuf for
429 * inspection later.
96d38f03 430 */
f324a387 431static void
8345edbf 432putchar(c, flags, tp)
843267b1 433 register int c;
f324a387 434 int flags;
8345edbf 435 struct tty *tp;
96d38f03 436{
c55a3dd0 437 extern int msgbufmapped;
f324a387 438 register struct msgbuf *mbp;
96d38f03 439
ed2d0915 440 if (panicstr)
f324a387 441 constty = NULL;
8345edbf
KB
442 if ((flags & TOCONS) && tp == NULL && constty) {
443 tp = constty;
ed2d0915
MK
444 flags |= TOTTY;
445 }
1d4b2ce4
MK
446 if ((flags & TOCONS) && panicstr == 0 && tp == 0 && constty) {
447 tp = constty;
448 flags |= TOTTY;
449 }
8345edbf
KB
450 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
451 (flags & TOCONS) && tp == constty)
f324a387
KB
452 constty = NULL;
453 if ((flags & TOLOG) &&
454 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
455 mbp = msgbufp;
9db58063 456 if (mbp->msg_magic != MSG_MAGIC) {
76db4195
SL
457 register int i;
458
9db58063
KM
459 mbp->msg_magic = MSG_MAGIC;
460 mbp->msg_bufx = mbp->msg_bufr = 0;
f324a387 461 for (i = 0; i < MSG_BSIZE; i++)
9db58063 462 mbp->msg_bufc[i] = 0;
90f8d91f 463 }
9db58063
KM
464 mbp->msg_bufc[mbp->msg_bufx++] = c;
465 if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
466 mbp->msg_bufx = 0;
96d38f03 467 }
1d4b2ce4 468 (*v_console)(c);
96d38f03 469}