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