hexdump.c revision 69214
138032Speter/*- 264562Sgshapiro * Copyright (c) 1986, 1988, 1991, 1993 338032Speter * The Regents of the University of California. All rights reserved. 490792Sgshapiro * (c) UNIX System Laboratories, Inc. 590792Sgshapiro * All or some portions of this file are derived from material licensed 690792Sgshapiro * to the University of California by American Telephone and Telegraph 790792Sgshapiro * Co. or Unix System Laboratories, Inc. and are reproduced herein with 838032Speter * the permission of UNIX System Laboratories, Inc. 990792Sgshapiro * 1090792Sgshapiro * Redistribution and use in source and binary forms, with or without 1190792Sgshapiro * modification, are permitted provided that the following conditions 1290792Sgshapiro * are met: 1338032Speter * 1. Redistributions of source code must retain the above copyright 1490792Sgshapiro * notice, this list of conditions and the following disclaimer. 1538032Speter * 2. Redistributions in binary form must reproduce the above copyright 1690792Sgshapiro * notice, this list of conditions and the following disclaimer in the 1790792Sgshapiro * documentation and/or other materials provided with the distribution. 1890792Sgshapiro * 3. All advertising materials mentioning features or use of this software 1990792Sgshapiro * must display the following acknowledgement: 2090792Sgshapiro * This product includes software developed by the University of 2190792Sgshapiro * California, Berkeley and its contributors. 2290792Sgshapiro * 4. Neither the name of the University nor the names of its contributors 2390792Sgshapiro * may be used to endorse or promote products derived from this software 2490792Sgshapiro * without specific prior written permission. 2590792Sgshapiro * 2690792Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2790792Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2890792Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2990792Sgshapiro * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3090792Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31132943Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3290792Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3390792Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3490792Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3590792Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3690792Sgshapiro * SUCH DAMAGE. 3790792Sgshapiro * 3890792Sgshapiro * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 3990792Sgshapiro * $FreeBSD: head/sys/kern/subr_prf.c 69214 2000-11-26 20:35:21Z phk $ 4090792Sgshapiro */ 4190792Sgshapiro 4290792Sgshapiro#include <sys/param.h> 4390792Sgshapiro#include <sys/systm.h> 4490792Sgshapiro#include <sys/kernel.h> 4590792Sgshapiro#include <sys/msgbuf.h> 4690792Sgshapiro#include <sys/malloc.h> 4790792Sgshapiro#include <sys/proc.h> 4890792Sgshapiro#include <sys/tty.h> 4938032Speter#include <sys/syslog.h> 5090792Sgshapiro#include <sys/cons.h> 5138032Speter 5238032Speter/* 5338032Speter * Note that stdarg.h and the ANSI style va_start macro is used for both 5438032Speter * ANSI and traditional C compilers. 5538032Speter */ 5638032Speter#include <machine/stdarg.h> 5738032Speter 5838032Speter#define TOCONS 0x01 5938032Speter#define TOTTY 0x02 6038032Speter#define TOLOG 0x04 6164562Sgshapiro 6264562Sgshapiro/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 6364562Sgshapiro#define MAXNBUF (sizeof(quad_t) * NBBY + 1) 6464562Sgshapiro 6564562Sgshapirostruct putchar_arg { 6638032Speter int flags; 6738032Speter struct tty *tty; 6838032Speter}; 6938032Speter 7038032Speterstruct snprintf_arg { 7138032Speter char *str; 7238032Speter size_t remain; 7338032Speter}; 7438032Speter 7538032Speterstruct tty *constty; /* pointer to console "window" tty */ 7638032Speter 7738032Speterstatic void (*v_putc)(int) = cnputc; /* routine to putc on virtual console */ 7838032Speterstatic void logpri __P((int level)); 7938032Speterstatic void msglogchar(int c, void *dummyarg); 80261194Sgshapirostatic void putchar __P((int ch, void *arg)); 8164562Sgshapirostatic char *ksprintn __P((char *nbuf, u_long num, int base, int *len)); 8238032Speterstatic char *ksprintqn __P((char *nbuf, u_quad_t num, int base, int *len)); 8338032Speterstatic void snprintf_func __P((int ch, void *arg)); 8438032Speter 8538032Speterstatic int consintr = 1; /* Ok to handle console interrupts? */ 8638032Speterstatic int msgbufmapped; /* Set when safe to use msgbuf */ 8738032Speter 8838032Speter/* 8938032Speter * Warn that a system table is full. 9038032Speter */ 9138032Spetervoid 9238032Spetertablefull(tab) 9338032Speter const char *tab; 9438032Speter{ 9538032Speter 9638032Speter log(LOG_ERR, "%s: table is full\n", tab); 9738032Speter} 9838032Speter 9938032Speter/* 10038032Speter * Uprintf prints to the controlling terminal for the current process. 10138032Speter * It may block if the tty queue is overfull. No message is printed if 10238032Speter * the queue does not clear in a reasonable time. 10338032Speter */ 10464562Sgshapiroint 10538032Speteruprintf(const char *fmt, ...) 10638032Speter{ 10738032Speter struct proc *p = curproc; 10838032Speter va_list ap; 10938032Speter struct putchar_arg pca; 11064562Sgshapiro int retval = 0; 11138032Speter 11238032Speter if (p && p != idleproc && p->p_flag & P_CONTROLT && 11338032Speter p->p_session->s_ttyvp) { 11464562Sgshapiro va_start(ap, fmt); 11538032Speter pca.tty = p->p_session->s_ttyp; 11638032Speter pca.flags = TOTTY; 11738032Speter retval = kvprintf(fmt, putchar, &pca, 10, ap); 11838032Speter va_end(ap); 11938032Speter } 12038032Speter return retval; 12138032Speter} 12264562Sgshapiro 12338032Speter/* 12438032Speter * tprintf prints on the controlling terminal associated 12564562Sgshapiro * with the given session, possibly to the log as well. 12638032Speter */ 12738032Spetervoid 12838032Spetertprintf(struct proc *p, int pri, const char *fmt, ...) 12964562Sgshapiro{ 13064562Sgshapiro struct tty *tp = NULL; 13138032Speter int flags = 0, shld = 0; 13290792Sgshapiro va_list ap; 13390792Sgshapiro struct putchar_arg pca; 134132943Sgshapiro int retval; 135132943Sgshapiro 13638032Speter if (pri != -1) { 13738032Speter logpri(pri); 13838032Speter flags |= TOLOG; 13938032Speter } 14038032Speter if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 14138032Speter SESSHOLD(p->p_session); 14238032Speter shld++; 14390792Sgshapiro if (ttycheckoutq(p->p_session->s_ttyp, 0)) { 14464562Sgshapiro flags |= TOTTY; 14564562Sgshapiro tp = p->p_session->s_ttyp; 14638032Speter } 14764562Sgshapiro } 14864562Sgshapiro pca.tty = tp; 14964562Sgshapiro pca.flags = flags; 15064562Sgshapiro va_start(ap, fmt); 15138032Speter retval = kvprintf(fmt, putchar, &pca, 10, ap); 15290792Sgshapiro va_end(ap); 15390792Sgshapiro if (shld) 15490792Sgshapiro SESSRELE(p->p_session); 15590792Sgshapiro logwakeup(); 15690792Sgshapiro} 15790792Sgshapiro 15890792Sgshapiro/* 15964562Sgshapiro * Ttyprintf displays a message on a tty; it should be used only by 16090792Sgshapiro * the tty driver, or anything that knows the underlying tty will not 161285229Sgshapiro * be revoke(2)'d away. Other callers should use tprintf. 162285229Sgshapiro */ 163285229Sgshapiroint 164285229Sgshapirottyprintf(struct tty *tp, const char *fmt, ...) 165285229Sgshapiro{ 166285229Sgshapiro va_list ap; 167285229Sgshapiro struct putchar_arg pca; 168285229Sgshapiro int retval; 169285229Sgshapiro 170285229Sgshapiro va_start(ap, fmt); 171285229Sgshapiro pca.tty = tp; 172285229Sgshapiro pca.flags = TOTTY; 173285229Sgshapiro retval = kvprintf(fmt, putchar, &pca, 10, ap); 174285229Sgshapiro va_end(ap); 175285229Sgshapiro return retval; 176285229Sgshapiro} 177285229Sgshapiro 178285229Sgshapiroextern int log_open; 179285229Sgshapiro 180285229Sgshapiro/* 18138032Speter * Log writes to the log buffer, and guarantees not to sleep (so can be 18238032Speter * called by interrupt routines). If there is no process reading the 18338032Speter * log yet, it writes to the console also. 18438032Speter */ 18538032Spetervoid 18638032Speterlog(int level, const char *fmt, ...) 18738032Speter{ 18838032Speter int s; 18938032Speter va_list ap; 19038032Speter int retval; 19138032Speter 19238032Speter s = splhigh(); 19338032Speter if (level != -1) 19438032Speter logpri(level); 19538032Speter va_start(ap, fmt); 19638032Speter 19738032Speter retval = kvprintf(fmt, msglogchar, NULL, 10, ap); 19838032Speter va_end(ap); 19938032Speter 20038032Speter splx(s); 20138032Speter if (!log_open) { 20238032Speter struct putchar_arg pca; 20364562Sgshapiro va_start(ap, fmt); 20438032Speter pca.tty = NULL; 20564562Sgshapiro pca.flags = TOCONS; 20638032Speter retval += kvprintf(fmt, putchar, &pca, 10, ap); 20738032Speter va_end(ap); 20838032Speter } 20938032Speter logwakeup(); 21038032Speter} 21138032Speter 21238032Speterstatic void 213110560Sgshapirologpri(level) 214110560Sgshapiro int level; 215110560Sgshapiro{ 216110560Sgshapiro char nbuf[MAXNBUF]; 217110560Sgshapiro char *p; 218110560Sgshapiro 21990792Sgshapiro msglogchar('<', NULL); 220110560Sgshapiro for (p = ksprintn(nbuf, (u_long)level, 10, NULL); *p;) 22190792Sgshapiro msglogchar(*p--, NULL); 22290792Sgshapiro msglogchar('>', NULL); 22390792Sgshapiro} 22490792Sgshapiro 22590792Sgshapiroint 22690792Sgshapiroprintf(const char *fmt, ...) 22790792Sgshapiro{ 22890792Sgshapiro va_list ap; 22990792Sgshapiro int savintr; 23090792Sgshapiro struct putchar_arg pca; 23190792Sgshapiro int retval; 23290792Sgshapiro 23390792Sgshapiro savintr = consintr; /* disable interrupts */ 23438032Speter consintr = 0; 23538032Speter va_start(ap, fmt); 23638032Speter pca.tty = NULL; 23738032Speter pca.flags = TOCONS | TOLOG; 23838032Speter retval = kvprintf(fmt, putchar, &pca, 10, ap); 23938032Speter va_end(ap); 24064562Sgshapiro if (!panicstr) 24164562Sgshapiro logwakeup(); 24264562Sgshapiro consintr = savintr; /* reenable interrupts */ 24364562Sgshapiro return retval; 24464562Sgshapiro} 24538032Speter 24664562Sgshapiroint 24764562Sgshapirovprintf(const char *fmt, va_list ap) 24864562Sgshapiro{ 24964562Sgshapiro int savintr; 25064562Sgshapiro struct putchar_arg pca; 25164562Sgshapiro int retval; 25264562Sgshapiro 25364562Sgshapiro savintr = consintr; /* disable interrupts */ 25464562Sgshapiro consintr = 0; 25564562Sgshapiro pca.tty = NULL; 25664562Sgshapiro pca.flags = TOCONS | TOLOG; 25764562Sgshapiro retval = kvprintf(fmt, putchar, &pca, 10, ap); 25864562Sgshapiro if (!panicstr) 25964562Sgshapiro logwakeup(); 26064562Sgshapiro consintr = savintr; /* reenable interrupts */ 26164562Sgshapiro return retval; 26264562Sgshapiro} 26364562Sgshapiro 26464562Sgshapiro/* 26564562Sgshapiro * Print a character on console or users terminal. If destination is 26664562Sgshapiro * the console then the last bunch of characters are saved in msgbuf for 26764562Sgshapiro * inspection later. 26864562Sgshapiro */ 26964562Sgshapirostatic void 27064562Sgshapiroputchar(int c, void *arg) 27164562Sgshapiro{ 27264562Sgshapiro struct putchar_arg *ap = (struct putchar_arg*) arg; 27364562Sgshapiro int flags = ap->flags; 27464562Sgshapiro struct tty *tp = ap->tty; 27564562Sgshapiro if (panicstr) 27664562Sgshapiro constty = NULL; 27764562Sgshapiro if ((flags & TOCONS) && tp == NULL && constty) { 27864562Sgshapiro tp = constty; 27964562Sgshapiro flags |= TOTTY; 28064562Sgshapiro } 28164562Sgshapiro if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 28264562Sgshapiro (flags & TOCONS) && tp == constty) 28364562Sgshapiro constty = NULL; 28464562Sgshapiro if ((flags & TOLOG)) 28564562Sgshapiro msglogchar(c, NULL); 28664562Sgshapiro if ((flags & TOCONS) && constty == NULL && c != '\0') 28764562Sgshapiro (*v_putc)(c); 28864562Sgshapiro} 28964562Sgshapiro 29064562Sgshapiro/* 29164562Sgshapiro * Scaled down version of sprintf(3). 29264562Sgshapiro */ 29364562Sgshapiroint 29464562Sgshapirosprintf(char *buf, const char *cfmt, ...) 29564562Sgshapiro{ 29680785Sgshapiro int retval; 29780785Sgshapiro va_list ap; 29880785Sgshapiro 29980785Sgshapiro va_start(ap, cfmt); 30080785Sgshapiro retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 30138032Speter buf[retval] = '\0'; 30238032Speter va_end(ap); 30338032Speter return retval; 30438032Speter} 30538032Speter 30638032Speter/* 30738032Speter * Scaled down version of vsprintf(3). 30838032Speter */ 30938032Speterint 31038032Spetervsprintf(char *buf, const char *cfmt, va_list ap) 31138032Speter{ 31238032Speter int retval; 31338032Speter 31438032Speter retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 31538032Speter buf[retval] = '\0'; 31638032Speter return retval; 31738032Speter} 31838032Speter 31938032Speter/* 32038032Speter * Scaled down version of snprintf(3). 32164562Sgshapiro */ 32238032Speterint 32338032Spetersnprintf(char *str, size_t size, const char *format, ...) 32438032Speter{ 32538032Speter int retval; 32638032Speter va_list ap; 32738032Speter 32864562Sgshapiro va_start(ap, format); 32938032Speter retval = vsnprintf(str, size, format, ap); 33038032Speter va_end(ap); 33138032Speter return(retval); 33264562Sgshapiro} 33364562Sgshapiro 33473188Sgshapiro/* 33564562Sgshapiro * Scaled down version of vsnprintf(3). 33673188Sgshapiro */ 33764562Sgshapiroint 33873188Sgshapirovsnprintf(char *str, size_t size, const char *format, va_list ap) 33973188Sgshapiro{ 34090792Sgshapiro struct snprintf_arg info; 34190792Sgshapiro int retval; 34290792Sgshapiro 34390792Sgshapiro info.str = str; 34464562Sgshapiro info.remain = size; 34538032Speter retval = kvprintf(format, snprintf_func, &info, 10, ap); 34638032Speter if (info.remain >= 1) 34764562Sgshapiro *info.str++ = '\0'; 34864562Sgshapiro return retval; 34938032Speter} 35038032Speter 35138032Speterstatic void 35238032Spetersnprintf_func(int ch, void *arg) 35364562Sgshapiro{ 35464562Sgshapiro struct snprintf_arg *const info = arg; 35564562Sgshapiro 35638032Speter if (info->remain >= 2) { 35738032Speter *info->str++ = ch; 35838032Speter info->remain--; 35938032Speter } 36064562Sgshapiro} 36164562Sgshapiro 36264562Sgshapiro/* 36364562Sgshapiro * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 36464562Sgshapiro * order; return an optional length and a pointer to the last character 36538032Speter * written in the buffer (i.e., the first character of the string). 36638032Speter * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 36738032Speter */ 36838032Speterstatic char * 36938032Speterksprintn(nbuf, ul, base, lenp) 37038032Speter char *nbuf; 37138032Speter u_long ul; 37290792Sgshapiro int base, *lenp; 37338032Speter{ 37438032Speter char *p; 37564562Sgshapiro 37638032Speter p = nbuf; 37790792Sgshapiro *p = '\0'; 37890792Sgshapiro do { 37990792Sgshapiro *++p = hex2ascii(ul % base); 38090792Sgshapiro } while (ul /= base); 381102528Sgshapiro if (lenp) 38238032Speter *lenp = p - nbuf; 38390792Sgshapiro return (p); 38438032Speter} 38564562Sgshapiro/* ksprintn, but for a quad_t. */ 38664562Sgshapirostatic char * 38764562Sgshapiroksprintqn(nbuf, uq, base, lenp) 38864562Sgshapiro char *nbuf; 38964562Sgshapiro u_quad_t uq; 39064562Sgshapiro int base, *lenp; 39164562Sgshapiro{ 39238032Speter char *p; 39364562Sgshapiro 39438032Speter p = nbuf; 39564562Sgshapiro *p = '\0'; 39664562Sgshapiro do { 39764562Sgshapiro *++p = hex2ascii(uq % base); 39894334Sgshapiro } while (uq /= base); 39994334Sgshapiro if (lenp) 40094334Sgshapiro *lenp = p - nbuf; 40166494Sgshapiro return (p); 40238032Speter} 40338032Speter 40466494Sgshapiro/* 40566494Sgshapiro * Scaled down version of printf(3). 40666494Sgshapiro * 40766494Sgshapiro * Two additional formats: 40890792Sgshapiro * 40990792Sgshapiro * The format %b is supported to decode error registers. 41090792Sgshapiro * Its usage is: 41190792Sgshapiro * 41290792Sgshapiro * printf("reg=%b\n", regval, "<base><arg>*"); 41364562Sgshapiro * 41464562Sgshapiro * where <base> is the output base expressed as a control character, e.g. 41564562Sgshapiro * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 41638032Speter * the first of which gives the bit number to be inspected (origin 1), and 41738032Speter * the next characters (up to a control character, i.e. a character <= 32), 41838032Speter * give the name of the register. Thus: 41938032Speter * 420285229Sgshapiro * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 421285229Sgshapiro * 422285229Sgshapiro * would produce output: 423285229Sgshapiro * 424168515Sgshapiro * reg=3<BITTWO,BITONE> 425168515Sgshapiro * 426168515Sgshapiro * XXX: %D -- Hexdump, takes pointer and separator string: 42738032Speter * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 42838032Speter * ("%*D", len, ptr, " " -> XX XX XX XX ... 42938032Speter */ 43038032Speterint 43138032Speterkvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 43238032Speter{ 43338032Speter#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 43438032Speter char nbuf[MAXNBUF]; 43538032Speter char *p, *q, *d; 43638032Speter u_char *up; 43738032Speter int ch, n; 43838032Speter u_long ul; 43990792Sgshapiro u_quad_t uq; 44038032Speter int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 44138032Speter int dwidth; 44238032Speter char padc; 44338032Speter int retval = 0; 44438032Speter 44538032Speter ul = 0; 44638032Speter uq = 0; 44764562Sgshapiro if (!func) 44838032Speter d = (char *) arg; 44938032Speter else 45090792Sgshapiro d = NULL; 45138032Speter 45243730Speter if (fmt == NULL) 45343730Speter fmt = "(fmt null)\n"; 45438032Speter 45564562Sgshapiro if (radix < 2 || radix > 36) 45643730Speter radix = 10; 45738032Speter 45838032Speter for (;;) { 45938032Speter padc = ' '; 46043730Speter width = 0; 46138032Speter while ((ch = (u_char)*fmt++) != '%') { 46238032Speter if (ch == '\0') 46338032Speter return retval; 46490792Sgshapiro PCHAR(ch); 46538032Speter } 46638032Speter qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 46738032Speter sign = 0; dot = 0; dwidth = 0; 46838032Speterreswitch: switch (ch = (u_char)*fmt++) { 46990792Sgshapiro case '.': 47038032Speter dot = 1; 47138032Speter goto reswitch; 47264562Sgshapiro case '#': 47364562Sgshapiro sharpflag = 1; 47438032Speter goto reswitch; 47590792Sgshapiro case '+': 47664562Sgshapiro sign = 1; 47738032Speter goto reswitch; 47838032Speter case '-': 47938032Speter ladjust = 1; 48038032Speter goto reswitch; 48138032Speter case '%': 48238032Speter PCHAR(ch); 48338032Speter break; 48438032Speter case '*': 48538032Speter if (!dot) { 48690792Sgshapiro width = va_arg(ap, int); 48764562Sgshapiro if (width < 0) { 48864562Sgshapiro ladjust = !ladjust; 48938032Speter width = -width; 49038032Speter } 49198121Sgshapiro } else { 49298121Sgshapiro dwidth = va_arg(ap, int); 49398121Sgshapiro } 49498121Sgshapiro goto reswitch; 49598121Sgshapiro case '0': 49698121Sgshapiro if (!dot) { 49798121Sgshapiro padc = '0'; 49898121Sgshapiro goto reswitch; 49998121Sgshapiro } 50098121Sgshapiro case '1': case '2': case '3': case '4': 50198121Sgshapiro case '5': case '6': case '7': case '8': case '9': 50298121Sgshapiro for (n = 0;; ++fmt) { 50398121Sgshapiro n = n * 10 + ch - '0'; 504110560Sgshapiro ch = *fmt; 505110560Sgshapiro if (ch < '0' || ch > '9') 506110560Sgshapiro break; 507110560Sgshapiro } 50838032Speter if (dot) 50943730Speter dwidth = n; 51043730Speter else 51164562Sgshapiro width = n; 51264562Sgshapiro goto reswitch; 51364562Sgshapiro case 'b': 51464562Sgshapiro ul = va_arg(ap, int); 51564562Sgshapiro p = va_arg(ap, char *); 51664562Sgshapiro for (q = ksprintn(nbuf, ul, *p++, NULL); *q;) 51764562Sgshapiro PCHAR(*q--); 51890792Sgshapiro 51990792Sgshapiro if (!ul) 52038032Speter break; 52164562Sgshapiro 522157001Sgshapiro for (tmp = 0; *p;) { 523157001Sgshapiro n = *p++; 524157001Sgshapiro if (ul & (1 << (n - 1))) { 525157001Sgshapiro PCHAR(tmp ? ',' : '<'); 526157001Sgshapiro for (; (n = *p) > ' '; ++p) 527157001Sgshapiro PCHAR(n); 52838032Speter tmp = 1; 52964562Sgshapiro } else 53038032Speter for (; *p > ' '; ++p) 53190792Sgshapiro continue; 53290792Sgshapiro } 53390792Sgshapiro if (tmp) 53464562Sgshapiro PCHAR('>'); 53564562Sgshapiro break; 53664562Sgshapiro case 'c': 53764562Sgshapiro PCHAR(va_arg(ap, int)); 53864562Sgshapiro break; 53938032Speter case 'D': 54038032Speter up = va_arg(ap, u_char *); 54138032Speter p = va_arg(ap, char *); 54238032Speter if (!width) 54338032Speter width = 16; 54464562Sgshapiro while(width--) { 54538032Speter PCHAR(hex2ascii(*up >> 4)); 54638032Speter PCHAR(hex2ascii(*up & 0x0f)); 54738032Speter up++; 54838032Speter if (width) 54938032Speter for (q=p;*q;q++) 55038032Speter PCHAR(*q); 55138032Speter } 55238032Speter break; 55338032Speter case 'd': 55438032Speter if (qflag) 55538032Speter uq = va_arg(ap, quad_t); 55638032Speter else if (lflag) 55738032Speter ul = va_arg(ap, long); 55871345Sgshapiro else 55982017Sgshapiro ul = va_arg(ap, int); 56071345Sgshapiro sign = 1; 56171345Sgshapiro base = 10; 56290792Sgshapiro goto number; 56371345Sgshapiro case 'l': 56471345Sgshapiro if (lflag) { 56571345Sgshapiro lflag = 0; 56671345Sgshapiro qflag = 1; 56771345Sgshapiro } else 56838032Speter lflag = 1; 56964562Sgshapiro goto reswitch; 57064562Sgshapiro case 'o': 57164562Sgshapiro if (qflag) 57238032Speter uq = va_arg(ap, u_quad_t); 57338032Speter else if (lflag) 57438032Speter ul = va_arg(ap, u_long); 57538032Speter else 57638032Speter ul = va_arg(ap, u_int); 57738032Speter base = 8; 57838032Speter goto nosign; 57938032Speter case 'p': 58038032Speter ul = (uintptr_t)va_arg(ap, void *); 58138032Speter base = 16; 58238032Speter sharpflag = (width == 0); 58338032Speter goto nosign; 58438032Speter case 'q': 58538032Speter qflag = 1; 58638032Speter goto reswitch; 58738032Speter case 'n': 58838032Speter case 'r': 58938032Speter if (qflag) 59038032Speter uq = va_arg(ap, u_quad_t); 59138032Speter else if (lflag) 59290792Sgshapiro ul = va_arg(ap, u_long); 59338032Speter else 59438032Speter ul = sign ? 59538032Speter (u_long)va_arg(ap, int) : va_arg(ap, u_int); 59638032Speter base = radix; 59738032Speter goto number; 59838032Speter case 's': 59990792Sgshapiro p = va_arg(ap, char *); 60038032Speter if (p == NULL) 60138032Speter p = "(null)"; 60238032Speter if (!dot) 60338032Speter n = strlen (p); 60438032Speter else 60538032Speter for (n = 0; n < dwidth && p[n]; n++) 60638032Speter continue; 60738032Speter 60838032Speter width -= n; 60938032Speter 61064562Sgshapiro if (!ladjust && width > 0) 61138032Speter while (width--) 61238032Speter PCHAR(padc); 61338032Speter while (n--) 61438032Speter PCHAR(*p++); 61564562Sgshapiro if (ladjust && width > 0) 61664562Sgshapiro while (width--) 61764562Sgshapiro PCHAR(padc); 61838032Speter break; 61966494Sgshapiro case 'u': 62038032Speter if (qflag) 62138032Speter uq = va_arg(ap, u_quad_t); 62238032Speter else if (lflag) 62338032Speter ul = va_arg(ap, u_long); 62490792Sgshapiro else 62590792Sgshapiro ul = va_arg(ap, u_int); 62690792Sgshapiro base = 10; 62738032Speter goto nosign; 62864562Sgshapiro case 'x': 62964562Sgshapiro case 'X': 63064562Sgshapiro if (qflag) 63138032Speter uq = va_arg(ap, u_quad_t); 63238032Speter else if (lflag) 63338032Speter ul = va_arg(ap, u_long); 63438032Speter else 63538032Speter ul = va_arg(ap, u_int); 63638032Speter base = 16; 63738032Speter goto nosign; 63838032Speter case 'z': 63938032Speter if (qflag) 64038032Speter uq = va_arg(ap, u_quad_t); 64138032Speter else if (lflag) 64238032Speter ul = va_arg(ap, u_long); 64338032Speter else 64471345Sgshapiro ul = sign ? 64538032Speter (u_long)va_arg(ap, int) : va_arg(ap, u_int); 64638032Speter base = 16; 64738032Speter goto number; 64838032Speternosign: sign = 0; 64938032Speternumber: 65038032Speter if (qflag) { 65138032Speter if (sign && (quad_t)uq < 0) { 65238032Speter neg = 1; 65338032Speter uq = -(quad_t)uq; 65438032Speter } 65538032Speter p = ksprintqn(nbuf, uq, base, &tmp); 65638032Speter } else { 65738032Speter if (sign && (long)ul < 0) { 65838032Speter neg = 1; 65938032Speter ul = -(long)ul; 66038032Speter } 66138032Speter p = ksprintn(nbuf, ul, base, &tmp); 662111823Sgshapiro } 663111823Sgshapiro if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 66443730Speter if (base == 8) 66538032Speter tmp++; 66638032Speter else if (base == 16) 66790792Sgshapiro tmp += 2; 66890792Sgshapiro } 66990792Sgshapiro if (neg) 67038032Speter tmp++; 67138032Speter 67238032Speter if (!ladjust && width && (width -= tmp) > 0) 67338032Speter while (width--) 67438032Speter PCHAR(padc); 67538032Speter if (neg) 67638032Speter PCHAR('-'); 67738032Speter if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 67838032Speter if (base == 8) { 67938032Speter PCHAR('0'); 68038032Speter } else if (base == 16) { 68138032Speter PCHAR('0'); 68238032Speter PCHAR('x'); 68390792Sgshapiro } 68490792Sgshapiro } 68590792Sgshapiro 68690792Sgshapiro while (*p) 68790792Sgshapiro PCHAR(*p--); 68890792Sgshapiro 68938032Speter if (ladjust && width && (width -= tmp) > 0) 69098121Sgshapiro while (width--) 69198121Sgshapiro PCHAR(padc); 69298121Sgshapiro 69398121Sgshapiro break; 69498121Sgshapiro default: 69598121Sgshapiro PCHAR('%'); 69698121Sgshapiro if (lflag) 69798121Sgshapiro PCHAR('l'); 69864562Sgshapiro PCHAR(ch); 69964562Sgshapiro break; 70038032Speter } 70138032Speter } 70238032Speter#undef PCHAR 70343730Speter} 70443730Speter 70543730Speter/* 70643730Speter * Put character in log buffer. 70738032Speter */ 70838032Speterstatic void 70938032Spetermsglogchar(int c, void *dummyarg) 71038032Speter{ 71138032Speter struct msgbuf *mbp; 71238032Speter 71338032Speter if (c != '\0' && c != '\r' && c != 0177 && msgbufmapped) { 71438032Speter mbp = msgbufp; 71538032Speter mbp->msg_ptr[mbp->msg_bufx++] = c; 71643730Speter if (mbp->msg_bufx >= mbp->msg_size) 71738032Speter mbp->msg_bufx = 0; 71864562Sgshapiro /* If the buffer is full, keep the most recent data. */ 71990792Sgshapiro if (mbp->msg_bufr == mbp->msg_bufx) { 72064562Sgshapiro if (++mbp->msg_bufr >= mbp->msg_size) 72138032Speter mbp->msg_bufr = 0; 72243730Speter } 72338032Speter } 72438032Speter} 72564562Sgshapiro 72638032Speterstatic void 72738032Spetermsgbufcopy(struct msgbuf *oldp) 72838032Speter{ 72938032Speter int pos; 73038032Speter 73164562Sgshapiro pos = oldp->msg_bufr; 73264562Sgshapiro while (pos != oldp->msg_bufx) { 73338032Speter msglogchar(oldp->msg_ptr[pos], NULL); 73490792Sgshapiro if (++pos >= oldp->msg_size) 73590792Sgshapiro pos = 0; 73690792Sgshapiro } 73790792Sgshapiro} 73890792Sgshapiro 73938032Spetervoid 74038032Spetermsgbufinit(void *ptr, size_t size) 74164562Sgshapiro{ 74264562Sgshapiro char *cp; 74364562Sgshapiro static struct msgbuf *oldp = NULL; 74464562Sgshapiro 74564562Sgshapiro cp = (char *)ptr; 74664562Sgshapiro msgbufp = (struct msgbuf *) (cp + size - sizeof(*msgbufp)); 74764562Sgshapiro if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp) { 74838032Speter bzero(cp, size); 74964562Sgshapiro msgbufp->msg_magic = MSG_MAGIC; 75064562Sgshapiro msgbufp->msg_size = (char *)msgbufp - cp; 75164562Sgshapiro msgbufp->msg_ptr = cp; 75264562Sgshapiro } 75364562Sgshapiro if (msgbufmapped && oldp != msgbufp) 75438032Speter msgbufcopy(oldp); 75538032Speter msgbufmapped = 1; 75664562Sgshapiro oldp = msgbufp; 75738032Speter} 75838032Speter 75938032Speter#include "opt_ddb.h" 76064562Sgshapiro#ifdef DDB 76164562Sgshapiro#include <ddb/ddb.h> 76264562Sgshapiro 76364562SgshapiroDB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 76464562Sgshapiro{ 76564562Sgshapiro int i, j; 76690792Sgshapiro 76764562Sgshapiro if (!msgbufmapped) { 76864562Sgshapiro db_printf("msgbuf not mapped yet\n"); 76938032Speter return; 770285229Sgshapiro } 771285229Sgshapiro db_printf("msgbufp = %p\n", msgbufp); 772285229Sgshapiro db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n", 773285229Sgshapiro msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, 774285229Sgshapiro msgbufp->msg_bufx, msgbufp->msg_ptr); 775285229Sgshapiro for (i = 0; i < msgbufp->msg_size; i++) { 776285229Sgshapiro j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; 777285229Sgshapiro db_printf("%c", msgbufp->msg_ptr[j]); 778285229Sgshapiro } 779285229Sgshapiro db_printf("\n"); 78064562Sgshapiro} 78171345Sgshapiro 78271345Sgshapiro#endif /* DDB */ 78371345Sgshapiro