hexdump.c revision 1549
144290Swollman/*- 244290Swollman * Copyright (c) 1986, 1988, 1991, 1993 344290Swollman * The Regents of the University of California. All rights reserved. 444290Swollman * (c) UNIX System Laboratories, Inc. 544290Swollman * All or some portions of this file are derived from material licensed 644290Swollman * to the University of California by American Telephone and Telegraph 744290Swollman * Co. or Unix System Laboratories, Inc. and are reproduced herein with 844290Swollman * the permission of UNIX System Laboratories, Inc. 944290Swollman * 1044290Swollman * Redistribution and use in source and binary forms, with or without 1144290Swollman * modification, are permitted provided that the following conditions 1244290Swollman * are met: 1344290Swollman * 1. Redistributions of source code must retain the above copyright 1444290Swollman * notice, this list of conditions and the following disclaimer. 1544290Swollman * 2. Redistributions in binary form must reproduce the above copyright 1644290Swollman * notice, this list of conditions and the following disclaimer in the 1744290Swollman * documentation and/or other materials provided with the distribution. 1844290Swollman * 3. All advertising materials mentioning features or use of this software 1944290Swollman * must display the following acknowledgement: 2044290Swollman * This product includes software developed by the University of 2144290Swollman * California, Berkeley and its contributors. 2244290Swollman * 4. Neither the name of the University nor the names of its contributors 2344290Swollman * may be used to endorse or promote products derived from this software 2444290Swollman * without specific prior written permission. 2544290Swollman * 2644290Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2744290Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2844290Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2944290Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3044290Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3144290Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3244290Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3344290Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3444290Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3544290Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3644290Swollman * SUCH DAMAGE. 3744290Swollman * 3844290Swollman * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 3944290Swollman */ 4044290Swollman 4144290Swollman#include <sys/param.h> 4244290Swollman#include <sys/systm.h> 4344290Swollman#include <sys/buf.h> 4444290Swollman#include <sys/conf.h> 4544290Swollman#include <sys/reboot.h> 4644290Swollman#include <sys/msgbuf.h> 4744290Swollman#include <sys/proc.h> 4844290Swollman#include <sys/ioctl.h> 4944290Swollman#include <sys/vnode.h> 5044290Swollman#include <sys/file.h> 5144290Swollman#include <sys/tty.h> 5244290Swollman#include <sys/tprintf.h> 5344290Swollman#include <sys/syslog.h> 5444290Swollman#include <sys/malloc.h> 5544290Swollman 5644290Swollman/* 5744290Swollman * Note that stdarg.h and the ANSI style va_start macro is used for both 5844290Swollman * ANSI and traditional C compilers. 5984211Sdillon */ 6084211Sdillon#include <machine/stdarg.h> 6184211Sdillon 6244290Swollman#ifdef KADB 6344290Swollman#include <machine/kdbparam.h> 6444290Swollman#endif 6544290Swollman 6644290Swollman#define TOCONS 0x01 6744290Swollman#define TOTTY 0x02 6844290Swollman#define TOLOG 0x04 6944290Swollman 7044290Swollmanstruct tty *constty; /* pointer to console "window" tty */ 7144290Swollman 7244290Swollmanextern cnputc(); /* standard console putc */ 7344290Swollmanint (*v_putc)() = cnputc; /* routine to putc on virtual console */ 7444290Swollman 7544290Swollmanvoid logpri __P((int level)); 7644290Swollmanstatic void putchar __P((int ch, int flags, struct tty *tp)); 7744290Swollmanstatic char *ksprintn __P((u_long num, int base, int *len)); 7844290Swollmanvoid kprintf __P((const char *fmt, int flags, struct tty *tp, va_list ap)); 7944290Swollman 8044290Swollmanint consintr = 1; /* Ok to handle console interrupts? */ 8144290Swollman 8244290Swollman/* 8344290Swollman * Variable panicstr contains argument to first call to panic; used as flag 8444290Swollman * to indicate that the kernel has already called panic. 8544290Swollman */ 8644290Swollmanconst char *panicstr; 8744290Swollman 8844290Swollman/* 8944290Swollman * Panic is called on unresolvable fatal errors. It prints "panic: mesg", 9044290Swollman * and then reboots. If we are called twice, then we avoid trying to sync 9144290Swollman * the disks as this often leads to recursive panics. 9244290Swollman */ 9344290Swollman#ifdef __GNUC__ 9444290Swollmanvolatile void boot(int flags); /* boot() does not return */ 9544290Swollmanvolatile /* panic() does not return */ 9644290Swollman#endif 9744290Swollmanvoid 9844290Swollman#ifdef __STDC__ 9944290Swollmanpanic(const char *fmt, ...) 10044290Swollman#else 10144290Swollmanpanic(fmt, va_alist) 10244290Swollman char *fmt; 10344290Swollman#endif 10444290Swollman{ 10544290Swollman int bootopt; 10644290Swollman va_list ap; 10744290Swollman 10844290Swollman bootopt = RB_AUTOBOOT | RB_DUMP; 10944290Swollman if (panicstr) 11044290Swollman bootopt |= RB_NOSYNC; 11144290Swollman else 11244290Swollman panicstr = fmt; 11344290Swollman 11444290Swollman va_start(ap, fmt); 11544290Swollman printf("panic: %r\n", fmt, ap); 11644290Swollman va_end(ap); 11744290Swollman 118154479Sphk#ifdef KGDB 11944290Swollman kgdb_panic(); 120154479Sphk#endif 12144304Swollman#ifdef KADB 12244290Swollman if (boothowto & RB_KDB) 12392913Sobrien kdbpanic(); 12444290Swollman#endif 12544290Swollman#include "ddb.h" 126154479Sphk#if NDDB > 0 12744290Swollman Debugger ("panic"); 12844290Swollman#endif 12944290Swollman boot(bootopt); 13044290Swollman} 13144290Swollman 13244290Swollman/* 13344290Swollman * Warn that a system table is full. 13444290Swollman */ 13544290Swollmanvoid 13644290Swollmantablefull(tab) 13744290Swollman const char *tab; 13844290Swollman{ 13944290Swollman 14044290Swollman log(LOG_ERR, "%s: table is full\n", tab); 14144290Swollman} 14244290Swollman 14344290Swollman/* 14444290Swollman * Uprintf prints to the controlling terminal for the current process. 14544290Swollman * It may block if the tty queue is overfull. No message is printed if 14644290Swollman * the queue does not clear in a reasonable time. 14744290Swollman */ 14844290Swollmanvoid 14944290Swollman#ifdef __STDC__ 15044290Swollmanuprintf(const char *fmt, ...) 15144290Swollman#else 15244290Swollmanuprintf(fmt, va_alist) 15344290Swollman char *fmt; 15444290Swollman#endif 15544290Swollman{ 15644290Swollman register struct proc *p = curproc; 15744290Swollman va_list ap; 15844290Swollman 15944290Swollman if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 16044290Swollman va_start(ap, fmt); 16144290Swollman kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap); 16244290Swollman va_end(ap); 16344290Swollman } 16444290Swollman} 16544290Swollman 16644290Swollmantpr_t 16744290Swollmantprintf_open(p) 16844290Swollman register struct proc *p; 16944290Swollman{ 17044290Swollman 17144290Swollman if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 17244290Swollman SESSHOLD(p->p_session); 17344290Swollman return ((tpr_t) p->p_session); 17444290Swollman } 17544290Swollman return ((tpr_t) NULL); 17644290Swollman} 17744290Swollman 17844290Swollmanvoid 17944290Swollmantprintf_close(sess) 18044290Swollman tpr_t sess; 18144290Swollman{ 18244290Swollman 18344290Swollman if (sess) 18444290Swollman SESSRELE((struct session *) sess); 18544290Swollman} 18644290Swollman 18744290Swollman/* 18844290Swollman * tprintf prints on the controlling terminal associated 18944290Swollman * with the given session. 19044290Swollman */ 19144290Swollmanvoid 19244290Swollman#ifdef __STDC__ 19344290Swollmantprintf(tpr_t tpr, const char *fmt, ...) 19444290Swollman#else 19544290Swollmantprintf(tpr, fmt, va_alist) 19644290Swollman tpr_t tpr; 19744290Swollman char *fmt; 19844290Swollman#endif 19944290Swollman{ 20044290Swollman register struct session *sess = (struct session *)tpr; 20144290Swollman struct tty *tp = NULL; 20244290Swollman int flags = TOLOG; 20344290Swollman va_list ap; 20444290Swollman 20544290Swollman logpri(LOG_INFO); 20644290Swollman if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { 20744290Swollman flags |= TOTTY; 20844290Swollman tp = sess->s_ttyp; 20944290Swollman } 21044290Swollman va_start(ap, fmt); 21144290Swollman kprintf(fmt, flags, tp, ap); 21244290Swollman va_end(ap); 21344290Swollman logwakeup(); 21444290Swollman} 21544290Swollman 21644290Swollman/* 21744290Swollman * Ttyprintf displays a message on a tty; it should be used only by 21844290Swollman * the tty driver, or anything that knows the underlying tty will not 21944290Swollman * be revoke(2)'d away. Other callers should use tprintf. 22044290Swollman */ 22144290Swollmanvoid 22244290Swollman#ifdef __STDC__ 22344290Swollmanttyprintf(struct tty *tp, const char *fmt, ...) 22444290Swollman#else 22544290Swollmanttyprintf(tp, fmt, va_alist) 22644290Swollman struct tty *tp; 22744290Swollman char *fmt; 22844290Swollman#endif 22944290Swollman{ 23044290Swollman va_list ap; 23144290Swollman 23244290Swollman va_start(ap, fmt); 23344290Swollman kprintf(fmt, TOTTY, tp, ap); 23444290Swollman va_end(ap); 23544290Swollman} 23644290Swollman 23744290Swollmanextern int log_open; 23844290Swollman 23944290Swollman/* 24044290Swollman * Log writes to the log buffer, and guarantees not to sleep (so can be 24144290Swollman * called by interrupt routines). If there is no process reading the 24244290Swollman * log yet, it writes to the console also. 24344290Swollman */ 24444290Swollmanvoid 24544290Swollman#ifdef __STDC__ 24644290Swollmanlog(int level, const char *fmt, ...) 24744290Swollman#else 24844290Swollmanlog(level, fmt, va_alist) 24944290Swollman int level; 25044290Swollman char *fmt; 25144290Swollman#endif 25244290Swollman{ 25344290Swollman register int s; 25444290Swollman va_list ap; 25544290Swollman 25644290Swollman s = splhigh(); 25744290Swollman logpri(level); 25844290Swollman va_start(ap, fmt); 25944290Swollman kprintf(fmt, TOLOG, NULL, ap); 26044290Swollman splx(s); 26144290Swollman va_end(ap); 26244290Swollman if (!log_open) { 26344290Swollman va_start(ap, fmt); 26444290Swollman kprintf(fmt, TOCONS, NULL, ap); 26544290Swollman va_end(ap); 26644290Swollman } 26744290Swollman logwakeup(); 26844290Swollman} 26944290Swollman 27044290Swollmanvoid 27144290Swollmanlogpri(level) 27244290Swollman int level; 27344290Swollman{ 27444290Swollman register int ch; 27544290Swollman register char *p; 27644290Swollman 27744290Swollman putchar('<', TOLOG, NULL); 27844290Swollman for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;) 27944290Swollman putchar(ch, TOLOG, NULL); 28044290Swollman putchar('>', TOLOG, NULL); 28144290Swollman} 28244290Swollman 28344290Swollmanvoid 28444290Swollman#ifdef __STDC__ 28544290Swollmanaddlog(const char *fmt, ...) 28644290Swollman#else 28744290Swollmanaddlog(fmt, va_alist) 28844290Swollman char *fmt; 28944290Swollman#endif 29044290Swollman{ 29144290Swollman register int s; 29244290Swollman va_list ap; 29344290Swollman 29492913Sobrien s = splhigh(); 29544290Swollman va_start(ap, fmt); 29644290Swollman kprintf(fmt, TOLOG, NULL, ap); 29744290Swollman splx(s); 29844290Swollman va_end(ap); 29944290Swollman if (!log_open) { 30044290Swollman va_start(ap, fmt); 30144290Swollman kprintf(fmt, TOCONS, NULL, ap); 30244290Swollman va_end(ap); 30344290Swollman } 30444290Swollman logwakeup(); 30544290Swollman} 30644290Swollman 30744290Swollmanvoid 30844290Swollman#ifdef __STDC__ 30944290Swollmanprintf(const char *fmt, ...) 31044290Swollman#else 31144290Swollmanprintf(fmt, va_alist) 31244290Swollman char *fmt; 31344290Swollman#endif 31444290Swollman{ 31544290Swollman va_list ap; 31644290Swollman register int savintr; 31744290Swollman 31844290Swollman savintr = consintr; /* disable interrupts */ 31944290Swollman consintr = 0; 32044290Swollman va_start(ap, fmt); 32144290Swollman kprintf(fmt, TOCONS | TOLOG, NULL, ap); 32244290Swollman va_end(ap); 32344290Swollman if (!panicstr) 32444290Swollman logwakeup(); 32544290Swollman consintr = savintr; /* reenable interrupts */ 32644290Swollman} 32744290Swollman 32844290Swollman/* 32944290Swollman * Scaled down version of printf(3). 33044290Swollman * 33144290Swollman * Two additional formats: 33244290Swollman * 33344290Swollman * The format %b is supported to decode error registers. 33444290Swollman * Its usage is: 33544290Swollman * 33644290Swollman * printf("reg=%b\n", regval, "<base><arg>*"); 33744290Swollman * 33844290Swollman * where <base> is the output base expressed as a control character, e.g. 33944290Swollman * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 34044290Swollman * the first of which gives the bit number to be inspected (origin 1), and 34144290Swollman * the next characters (up to a control character, i.e. a character <= 32), 34244290Swollman * give the name of the register. Thus: 34344290Swollman * 34444290Swollman * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 34544290Swollman * 34644290Swollman * would produce output: 34744290Swollman * 34844290Swollman * reg=3<BITTWO,BITONE> 34944290Swollman * 35044290Swollman * The format %r passes an additional format string and argument list 35144290Swollman * recursively. Its usage is: 35244290Swollman * 35344290Swollman * fn(char *fmt, ...) 35444290Swollman * { 35544290Swollman * va_list ap; 35644290Swollman * va_start(ap, fmt); 35744290Swollman * printf("prefix: %r: suffix\n", fmt, ap); 35844290Swollman * va_end(ap); 35944290Swollman * } 36044290Swollman * 36144290Swollman * Space or zero padding and a field width are supported for the numeric 36244290Swollman * formats only. 36344290Swollman */ 36444290Swollmanvoid 36544290Swollmankprintf(fmt, flags, tp, ap) 36644290Swollman register const char *fmt; 36744290Swollman int flags; 36844290Swollman struct tty *tp; 36944290Swollman va_list ap; 37044290Swollman{ 37144290Swollman register char *p, *q; 37244290Swollman register int ch, n; 37344290Swollman u_long ul; 37444290Swollman int base, lflag, tmp, width; 37544290Swollman char padc; 37644290Swollman 37744290Swollman for (;;) { 37844290Swollman padc = ' '; 37944290Swollman width = 0; 38044290Swollman while ((ch = *(u_char *)fmt++) != '%') { 38144290Swollman if (ch == '\0') 38244290Swollman return; 38344290Swollman putchar(ch, flags, tp); 38444290Swollman } 38544290Swollman lflag = 0; 38644290Swollmanreswitch: switch (ch = *(u_char *)fmt++) { 38744290Swollman case '0': 38844290Swollman padc = '0'; 38944290Swollman goto reswitch; 39044290Swollman case '1': case '2': case '3': case '4': 39144290Swollman case '5': case '6': case '7': case '8': case '9': 39244290Swollman for (width = 0;; ++fmt) { 39344290Swollman width = width * 10 + ch - '0'; 39444290Swollman ch = *fmt; 39544290Swollman if (ch < '0' || ch > '9') 39644290Swollman break; 39744290Swollman } 39844290Swollman goto reswitch; 39944290Swollman case 'l': 40044290Swollman lflag = 1; 40144290Swollman goto reswitch; 40244290Swollman case 'b': 40344290Swollman ul = va_arg(ap, int); 40444290Swollman p = va_arg(ap, char *); 40544290Swollman for (q = ksprintn(ul, *p++, NULL); ch = *q--;) 40644290Swollman putchar(ch, flags, tp); 40744290Swollman 40844290Swollman if (!ul) 40944290Swollman break; 41044290Swollman 41144290Swollman for (tmp = 0; n = *p++;) { 41292913Sobrien if (ul & (1 << (n - 1))) { 41392913Sobrien putchar(tmp ? ',' : '<', flags, tp); 41492913Sobrien for (; (n = *p) > ' '; ++p) 41544290Swollman putchar(n, flags, tp); 41644290Swollman tmp = 1; 41744290Swollman } else 41844290Swollman for (; *p > ' '; ++p) 41944290Swollman continue; 42044290Swollman } 42144290Swollman if (tmp) 42244290Swollman putchar('>', flags, tp); 42344290Swollman break; 42444290Swollman case 'c': 42544290Swollman putchar(va_arg(ap, int), flags, tp); 42644290Swollman break; 42744290Swollman case 'r': 42844290Swollman p = va_arg(ap, char *); 42944290Swollman kprintf(p, flags, tp, va_arg(ap, va_list)); 43044290Swollman break; 43144290Swollman case 's': 43244290Swollman p = va_arg(ap, char *); 43344290Swollman while (ch = *p++) 43444290Swollman putchar(ch, flags, tp); 43544290Swollman break; 43644290Swollman case 'd': 43744290Swollman ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 43844290Swollman if ((long)ul < 0) { 43944290Swollman putchar('-', flags, tp); 44044290Swollman ul = -(long)ul; 44144290Swollman } 44244290Swollman base = 10; 44344290Swollman goto number; 44444290Swollman case 'o': 44544290Swollman ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 44644290Swollman base = 8; 44744290Swollman goto number; 44844290Swollman case 'u': 44944290Swollman ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 45044290Swollman base = 10; 45144290Swollman goto number; 45244290Swollman case 'x': 45344290Swollman ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 45444290Swollman base = 16; 455number: p = ksprintn(ul, base, &tmp); 456 if (width && (width -= tmp) > 0) 457 while (width--) 458 putchar(padc, flags, tp); 459 while (ch = *p--) 460 putchar(ch, flags, tp); 461 break; 462 default: 463 putchar('%', flags, tp); 464 if (lflag) 465 putchar('l', flags, tp); 466 /* FALLTHROUGH */ 467 case '%': 468 putchar(ch, flags, tp); 469 } 470 } 471} 472 473/* 474 * Print a character on console or users terminal. If destination is 475 * the console then the last MSGBUFS characters are saved in msgbuf for 476 * inspection later. 477 */ 478static void 479putchar(c, flags, tp) 480 register int c; 481 int flags; 482 struct tty *tp; 483{ 484 extern int msgbufmapped; 485 register struct msgbuf *mbp; 486 487 if (panicstr) 488 constty = NULL; 489 if ((flags & TOCONS) && tp == NULL && constty) { 490 tp = constty; 491 flags |= TOTTY; 492 } 493 if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 494 (flags & TOCONS) && tp == constty) 495 constty = NULL; 496 if ((flags & TOLOG) && 497 c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 498 mbp = msgbufp; 499 if (mbp->msg_magic != MSG_MAGIC) { 500 bzero((caddr_t)mbp, sizeof(*mbp)); 501 mbp->msg_magic = MSG_MAGIC; 502 } 503 mbp->msg_bufc[mbp->msg_bufx++] = c; 504 if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE) 505 mbp->msg_bufx = 0; 506 } 507 if ((flags & TOCONS) && constty == NULL && c != '\0') 508 (*v_putc)(c); 509} 510 511/* 512 * Scaled down version of sprintf(3). 513 */ 514#ifdef __STDC__ 515int 516sprintf(char *buf, const char *cfmt, ...) 517#else 518int 519sprintf(buf, cfmt, va_alist) 520 char *buf, *cfmt; 521#endif 522{ 523 register const char *fmt = cfmt; 524 register char *p, *bp; 525 register int ch, base; 526 u_long ul; 527 int lflag; 528 va_list ap; 529 530 va_start(ap, cfmt); 531 for (bp = buf; ; ) { 532 while ((ch = *(u_char *)fmt++) != '%') 533 if ((*bp++ = ch) == '\0') 534 return ((bp - buf) - 1); 535 536 lflag = 0; 537reswitch: switch (ch = *(u_char *)fmt++) { 538 case 'l': 539 lflag = 1; 540 goto reswitch; 541 case 'c': 542 *bp++ = va_arg(ap, int); 543 break; 544 case 's': 545 p = va_arg(ap, char *); 546 while (*bp++ = *p++) 547 continue; 548 --bp; 549 break; 550 case 'd': 551 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 552 if ((long)ul < 0) { 553 *bp++ = '-'; 554 ul = -(long)ul; 555 } 556 base = 10; 557 goto number; 558 break; 559 case 'o': 560 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 561 base = 8; 562 goto number; 563 break; 564 case 'u': 565 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 566 base = 10; 567 goto number; 568 break; 569 case 'x': 570 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 571 base = 16; 572number: for (p = ksprintn(ul, base, NULL); ch = *p--;) 573 *bp++ = ch; 574 break; 575 default: 576 *bp++ = '%'; 577 if (lflag) 578 *bp++ = 'l'; 579 /* FALLTHROUGH */ 580 case '%': 581 *bp++ = ch; 582 } 583 } 584 va_end(ap); 585} 586 587/* 588 * Put a number (base <= 16) in a buffer in reverse order; return an 589 * optional length and a pointer to the NULL terminated (preceded?) 590 * buffer. 591 */ 592static char * 593ksprintn(ul, base, lenp) 594 register u_long ul; 595 register int base, *lenp; 596{ /* A long in base 8, plus NULL. */ 597 static char buf[sizeof(long) * NBBY / 3 + 2]; 598 register char *p; 599 600 p = buf; 601 do { 602 *++p = "0123456789abcdef"[ul % base]; 603 } while (ul /= base); 604 if (lenp) 605 *lenp = p - buf; 606 return (p); 607} 608