hexdump.c revision 70240
1230837Sdelphij/*- 2230837Sdelphij * Copyright (c) 1986, 1988, 1991, 1993 3230837Sdelphij * The Regents of the University of California. All rights reserved. 4230837Sdelphij * (c) UNIX System Laboratories, Inc. 5230837Sdelphij * All or some portions of this file are derived from material licensed 6230837Sdelphij * to the University of California by American Telephone and Telegraph 7230837Sdelphij * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8230837Sdelphij * the permission of UNIX System Laboratories, Inc. 9230837Sdelphij * 10230837Sdelphij * Redistribution and use in source and binary forms, with or without 11230837Sdelphij * modification, are permitted provided that the following conditions 12230837Sdelphij * are met: 13230837Sdelphij * 1. Redistributions of source code must retain the above copyright 14230837Sdelphij * notice, this list of conditions and the following disclaimer. 15230837Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 16230837Sdelphij * notice, this list of conditions and the following disclaimer in the 17230837Sdelphij * documentation and/or other materials provided with the distribution. 18230837Sdelphij * 3. All advertising materials mentioning features or use of this software 19230837Sdelphij * must display the following acknowledgement: 20230837Sdelphij * This product includes software developed by the University of 21230837Sdelphij * California, Berkeley and its contributors. 22230837Sdelphij * 4. Neither the name of the University nor the names of its contributors 23230837Sdelphij * may be used to endorse or promote products derived from this software 24230837Sdelphij * without specific prior written permission. 25230837Sdelphij * 26230837Sdelphij * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27230837Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28230837Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29230837Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30230837Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31230837Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32230837Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33230837Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34230837Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35230837Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36230837Sdelphij * SUCH DAMAGE. 37230837Sdelphij * 38230837Sdelphij * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 39230837Sdelphij * $FreeBSD: head/sys/kern/subr_prf.c 70240 2000-12-20 22:07:59Z phk $ 40230837Sdelphij */ 41230837Sdelphij 42230837Sdelphij#include <sys/param.h> 43230837Sdelphij#include <sys/systm.h> 44230837Sdelphij#include <sys/kernel.h> 45230837Sdelphij#include <sys/msgbuf.h> 46230837Sdelphij#include <sys/malloc.h> 47230837Sdelphij#include <sys/proc.h> 48230837Sdelphij#include <sys/tty.h> 49230837Sdelphij#include <sys/syslog.h> 50230837Sdelphij#include <sys/cons.h> 51230837Sdelphij#include <sys/uio.h> 52230837Sdelphij 53230837Sdelphij/* 54230837Sdelphij * Note that stdarg.h and the ANSI style va_start macro is used for both 55230837Sdelphij * ANSI and traditional C compilers. 56230837Sdelphij */ 57230837Sdelphij#include <machine/stdarg.h> 58230837Sdelphij 59230837Sdelphij#define TOCONS 0x01 60230837Sdelphij#define TOTTY 0x02 61230837Sdelphij#define TOLOG 0x04 62230837Sdelphij 63230837Sdelphij/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 64230837Sdelphij#define MAXNBUF (sizeof(quad_t) * NBBY + 1) 65230837Sdelphij 66230837Sdelphijstruct putchar_arg { 67230837Sdelphij int flags; 68230837Sdelphij int pri; 69230837Sdelphij struct tty *tty; 70230837Sdelphij}; 71230837Sdelphij 72230837Sdelphijstruct snprintf_arg { 73230837Sdelphij char *str; 74230837Sdelphij size_t remain; 75230837Sdelphij}; 76230837Sdelphij 77230837Sdelphijextern int log_open; 78230837Sdelphij 79230837Sdelphijstruct tty *constty; /* pointer to console "window" tty */ 80230837Sdelphij 81230837Sdelphijstatic void (*v_putc)(int) = cnputc; /* routine to putc on virtual console */ 82230837Sdelphijstatic void msglogchar(int c, int pri); 83230837Sdelphijstatic void msgaddchar(int c, void *dummy); 84230837Sdelphijstatic void putchar __P((int ch, void *arg)); 85230837Sdelphijstatic char *ksprintn __P((char *nbuf, u_long num, int base, int *len)); 86230837Sdelphijstatic char *ksprintqn __P((char *nbuf, u_quad_t num, int base, int *len)); 87230837Sdelphijstatic void snprintf_func __P((int ch, void *arg)); 88230837Sdelphij 89230837Sdelphijstatic int consintr = 1; /* Ok to handle console interrupts? */ 90230837Sdelphijstatic int msgbufmapped; /* Set when safe to use msgbuf */ 91230837Sdelphijint msgbuftrigger; 92230837Sdelphij 93230837Sdelphij/* 94230837Sdelphij * Warn that a system table is full. 95230837Sdelphij */ 96230837Sdelphijvoid 97230837Sdelphijtablefull(const char *tab) 98230837Sdelphij{ 99230837Sdelphij 100230837Sdelphij log(LOG_ERR, "%s: table is full\n", tab); 101230837Sdelphij} 102230837Sdelphij 103230837Sdelphij/* 104230837Sdelphij * Uprintf prints to the controlling terminal for the current process. 105230837Sdelphij * It may block if the tty queue is overfull. No message is printed if 106230837Sdelphij * the queue does not clear in a reasonable time. 107230837Sdelphij */ 108230837Sdelphijint 109230837Sdelphijuprintf(const char *fmt, ...) 110230837Sdelphij{ 111230837Sdelphij struct proc *p = curproc; 112230837Sdelphij va_list ap; 113230837Sdelphij struct putchar_arg pca; 114230837Sdelphij int retval = 0; 115230837Sdelphij 116230837Sdelphij if (p && p != idleproc && p->p_flag & P_CONTROLT && 117230837Sdelphij p->p_session->s_ttyvp) { 118230837Sdelphij va_start(ap, fmt); 119230837Sdelphij pca.tty = p->p_session->s_ttyp; 120230837Sdelphij pca.flags = TOTTY; 121230837Sdelphij retval = kvprintf(fmt, putchar, &pca, 10, ap); 122230837Sdelphij va_end(ap); 123230837Sdelphij } 124230837Sdelphij return retval; 125230837Sdelphij} 126230837Sdelphij 127230837Sdelphij/* 128230837Sdelphij * tprintf prints on the controlling terminal associated 129230837Sdelphij * with the given session, possibly to the log as well. 130230837Sdelphij */ 131230837Sdelphijvoid 132230837Sdelphijtprintf(struct proc *p, int pri, const char *fmt, ...) 133230837Sdelphij{ 134230837Sdelphij struct tty *tp = NULL; 135230837Sdelphij int flags = 0, shld = 0; 136230837Sdelphij va_list ap; 137230837Sdelphij struct putchar_arg pca; 138230837Sdelphij int retval; 139230837Sdelphij 140230837Sdelphij if (pri != -1) 141230837Sdelphij flags |= TOLOG; 142230837Sdelphij if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 143230837Sdelphij SESSHOLD(p->p_session); 144230837Sdelphij shld++; 145230837Sdelphij if (ttycheckoutq(p->p_session->s_ttyp, 0)) { 146230837Sdelphij flags |= TOTTY; 147230837Sdelphij tp = p->p_session->s_ttyp; 148230837Sdelphij } 149230837Sdelphij } 150230837Sdelphij pca.pri = pri; 151230837Sdelphij pca.tty = tp; 152230837Sdelphij pca.flags = flags; 153230837Sdelphij va_start(ap, fmt); 154230837Sdelphij retval = kvprintf(fmt, putchar, &pca, 10, ap); 155230837Sdelphij va_end(ap); 156230837Sdelphij if (shld) 157230837Sdelphij SESSRELE(p->p_session); 158230837Sdelphij msgbuftrigger = 1; 159230837Sdelphij} 160230837Sdelphij 161230837Sdelphij/* 162230837Sdelphij * Ttyprintf displays a message on a tty; it should be used only by 163230837Sdelphij * the tty driver, or anything that knows the underlying tty will not 164230837Sdelphij * be revoke(2)'d away. Other callers should use tprintf. 165230837Sdelphij */ 166230837Sdelphijint 167230837Sdelphijttyprintf(struct tty *tp, const char *fmt, ...) 168230837Sdelphij{ 169230837Sdelphij va_list ap; 170230837Sdelphij struct putchar_arg pca; 171230837Sdelphij int retval; 172230837Sdelphij 173230837Sdelphij va_start(ap, fmt); 174230837Sdelphij pca.tty = tp; 175230837Sdelphij pca.flags = TOTTY; 176230837Sdelphij retval = kvprintf(fmt, putchar, &pca, 10, ap); 177230837Sdelphij va_end(ap); 178230837Sdelphij return retval; 179230837Sdelphij} 180230837Sdelphij 181230837Sdelphij/* 182230837Sdelphij * Log writes to the log buffer, and guarantees not to sleep (so can be 183230837Sdelphij * called by interrupt routines). If there is no process reading the 184230837Sdelphij * log yet, it writes to the console also. 185230837Sdelphij */ 186230837Sdelphijvoid 187230837Sdelphijlog(int level, const char *fmt, ...) 188230837Sdelphij{ 189230837Sdelphij va_list ap; 190230837Sdelphij int retval; 191230837Sdelphij struct putchar_arg pca; 192230837Sdelphij 193230837Sdelphij pca.tty = NULL; 194230837Sdelphij pca.pri = level; 195230837Sdelphij pca.flags = log_open ? TOLOG : TOCONS; 196230837Sdelphij 197230837Sdelphij va_start(ap, fmt); 198230837Sdelphij retval = kvprintf(fmt, putchar, &pca, 10, ap); 199230837Sdelphij va_end(ap); 200230837Sdelphij 201230837Sdelphij msgbuftrigger = 1; 202230837Sdelphij} 203230837Sdelphij 204230837Sdelphij#define CONSCHUNK 128 205230837Sdelphij 206230837Sdelphijvoid 207230837Sdelphijlog_console(struct uio *uio) 208230837Sdelphij{ 209230837Sdelphij int c, i, error, iovlen, nl; 210230837Sdelphij struct uio muio; 211230837Sdelphij struct iovec *miov = NULL; 212230837Sdelphij char *consbuffer; 213230837Sdelphij int pri; 214230837Sdelphij 215230837Sdelphij pri = LOG_INFO | LOG_CONSOLE; 216230837Sdelphij muio = *uio; 217230837Sdelphij iovlen = uio->uio_iovcnt * sizeof (struct iovec); 218230837Sdelphij MALLOC(miov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 219230837Sdelphij MALLOC(consbuffer, char *, CONSCHUNK, M_TEMP, M_WAITOK); 220230837Sdelphij bcopy((caddr_t)muio.uio_iov, (caddr_t)miov, iovlen); 221230837Sdelphij muio.uio_iov = miov; 222230837Sdelphij uio = &muio; 223230837Sdelphij 224230837Sdelphij nl = 0; 225230837Sdelphij while (uio->uio_resid > 0) { 226230837Sdelphij c = imin(uio->uio_resid, CONSCHUNK); 227230837Sdelphij error = uiomove(consbuffer, c, uio); 228230837Sdelphij if (error != 0) 229230837Sdelphij return; 230230837Sdelphij for (i = 0; i < c; i++) { 231230837Sdelphij msglogchar(consbuffer[i], pri); 232230837Sdelphij if (consbuffer[i] == '\n') 233230837Sdelphij nl = 1; 234230837Sdelphij else 235230837Sdelphij nl = 0; 236230837Sdelphij } 237230837Sdelphij } 238230837Sdelphij if (!nl) 239230837Sdelphij msglogchar('\n', pri); 240230837Sdelphij msgbuftrigger = 1; 241230837Sdelphij FREE(miov, M_TEMP); 242230837Sdelphij FREE(consbuffer, M_TEMP); 243230837Sdelphij return; 244230837Sdelphij} 245230837Sdelphij 246230837Sdelphijint 247230837Sdelphijprintf(const char *fmt, ...) 248230837Sdelphij{ 249230837Sdelphij va_list ap; 250230837Sdelphij int savintr; 251230837Sdelphij struct putchar_arg pca; 252230837Sdelphij int retval; 253230837Sdelphij 254230837Sdelphij savintr = consintr; /* disable interrupts */ 255230837Sdelphij consintr = 0; 256230837Sdelphij va_start(ap, fmt); 257230837Sdelphij pca.tty = NULL; 258230837Sdelphij pca.flags = TOCONS | TOLOG; 259230837Sdelphij pca.pri = -1; 260230837Sdelphij retval = kvprintf(fmt, putchar, &pca, 10, ap); 261230837Sdelphij va_end(ap); 262230837Sdelphij if (!panicstr) 263230837Sdelphij msgbuftrigger = 1; 264230837Sdelphij consintr = savintr; /* reenable interrupts */ 265230837Sdelphij return retval; 266230837Sdelphij} 267230837Sdelphij 268230837Sdelphijint 269230837Sdelphijvprintf(const char *fmt, va_list ap) 270230837Sdelphij{ 271230837Sdelphij int savintr; 272230837Sdelphij struct putchar_arg pca; 273230837Sdelphij int retval; 274230837Sdelphij 275230837Sdelphij savintr = consintr; /* disable interrupts */ 276230837Sdelphij consintr = 0; 277230837Sdelphij pca.tty = NULL; 278230837Sdelphij pca.flags = TOCONS | TOLOG; 279230837Sdelphij pca.pri = -1; 280230837Sdelphij retval = kvprintf(fmt, putchar, &pca, 10, ap); 281230837Sdelphij if (!panicstr) 282230837Sdelphij msgbuftrigger = 1; 283230837Sdelphij consintr = savintr; /* reenable interrupts */ 284230837Sdelphij return retval; 285230837Sdelphij} 286230837Sdelphij 287230837Sdelphij/* 288230837Sdelphij * Print a character on console or users terminal. If destination is 289230837Sdelphij * the console then the last bunch of characters are saved in msgbuf for 290230837Sdelphij * inspection later. 291230837Sdelphij */ 292230837Sdelphijstatic void 293230837Sdelphijputchar(int c, void *arg) 294230837Sdelphij{ 295230837Sdelphij struct putchar_arg *ap = (struct putchar_arg*) arg; 296230837Sdelphij int flags = ap->flags; 297230837Sdelphij struct tty *tp = ap->tty; 298230837Sdelphij if (panicstr) 299230837Sdelphij constty = NULL; 300230837Sdelphij if ((flags & TOCONS) && tp == NULL && constty) { 301230837Sdelphij tp = constty; 302230837Sdelphij flags |= TOTTY; 303230837Sdelphij } 304230837Sdelphij if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 305230837Sdelphij (flags & TOCONS) && tp == constty) 306230837Sdelphij constty = NULL; 307230837Sdelphij if ((flags & TOLOG)) 308230837Sdelphij msglogchar(c, ap->pri); 309230837Sdelphij if ((flags & TOCONS) && constty == NULL && c != '\0') 310230837Sdelphij (*v_putc)(c); 311230837Sdelphij} 312230837Sdelphij 313230837Sdelphij/* 314230837Sdelphij * Scaled down version of sprintf(3). 315230837Sdelphij */ 316230837Sdelphijint 317230837Sdelphijsprintf(char *buf, const char *cfmt, ...) 318230837Sdelphij{ 319230837Sdelphij int retval; 320230837Sdelphij va_list ap; 321230837Sdelphij 322230837Sdelphij va_start(ap, cfmt); 323230837Sdelphij retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 324230837Sdelphij buf[retval] = '\0'; 325230837Sdelphij va_end(ap); 326230837Sdelphij return retval; 327230837Sdelphij} 328230837Sdelphij 329230837Sdelphij/* 330230837Sdelphij * Scaled down version of vsprintf(3). 331230837Sdelphij */ 332230837Sdelphijint 333230837Sdelphijvsprintf(char *buf, const char *cfmt, va_list ap) 334230837Sdelphij{ 335230837Sdelphij int retval; 336230837Sdelphij 337230837Sdelphij retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 338230837Sdelphij buf[retval] = '\0'; 339230837Sdelphij return retval; 340230837Sdelphij} 341230837Sdelphij 342230837Sdelphij/* 343230837Sdelphij * Scaled down version of snprintf(3). 344230837Sdelphij */ 345230837Sdelphijint 346230837Sdelphijsnprintf(char *str, size_t size, const char *format, ...) 347230837Sdelphij{ 348230837Sdelphij int retval; 349230837Sdelphij va_list ap; 350230837Sdelphij 351230837Sdelphij va_start(ap, format); 352230837Sdelphij retval = vsnprintf(str, size, format, ap); 353230837Sdelphij va_end(ap); 354230837Sdelphij return(retval); 355230837Sdelphij} 356230837Sdelphij 357230837Sdelphij/* 358230837Sdelphij * Scaled down version of vsnprintf(3). 359230837Sdelphij */ 360230837Sdelphijint 361230837Sdelphijvsnprintf(char *str, size_t size, const char *format, va_list ap) 362230837Sdelphij{ 363230837Sdelphij struct snprintf_arg info; 364230837Sdelphij int retval; 365230837Sdelphij 366230837Sdelphij info.str = str; 367230837Sdelphij info.remain = size; 368230837Sdelphij retval = kvprintf(format, snprintf_func, &info, 10, ap); 369230837Sdelphij if (info.remain >= 1) 370230837Sdelphij *info.str++ = '\0'; 371230837Sdelphij return retval; 372230837Sdelphij} 373230837Sdelphij 374230837Sdelphijstatic void 375230837Sdelphijsnprintf_func(int ch, void *arg) 376230837Sdelphij{ 377230837Sdelphij struct snprintf_arg *const info = arg; 378230837Sdelphij 379230837Sdelphij if (info->remain >= 2) { 380230837Sdelphij *info->str++ = ch; 381230837Sdelphij info->remain--; 382230837Sdelphij } 383230837Sdelphij} 384230837Sdelphij 385230837Sdelphij/* 386230837Sdelphij * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 387230837Sdelphij * order; return an optional length and a pointer to the last character 388230837Sdelphij * written in the buffer (i.e., the first character of the string). 389230837Sdelphij * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 390230837Sdelphij */ 391230837Sdelphijstatic char * 392230837Sdelphijksprintn(nbuf, ul, base, lenp) 393230837Sdelphij char *nbuf; 394230837Sdelphij u_long ul; 395230837Sdelphij int base, *lenp; 396230837Sdelphij{ 397230837Sdelphij char *p; 398230837Sdelphij 399230837Sdelphij p = nbuf; 400230837Sdelphij *p = '\0'; 401230837Sdelphij do { 402230837Sdelphij *++p = hex2ascii(ul % base); 403230837Sdelphij } while (ul /= base); 404230837Sdelphij if (lenp) 405230837Sdelphij *lenp = p - nbuf; 406230837Sdelphij return (p); 407230837Sdelphij} 408230837Sdelphij/* ksprintn, but for a quad_t. */ 409230837Sdelphijstatic char * 410230837Sdelphijksprintqn(nbuf, uq, base, lenp) 411230837Sdelphij char *nbuf; 412230837Sdelphij u_quad_t uq; 413230837Sdelphij int base, *lenp; 414230837Sdelphij{ 415230837Sdelphij char *p; 416230837Sdelphij 417230837Sdelphij p = nbuf; 418230837Sdelphij *p = '\0'; 419230837Sdelphij do { 420230837Sdelphij *++p = hex2ascii(uq % base); 421230837Sdelphij } while (uq /= base); 422230837Sdelphij if (lenp) 423230837Sdelphij *lenp = p - nbuf; 424230837Sdelphij return (p); 425230837Sdelphij} 426230837Sdelphij 427230837Sdelphij/* 428230837Sdelphij * Scaled down version of printf(3). 429230837Sdelphij * 430230837Sdelphij * Two additional formats: 431230837Sdelphij * 432230837Sdelphij * The format %b is supported to decode error registers. 433230837Sdelphij * Its usage is: 434230837Sdelphij * 435230837Sdelphij * printf("reg=%b\n", regval, "<base><arg>*"); 436230837Sdelphij * 437230837Sdelphij * where <base> is the output base expressed as a control character, e.g. 438230837Sdelphij * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 439230837Sdelphij * the first of which gives the bit number to be inspected (origin 1), and 440230837Sdelphij * the next characters (up to a control character, i.e. a character <= 32), 441230837Sdelphij * give the name of the register. Thus: 442230837Sdelphij * 443230837Sdelphij * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 444230837Sdelphij * 445230837Sdelphij * would produce output: 446230837Sdelphij * 447230837Sdelphij * reg=3<BITTWO,BITONE> 448230837Sdelphij * 449230837Sdelphij * XXX: %D -- Hexdump, takes pointer and separator string: 450230837Sdelphij * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 451230837Sdelphij * ("%*D", len, ptr, " " -> XX XX XX XX ... 452230837Sdelphij */ 453230837Sdelphijint 454230837Sdelphijkvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 455230837Sdelphij{ 456230837Sdelphij#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 457230837Sdelphij char nbuf[MAXNBUF]; 458230837Sdelphij char *p, *q, *d; 459230837Sdelphij u_char *up; 460230837Sdelphij int ch, n; 461230837Sdelphij u_long ul; 462230837Sdelphij u_quad_t uq; 463230837Sdelphij int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 464230837Sdelphij int dwidth; 465230837Sdelphij char padc; 466230837Sdelphij int retval = 0; 467230837Sdelphij 468230837Sdelphij ul = 0; 469230837Sdelphij uq = 0; 470230837Sdelphij if (!func) 471230837Sdelphij d = (char *) arg; 472230837Sdelphij else 473230837Sdelphij d = NULL; 474230837Sdelphij 475230837Sdelphij if (fmt == NULL) 476230837Sdelphij fmt = "(fmt null)\n"; 477230837Sdelphij 478230837Sdelphij if (radix < 2 || radix > 36) 479230837Sdelphij radix = 10; 480230837Sdelphij 481230837Sdelphij for (;;) { 482230837Sdelphij padc = ' '; 483230837Sdelphij width = 0; 484230837Sdelphij while ((ch = (u_char)*fmt++) != '%') { 485230837Sdelphij if (ch == '\0') 486230837Sdelphij return retval; 487230837Sdelphij PCHAR(ch); 488230837Sdelphij } 489230837Sdelphij qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 490230837Sdelphij sign = 0; dot = 0; dwidth = 0; 491230837Sdelphijreswitch: switch (ch = (u_char)*fmt++) { 492230837Sdelphij case '.': 493230837Sdelphij dot = 1; 494230837Sdelphij goto reswitch; 495230837Sdelphij case '#': 496230837Sdelphij sharpflag = 1; 497230837Sdelphij goto reswitch; 498230837Sdelphij case '+': 499230837Sdelphij sign = 1; 500230837Sdelphij goto reswitch; 501230837Sdelphij case '-': 502230837Sdelphij ladjust = 1; 503230837Sdelphij goto reswitch; 504230837Sdelphij case '%': 505230837Sdelphij PCHAR(ch); 506230837Sdelphij break; 507230837Sdelphij case '*': 508230837Sdelphij if (!dot) { 509230837Sdelphij width = va_arg(ap, int); 510230837Sdelphij if (width < 0) { 511230837Sdelphij ladjust = !ladjust; 512230837Sdelphij width = -width; 513230837Sdelphij } 514230837Sdelphij } else { 515230837Sdelphij dwidth = va_arg(ap, int); 516230837Sdelphij } 517230837Sdelphij goto reswitch; 518230837Sdelphij case '0': 519230837Sdelphij if (!dot) { 520230837Sdelphij padc = '0'; 521230837Sdelphij goto reswitch; 522230837Sdelphij } 523230837Sdelphij case '1': case '2': case '3': case '4': 524230837Sdelphij case '5': case '6': case '7': case '8': case '9': 525230837Sdelphij for (n = 0;; ++fmt) { 526230837Sdelphij n = n * 10 + ch - '0'; 527230837Sdelphij ch = *fmt; 528230837Sdelphij if (ch < '0' || ch > '9') 529230837Sdelphij break; 530230837Sdelphij } 531230837Sdelphij if (dot) 532230837Sdelphij dwidth = n; 533230837Sdelphij else 534230837Sdelphij width = n; 535230837Sdelphij goto reswitch; 536230837Sdelphij case 'b': 537230837Sdelphij ul = va_arg(ap, int); 538230837Sdelphij p = va_arg(ap, char *); 539230837Sdelphij for (q = ksprintn(nbuf, ul, *p++, NULL); *q;) 540230837Sdelphij PCHAR(*q--); 541230837Sdelphij 542230837Sdelphij if (!ul) 543230837Sdelphij break; 544230837Sdelphij 545230837Sdelphij for (tmp = 0; *p;) { 546230837Sdelphij n = *p++; 547230837Sdelphij if (ul & (1 << (n - 1))) { 548230837Sdelphij PCHAR(tmp ? ',' : '<'); 549230837Sdelphij for (; (n = *p) > ' '; ++p) 550230837Sdelphij PCHAR(n); 551230837Sdelphij tmp = 1; 552230837Sdelphij } else 553230837Sdelphij for (; *p > ' '; ++p) 554230837Sdelphij continue; 555230837Sdelphij } 556230837Sdelphij if (tmp) 557230837Sdelphij PCHAR('>'); 558230837Sdelphij break; 559230837Sdelphij case 'c': 560230837Sdelphij PCHAR(va_arg(ap, int)); 561230837Sdelphij break; 562230837Sdelphij case 'D': 563230837Sdelphij up = va_arg(ap, u_char *); 564230837Sdelphij p = va_arg(ap, char *); 565230837Sdelphij if (!width) 566230837Sdelphij width = 16; 567230837Sdelphij while(width--) { 568230837Sdelphij PCHAR(hex2ascii(*up >> 4)); 569230837Sdelphij PCHAR(hex2ascii(*up & 0x0f)); 570230837Sdelphij up++; 571230837Sdelphij if (width) 572230837Sdelphij for (q=p;*q;q++) 573230837Sdelphij PCHAR(*q); 574230837Sdelphij } 575230837Sdelphij break; 576230837Sdelphij case 'd': 577230837Sdelphij if (qflag) 578230837Sdelphij uq = va_arg(ap, quad_t); 579230837Sdelphij else if (lflag) 580230837Sdelphij ul = va_arg(ap, long); 581230837Sdelphij else 582230837Sdelphij ul = va_arg(ap, int); 583230837Sdelphij sign = 1; 584230837Sdelphij base = 10; 585230837Sdelphij goto number; 586230837Sdelphij case 'l': 587230837Sdelphij if (lflag) { 588230837Sdelphij lflag = 0; 589230837Sdelphij qflag = 1; 590230837Sdelphij } else 591230837Sdelphij lflag = 1; 592230837Sdelphij goto reswitch; 593230837Sdelphij case 'o': 594230837Sdelphij if (qflag) 595230837Sdelphij uq = va_arg(ap, u_quad_t); 596230837Sdelphij else if (lflag) 597230837Sdelphij ul = va_arg(ap, u_long); 598230837Sdelphij else 599230837Sdelphij ul = va_arg(ap, u_int); 600230837Sdelphij base = 8; 601230837Sdelphij goto nosign; 602230837Sdelphij case 'p': 603230837Sdelphij ul = (uintptr_t)va_arg(ap, void *); 604230837Sdelphij base = 16; 605230837Sdelphij sharpflag = (width == 0); 606230837Sdelphij goto nosign; 607230837Sdelphij case 'q': 608230837Sdelphij qflag = 1; 609230837Sdelphij goto reswitch; 610230837Sdelphij case 'n': 611230837Sdelphij case 'r': 612230837Sdelphij if (qflag) 613230837Sdelphij uq = va_arg(ap, u_quad_t); 614230837Sdelphij else if (lflag) 615230837Sdelphij ul = va_arg(ap, u_long); 616230837Sdelphij else 617230837Sdelphij ul = sign ? 618230837Sdelphij (u_long)va_arg(ap, int) : va_arg(ap, u_int); 619230837Sdelphij base = radix; 620230837Sdelphij goto number; 621230837Sdelphij case 's': 622230837Sdelphij p = va_arg(ap, char *); 623230837Sdelphij if (p == NULL) 624230837Sdelphij p = "(null)"; 625230837Sdelphij if (!dot) 626230837Sdelphij n = strlen (p); 627230837Sdelphij else 628230837Sdelphij for (n = 0; n < dwidth && p[n]; n++) 629230837Sdelphij continue; 630230837Sdelphij 631230837Sdelphij width -= n; 632230837Sdelphij 633230837Sdelphij if (!ladjust && width > 0) 634230837Sdelphij while (width--) 635230837Sdelphij PCHAR(padc); 636230837Sdelphij while (n--) 637230837Sdelphij PCHAR(*p++); 638230837Sdelphij if (ladjust && width > 0) 639230837Sdelphij while (width--) 640230837Sdelphij PCHAR(padc); 641230837Sdelphij break; 642230837Sdelphij case 'u': 643230837Sdelphij if (qflag) 644230837Sdelphij uq = va_arg(ap, u_quad_t); 645230837Sdelphij else if (lflag) 646230837Sdelphij ul = va_arg(ap, u_long); 647230837Sdelphij else 648230837Sdelphij ul = va_arg(ap, u_int); 649230837Sdelphij base = 10; 650230837Sdelphij goto nosign; 651230837Sdelphij case 'x': 652230837Sdelphij case 'X': 653230837Sdelphij if (qflag) 654230837Sdelphij uq = va_arg(ap, u_quad_t); 655230837Sdelphij else if (lflag) 656230837Sdelphij ul = va_arg(ap, u_long); 657230837Sdelphij else 658230837Sdelphij ul = va_arg(ap, u_int); 659230837Sdelphij base = 16; 660230837Sdelphij goto nosign; 661230837Sdelphij case 'z': 662230837Sdelphij if (qflag) 663230837Sdelphij uq = va_arg(ap, u_quad_t); 664230837Sdelphij else if (lflag) 665230837Sdelphij ul = va_arg(ap, u_long); 666230837Sdelphij else 667230837Sdelphij ul = sign ? 668230837Sdelphij (u_long)va_arg(ap, int) : va_arg(ap, u_int); 669230837Sdelphij base = 16; 670230837Sdelphij goto number; 671230837Sdelphijnosign: sign = 0; 672number: 673 if (qflag) { 674 if (sign && (quad_t)uq < 0) { 675 neg = 1; 676 uq = -(quad_t)uq; 677 } 678 p = ksprintqn(nbuf, uq, base, &tmp); 679 } else { 680 if (sign && (long)ul < 0) { 681 neg = 1; 682 ul = -(long)ul; 683 } 684 p = ksprintn(nbuf, ul, base, &tmp); 685 } 686 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 687 if (base == 8) 688 tmp++; 689 else if (base == 16) 690 tmp += 2; 691 } 692 if (neg) 693 tmp++; 694 695 if (!ladjust && width && (width -= tmp) > 0) 696 while (width--) 697 PCHAR(padc); 698 if (neg) 699 PCHAR('-'); 700 if (sharpflag && (qflag ? uq != 0 : ul != 0)) { 701 if (base == 8) { 702 PCHAR('0'); 703 } else if (base == 16) { 704 PCHAR('0'); 705 PCHAR('x'); 706 } 707 } 708 709 while (*p) 710 PCHAR(*p--); 711 712 if (ladjust && width && (width -= tmp) > 0) 713 while (width--) 714 PCHAR(padc); 715 716 break; 717 default: 718 PCHAR('%'); 719 if (lflag) 720 PCHAR('l'); 721 PCHAR(ch); 722 break; 723 } 724 } 725#undef PCHAR 726} 727 728/* 729 * Put character in log buffer with a particular priority. 730 */ 731static void 732msglogchar(int c, int pri) 733{ 734 static int lastpri = -1; 735 static int dangling; 736 char nbuf[MAXNBUF]; 737 char *p; 738 739 if (!msgbufmapped) 740 return; 741 if (c == '\0' || c == '\r') 742 return; 743 if (pri != -1 && pri != lastpri) { 744 if (dangling) { 745 msgaddchar('\n', NULL); 746 dangling = 0; 747 } 748 msgaddchar('<', NULL); 749 for (p = ksprintn(nbuf, (u_long)pri, 10, NULL); *p;) 750 msgaddchar(*p--, NULL); 751 msgaddchar('>', NULL); 752 lastpri = pri; 753 } 754 msgaddchar(c, NULL); 755 if (c == '\n') { 756 dangling = 0; 757 lastpri = -1; 758 } else { 759 dangling = 1; 760 } 761} 762 763/* 764 * Put char in log buffer 765 */ 766static void 767msgaddchar(int c, void *dummy) 768{ 769 struct msgbuf *mbp; 770 771 if (!msgbufmapped) 772 return; 773 mbp = msgbufp; 774 mbp->msg_ptr[mbp->msg_bufx++] = c; 775 if (mbp->msg_bufx >= mbp->msg_size) 776 mbp->msg_bufx = 0; 777 /* If the buffer is full, keep the most recent data. */ 778 if (mbp->msg_bufr == mbp->msg_bufx) { 779 if (++mbp->msg_bufr >= mbp->msg_size) 780 mbp->msg_bufr = 0; 781 } 782} 783 784static void 785msgbufcopy(struct msgbuf *oldp) 786{ 787 int pos; 788 789 pos = oldp->msg_bufr; 790 while (pos != oldp->msg_bufx) { 791 msglogchar(oldp->msg_ptr[pos], -1); 792 if (++pos >= oldp->msg_size) 793 pos = 0; 794 } 795} 796 797void 798msgbufinit(void *ptr, size_t size) 799{ 800 char *cp; 801 static struct msgbuf *oldp = NULL; 802 803 cp = (char *)ptr; 804 msgbufp = (struct msgbuf *) (cp + size - sizeof(*msgbufp)); 805 if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp) { 806 bzero(cp, size); 807 msgbufp->msg_magic = MSG_MAGIC; 808 msgbufp->msg_size = (char *)msgbufp - cp; 809 msgbufp->msg_ptr = cp; 810 } 811 if (msgbufmapped && oldp != msgbufp) 812 msgbufcopy(oldp); 813 msgbufmapped = 1; 814 oldp = msgbufp; 815} 816 817#include "opt_ddb.h" 818#ifdef DDB 819#include <ddb/ddb.h> 820 821DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 822{ 823 int i, j; 824 825 if (!msgbufmapped) { 826 db_printf("msgbuf not mapped yet\n"); 827 return; 828 } 829 db_printf("msgbufp = %p\n", msgbufp); 830 db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n", 831 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, 832 msgbufp->msg_bufx, msgbufp->msg_ptr); 833 for (i = 0; i < msgbufp->msg_size; i++) { 834 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; 835 db_printf("%c", msgbufp->msg_ptr[j]); 836 } 837 db_printf("\n"); 838} 839 840#endif /* DDB */ 841