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