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.6 (Berkeley) 03/13/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 * Should determine whether current terminal user is related 88 * to this process. 89 */ 90 /*VARARGS1*/ 91 uprintf(fmt, x1) 92 char *fmt; 93 unsigned x1; 94 { 95 #ifdef notdef 96 register struct proc *p; 97 #endif 98 register struct tty *tp; 99 100 if ((tp = u.u_ttyp) == NULL) 101 return; 102 #ifdef notdef 103 if (tp->t_pgrp && (p = pfind(tp->t_pgrp))) 104 if (p->p_uid != u.u_uid) /* doesn't account for setuid */ 105 return; 106 #endif 107 (void)ttycheckoutq(tp, 1); 108 prf(fmt, &x1, TOTTY, tp); 109 } 110 111 /* 112 * tprintf prints on the specified terminal (console if none) 113 * and logs the message. It is designed for error messages from 114 * single-open devices, and may be called from interrupt level 115 * (does not sleep). 116 */ 117 /*VARARGS2*/ 118 tprintf(tp, fmt, x1) 119 register struct tty *tp; 120 char *fmt; 121 unsigned x1; 122 { 123 int flags = TOTTY | TOLOG; 124 125 logpri(LOG_INFO); 126 if (tp == (struct tty *)NULL) 127 tp = &cons; 128 if (ttycheckoutq(tp, 0) == 0) 129 flags = TOLOG; 130 prf(fmt, &x1, flags, tp); 131 logwakeup(); 132 } 133 134 /* 135 * Log writes to the log buffer, 136 * and guarantees not to sleep (so can be called by interrupt routines). 137 * If there is no process reading the log yet, it writes to the console also. 138 */ 139 /*VARARGS2*/ 140 log(level, fmt, x1) 141 char *fmt; 142 unsigned x1; 143 { 144 register s = splhigh(); 145 extern int log_open; 146 147 logpri(level); 148 prf(fmt, &x1, TOLOG, (struct tty *)0); 149 splx(s); 150 if (!log_open) 151 prf(fmt, &x1, TOCONS, (struct tty *)0); 152 logwakeup(); 153 } 154 155 logpri(level) 156 int level; 157 { 158 159 putchar('<', TOLOG, (struct tty *)0); 160 printn((u_long)level, 10, TOLOG, (struct tty *)0); 161 putchar('>', TOLOG, (struct tty *)0); 162 } 163 164 prf(fmt, adx, flags, ttyp) 165 register char *fmt; 166 register u_int *adx; 167 struct tty *ttyp; 168 { 169 register int b, c, i; 170 char *s; 171 int any; 172 173 loop: 174 while ((c = *fmt++) != '%') { 175 if (c == '\0') 176 return; 177 putchar(c, flags, ttyp); 178 } 179 again: 180 c = *fmt++; 181 /* THIS CODE IS MACHINE DEPENDENT IN HANDLING %l? AND %c */ 182 switch (c) { 183 184 case 'l': 185 goto again; 186 case 'x': case 'X': 187 b = 16; 188 goto number; 189 case 'd': case 'D': 190 b = -10; 191 goto number; 192 case 'u': 193 b = 10; 194 goto number; 195 case 'o': case 'O': 196 b = 8; 197 number: 198 printn((u_long)*adx, b, flags, ttyp); 199 break; 200 case 'c': 201 b = *adx; 202 #if ENDIAN == LITTLE 203 for (i = 24; i >= 0; i -= 8) 204 if (c = (b >> i) & 0x7f) 205 putchar(c, flags, ttyp); 206 #endif 207 #if ENDIAN == BIG 208 if (c = (b & 0x7f)) 209 putchar(c, flags, ttyp); 210 #endif 211 break; 212 case 'b': 213 b = *adx++; 214 s = (char *)*adx; 215 printn((u_long)b, *s++, flags, ttyp); 216 any = 0; 217 if (b) { 218 while (i = *s++) { 219 if (b & (1 << (i-1))) { 220 putchar(any ? ',' : '<', flags, ttyp); 221 any = 1; 222 for (; (c = *s) > 32; s++) 223 putchar(c, flags, ttyp); 224 } else 225 for (; *s > 32; s++) 226 ; 227 } 228 if (any) 229 putchar('>', flags, ttyp); 230 } 231 break; 232 233 case 's': 234 s = (char *)*adx; 235 while (c = *s++) 236 putchar(c, flags, ttyp); 237 break; 238 239 case '%': 240 putchar('%', flags, ttyp); 241 break; 242 } 243 adx++; 244 goto loop; 245 } 246 247 /* 248 * Printn prints a number n in base b. 249 * We don't use recursion to avoid deep kernel stacks. 250 */ 251 printn(n, b, flags, ttyp) 252 u_long n; 253 struct tty *ttyp; 254 { 255 char prbuf[11]; 256 register char *cp; 257 258 if (b == -10) { 259 if ((int)n < 0) { 260 putchar('-', flags, ttyp); 261 n = (unsigned)(-(int)n); 262 } 263 b = -b; 264 } 265 cp = prbuf; 266 do { 267 *cp++ = "0123456789abcdef"[n%b]; 268 n /= b; 269 } while (n); 270 do 271 putchar(*--cp, flags, ttyp); 272 while (cp > prbuf); 273 } 274 275 /* 276 * Panic is called on unresolvable fatal errors. 277 * It prints "panic: mesg", and then reboots. 278 * If we are called twice, then we avoid trying to 279 * sync the disks as this often leads to recursive panics. 280 */ 281 panic(s) 282 char *s; 283 { 284 int bootopt = RB_AUTOBOOT | RB_DUMP; 285 286 if (panicstr) 287 bootopt |= RB_NOSYNC; 288 else { 289 panicstr = s; 290 } 291 printf("panic: %s\n", s); 292 #ifdef KDB 293 if (boothowto & RB_KDB) { 294 int s = splnet(); /* below kdb pri */ 295 296 setsoftkdb(); 297 splx(s); 298 } 299 #endif 300 boot(bootopt); 301 } 302 303 /* 304 * Warn that a system table is full. 305 */ 306 tablefull(tab) 307 char *tab; 308 { 309 310 log(LOG_ERR, "%s: table is full\n", tab); 311 } 312 313 /* 314 * Hard error is the preface to plaintive error messages 315 * about failing disk transfers. 316 */ 317 harderr(bp, cp) 318 struct buf *bp; 319 char *cp; 320 { 321 322 printf("%s%d%c: hard error sn%d ", cp, 323 minor(bp->b_dev) >> 3, 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 324 } 325 326 /* 327 * Print a character on console or users terminal. 328 * If destination is console then the last MSGBUFS characters 329 * are saved in msgbuf for inspection later. 330 */ 331 /*ARGSUSED*/ 332 putchar(c, flags, tp) 333 register int c; 334 struct tty *tp; 335 { 336 int startflags = flags; 337 338 if (panicstr) 339 constty = 0; 340 if ((flags & TOCONS) && tp == 0 && constty) { 341 tp = constty; 342 flags |= TOTTY; 343 } 344 if (flags & TOTTY) { 345 register s = spltty(); 346 347 if (tp && (tp->t_state & (TS_CARR_ON | TS_ISOPEN)) == 348 (TS_CARR_ON | TS_ISOPEN)) { 349 if (c == '\n') 350 (void) ttyoutput('\r', tp); 351 (void) ttyoutput(c, tp); 352 ttstart(tp); 353 } else if ((flags & TOCONS) && tp == constty) 354 constty = 0; 355 splx(s); 356 } 357 /* 358 * Can send to log only after memory management enabled: 359 * this has happened by the time maxmem is set. 360 */ 361 if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 && maxmem) { 362 if (msgbuf.msg_magic != MSG_MAGIC) { 363 register int i; 364 365 msgbuf.msg_magic = MSG_MAGIC; 366 msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 367 for (i=0; i < MSG_BSIZE; i++) 368 msgbuf.msg_bufc[i] = 0; 369 } 370 msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 371 if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 372 msgbuf.msg_bufx = 0; 373 } 374 if ((flags & TOCONS) && constty == 0 && c != '\0') 375 (*v_putc)(c); 376 } 377