add some missing returns, correct args to ipcaccess, general cleanup
[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 *
53276cec 6 * @(#)subr_prf.c 7.17 (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"
71e86b6c
MT
20#include "vnode.h"
21#include "file.h"
94368568 22#include "tty.h"
bd10af3f 23#include "syslog.h"
96d38f03 24
40ed2c45 25#include "machine/mtpr.h"
f7f8b75f 26#ifdef KADB
40ed2c45 27#include "machine/kdbparam.h"
3eb8e016
MK
28#endif
29
34ef3482
RC
30#define TOCONS 0x1
31#define TOTTY 0x2
32#define TOLOG 0x4
33
8cbb423c
BJ
34/*
35 * In case console is off,
36 * panicstr contains argument to last
37 * call to panic.
38 */
8cbb423c
BJ
39char *panicstr;
40
ed2d0915 41extern cnputc(); /* standard console putc */
ae032917 42int (*v_putc)() = cnputc; /* routine to putc on virtual console */
ed2d0915
MK
43extern struct tty cons; /* standard console tty */
44struct tty *constty; /* pointer to console "window" tty */
ae032917
MT
45
46#ifdef KADB
47extern cngetc(); /* standard console getc */
48extern cnpoll();
49int (*v_getc)() = cngetc; /* "" getc from virtual console */
50int (*v_poll)() = cnpoll; /* kdb hook to enable input polling */
51#endif
ed2d0915 52
1d4b2ce4
MK
53extern cnputc(); /* standard console putc */
54extern struct tty cons; /* standard console tty */
55struct tty *constty; /* pointer to console "window" tty */
56int (*v_console)() = cnputc; /* routine to putc on virtual console */
57
8cbb423c
BJ
58/*
59 * Scaled down version of C Library printf.
b725a0ca
BJ
60 * Used to print diagnostic information directly on console tty.
61 * Since it is not interrupt driven, all system activities are
62 * suspended. Printf should not be used for chit-chat.
63 *
64 * One additional format: %b is supported to decode error registers.
65 * Usage is:
66 * printf("reg=%b\n", regval, "<base><arg>*");
67 * Where <base> is the output base expressed as a control character,
68 * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of
69 * characters, the first of which gives the bit number to be inspected
70 * (origin 1), and the next characters (up to a control character, i.e.
71 * a character <= 32), give the name of the register. Thus
72 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
73 * would produce output:
8d907ccf 74 * reg=3<BITTWO,BITONE>
6a79e262
MK
75 *
76 * Another additional format: %r is used to pass an additional format string
77 * and argument list recursively. Usage is typically:
78 *
79 * fn(otherstuff, fmt [, arg1, ... ] )
80 * char *fmt;
81 * u_int arg1, ...;
82 *
83 * printf("prefix: %r, other stuff\n", fmt, &arg1);
8cbb423c 84 */
fb1db32c
MK
85#if defined(tahoe)
86int consintr;
87#endif
88
8cbb423c
BJ
89/*VARARGS1*/
90printf(fmt, x1)
b725a0ca
BJ
91 char *fmt;
92 unsigned x1;
96d38f03 93{
fb1db32c
MK
94#if defined(tahoe)
95 register int savintr;
96d38f03 96
fb1db32c
MK
97 savintr = consintr, consintr = 0; /* disable interrupts */
98#endif
71e86b6c 99 prf(fmt, &x1, TOCONS | TOLOG, (caddr_t)0);
53276cec
KM
100 if (!panicstr)
101 logwakeup();
fb1db32c
MK
102#if defined(tahoe)
103 consintr = savintr; /* reenable interrupts */
104#endif
96d38f03
BJ
105}
106
843267b1 107/*
71e86b6c 108 * Uprintf prints to the controlling terminal for the current process.
6f71a9f6 109 * It may block if the tty queue is overfull.
ca9b16e5
MK
110 * No message is printed if the queue does not clear
111 * in a reasonable time.
843267b1
BJ
112 */
113/*VARARGS1*/
114uprintf(fmt, x1)
b725a0ca 115 char *fmt;
843267b1 116 unsigned x1;
96d38f03 117{
71e86b6c 118 register struct tty *tp = u.u_procp->p_session->s_ttyp;
96d38f03 119
71e86b6c 120 if (tp != NULL && tp->t_session == u.u_procp->p_session)
53276cec 121 prf(fmt, &x1, TOTTY, (caddr_t)tp);
34ef3482
RC
122}
123
bd10af3f
MK
124/*
125 * tprintf prints on the specified terminal (console if none)
126 * and logs the message. It is designed for error messages from
6f71a9f6
MK
127 * single-open devices, and may be called from interrupt level
128 * (does not sleep).
bd10af3f 129 */
34ef3482 130/*VARARGS2*/
71e86b6c
MT
131tprintf(vp, fmt, x1)
132 register caddr_t vp;
34ef3482
RC
133 char *fmt;
134 unsigned x1;
135{
53276cec 136#ifdef notyet
6f71a9f6 137 int flags = TOTTY | TOLOG;
34ef3482 138
6f71a9f6 139 logpri(LOG_INFO);
71e86b6c
MT
140
141 if (vp == NULL ||
142 VOP_IOCTL(vp, TIOCCHECKOUTQ, &val, FWRITE, NOCRED) != 0 ||
143 val == 0)
6f71a9f6 144 flags = TOLOG;
71e86b6c 145 prf(fmt, &x1, flags, vp);
6f71a9f6 146 logwakeup();
71e86b6c
MT
147#else
148 printf("tprintf called\n");
149#endif
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);
71e86b6c 166 prf(fmt, &x1, TOLOG, (caddr_t)0);
34ef3482 167 splx(s);
bd10af3f 168 if (!log_open)
71e86b6c 169 prf(fmt, &x1, TOCONS, (caddr_t)0);
34ef3482 170 logwakeup();
96d38f03
BJ
171}
172
6f71a9f6
MK
173logpri(level)
174 int level;
175{
176
53276cec
KM
177 putchar('<', TOLOG, (caddr_t)0);
178 printn((u_long)level, 10, TOLOG, (caddr_t)0);
179 putchar('>', TOLOG, (caddr_t)0);
6f71a9f6
MK
180}
181
c55a3dd0
MK
182/*VARARGS1*/
183addlog(fmt, x1)
184 char *fmt;
185 unsigned x1;
186{
187 register s = splhigh();
188
71e86b6c 189 prf(fmt, &x1, TOLOG, (caddr_t)0);
c55a3dd0
MK
190 splx(s);
191 if (!log_open)
71e86b6c 192 prf(fmt, &x1, TOCONS, (caddr_t)0);
c55a3dd0
MK
193 logwakeup();
194}
195
71e86b6c 196prf(fmt, adx, flags, where)
b725a0ca
BJ
197 register char *fmt;
198 register u_int *adx;
71e86b6c 199 caddr_t where;
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;
71e86b6c 209 putchar(c, flags, where);
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:
71e86b6c 230 printn((u_long)*adx, b, flags, where);
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)
71e86b6c 237 putchar(c, flags, where);
fb1db32c 238#endif
c55a3dd0 239#if BYTE_ORDER == BIG_ENDIAN
fb1db32c 240 if (c = (b & 0x7f))
71e86b6c 241 putchar(c, flags, where);
fb1db32c 242#endif
843267b1 243 break;
3c79e4ff
BJ
244 case 'b':
245 b = *adx++;
246 s = (char *)*adx;
71e86b6c 247 printn((u_long)b, *s++, flags, where);
3c79e4ff
BJ
248 any = 0;
249 if (b) {
3c79e4ff
BJ
250 while (i = *s++) {
251 if (b & (1 << (i-1))) {
71e86b6c 252 putchar(any ? ',' : '<', flags, where);
3c79e4ff
BJ
253 any = 1;
254 for (; (c = *s) > 32; s++)
71e86b6c 255 putchar(c, flags, where);
3c79e4ff
BJ
256 } else
257 for (; *s > 32; s++)
258 ;
259 }
1ce587f2 260 if (any)
71e86b6c 261 putchar('>', flags, where);
3c79e4ff
BJ
262 }
263 break;
264
843267b1 265 case 's':
8cbb423c 266 s = (char *)*adx;
96d38f03 267 while (c = *s++)
71e86b6c 268 putchar(c, flags, where);
843267b1 269 break;
2bb8d359 270
c55a3dd0
MK
271 case 'r':
272 s = (char *)*adx++;
71e86b6c 273 prf(s, (u_int *)*adx, flags, where);
c55a3dd0
MK
274 break;
275
2bb8d359 276 case '%':
71e86b6c 277 putchar('%', flags, where);
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 */
71e86b6c 288printn(n, b, flags, where)
a0eab615 289 u_long n;
71e86b6c 290 caddr_t where;
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) {
71e86b6c 297 putchar('-', flags, where);
fb1db32c
MK
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
71e86b6c 308 putchar(*--cp, flags, where);
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*/
71e86b6c 356putchar(c, flags, where)
843267b1 357 register int c;
71e86b6c 358 caddr_t where;
96d38f03 359{
c55a3dd0 360 extern int msgbufmapped;
96d38f03 361
ed2d0915
MK
362 if (panicstr)
363 constty = 0;
71e86b6c
MT
364 if ((flags & TOCONS) && where == 0 && constty) {
365 where = (caddr_t)constty;
ed2d0915
MK
366 flags |= TOTTY;
367 }
1d4b2ce4
MK
368 if ((flags & TOCONS) && panicstr == 0 && tp == 0 && constty) {
369 tp = constty;
370 flags |= TOTTY;
371 }
71e86b6c
MT
372 if ((flags & TOTTY) && where && tputchar(c, (struct tty *)where) < 0 &&
373 (flags & TOCONS) && (struct tty *)where == constty)
374 constty = 0;
c55a3dd0
MK
375 if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 &&
376 msgbufmapped) {
90f8d91f 377 if (msgbuf.msg_magic != MSG_MAGIC) {
76db4195
SL
378 register int i;
379
90f8d91f 380 msgbuf.msg_magic = MSG_MAGIC;
34ef3482 381 msgbuf.msg_bufx = msgbuf.msg_bufr = 0;
76db4195
SL
382 for (i=0; i < MSG_BSIZE; i++)
383 msgbuf.msg_bufc[i] = 0;
90f8d91f 384 }
7e401e0e 385 msgbuf.msg_bufc[msgbuf.msg_bufx++] = c;
90f8d91f
BJ
386 if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE)
387 msgbuf.msg_bufx = 0;
96d38f03 388 }
1d4b2ce4 389 (*v_console)(c);
96d38f03 390}