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