new naming convention
[unix-history] / usr / src / sys / kern / subr_prf.c
CommitLineData
da7c5cc6 1/*
e018935f 2 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
2100bbbc 6 * @(#)subr_prf.c 7.14 (Berkeley) %G%
da7c5cc6 7 */
8cbb423c 8
94368568
JB
9#include "param.h"
10#include "systm.h"
11#include "seg.h"
12#include "buf.h"
13#include "conf.h"
14#include "reboot.h"
15#include "vm.h"
16#include "msgbuf.h"
94368568
JB
17#include "user.h"
18#include "proc.h"
3358b36b 19#include "ioctl.h"
94368568 20#include "tty.h"
bd10af3f 21#include "syslog.h"
96d38f03 22
40ed2c45 23#include "machine/mtpr.h"
f7f8b75f 24#ifdef KADB
40ed2c45 25#include "machine/kdbparam.h"
3eb8e016
MK
26#endif
27
34ef3482
RC
28#define TOCONS 0x1
29#define TOTTY 0x2
30#define TOLOG 0x4
31
8cbb423c
BJ
32/*
33 * In case console is off,
34 * panicstr contains argument to last
35 * call to panic.
36 */
8cbb423c
BJ
37char *panicstr;
38
ed2d0915
MK
39extern cnputc(); /* standard console putc */
40extern struct tty cons; /* standard console tty */
41struct tty *constty; /* pointer to console "window" tty */
42int (*v_putc)() = cnputc; /* routine to putc on virtual console */
43
1d4b2ce4
MK
44extern cnputc(); /* standard console putc */
45extern struct tty cons; /* standard console tty */
46struct tty *constty; /* pointer to console "window" tty */
47int (*v_console)() = cnputc; /* routine to putc on virtual console */
48
8cbb423c
BJ
49/*
50 * Scaled down version of C Library printf.
b725a0ca
BJ
51 * Used to print diagnostic information directly on console tty.
52 * Since it is not interrupt driven, all system activities are
53 * suspended. Printf should not be used for chit-chat.
54 *
55 * One additional format: %b is supported to decode error registers.
56 * Usage is:
57 * printf("reg=%b\n", regval, "<base><arg>*");
58 * Where <base> is the output base expressed as a control character,
59 * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of
60 * characters, the first of which gives the bit number to be inspected
61 * (origin 1), and the next characters (up to a control character, i.e.
62 * a character <= 32), give the name of the register. Thus
63 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
64 * would produce output:
8d907ccf 65 * reg=3<BITTWO,BITONE>
6a79e262
MK
66 *
67 * Another additional format: %r is used to pass an additional format string
68 * and argument list recursively. Usage is typically:
69 *
70 * fn(otherstuff, fmt [, arg1, ... ] )
71 * char *fmt;
72 * u_int arg1, ...;
73 *
74 * printf("prefix: %r, other stuff\n", fmt, &arg1);
8cbb423c 75 */
fb1db32c
MK
76#if defined(tahoe)
77int consintr;
78#endif
79
8cbb423c
BJ
80/*VARARGS1*/
81printf(fmt, x1)
b725a0ca
BJ
82 char *fmt;
83 unsigned x1;
96d38f03 84{
fb1db32c
MK
85#if defined(tahoe)
86 register int savintr;
96d38f03 87
fb1db32c
MK
88 savintr = consintr, consintr = 0; /* disable interrupts */
89#endif
34ef3482
RC
90 prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0);
91 logwakeup();
fb1db32c
MK
92#if defined(tahoe)
93 consintr = savintr; /* reenable interrupts */
94#endif
96d38f03
BJ
95}
96
843267b1 97/*
6f71a9f6
MK
98 * Uprintf prints to the current user's terminal.
99 * It may block if the tty queue is overfull.
ca9b16e5
MK
100 * No message is printed if the queue does not clear
101 * in a reasonable time.
6f71a9f6
MK
102 * Should determine whether current terminal user is related
103 * to this process.
843267b1
BJ
104 */
105/*VARARGS1*/
106uprintf(fmt, x1)
b725a0ca 107 char *fmt;
843267b1 108 unsigned x1;
96d38f03 109{
c359fb80 110#ifdef notdef
6f71a9f6 111 register struct proc *p;
c359fb80 112#endif
6f71a9f6 113 register struct tty *tp;
96d38f03 114
6f71a9f6
MK
115 if ((tp = u.u_ttyp) == NULL)
116 return;
117#ifdef notdef
118 if (tp->t_pgrp && (p = pfind(tp->t_pgrp)))
c359fb80 119 if (p->p_uid != u.u_uid) /* doesn't account for setuid */
6f71a9f6
MK
120 return;
121#endif
ca9b16e5
MK
122 if (ttycheckoutq(tp, 1))
123 prf(fmt, &x1, TOTTY, tp);
34ef3482
RC
124}
125
bd10af3f
MK
126/*
127 * tprintf prints on the specified terminal (console if none)
128 * and logs the message. It is designed for error messages from
6f71a9f6
MK
129 * single-open devices, and may be called from interrupt level
130 * (does not sleep).
bd10af3f 131 */
34ef3482 132/*VARARGS2*/
6f71a9f6
MK
133tprintf(tp, fmt, x1)
134 register struct tty *tp;
34ef3482
RC
135 char *fmt;
136 unsigned x1;
137{
6f71a9f6 138 int flags = TOTTY | TOLOG;
34ef3482 139
6f71a9f6 140 logpri(LOG_INFO);
1d4b2ce4
MK
141 if (tp == (struct tty *)NULL) {
142 tp = constty;
143 if (tp == (struct tty *)NULL)
144 tp = &cons;
145 }
6f71a9f6
MK
146 if (ttycheckoutq(tp, 0) == 0)
147 flags = TOLOG;
148 prf(fmt, &x1, flags, tp);
149 logwakeup();
34ef3482
RC
150}
151
152/*
153 * Log writes to the log buffer,
8d907ccf 154 * and guarantees not to sleep (so can be called by interrupt routines).
bd10af3f 155 * If there is no process reading the log yet, it writes to the console also.
34ef3482
RC
156 */
157/*VARARGS2*/
158log(level, fmt, x1)
159 char *fmt;
160 unsigned x1;
161{
162 register s = splhigh();
bd10af3f 163 extern int log_open;
34ef3482 164
6f71a9f6 165 logpri(level);
34ef3482
RC
166 prf(fmt, &x1, TOLOG, (struct tty *)0);
167 splx(s);
bd10af3f
MK
168 if (!log_open)
169 prf(fmt, &x1, TOCONS, (struct tty *)0);
34ef3482 170 logwakeup();
96d38f03
BJ
171}
172
6f71a9f6
MK
173logpri(level)
174 int level;
175{
176
177 putchar('<', TOLOG, (struct tty *)0);
8011f5df 178 printn((u_long)level, 10, TOLOG, (struct tty *)0);
6f71a9f6
MK
179 putchar('>', TOLOG, (struct tty *)0);
180}
181
c55a3dd0
MK
182/*VARARGS1*/
183addlog(fmt, x1)
184 char *fmt;
185 unsigned x1;
186{
187 register s = splhigh();
188
189 prf(fmt, &x1, TOLOG, (struct tty *)0);
190 splx(s);
191 if (!log_open)
192 prf(fmt, &x1, TOCONS, (struct tty *)0);
193 logwakeup();
194}
195
34ef3482 196prf(fmt, adx, flags, ttyp)
b725a0ca
BJ
197 register char *fmt;
198 register u_int *adx;
34ef3482 199 struct tty *ttyp;
8cbb423c 200{
d5726689 201 register int b, c, i;
8cbb423c 202 char *s;
3c79e4ff 203 int any;
8cbb423c 204
8cbb423c 205loop:
843267b1 206 while ((c = *fmt++) != '%') {
34ef3482 207 if (c == '\0')
8cbb423c 208 return;
34ef3482 209 putchar(c, flags, ttyp);
8cbb423c 210 }
843267b1 211again:
8cbb423c 212 c = *fmt++;
fb1db32c 213 /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */
843267b1
BJ
214 switch (c) {
215
216 case 'l':
217 goto again;
218 case 'x': case 'X':
219 b = 16;
220 goto number;
221 case 'd': case 'D':
fb1db32c
MK
222 b = -10;
223 goto number;
224 case 'u':
843267b1
BJ
225 b = 10;
226 goto number;
227 case 'o': case 'O':
228 b = 8;
229number:
34ef3482 230 printn((u_long)*adx, b, flags, ttyp);
843267b1
BJ
231 break;
232 case 'c':
d5726689 233 b = *adx;
c55a3dd0 234#if BYTE_ORDER == LITTLE_ENDIAN
d5726689
BJ
235 for (i = 24; i >= 0; i -= 8)
236 if (c = (b >> i) & 0x7f)
34ef3482 237 putchar(c, flags, ttyp);
fb1db32c 238#endif
c55a3dd0 239#if BYTE_ORDER == BIG_ENDIAN
fb1db32c
MK
240 if (c = (b & 0x7f))
241 putchar(c, flags, ttyp);
242#endif
843267b1 243 break;
3c79e4ff
BJ
244 case 'b':
245 b = *adx++;
246 s = (char *)*adx;
34ef3482 247 printn((u_long)b, *s++, flags, ttyp);
3c79e4ff
BJ
248 any = 0;
249 if (b) {
3c79e4ff
BJ
250 while (i = *s++) {
251 if (b & (1 << (i-1))) {
fb1db32c 252 putchar(any ? ',' : '<', flags, ttyp);
3c79e4ff
BJ
253 any = 1;
254 for (; (c = *s) > 32; s++)
34ef3482 255 putchar(c, flags, ttyp);
3c79e4ff
BJ
256 } else
257 for (; *s > 32; s++)
258 ;
259 }
1ce587f2 260 if (any)
34ef3482 261 putchar('>', flags, ttyp);
3c79e4ff
BJ
262 }
263 break;
264
843267b1 265 case 's':
8cbb423c 266 s = (char *)*adx;
96d38f03 267 while (c = *s++)
34ef3482 268 putchar(c, flags, ttyp);
843267b1 269 break;
2bb8d359 270
c55a3dd0
MK
271 case 'r':
272 s = (char *)*adx++;
6a79e262 273 prf(s, (u_int *)*adx, flags, ttyp);
c55a3dd0
MK
274 break;
275
2bb8d359 276 case '%':
34ef3482 277 putchar('%', flags, ttyp);
2bb8d359 278 break;
8cbb423c
BJ
279 }
280 adx++;
281 goto loop;
282}
283
b725a0ca
BJ
284/*
285 * Printn prints a number n in base b.
286 * We don't use recursion to avoid deep kernel stacks.
287 */
34ef3482 288printn(n, b, flags, ttyp)
a0eab615 289 u_long n;
34ef3482 290 struct tty *ttyp;
8cbb423c 291{
d5726689 292 char prbuf[11];
843267b1 293 register char *cp;
8cbb423c 294
fb1db32c
MK
295 if (b == -10) {
296 if ((int)n < 0) {
297 putchar('-', flags, ttyp);
298 n = (unsigned)(-(int)n);
299 }
300 b = -b;
8cbb423c 301 }
d5726689 302 cp = prbuf;
843267b1
BJ
303 do {
304 *cp++ = "0123456789abcdef"[n%b];
305 n /= b;
306 } while (n);
307 do
34ef3482 308 putchar(*--cp, flags, ttyp);
d5726689 309 while (cp > prbuf);
8cbb423c
BJ
310}
311
312/*
0dc06be8 313 * Panic is called on unresolvable fatal errors.
b725a0ca
BJ
314 * It prints "panic: mesg", and then reboots.
315 * If we are called twice, then we avoid trying to
316 * sync the disks as this often leads to recursive panics.
8cbb423c
BJ
317 */
318panic(s)
b725a0ca 319 char *s;
8cbb423c 320{
295184b1 321 int bootopt = RB_AUTOBOOT | RB_DUMP;
843267b1 322
68503f9a
BJ
323 if (panicstr)
324 bootopt |= RB_NOSYNC;
cddce008 325 else {
961945a8 326 panicstr = s;
961945a8 327 }
a9c526c1 328 printf("panic: %s\n", s);
f7f8b75f 329#ifdef KADB
3eb8e016 330 if (boothowto & RB_KDB) {
e018935f 331 int x = splnet(); /* below kdb pri */
3eb8e016
MK
332
333 setsoftkdb();
e018935f 334 splx(x);
3eb8e016
MK
335 }
336#endif
295184b1 337 boot(bootopt);
8cbb423c
BJ
338}
339
fdd11a14
BJ
340/*
341 * Warn that a system table is full.
342 */
343tablefull(tab)
344 char *tab;
345{
346
283ffc90 347 log(LOG_ERR, "%s: table is full\n", tab);
fdd11a14
BJ
348}
349
96d38f03 350/*
843267b1 351 * Print a character on console or users terminal.
96d38f03
BJ
352 * If destination is console then the last MSGBUFS characters
353 * are saved in msgbuf for inspection later.
354 */
49c84d3f 355/*ARGSUSED*/
8d907ccf 356putchar(c, flags, tp)
843267b1 357 register int c;
8d907ccf 358 struct tty *tp;
96d38f03 359{
c55a3dd0 360 extern int msgbufmapped;
96d38f03 361
ed2d0915
MK
362 if (panicstr)
363 constty = 0;
364 if ((flags & TOCONS) && tp == 0 && constty) {
365 tp = constty;
366 flags |= TOTTY;
367 }
1d4b2ce4
MK
368 if ((flags & TOCONS) && panicstr == 0 && tp == 0 && constty) {
369 tp = constty;
370 flags |= TOTTY;
371 }
34ef3482 372 if (flags & TOTTY) {
6f71a9f6
MK
373 register s = spltty();
374
375 if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
376 (TS_CARR_ON | TS_ISOPEN)) {
843267b1 377 if (c == '\n')
2752c877
BJ
378 (void) ttyoutput('\r', tp);
379 (void) ttyoutput(c, tp);
d11b28dc 380 ttstart(tp);
1d4b2ce4
MK
381 flags &= ~TOCONS;
382 } else if ((flags & TOCONS) && tp == constty)
383 constty = 0;
6f71a9f6 384 splx(s);
d11b28dc 385 }
c55a3dd0
MK
386 if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 &&
387 msgbufmapped) {
90f8d91f 388 if (msgbuf.msg_magic != MSG_MAGIC) {
76db4195
SL
389 register int i;
390
90f8d91f 391 msgbuf.msg_magic = MSG_MAGIC;
34ef3482 392 msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
76db4195
SL
393 for (i=0; i < MSG_BSIZE; i++)
394 msgbuf.msg_bufc[i] = 0;
90f8d91f 395 }
7e401e0e 396 msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
90f8d91f
BJ
397 if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
398 msgbuf.msg_bufx = 0;
96d38f03 399 }
1d4b2ce4 400 (*v_console)(c);
96d38f03 401}