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