1 /* subr_prf.c 6.6 85/03/18 */ 2 3 #include "param.h" 4 #include "systm.h" 5 #include "seg.h" 6 #include "buf.h" 7 #include "conf.h" 8 #include "reboot.h" 9 #include "vm.h" 10 #include "msgbuf.h" 11 #include "dir.h" 12 #include "user.h" 13 #include "proc.h" 14 #include "ioctl.h" 15 #include "tty.h" 16 #include "syslog.h" 17 18 #ifdef vax 19 #include "../vax/mtpr.h" 20 #endif 21 22 #define TOCONS 0x1 23 #define TOTTY 0x2 24 #define TOLOG 0x4 25 26 /* 27 * In case console is off, 28 * panicstr contains argument to last 29 * call to panic. 30 */ 31 char *panicstr; 32 33 /* 34 * Scaled down version of C Library printf. 35 * Used to print diagnostic information directly on console tty. 36 * Since it is not interrupt driven, all system activities are 37 * suspended. Printf should not be used for chit-chat. 38 * 39 * One additional format: %b is supported to decode error registers. 40 * Usage is: 41 * printf("reg=%b\n", regval, "<base><arg>*"); 42 * Where <base> is the output base expressed as a control character, 43 * e.g. \10 gives octal; \20 gives hex. Each arg is a sequence of 44 * characters, the first of which gives the bit number to be inspected 45 * (origin 1), and the next characters (up to a control character, i.e. 46 * a character <= 32), give the name of the register. Thus 47 * printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 48 * would produce output: 49 * reg=3<BITTWO,BITONE> 50 */ 51 /*VARARGS1*/ 52 printf(fmt, x1) 53 char *fmt; 54 unsigned x1; 55 { 56 57 prf(fmt, &x1, TOCONS | TOLOG, (struct tty *)0); 58 logwakeup(); 59 } 60 61 /* 62 * Uprintf prints to the current user's terminal 63 * and does no watermark checking - (so no verbose messages). 64 */ 65 /*VARARGS1*/ 66 uprintf(fmt, x1) 67 char *fmt; 68 unsigned x1; 69 { 70 71 prf(fmt, &x1, TOTTY, u.u_ttyp); 72 } 73 74 /* 75 * tprintf prints on the specified terminal (console if none) 76 * and logs the message. It is designed for error messages from 77 * single-open devices, and may be called from interrupt level. 78 */ 79 /*VARARGS2*/ 80 tprintf(ttyp, fmt, x1) 81 struct tty *ttyp; 82 char *fmt; 83 unsigned x1; 84 { 85 86 prf(fmt, &x1, TOTTY | TOLOG, ttyp); 87 } 88 89 /* 90 * Log writes to the log buffer, 91 * and guarantees not to sleep (so can be called by interrupt routines). 92 * If there is no process reading the log yet, it writes to the console also. 93 */ 94 /*VARARGS2*/ 95 log(level, fmt, x1) 96 char *fmt; 97 unsigned x1; 98 { 99 register s = splhigh(); 100 extern int log_open; 101 102 putchar('<', TOLOG, (struct tty *)0); 103 printn(level, 10, TOLOG, (struct tty *)0); 104 putchar('>', TOLOG, (struct tty *)0); 105 prf(fmt, &x1, TOLOG, (struct tty *)0); 106 splx(s); 107 if (!log_open) 108 prf(fmt, &x1, TOCONS, (struct tty *)0); 109 logwakeup(); 110 } 111 112 prf(fmt, adx, flags, ttyp) 113 register char *fmt; 114 register u_int *adx; 115 struct tty *ttyp; 116 { 117 register int b, c, i; 118 char *s; 119 int any; 120 121 loop: 122 while ((c = *fmt++) != '%') { 123 if (c == '\0') 124 return; 125 putchar(c, flags, ttyp); 126 } 127 again: 128 c = *fmt++; 129 /* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */ 130 switch (c) { 131 132 case 'l': 133 goto again; 134 case 'x': case 'X': 135 b = 16; 136 goto number; 137 case 'd': case 'D': 138 case 'u': /* what a joke */ 139 b = 10; 140 goto number; 141 case 'o': case 'O': 142 b = 8; 143 number: 144 printn((u_long)*adx, b, flags, ttyp); 145 break; 146 case 'c': 147 b = *adx; 148 for (i = 24; i >= 0; i -= 8) 149 if (c = (b >> i) & 0x7f) 150 putchar(c, flags, ttyp); 151 break; 152 case 'b': 153 b = *adx++; 154 s = (char *)*adx; 155 printn((u_long)b, *s++, flags, ttyp); 156 any = 0; 157 if (b) { 158 while (i = *s++) { 159 if (b & (1 << (i-1))) { 160 putchar(any? ',' : '<', flags, ttyp); 161 any = 1; 162 for (; (c = *s) > 32; s++) 163 putchar(c, flags, ttyp); 164 } else 165 for (; *s > 32; s++) 166 ; 167 } 168 if (any) 169 putchar('>', flags, ttyp); 170 } 171 break; 172 173 case 's': 174 s = (char *)*adx; 175 while (c = *s++) 176 putchar(c, flags, ttyp); 177 break; 178 179 case '%': 180 putchar('%', flags, ttyp); 181 break; 182 } 183 adx++; 184 goto loop; 185 } 186 187 /* 188 * Printn prints a number n in base b. 189 * We don't use recursion to avoid deep kernel stacks. 190 */ 191 printn(n, b, flags, ttyp) 192 u_long n; 193 struct tty *ttyp; 194 { 195 char prbuf[11]; 196 register char *cp; 197 198 if (b == 10 && (int)n < 0) { 199 putchar('-', flags, ttyp); 200 n = (unsigned)(-(int)n); 201 } 202 cp = prbuf; 203 do { 204 *cp++ = "0123456789abcdef"[n%b]; 205 n /= b; 206 } while (n); 207 do 208 putchar(*--cp, flags, ttyp); 209 while (cp > prbuf); 210 } 211 212 /* 213 * Panic is called on unresolvable fatal errors. 214 * It prints "panic: mesg", and then reboots. 215 * If we are called twice, then we avoid trying to 216 * sync the disks as this often leads to recursive panics. 217 */ 218 panic(s) 219 char *s; 220 { 221 int bootopt = RB_AUTOBOOT; 222 223 if (panicstr) 224 bootopt |= RB_NOSYNC; 225 else { 226 panicstr = s; 227 } 228 printf("panic: %s\n", s); 229 boot(RB_PANIC, bootopt); 230 } 231 232 /* 233 * Warn that a system table is full. 234 */ 235 tablefull(tab) 236 char *tab; 237 { 238 239 log(KERN_FAIL, "%s: table is full\n", tab); 240 } 241 242 /* 243 * Hard error is the preface to plaintive error messages 244 * about failing disk transfers. 245 */ 246 harderr(bp, cp) 247 struct buf *bp; 248 char *cp; 249 { 250 251 printf("%s%d%c: hard error sn%d ", cp, 252 dkunit(bp), 'a'+(minor(bp->b_dev)&07), bp->b_blkno); 253 } 254 255 /* 256 * Print a character on console or users terminal. 257 * If destination is console then the last MSGBUFS characters 258 * are saved in msgbuf for inspection later. 259 */ 260 /*ARGSUSED*/ 261 putchar(c, flags, tp) 262 register int c; 263 struct tty *tp; 264 { 265 extern struct tty cons; 266 267 if (flags & TOTTY) { 268 if (tp == (struct tty *)NULL && (flags & TOCONS) == 0) 269 tp = &cons; 270 if (tp && (tp->t_state & TS_CARR_ON)) { 271 register s = spl6(); 272 if (c == '\n') 273 (void) ttyoutput('\r', tp); 274 (void) ttyoutput(c, tp); 275 ttstart(tp); 276 splx(s); 277 } 278 } 279 if ((flags & TOLOG) && c != '\0' && c != '\r' && c != 0177 280 #ifdef vax 281 && mfpr(MAPEN) 282 #endif 283 ) { 284 if (msgbuf.msg_magic != MSG_MAGIC) { 285 register int i; 286 287 msgbuf.msg_magic = MSG_MAGIC; 288 msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 289 for (i=0; i < MSG_BSIZE; i++) 290 msgbuf.msg_bufc[i] = 0; 291 } 292 if (msgbuf.msg_bufx < 0 || msgbuf.msg_bufx >= MSG_BSIZE) 293 msgbuf.msg_bufx = 0; 294 msgbuf.msg_bufc[msgbuf.msg_bufx++] = c; 295 } 296 if ((flags & TOCONS) && c != '\0') 297 cnputc(c); 298 } 299