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