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.8 (Berkeley) 02/08/88 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 /*VARARGS1*/ 167 addlog(fmt, x1) 168 char *fmt; 169 unsigned x1; 170 { 171 register s = splhigh(); 172 173 prf(fmt, &x1, TOLOG, (struct tty *)0); 174 splx(s); 175 if (!log_open) 176 prf(fmt, &x1, TOCONS, (struct tty *)0); 177 logwakeup(); 178 } 179 180 prf(fmt, adx, flags, ttyp) 181 register char *fmt; 182 register u_int *adx; 183 struct tty *ttyp; 184 { 185 register int b, c, i; 186 char *s; 187 int any; 188 189 loop: 190 while ((c = *fmt++) != '%') { 191 if (c == '\0') 192 return; 193 putchar(c, flags, ttyp); 194 } 195 again: 196 c = *fmt++; 197 /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 198 switch (c) { 199 200 case 'l': 201 goto again; 202 case 'x': case 'X': 203 b = 16; 204 goto number; 205 case 'd': case 'D': 206 b = -10; 207 goto number; 208 case 'u': 209 b = 10; 210 goto number; 211 case 'o': case 'O': 212 b = 8; 213 number: 214 printn((u_long)*adx, b, flags, ttyp); 215 break; 216 case 'c': 217 b = *adx; 218 #if BYTE_ORDER == LITTLE_ENDIAN 219 for (i = 24; i >= 0; i -= 8) 220 if (c = (b >> i) & 0x7f) 221 putchar(c, flags, ttyp); 222 #endif 223 #if BYTE_ORDER == BIG_ENDIAN 224 if (c = (b & 0x7f)) 225 putchar(c, flags, ttyp); 226 #endif 227 break; 228 case 'b': 229 b = *adx++; 230 s = (char *)*adx; 231 printn((u_long)b, *s++, flags, ttyp); 232 any = 0; 233 if (b) { 234 while (i = *s++) { 235 if (b & (1 << (i-1))) { 236 putchar(any ? ',' : '<', flags, ttyp); 237 any = 1; 238 for (; (c = *s) > 32; s++) 239 putchar(c, flags, ttyp); 240 } else 241 for (; *s > 32; s++) 242 ; 243 } 244 if (any) 245 putchar('>', flags, ttyp); 246 } 247 break; 248 249 case 's': 250 s = (char *)*adx; 251 while (c = *s++) 252 putchar(c, flags, ttyp); 253 break; 254 255 case 'r': 256 s = (char *)*adx++; 257 prf(s, *adx, flags, ttyp); 258 break; 259 260 case '%': 261 putchar('%', flags, ttyp); 262 break; 263 } 264 adx++; 265 goto loop; 266 } 267 268 /* 269 * Printn prints a number n in base b. 270 * We don't use recursion to avoid deep kernel stacks. 271 */ 272 printn(n, b, flags, ttyp) 273 u_long n; 274 struct tty *ttyp; 275 { 276 char prbuf[11]; 277 register char *cp; 278 279 if (b == -10) { 280 if ((int)n < 0) { 281 putchar('-', flags, ttyp); 282 n = (unsigned)(-(int)n); 283 } 284 b = -b; 285 } 286 cp = prbuf; 287 do { 288 *cp++ = "0123456789abcdef"[n%b]; 289 n /= b; 290 } while (n); 291 do 292 putchar(*--cp, flags, ttyp); 293 while (cp > prbuf); 294 } 295 296 /* 297 * Panic is called on unresolvable fatal errors. 298 * It prints "panic: mesg", and then reboots. 299 * If we are called twice, then we avoid trying to 300 * sync the disks as this often leads to recursive panics. 301 */ 302 panic(s) 303 char *s; 304 { 305 int bootopt = RB_AUTOBOOT | RB_DUMP; 306 307 if (panicstr) 308 bootopt |= RB_NOSYNC; 309 else { 310 panicstr = s; 311 } 312 printf("panic: %s\n", s); 313 #ifdef KDB 314 if (boothowto & RB_KDB) { 315 int s = splnet(); /* below kdb pri */ 316 317 setsoftkdb(); 318 splx(s); 319 } 320 #endif 321 boot(bootopt); 322 } 323 324 /* 325 * Warn that a system table is full. 326 */ 327 tablefull(tab) 328 char *tab; 329 { 330 331 log(LOG_ERR, "%s: table is full\n", tab); 332 } 333 334 /* 335 * Hard error is the preface to plaintive error messages 336 * about failing disk transfers. 337 */ 338 harderr(bp, cp) 339 struct buf *bp; 340 char *cp; 341 { 342 343 printf("%s%d%c: hard error sn%d ", cp, 344 minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 345 } 346 347 /* 348 * Print a character on console or users terminal. 349 * If destination is console then the last MSGBUFS characters 350 * are saved in msgbuf for inspection later. 351 */ 352 /*ARGSUSED*/ 353 putchar(c, flags, tp) 354 register int c; 355 struct tty *tp; 356 { 357 extern int msgbufmapped; 358 359 if (panicstr) 360 constty = 0; 361 if ((flags & TOCONS) && tp == 0 && constty) { 362 tp = constty; 363 flags |= TOTTY; 364 } 365 if (flags & TOTTY) { 366 register s = spltty(); 367 368 if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == 369 (TS_CARR_ON | TS_ISOPEN)) { 370 if (c == '\n') 371 (void) ttyoutput('\r', tp); 372 (void) ttyoutput(c, tp); 373 ttstart(tp); 374 } else if ((flags & TOCONS) && tp == constty) 375 constty = 0; 376 splx(s); 377 } 378 if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && 379 msgbufmapped) { 380 if (msgbuf.msg_magic != MSG_MAGIC) { 381 register int i; 382 383 msgbuf.msg_magic = MSG_MAGIC; 384 msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 385 for (i=0; i < MSG_BSIZE; i++) 386 msgbuf.msg_bufc[i] = 0; 387 } 388 msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 389 if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 390 msgbuf.msg_bufx = 0; 391 } 392 if ((flags & TOCONS) && constty == 0 && c != '\0') 393 (*v_putc)(c); 394 } 395