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