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