hexdump.c revision 7680
1218799Snwhitehorn/*- 2218799Snwhitehorn * Copyright (c) 1986, 1988, 1991, 1993 3218799Snwhitehorn * The Regents of the University of California. All rights reserved. 4218799Snwhitehorn * (c) UNIX System Laboratories, Inc. 5222468Sbz * All or some portions of this file are derived from material licensed 6222468Sbz * to the University of California by American Telephone and Telegraph 7218799Snwhitehorn * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8222468Sbz * the permission of UNIX System Laboratories, Inc. 9222468Sbz * 10222468Sbz * Redistribution and use in source and binary forms, with or without 11218799Snwhitehorn * modification, are permitted provided that the following conditions 12218799Snwhitehorn * are met: 13218799Snwhitehorn * 1. Redistributions of source code must retain the above copyright 14218799Snwhitehorn * notice, this list of conditions and the following disclaimer. 15218799Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 16218799Snwhitehorn * notice, this list of conditions and the following disclaimer in the 17218799Snwhitehorn * documentation and/or other materials provided with the distribution. 18218799Snwhitehorn * 3. All advertising materials mentioning features or use of this software 19218799Snwhitehorn * must display the following acknowledgement: 20218799Snwhitehorn * This product includes software developed by the University of 21218799Snwhitehorn * California, Berkeley and its contributors. 22218799Snwhitehorn * 4. Neither the name of the University nor the names of its contributors 23218799Snwhitehorn * may be used to endorse or promote products derived from this software 24218799Snwhitehorn * without specific prior written permission. 25218799Snwhitehorn * 26218799Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27218799Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28218799Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29218799Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30218799Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31218799Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32218799Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33218799Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34218799Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35218799Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36218799Snwhitehorn * SUCH DAMAGE. 37218799Snwhitehorn * 38218799Snwhitehorn * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 39218799Snwhitehorn * $Id: subr_prf.c,v 1.12 1995/04/01 20:18:43 joerg Exp $ 40218799Snwhitehorn */ 41218799Snwhitehorn 42218799Snwhitehorn#include <sys/param.h> 43218799Snwhitehorn#include <sys/systm.h> 44218799Snwhitehorn#include <sys/buf.h> 45218799Snwhitehorn#include <sys/conf.h> 46218799Snwhitehorn#include <sys/reboot.h> 47218799Snwhitehorn#include <sys/msgbuf.h> 48218799Snwhitehorn#include <sys/proc.h> 49218799Snwhitehorn#include <sys/ioctl.h> 50218799Snwhitehorn#include <sys/vnode.h> 51218799Snwhitehorn#include <sys/file.h> 52226741Snwhitehorn#include <sys/tty.h> 53226741Snwhitehorn#include <sys/tprintf.h> 54226741Snwhitehorn#include <sys/syslog.h> 55226741Snwhitehorn#include <sys/malloc.h> 56226741Snwhitehorn#include <machine/cons.h> 57226741Snwhitehorn 58226741Snwhitehorn/* 59218799Snwhitehorn * Note that stdarg.h and the ANSI style va_start macro is used for both 60218799Snwhitehorn * ANSI and traditional C compilers. 61218799Snwhitehorn */ 62218799Snwhitehorn#include <machine/stdarg.h> 63218799Snwhitehorn 64222619Sbz#ifdef KADB 65222611Sbz#include <machine/kdbparam.h> 66218799Snwhitehorn#endif 67218799Snwhitehorn 68218799Snwhitehorn 69218799Snwhitehorn#define TOCONS 0x01 70218799Snwhitehorn#define TOTTY 0x02 71222619Sbz#define TOLOG 0x04 72218799Snwhitehorn 73218799Snwhitehornstruct tty *constty; /* pointer to console "window" tty */ 74218799Snwhitehorn 75218799Snwhitehornvoid (*v_putc)(int) = cnputc; /* routine to putc on virtual console */ 76218799Snwhitehorn 77218799Snwhitehornvoid logpri __P((int level)); 78218799Snwhitehornstatic void putchar __P((int ch, int flags, struct tty *tp)); 79218799Snwhitehornstatic char *ksprintn __P((u_long num, int base, int *len)); 80218799Snwhitehorn 81222468Sbzint consintr = 1; /* Ok to handle console interrupts? */ 82222468Sbz 83222468Sbz/* 84222468Sbz * Variable panicstr contains argument to first call to panic; used as flag 85222468Sbz * to indicate that the kernel has already called panic. 86222468Sbz */ 87222468Sbzconst char *panicstr; 88222468Sbz 89222468Sbz/* 90222468Sbz * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 91218799Snwhitehorn * and then reboots. If we are called twice, then we avoid trying to sync 92222468Sbz * the disks as this often leads to recursive panics. 93222468Sbz */ 94222468Sbz#ifdef __GNUC__ 95222468Sbz__dead /* panic() does not return */ 96222468Sbz#endif 97222468Sbzvoid 98222468Sbz#ifdef __STDC__ 99222468Sbzpanic(const char *fmt, ...) 100218799Snwhitehorn#else 101222468Sbzpanic(fmt, va_alist) 102222468Sbz char *fmt; 103222468Sbz#endif 104222468Sbz{ 105222619Sbz int bootopt; 106222468Sbz va_list ap; 107222468Sbz 108222468Sbz bootopt = RB_AUTOBOOT | RB_DUMP; 109222468Sbz if (panicstr) 110222468Sbz bootopt |= RB_NOSYNC; 111222468Sbz else 112222468Sbz panicstr = fmt; 113222468Sbz 114222468Sbz va_start(ap, fmt); 115222468Sbz printf("panic: %r\n", fmt, ap); 116222468Sbz va_end(ap); 117222468Sbz 118222468Sbz#ifdef KGDB 119222468Sbz kgdb_panic(); 120222468Sbz#endif 121222468Sbz#ifdef KADB 122222468Sbz if (boothowto & RB_KDB) 123222468Sbz kdbpanic(); 124222468Sbz#endif 125222468Sbz#ifdef DDB 126222468Sbz Debugger ("panic"); 127222468Sbz#endif 128222468Sbz boot(bootopt); 129222468Sbz} 130222468Sbz 131222468Sbz/* 132222468Sbz * Warn that a system table is full. 133222468Sbz */ 134222468Sbzvoid 135222468Sbztablefull(tab) 136222468Sbz const char *tab; 137222468Sbz{ 138222468Sbz 139222468Sbz log(LOG_ERR, "%s: table is full\n", tab); 140222468Sbz} 141222468Sbz 142222468Sbz/* 143222468Sbz * Uprintf prints to the controlling terminal for the current process. 144222468Sbz * It may block if the tty queue is overfull. No message is printed if 145222468Sbz * the queue does not clear in a reasonable time. 146222468Sbz */ 147222468Sbzvoid 148222468Sbz#ifdef __STDC__ 149222468Sbzuprintf(const char *fmt, ...) 150222468Sbz#else 151222468Sbzuprintf(fmt, va_alist) 152222468Sbz char *fmt; 153222468Sbz#endif 154222468Sbz{ 155222468Sbz register struct proc *p = curproc; 156222468Sbz va_list ap; 157222468Sbz 158222468Sbz if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 159222468Sbz va_start(ap, fmt); 160222468Sbz kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); 161222468Sbz va_end(ap); 162222468Sbz } 163222468Sbz} 164222468Sbz 165222468Sbztpr_t 166222468Sbztprintf_open(p) 167222468Sbz register struct proc *p; 168222468Sbz{ 169218799Snwhitehorn 170218799Snwhitehorn if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 171218799Snwhitehorn SESSHOLD(p->p_session); 172218799Snwhitehorn return ((tpr_t) p->p_session); 173222468Sbz } 174222468Sbz return ((tpr_t) NULL); 175225430Sbz} 176218799Snwhitehorn 177218799Snwhitehornvoid 178218799Snwhitehorntprintf_close(sess) 179218799Snwhitehorn tpr_t sess; 180222468Sbz{ 181222468Sbz 182222468Sbz if (sess) 183222681Sbz SESSRELE((struct session *) sess); 184222468Sbz} 185222468Sbz 186222468Sbz/* 187222468Sbz * tprintf prints on the controlling terminal associated 188222468Sbz * with the given session. 189222468Sbz */ 190222468Sbzvoid 191222468Sbz#ifdef __STDC__ 192222468Sbztprintf(tpr_t tpr, const char *fmt, ...) 193222468Sbz#else 194222681Sbztprintf(tpr, fmt, va_alist) 195222681Sbz tpr_t tpr; 196222681Sbz char *fmt; 197222681Sbz#endif 198222468Sbz{ 199222681Sbz register struct session *sess = (struct session *)tpr; 200222681Sbz struct tty *tp = NULL; 201222468Sbz int flags = TOLOG; 202222468Sbz va_list ap; 203222468Sbz 204222468Sbz logpri(LOG_INFO); 205218799Snwhitehorn if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 206222619Sbz flags |= TOTTY; 207 tp = sess->s_ttyp; 208 } 209 va_start(ap, fmt); 210 kprintf(fmt, flags, tp, ap); 211 va_end(ap); 212 logwakeup(); 213} 214 215/* 216 * Ttyprintf displays a message on a tty; it should be used only by 217 * the tty driver, or anything that knows the underlying tty will not 218 * be revoke(2)'d away. Other callers should use tprintf. 219 */ 220void 221#ifdef __STDC__ 222ttyprintf(struct tty *tp, const char *fmt, ...) 223#else 224ttyprintf(tp, fmt, va_alist) 225 struct tty *tp; 226 char *fmt; 227#endif 228{ 229 va_list ap; 230 231 va_start(ap, fmt); 232 kprintf(fmt, TOTTY, tp, ap); 233 va_end(ap); 234} 235 236extern int log_open; 237 238/* 239 * Log writes to the log buffer, and guarantees not to sleep (so can be 240 * called by interrupt routines). If there is no process reading the 241 * log yet, it writes to the console also. 242 */ 243void 244#ifdef __STDC__ 245log(int level, const char *fmt, ...) 246#else 247log(level, fmt, va_alist) 248 int level; 249 char *fmt; 250#endif 251{ 252 register int s; 253 va_list ap; 254 255 s = splhigh(); 256 logpri(level); 257 va_start(ap, fmt); 258 kprintf(fmt, TOLOG, NULL, ap); 259 splx(s); 260 va_end(ap); 261 if (!log_open) { 262 va_start(ap, fmt); 263 kprintf(fmt, TOCONS, NULL, ap); 264 va_end(ap); 265 } 266 logwakeup(); 267} 268 269void 270logpri(level) 271 int level; 272{ 273 register char *p; 274 275 putchar('<', TOLOG, NULL); 276 for (p = ksprintn((u_long)level, 10, NULL); *p;) 277 putchar(*p--, TOLOG, NULL); 278 putchar('>', TOLOG, NULL); 279} 280 281void 282#ifdef __STDC__ 283addlog(const char *fmt, ...) 284#else 285addlog(fmt, va_alist) 286 char *fmt; 287#endif 288{ 289 register int s; 290 va_list ap; 291 292 s = splhigh(); 293 va_start(ap, fmt); 294 kprintf(fmt, TOLOG, NULL, ap); 295 splx(s); 296 va_end(ap); 297 if (!log_open) { 298 va_start(ap, fmt); 299 kprintf(fmt, TOCONS, NULL, ap); 300 va_end(ap); 301 } 302 logwakeup(); 303} 304 305void 306#ifdef __STDC__ 307printf(const char *fmt, ...) 308#else 309printf(fmt, va_alist) 310 char *fmt; 311#endif 312{ 313 va_list ap; 314 register int savintr; 315 316 savintr = consintr; /* disable interrupts */ 317 consintr = 0; 318 va_start(ap, fmt); 319 kprintf(fmt, TOCONS | TOLOG, NULL, ap); 320 va_end(ap); 321 if (!panicstr) 322 logwakeup(); 323 consintr = savintr; /* reenable interrupts */ 324} 325 326/* 327 * Scaled down version of printf(3). 328 * 329 * Two additional formats: 330 * 331 * The format %b is supported to decode error registers. 332 * Its usage is: 333 * 334 * printf("reg=%b\n", regval, "<base><arg>*"); 335 * 336 * where <base> is the output base expressed as a control character, e.g. 337 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 338 * the first of which gives the bit number to be inspected (origin 1), and 339 * the next characters (up to a control character, i.e. a character <= 32), 340 * give the name of the register. Thus: 341 * 342 * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 343 * 344 * would produce output: 345 * 346 * reg=3<BITTWO,BITONE> 347 * 348 * The format %r passes an additional format string and argument list 349 * recursively. Its usage is: 350 * 351 * fn(char *fmt, ...) 352 * { 353 * va_list ap; 354 * va_start(ap, fmt); 355 * printf("prefix: %r: suffix\n", fmt, ap); 356 * va_end(ap); 357 * } 358 * 359 * Space or zero padding and a field width are supported for the numeric 360 * formats only. 361 */ 362void 363kprintf(fmt, flags, tp, ap) 364 register const char *fmt; 365 int flags; 366 struct tty *tp; 367 va_list ap; 368{ 369 register char *p, *q; 370 register int ch, n; 371 u_long ul; 372 int base, lflag, tmp, width; 373 char padc; 374 375 if (fmt == NULL) 376 fmt = "(fmt null)\n"; 377 for (;;) { 378 padc = ' '; 379 width = 0; 380 while ((ch = *(u_char *)fmt++) != '%') { 381 if (ch == '\0') 382 return; 383 putchar(ch, flags, tp); 384 } 385 lflag = 0; 386reswitch: switch (ch = *(u_char *)fmt++) { 387 case '0': 388 padc = '0'; 389 goto reswitch; 390 case '1': case '2': case '3': case '4': 391 case '5': case '6': case '7': case '8': case '9': 392 for (width = 0;; ++fmt) { 393 width = width * 10 + ch - '0'; 394 ch = *fmt; 395 if (ch < '0' || ch > '9') 396 break; 397 } 398 goto reswitch; 399 case 'l': 400 lflag = 1; 401 goto reswitch; 402 case 'b': 403 ul = va_arg(ap, int); 404 p = va_arg(ap, char *); 405 for (q = ksprintn(ul, *p++, NULL); *q;) 406 putchar(*q--, flags, tp); 407 408 if (!ul) 409 break; 410 411 for (tmp = 0; *p;) { 412 n = *p++; 413 if (ul & (1 << (n - 1))) { 414 putchar(tmp ? ',' : '<', flags, tp); 415 for (; (n = *p) > ' '; ++p) 416 putchar(n, flags, tp); 417 tmp = 1; 418 } else 419 for (; *p > ' '; ++p) 420 continue; 421 } 422 if (tmp) 423 putchar('>', flags, tp); 424 break; 425 case 'c': 426 putchar(va_arg(ap, int), flags, tp); 427 break; 428 case 'r': 429 p = va_arg(ap, char *); 430 kprintf(p, flags, tp, va_arg(ap, va_list)); 431 break; 432 case 's': 433 p = va_arg(ap, char *); 434 if (p == NULL) 435 p = "(null)"; 436 while (*p) 437 putchar(*p++, flags, tp); 438 break; 439 case 'd': 440 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 441 if ((long)ul < 0) { 442 putchar('-', flags, tp); 443 ul = -(long)ul; 444 } 445 base = 10; 446 goto number; 447 case 'o': 448 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 449 base = 8; 450 goto number; 451 case 'u': 452 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 453 base = 10; 454 goto number; 455 case 'p': 456 ul = (u_long) va_arg(ap, void *); 457 width=8; 458 base=16; 459 putchar('0',flags,tp); 460 putchar('x',flags,tp); 461 goto number; 462 case 'x': 463 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 464 base = 16; 465number: p = ksprintn(ul, base, &tmp); 466 if (width && (width -= tmp) > 0) 467 while (width--) 468 putchar(padc, flags, tp); 469 while (*p) 470 putchar(*p--, flags, tp); 471 break; 472 default: 473 putchar('%', flags, tp); 474 if (lflag) 475 putchar('l', flags, tp); 476 /* FALLTHROUGH */ 477 case '%': 478 putchar(ch, flags, tp); 479 } 480 } 481} 482 483/* 484 * Print a character on console or users terminal. If destination is 485 * the console then the last MSGBUFS characters are saved in msgbuf for 486 * inspection later. 487 */ 488static void 489putchar(c, flags, tp) 490 register int c; 491 int flags; 492 struct tty *tp; 493{ 494 register struct msgbuf *mbp; 495 496 if (panicstr) 497 constty = NULL; 498 if ((flags & TOCONS) && tp == NULL && constty) { 499 tp = constty; 500 flags |= TOTTY; 501 } 502 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 503 (flags & TOCONS) && tp == constty) 504 constty = NULL; 505 if ((flags & TOLOG) && 506 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 507 mbp = msgbufp; 508 if (mbp->msg_magic != MSG_MAGIC) { 509 bzero((caddr_t)mbp, sizeof(*mbp)); 510 mbp->msg_magic = MSG_MAGIC; 511 } 512 mbp->msg_bufc[mbp->msg_bufx++] = c; 513 if (mbp->msg_bufx >= MSG_BSIZE) 514 mbp->msg_bufx = 0; 515 if (mbp->msg_bufr == mbp->msg_bufx) { 516 mbp->msg_bufr++; 517 if (mbp->msg_bufr >= MSG_BSIZE) 518 mbp->msg_bufr = 0; 519 } 520 } 521 if ((flags & TOCONS) && constty == NULL && c != '\0') 522 (*v_putc)(c); 523} 524 525/* 526 * Scaled down version of sprintf(3). 527 */ 528#ifdef __STDC__ 529int 530sprintf(char *buf, const char *cfmt, ...) 531#else 532int 533sprintf(buf, cfmt, va_alist) 534 char *buf, *cfmt; 535#endif 536{ 537 register const char *fmt = cfmt; 538 register char *p, *bp; 539 register int ch, base; 540 u_long ul; 541 int lflag; 542 va_list ap; 543 544 va_start(ap, cfmt); 545 for (bp = buf; ; ) { 546 while ((ch = *(u_char *)fmt++) != '%') 547 if ((*bp++ = ch) == '\0') 548 return ((bp - buf) - 1); 549 550 lflag = 0; 551reswitch: switch (ch = *(u_char *)fmt++) { 552 case 'l': 553 lflag = 1; 554 goto reswitch; 555 case 'c': 556 *bp++ = va_arg(ap, int); 557 break; 558 case 's': 559 p = va_arg(ap, char *); 560 while (*p) 561 *bp++ = *p++; 562 break; 563 case 'd': 564 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 565 if ((long)ul < 0) { 566 *bp++ = '-'; 567 ul = -(long)ul; 568 } 569 base = 10; 570 goto number; 571 break; 572 case 'o': 573 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 574 base = 8; 575 goto number; 576 break; 577 case 'u': 578 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 579 base = 10; 580 goto number; 581 break; 582 case 'x': 583 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 584 base = 16; 585number: for (p = ksprintn(ul, base, NULL); *p;) 586 *bp++ = *p--; 587 break; 588 default: 589 *bp++ = '%'; 590 if (lflag) 591 *bp++ = 'l'; 592 /* FALLTHROUGH */ 593 case '%': 594 *bp++ = ch; 595 } 596 } 597 va_end(ap); 598} 599 600/* 601 * Put a number (base <= 16) in a buffer in reverse order; return an 602 * optional length and a pointer to the NULL terminated (preceded?) 603 * buffer. 604 */ 605static char * 606ksprintn(ul, base, lenp) 607 register u_long ul; 608 register int base, *lenp; 609{ /* A long in base 8, plus NULL. */ 610 static char buf[sizeof(long) * NBBY / 3 + 2]; 611 register char *p; 612 613 p = buf; 614 do { 615 *++p = "0123456789abcdef"[ul % base]; 616 } while (ul /= base); 617 if (lenp) 618 *lenp = p - buf; 619 return (p); 620} 621