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