hexdump.c revision 109623
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 109623 2003-01-21 08:56:16Z alfred $ 4090792Sgshapiro */ 4190792Sgshapiro 4290792Sgshapiro#include "opt_ddb.h" 4390792Sgshapiro 4490792Sgshapiro#include <sys/param.h> 4590792Sgshapiro#include <sys/systm.h> 4690792Sgshapiro#include <sys/lock.h> 4790792Sgshapiro#include <sys/mutex.h> 4890792Sgshapiro#include <sys/sx.h> 4938032Speter#include <sys/kernel.h> 5090792Sgshapiro#include <sys/msgbuf.h> 5138032Speter#include <sys/malloc.h> 5238032Speter#include <sys/proc.h> 5338032Speter#include <sys/stddef.h> 5438032Speter#include <sys/stdint.h> 5538032Speter#include <sys/sysctl.h> 5638032Speter#include <sys/tty.h> 5738032Speter#include <sys/syslog.h> 5838032Speter#include <sys/cons.h> 5938032Speter#include <sys/uio.h> 6038032Speter 6164562Sgshapiro#ifdef DDB 6264562Sgshapiro#include <ddb/ddb.h> 6364562Sgshapiro#endif 6464562Sgshapiro 6564562Sgshapiro/* 6638032Speter * Note that stdarg.h and the ANSI style va_start macro is used for both 6738032Speter * ANSI and traditional C compilers. 6838032Speter */ 6938032Speter#include <machine/stdarg.h> 7038032Speter 7138032Speter#define TOCONS 0x01 7238032Speter#define TOTTY 0x02 7338032Speter#define TOLOG 0x04 7438032Speter 7538032Speter/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 7638032Speter#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 7738032Speter 7838032Speterstruct putchar_arg { 7938032Speter int flags; 80261194Sgshapiro int pri; 8164562Sgshapiro struct tty *tty; 8238032Speter}; 8338032Speter 8438032Speterstruct snprintf_arg { 8538032Speter char *str; 8638032Speter size_t remain; 8738032Speter}; 8838032Speter 8938032Speterextern int log_open; 9038032Speter 9138032Speterstruct tty *constty; /* pointer to console "window" tty */ 9238032Speter 9338032Speterstatic void (*v_putc)(int) = cnputc; /* routine to putc on virtual console */ 9438032Speterstatic void msglogchar(int c, int pri); 9538032Speterstatic void msgaddchar(int c, void *dummy); 9638032Speterstatic void putchar(int ch, void *arg); 9738032Speterstatic char *ksprintn(char *nbuf, uintmax_t num, int base, int *len); 9838032Speterstatic void snprintf_func(int ch, void *arg); 9938032Speter 10038032Speterstatic int consintr = 1; /* Ok to handle console interrupts? */ 10138032Speterstatic int msgbufmapped; /* Set when safe to use msgbuf */ 10238032Speterint msgbuftrigger; 10338032Speter 10464562Sgshapirostatic int log_console_output = 1; 10538032SpeterTUNABLE_INT("kern.log_console_output", &log_console_output); 10638032SpeterSYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW, 10738032Speter &log_console_output, 0, ""); 10838032Speter 10938032Speter/* 11064562Sgshapiro * Warn that a system table is full. 11138032Speter */ 11238032Spetervoid 11338032Spetertablefull(const char *tab) 11464562Sgshapiro{ 11538032Speter 11638032Speter log(LOG_ERR, "%s: table is full\n", tab); 11738032Speter} 11838032Speter 11938032Speter/* 12038032Speter * Uprintf prints to the controlling terminal for the current process. 12138032Speter * It may block if the tty queue is overfull. No message is printed if 12264562Sgshapiro * the queue does not clear in a reasonable time. 12338032Speter */ 12438032Speterint 12564562Sgshapirouprintf(const char *fmt, ...) 12638032Speter{ 12738032Speter struct thread *td = curthread; 12838032Speter struct proc *p = td->td_proc; 12964562Sgshapiro va_list ap; 13064562Sgshapiro struct putchar_arg pca; 13138032Speter int retval; 13290792Sgshapiro 13390792Sgshapiro if (td == NULL || td == PCPU_GET(idlethread)) 134132943Sgshapiro return (0); 135132943Sgshapiro 13638032Speter p = td->td_proc; 13738032Speter PROC_LOCK(p); 13838032Speter if ((p->p_flag & P_CONTROLT) == 0) { 13938032Speter PROC_UNLOCK(p); 14038032Speter return (0); 14138032Speter } 14238032Speter SESS_LOCK(p->p_session); 14390792Sgshapiro pca.tty = p->p_session->s_ttyp; 14464562Sgshapiro SESS_UNLOCK(p->p_session); 14564562Sgshapiro PROC_UNLOCK(p); 14638032Speter if (pca.tty == NULL) 14764562Sgshapiro return (0); 14864562Sgshapiro pca.flags = TOTTY; 14964562Sgshapiro va_start(ap, fmt); 15064562Sgshapiro retval = kvprintf(fmt, putchar, &pca, 10, ap); 15138032Speter va_end(ap); 15290792Sgshapiro 15390792Sgshapiro return (retval); 15490792Sgshapiro} 15590792Sgshapiro 15690792Sgshapiro/* 15790792Sgshapiro * tprintf prints on the controlling terminal associated 15890792Sgshapiro * with the given session, possibly to the log as well. 15964562Sgshapiro */ 16090792Sgshapirovoid 161285229Sgshapirotprintf(struct proc *p, int pri, const char *fmt, ...) 162285229Sgshapiro{ 163285229Sgshapiro struct tty *tp = NULL; 164285229Sgshapiro int flags = 0, shld = 0; 165285229Sgshapiro va_list ap; 166285229Sgshapiro struct putchar_arg pca; 167285229Sgshapiro int retval; 168285229Sgshapiro 169285229Sgshapiro if (pri != -1) 170285229Sgshapiro flags |= TOLOG; 171285229Sgshapiro if (p != NULL) { 172285229Sgshapiro PROC_LOCK(p); 173285229Sgshapiro if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 174285229Sgshapiro SESS_LOCK(p->p_session); 175285229Sgshapiro SESSHOLD(p->p_session); 176285229Sgshapiro tp = p->p_session->s_ttyp; 177285229Sgshapiro SESS_UNLOCK(p->p_session); 178285229Sgshapiro PROC_UNLOCK(p); 179285229Sgshapiro shld++; 180285229Sgshapiro if (ttycheckoutq(tp, 0)) 18138032Speter flags |= TOTTY; 18238032Speter else 18338032Speter tp = NULL; 18438032Speter } else 18538032Speter PROC_UNLOCK(p); 18638032Speter } 18738032Speter pca.pri = pri; 18838032Speter pca.tty = tp; 18938032Speter pca.flags = flags; 19038032Speter va_start(ap, fmt); 19138032Speter retval = kvprintf(fmt, putchar, &pca, 10, ap); 19238032Speter va_end(ap); 19338032Speter if (shld) { 19438032Speter PROC_LOCK(p); 19538032Speter SESS_LOCK(p->p_session); 19638032Speter SESSRELE(p->p_session); 19738032Speter SESS_UNLOCK(p->p_session); 19838032Speter PROC_UNLOCK(p); 19938032Speter } 20038032Speter msgbuftrigger = 1; 20138032Speter} 20238032Speter 20364562Sgshapiro/* 20438032Speter * Ttyprintf displays a message on a tty; it should be used only by 20564562Sgshapiro * the tty driver, or anything that knows the underlying tty will not 20638032Speter * be revoke(2)'d away. Other callers should use tprintf. 20738032Speter */ 20838032Speterint 20938032Speterttyprintf(struct tty *tp, const char *fmt, ...) 21038032Speter{ 21138032Speter va_list ap; 21238032Speter struct putchar_arg pca; 213110560Sgshapiro int retval; 214110560Sgshapiro 215110560Sgshapiro va_start(ap, fmt); 216110560Sgshapiro pca.tty = tp; 217110560Sgshapiro pca.flags = TOTTY; 218110560Sgshapiro retval = kvprintf(fmt, putchar, &pca, 10, ap); 21990792Sgshapiro va_end(ap); 220110560Sgshapiro return (retval); 22190792Sgshapiro} 22290792Sgshapiro 22390792Sgshapiro/* 22490792Sgshapiro * Log writes to the log buffer, and guarantees not to sleep (so can be 22590792Sgshapiro * called by interrupt routines). If there is no process reading the 22690792Sgshapiro * log yet, it writes to the console also. 22790792Sgshapiro */ 22890792Sgshapirovoid 22990792Sgshapirolog(int level, const char *fmt, ...) 23090792Sgshapiro{ 23190792Sgshapiro va_list ap; 23290792Sgshapiro int retval; 23390792Sgshapiro struct putchar_arg pca; 23438032Speter 23538032Speter pca.tty = NULL; 23638032Speter pca.pri = level; 23738032Speter pca.flags = log_open ? TOLOG : TOCONS; 23838032Speter 23938032Speter va_start(ap, fmt); 24064562Sgshapiro retval = kvprintf(fmt, putchar, &pca, 10, ap); 24164562Sgshapiro va_end(ap); 24264562Sgshapiro 24364562Sgshapiro msgbuftrigger = 1; 24464562Sgshapiro} 24538032Speter 24664562Sgshapiro#define CONSCHUNK 128 24764562Sgshapiro 24864562Sgshapirovoid 24964562Sgshapirolog_console(struct uio *uio) 25064562Sgshapiro{ 25164562Sgshapiro int c, i, error, iovlen, nl; 25264562Sgshapiro struct uio muio; 25364562Sgshapiro struct iovec *miov = NULL; 25464562Sgshapiro char *consbuffer; 25564562Sgshapiro int pri; 25664562Sgshapiro 25764562Sgshapiro if (!log_console_output) 25864562Sgshapiro return; 25964562Sgshapiro 26064562Sgshapiro pri = LOG_INFO | LOG_CONSOLE; 26164562Sgshapiro muio = *uio; 26264562Sgshapiro iovlen = uio->uio_iovcnt * sizeof (struct iovec); 26364562Sgshapiro MALLOC(miov, struct iovec *, iovlen, M_TEMP, 0); 26464562Sgshapiro MALLOC(consbuffer, char *, CONSCHUNK, M_TEMP, 0); 26564562Sgshapiro bcopy(muio.uio_iov, miov, iovlen); 26664562Sgshapiro muio.uio_iov = miov; 26764562Sgshapiro uio = &muio; 26864562Sgshapiro 26964562Sgshapiro nl = 0; 27064562Sgshapiro while (uio->uio_resid > 0) { 27164562Sgshapiro c = imin(uio->uio_resid, CONSCHUNK); 27264562Sgshapiro error = uiomove(consbuffer, c, uio); 27364562Sgshapiro if (error != 0) 27464562Sgshapiro break; 27564562Sgshapiro for (i = 0; i < c; i++) { 27664562Sgshapiro msglogchar(consbuffer[i], pri); 27764562Sgshapiro if (consbuffer[i] == '\n') 27864562Sgshapiro nl = 1; 27964562Sgshapiro else 28064562Sgshapiro nl = 0; 28164562Sgshapiro } 28264562Sgshapiro } 28364562Sgshapiro if (!nl) 28464562Sgshapiro msglogchar('\n', pri); 28564562Sgshapiro msgbuftrigger = 1; 28664562Sgshapiro FREE(miov, M_TEMP); 28764562Sgshapiro FREE(consbuffer, M_TEMP); 28864562Sgshapiro return; 28964562Sgshapiro} 29064562Sgshapiro 29164562Sgshapiroint 29264562Sgshapiroprintf(const char *fmt, ...) 29364562Sgshapiro{ 29464562Sgshapiro va_list ap; 29564562Sgshapiro int savintr; 29680785Sgshapiro struct putchar_arg pca; 29780785Sgshapiro int retval; 29880785Sgshapiro 29980785Sgshapiro savintr = consintr; /* disable interrupts */ 30080785Sgshapiro consintr = 0; 30138032Speter va_start(ap, fmt); 30238032Speter pca.tty = NULL; 30338032Speter pca.flags = TOCONS | TOLOG; 30438032Speter pca.pri = -1; 30538032Speter retval = kvprintf(fmt, putchar, &pca, 10, ap); 30638032Speter va_end(ap); 30738032Speter if (!panicstr) 30838032Speter msgbuftrigger = 1; 30938032Speter consintr = savintr; /* reenable interrupts */ 31038032Speter return (retval); 31138032Speter} 31238032Speter 31338032Speterint 31438032Spetervprintf(const char *fmt, va_list ap) 31538032Speter{ 31638032Speter int savintr; 31738032Speter struct putchar_arg pca; 31838032Speter int retval; 31938032Speter 32038032Speter savintr = consintr; /* disable interrupts */ 32164562Sgshapiro consintr = 0; 32238032Speter pca.tty = NULL; 32338032Speter pca.flags = TOCONS | TOLOG; 32438032Speter pca.pri = -1; 32538032Speter retval = kvprintf(fmt, putchar, &pca, 10, ap); 32638032Speter if (!panicstr) 32738032Speter msgbuftrigger = 1; 32864562Sgshapiro consintr = savintr; /* reenable interrupts */ 32938032Speter return (retval); 33038032Speter} 33138032Speter 33264562Sgshapiro/* 33364562Sgshapiro * Print a character on console or users terminal. If destination is 33473188Sgshapiro * the console then the last bunch of characters are saved in msgbuf for 33564562Sgshapiro * inspection later. 33673188Sgshapiro */ 33764562Sgshapirostatic void 33873188Sgshapiroputchar(int c, void *arg) 33973188Sgshapiro{ 34090792Sgshapiro struct putchar_arg *ap = (struct putchar_arg*) arg; 34190792Sgshapiro int flags = ap->flags; 34290792Sgshapiro struct tty *tp = ap->tty; 34390792Sgshapiro if (panicstr) 34464562Sgshapiro constty = NULL; 34538032Speter if ((flags & TOCONS) && tp == NULL && constty) { 34638032Speter tp = constty; 34764562Sgshapiro flags |= TOTTY; 34864562Sgshapiro } 34938032Speter if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && 35038032Speter (flags & TOCONS) && tp == constty) 35138032Speter constty = NULL; 35238032Speter if ((flags & TOLOG)) 35364562Sgshapiro msglogchar(c, ap->pri); 35464562Sgshapiro if ((flags & TOCONS) && constty == NULL && c != '\0') 35564562Sgshapiro (*v_putc)(c); 35638032Speter} 35738032Speter 35838032Speter/* 35938032Speter * Scaled down version of sprintf(3). 36064562Sgshapiro */ 36164562Sgshapiroint 36264562Sgshapirosprintf(char *buf, const char *cfmt, ...) 36364562Sgshapiro{ 36464562Sgshapiro int retval; 36538032Speter va_list ap; 36638032Speter 36738032Speter va_start(ap, cfmt); 36838032Speter retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 36938032Speter buf[retval] = '\0'; 37038032Speter va_end(ap); 37138032Speter return (retval); 37290792Sgshapiro} 37338032Speter 37438032Speter/* 37564562Sgshapiro * Scaled down version of vsprintf(3). 37638032Speter */ 37790792Sgshapiroint 37890792Sgshapirovsprintf(char *buf, const char *cfmt, va_list ap) 37990792Sgshapiro{ 38090792Sgshapiro int retval; 381102528Sgshapiro 38238032Speter retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 38390792Sgshapiro buf[retval] = '\0'; 38438032Speter return (retval); 38564562Sgshapiro} 38664562Sgshapiro 38764562Sgshapiro/* 38864562Sgshapiro * Scaled down version of snprintf(3). 38964562Sgshapiro */ 39064562Sgshapiroint 39164562Sgshapirosnprintf(char *str, size_t size, const char *format, ...) 39238032Speter{ 39364562Sgshapiro int retval; 39438032Speter va_list ap; 39564562Sgshapiro 39664562Sgshapiro va_start(ap, format); 39764562Sgshapiro retval = vsnprintf(str, size, format, ap); 39894334Sgshapiro va_end(ap); 39994334Sgshapiro return(retval); 40094334Sgshapiro} 40166494Sgshapiro 40238032Speter/* 40338032Speter * Scaled down version of vsnprintf(3). 40466494Sgshapiro */ 40566494Sgshapiroint 40666494Sgshapirovsnprintf(char *str, size_t size, const char *format, va_list ap) 40766494Sgshapiro{ 40890792Sgshapiro struct snprintf_arg info; 40990792Sgshapiro int retval; 41090792Sgshapiro 41190792Sgshapiro info.str = str; 41290792Sgshapiro info.remain = size; 41364562Sgshapiro retval = kvprintf(format, snprintf_func, &info, 10, ap); 41464562Sgshapiro if (info.remain >= 1) 41564562Sgshapiro *info.str++ = '\0'; 41638032Speter return (retval); 41738032Speter} 41838032Speter 41938032Speterstatic void 420285229Sgshapirosnprintf_func(int ch, void *arg) 421285229Sgshapiro{ 422285229Sgshapiro struct snprintf_arg *const info = arg; 423285229Sgshapiro 424168515Sgshapiro if (info->remain >= 2) { 425168515Sgshapiro *info->str++ = ch; 426168515Sgshapiro info->remain--; 42738032Speter } 42838032Speter} 42938032Speter 43038032Speter/* 43138032Speter * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 43238032Speter * order; return an optional length and a pointer to the last character 43338032Speter * written in the buffer (i.e., the first character of the string). 43438032Speter * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 43538032Speter */ 43638032Speterstatic char * 43738032Speterksprintn(char *nbuf, uintmax_t num, int base, int *lenp) 43838032Speter{ 43990792Sgshapiro char *p; 44038032Speter 44138032Speter p = nbuf; 44238032Speter *p = '\0'; 44338032Speter do { 44438032Speter *++p = hex2ascii(num % base); 44538032Speter } while (num /= base); 44638032Speter if (lenp) 44764562Sgshapiro *lenp = p - nbuf; 44838032Speter return (p); 44938032Speter} 45090792Sgshapiro 45138032Speter/* 45243730Speter * Scaled down version of printf(3). 45343730Speter * 45438032Speter * Two additional formats: 45564562Sgshapiro * 45643730Speter * The format %b is supported to decode error registers. 45738032Speter * Its usage is: 45838032Speter * 45938032Speter * printf("reg=%b\n", regval, "<base><arg>*"); 46043730Speter * 46138032Speter * where <base> is the output base expressed as a control character, e.g. 46238032Speter * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 46338032Speter * the first of which gives the bit number to be inspected (origin 1), and 46490792Sgshapiro * the next characters (up to a control character, i.e. a character <= 32), 46538032Speter * give the name of the register. Thus: 46638032Speter * 46738032Speter * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 46838032Speter * 46990792Sgshapiro * would produce output: 47038032Speter * 47138032Speter * reg=3<BITTWO,BITONE> 47264562Sgshapiro * 47364562Sgshapiro * XXX: %D -- Hexdump, takes pointer and separator string: 47438032Speter * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 47590792Sgshapiro * ("%*D", len, ptr, " " -> XX XX XX XX ... 47664562Sgshapiro */ 47738032Speterint 47838032Speterkvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 47938032Speter{ 48038032Speter#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 48138032Speter char nbuf[MAXNBUF]; 48238032Speter char *d; 48338032Speter const char *p, *percent, *q; 48438032Speter u_char *up; 48538032Speter int ch, n; 48690792Sgshapiro uintmax_t num; 48764562Sgshapiro int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 48864562Sgshapiro int jflag, tflag, zflag; 48938032Speter int dwidth; 49038032Speter char padc; 49198121Sgshapiro int retval = 0; 49298121Sgshapiro 49398121Sgshapiro num = 0; 49498121Sgshapiro if (!func) 49598121Sgshapiro d = (char *) arg; 49698121Sgshapiro else 49798121Sgshapiro d = NULL; 49898121Sgshapiro 49998121Sgshapiro if (fmt == NULL) 50098121Sgshapiro fmt = "(fmt null)\n"; 50198121Sgshapiro 50298121Sgshapiro if (radix < 2 || radix > 36) 50398121Sgshapiro radix = 10; 504110560Sgshapiro 505110560Sgshapiro for (;;) { 506110560Sgshapiro padc = ' '; 507110560Sgshapiro width = 0; 50838032Speter while ((ch = (u_char)*fmt++) != '%') { 50943730Speter if (ch == '\0') 51043730Speter return (retval); 51164562Sgshapiro PCHAR(ch); 51264562Sgshapiro } 51364562Sgshapiro percent = fmt - 1; 51464562Sgshapiro qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 51564562Sgshapiro sign = 0; dot = 0; dwidth = 0; 51664562Sgshapiro jflag = 0; tflag = 0; zflag = 0; 51764562Sgshapiroreswitch: switch (ch = (u_char)*fmt++) { 51890792Sgshapiro case '.': 51990792Sgshapiro dot = 1; 52038032Speter goto reswitch; 52164562Sgshapiro case '#': 522157001Sgshapiro sharpflag = 1; 523157001Sgshapiro goto reswitch; 524157001Sgshapiro case '+': 525157001Sgshapiro sign = 1; 526157001Sgshapiro goto reswitch; 527157001Sgshapiro case '-': 52838032Speter ladjust = 1; 52964562Sgshapiro goto reswitch; 53038032Speter case '%': 53190792Sgshapiro PCHAR(ch); 53290792Sgshapiro break; 53390792Sgshapiro case '*': 53464562Sgshapiro if (!dot) { 53564562Sgshapiro width = va_arg(ap, int); 53664562Sgshapiro if (width < 0) { 53764562Sgshapiro ladjust = !ladjust; 53864562Sgshapiro width = -width; 53938032Speter } 54038032Speter } else { 54138032Speter dwidth = va_arg(ap, int); 54238032Speter } 54338032Speter goto reswitch; 54464562Sgshapiro case '0': 54538032Speter if (!dot) { 54638032Speter padc = '0'; 54738032Speter goto reswitch; 54838032Speter } 54938032Speter case '1': case '2': case '3': case '4': 55038032Speter case '5': case '6': case '7': case '8': case '9': 55138032Speter for (n = 0;; ++fmt) { 55238032Speter n = n * 10 + ch - '0'; 55338032Speter ch = *fmt; 55438032Speter if (ch < '0' || ch > '9') 55538032Speter break; 55638032Speter } 55738032Speter if (dot) 55871345Sgshapiro dwidth = n; 55982017Sgshapiro else 56071345Sgshapiro width = n; 56171345Sgshapiro goto reswitch; 56290792Sgshapiro case 'b': 56371345Sgshapiro num = (u_int)va_arg(ap, int); 56471345Sgshapiro p = va_arg(ap, char *); 56571345Sgshapiro for (q = ksprintn(nbuf, num, *p++, NULL); *q;) 56671345Sgshapiro PCHAR(*q--); 56771345Sgshapiro 56838032Speter if (num == 0) 56964562Sgshapiro break; 57064562Sgshapiro 57164562Sgshapiro for (tmp = 0; *p;) { 57238032Speter n = *p++; 57338032Speter if (num & (1 << (n - 1))) { 57438032Speter PCHAR(tmp ? ',' : '<'); 57538032Speter for (; (n = *p) > ' '; ++p) 57638032Speter PCHAR(n); 57738032Speter tmp = 1; 57838032Speter } else 57938032Speter for (; *p > ' '; ++p) 58038032Speter continue; 58138032Speter } 58238032Speter if (tmp) 58338032Speter PCHAR('>'); 58438032Speter break; 58538032Speter case 'c': 58638032Speter PCHAR(va_arg(ap, int)); 58738032Speter break; 58838032Speter case 'D': 58938032Speter up = va_arg(ap, u_char *); 59038032Speter p = va_arg(ap, char *); 59138032Speter if (!width) 59290792Sgshapiro width = 16; 59338032Speter while(width--) { 59438032Speter PCHAR(hex2ascii(*up >> 4)); 59538032Speter PCHAR(hex2ascii(*up & 0x0f)); 59638032Speter up++; 59738032Speter if (width) 59838032Speter for (q=p;*q;q++) 59990792Sgshapiro PCHAR(*q); 60038032Speter } 60138032Speter break; 60238032Speter case 'd': 60338032Speter case 'i': 60438032Speter base = 10; 60538032Speter sign = 1; 60638032Speter goto handle_sign; 60738032Speter case 'j': 60838032Speter jflag = 1; 60938032Speter goto reswitch; 61064562Sgshapiro case 'l': 61138032Speter if (lflag) { 61238032Speter lflag = 0; 61338032Speter qflag = 1; 61438032Speter } else 61564562Sgshapiro lflag = 1; 61664562Sgshapiro goto reswitch; 61764562Sgshapiro case 'n': 61838032Speter if (jflag) 61966494Sgshapiro *(va_arg(ap, intmax_t *)) = retval; 62038032Speter else if (qflag) 62138032Speter *(va_arg(ap, quad_t *)) = retval; 62238032Speter else if (lflag) 62338032Speter *(va_arg(ap, long *)) = retval; 62490792Sgshapiro else if (zflag) 62590792Sgshapiro *(va_arg(ap, size_t *)) = retval; 62690792Sgshapiro else 62738032Speter *(va_arg(ap, int *)) = retval; 62864562Sgshapiro break; 62964562Sgshapiro case 'o': 63064562Sgshapiro base = 8; 63138032Speter goto handle_nosign; 63238032Speter case 'p': 63338032Speter base = 16; 63438032Speter sharpflag = (width == 0); 63538032Speter sign = 0; 63638032Speter num = (uintptr_t)va_arg(ap, void *); 63738032Speter goto number; 63838032Speter case 'q': 63938032Speter qflag = 1; 64038032Speter goto reswitch; 64138032Speter case 'r': 64238032Speter base = radix; 64338032Speter if (sign) 64471345Sgshapiro goto handle_sign; 64538032Speter goto handle_nosign; 64638032Speter case 's': 64738032Speter p = va_arg(ap, char *); 64838032Speter if (p == NULL) 64938032Speter p = "(null)"; 65038032Speter if (!dot) 65138032Speter n = strlen (p); 65238032Speter else 65338032Speter for (n = 0; n < dwidth && p[n]; n++) 65438032Speter continue; 65538032Speter 65638032Speter width -= n; 65738032Speter 65838032Speter if (!ladjust && width > 0) 65938032Speter while (width--) 66038032Speter PCHAR(padc); 66138032Speter while (n--) 662111823Sgshapiro PCHAR(*p++); 663111823Sgshapiro if (ladjust && width > 0) 66443730Speter while (width--) 66538032Speter PCHAR(padc); 66638032Speter break; 66790792Sgshapiro case 't': 66890792Sgshapiro tflag = 1; 66990792Sgshapiro goto reswitch; 67038032Speter break; 67138032Speter case 'u': 67238032Speter base = 10; 67338032Speter goto handle_nosign; 67438032Speter case 'x': 67538032Speter case 'X': 67638032Speter base = 16; 67738032Speter goto handle_nosign; 67838032Speter case 'y': 67938032Speter base = 16; 68038032Speter sign = 1; 68138032Speter goto handle_sign; 68238032Speter case 'z': 68390792Sgshapiro zflag = 1; 68490792Sgshapiro goto reswitch; 68590792Sgshapirohandle_nosign: 68690792Sgshapiro sign = 0; 68790792Sgshapiro if (jflag) 68890792Sgshapiro num = va_arg(ap, uintmax_t); 68938032Speter else if (qflag) 69098121Sgshapiro num = va_arg(ap, u_quad_t); 69198121Sgshapiro else if (tflag) 69298121Sgshapiro num = va_arg(ap, ptrdiff_t); 69398121Sgshapiro else if (lflag) 69498121Sgshapiro num = va_arg(ap, u_long); 69598121Sgshapiro else if (zflag) 69698121Sgshapiro num = va_arg(ap, size_t); 69798121Sgshapiro else 69864562Sgshapiro num = va_arg(ap, u_int); 69964562Sgshapiro goto number; 70038032Speterhandle_sign: 70138032Speter if (jflag) 70238032Speter num = va_arg(ap, intmax_t); 70343730Speter else if (qflag) 70443730Speter num = va_arg(ap, quad_t); 70543730Speter else if (tflag) 70643730Speter num = va_arg(ap, ptrdiff_t); 70738032Speter else if (lflag) 70838032Speter num = va_arg(ap, long); 70938032Speter else if (zflag) 71038032Speter num = va_arg(ap, size_t); 71138032Speter else 71238032Speter num = va_arg(ap, int); 71338032Speternumber: 71438032Speter if (sign && (intmax_t)num < 0) { 71538032Speter neg = 1; 71643730Speter num = -(intmax_t)num; 71738032Speter } 71864562Sgshapiro p = ksprintn(nbuf, num, base, &tmp); 71990792Sgshapiro if (sharpflag && num != 0) { 72064562Sgshapiro if (base == 8) 72138032Speter tmp++; 72243730Speter else if (base == 16) 72338032Speter tmp += 2; 72438032Speter } 72564562Sgshapiro if (neg) 72638032Speter tmp++; 72738032Speter 72838032Speter if (!ladjust && width && (width -= tmp) > 0) 72938032Speter while (width--) 73038032Speter PCHAR(padc); 73164562Sgshapiro if (neg) 73264562Sgshapiro PCHAR('-'); 73338032Speter if (sharpflag && num != 0) { 73490792Sgshapiro if (base == 8) { 73590792Sgshapiro PCHAR('0'); 73690792Sgshapiro } else if (base == 16) { 73790792Sgshapiro PCHAR('0'); 73890792Sgshapiro PCHAR('x'); 73938032Speter } 74038032Speter } 74164562Sgshapiro 74264562Sgshapiro while (*p) 74364562Sgshapiro PCHAR(*p--); 74464562Sgshapiro 74564562Sgshapiro if (ladjust && width && (width -= tmp) > 0) 74664562Sgshapiro while (width--) 74764562Sgshapiro PCHAR(padc); 74838032Speter 74964562Sgshapiro break; 75064562Sgshapiro default: 75164562Sgshapiro while (percent < fmt) 75264562Sgshapiro PCHAR(*percent++); 75364562Sgshapiro break; 75438032Speter } 75538032Speter } 75664562Sgshapiro#undef PCHAR 75738032Speter} 75838032Speter 75938032Speter/* 76064562Sgshapiro * Put character in log buffer with a particular priority. 76164562Sgshapiro */ 76264562Sgshapirostatic void 76364562Sgshapiromsglogchar(int c, int pri) 76464562Sgshapiro{ 76564562Sgshapiro static int lastpri = -1; 76690792Sgshapiro static int dangling; 76764562Sgshapiro char nbuf[MAXNBUF]; 76864562Sgshapiro char *p; 76938032Speter 770285229Sgshapiro if (!msgbufmapped) 771285229Sgshapiro return; 772285229Sgshapiro if (c == '\0' || c == '\r') 773285229Sgshapiro return; 774285229Sgshapiro if (pri != -1 && pri != lastpri) { 775285229Sgshapiro if (dangling) { 776285229Sgshapiro msgaddchar('\n', NULL); 777285229Sgshapiro dangling = 0; 778285229Sgshapiro } 779285229Sgshapiro msgaddchar('<', NULL); 78064562Sgshapiro for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL); *p;) 78171345Sgshapiro msgaddchar(*p--, NULL); 78271345Sgshapiro msgaddchar('>', NULL); 78371345Sgshapiro lastpri = pri; 78471345Sgshapiro } 78564562Sgshapiro msgaddchar(c, NULL); 78664562Sgshapiro if (c == '\n') { 78764562Sgshapiro dangling = 0; 78864562Sgshapiro lastpri = -1; 78964562Sgshapiro } else { 79064562Sgshapiro dangling = 1; 79164562Sgshapiro } 79264562Sgshapiro} 79364562Sgshapiro 79438032Speter/* 79564562Sgshapiro * Put char in log buffer 79664562Sgshapiro */ 79764562Sgshapirostatic void 79864562Sgshapiromsgaddchar(int c, void *dummy) 79964562Sgshapiro{ 80064562Sgshapiro struct msgbuf *mbp; 80164562Sgshapiro 80264562Sgshapiro if (!msgbufmapped) 80364562Sgshapiro return; 80464562Sgshapiro mbp = msgbufp; 80564562Sgshapiro mbp->msg_ptr[mbp->msg_bufx++] = c; 80664562Sgshapiro if (mbp->msg_bufx >= mbp->msg_size) 80764562Sgshapiro mbp->msg_bufx = 0; 80864562Sgshapiro /* If the buffer is full, keep the most recent data. */ 80964562Sgshapiro if (mbp->msg_bufr == mbp->msg_bufx) { 81064562Sgshapiro if (++mbp->msg_bufr >= mbp->msg_size) 81164562Sgshapiro mbp->msg_bufr = 0; 81264562Sgshapiro } 81364562Sgshapiro} 81464562Sgshapiro 81564562Sgshapirostatic void 81671345Sgshapiromsgbufcopy(struct msgbuf *oldp) 81771345Sgshapiro{ 81871345Sgshapiro int pos; 81938032Speter 82073188Sgshapiro pos = oldp->msg_bufr; 82171345Sgshapiro while (pos != oldp->msg_bufx) { 82271345Sgshapiro msglogchar(oldp->msg_ptr[pos], -1); 82371345Sgshapiro if (++pos >= oldp->msg_size) 82471345Sgshapiro pos = 0; 82571345Sgshapiro } 82671345Sgshapiro} 82771345Sgshapiro 82871345Sgshapirovoid 82971345Sgshapiromsgbufinit(void *ptr, int size) 83071345Sgshapiro{ 83171345Sgshapiro char *cp; 83271345Sgshapiro static struct msgbuf *oldp = NULL; 83338032Speter 83464562Sgshapiro size -= sizeof(*msgbufp); 83564562Sgshapiro cp = (char *)ptr; 83664562Sgshapiro msgbufp = (struct msgbuf *) (cp + size); 83764562Sgshapiro if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_size != size || 83843730Speter msgbufp->msg_bufx >= size || msgbufp->msg_bufx < 0 || 83964562Sgshapiro msgbufp->msg_bufr >= size || msgbufp->msg_bufr < 0) { 84043730Speter bzero(cp, size); 84138032Speter bzero(msgbufp, sizeof(*msgbufp)); 84238032Speter msgbufp->msg_magic = MSG_MAGIC; 84364562Sgshapiro msgbufp->msg_size = (char *)msgbufp - cp; 84464562Sgshapiro } 84564562Sgshapiro msgbufp->msg_ptr = cp; 84638032Speter if (msgbufmapped && oldp != msgbufp) 84738032Speter msgbufcopy(oldp); 84838032Speter msgbufmapped = 1; 84938032Speter oldp = msgbufp; 85038032Speter} 85138032Speter 85238032SpeterSYSCTL_DECL(_security_bsd); 85338032Speter 85438032Speterstatic int unprivileged_read_msgbuf = 1; 85538032SpeterSYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf, 85638032Speter CTLFLAG_RW, &unprivileged_read_msgbuf, 0, 85764562Sgshapiro "Unprivileged processes may read the kernel message buffer"); 85864562Sgshapiro 85964562Sgshapiro/* Sysctls for accessing/clearing the msgbuf */ 86064562Sgshapirostatic int 86138032Spetersysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 86238032Speter{ 86338032Speter int error; 86438032Speter 86538032Speter if (!unprivileged_read_msgbuf) { 86638032Speter error = suser(req->td); 86738032Speter if (error) 86838032Speter return (error); 86943730Speter } 87064562Sgshapiro 87143730Speter /* 87238032Speter * Unwind the buffer, so that it's linear (possibly starting with 87338032Speter * some initial nulls). 87438032Speter */ 87538032Speter error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr + msgbufp->msg_bufx, 87638032Speter msgbufp->msg_size - msgbufp->msg_bufx, req); 87738032Speter if (error) 87838032Speter return (error); 87938032Speter if (msgbufp->msg_bufx > 0) { 88038032Speter error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr, 88138032Speter msgbufp->msg_bufx, req); 88243730Speter } 88364562Sgshapiro return (error); 88443730Speter} 88538032Speter 88638032SpeterSYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD, 88738032Speter 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 88838032Speter 88938032Speterstatic int msgbuf_clear; 89043730Speter 89164562Sgshapirostatic int 89243730Spetersysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 89338032Speter{ 89438032Speter int error; 89538032Speter error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 89638032Speter if (!error && req->newptr) { 89738032Speter /* Clear the buffer and reset write pointer */ 89838032Speter bzero(msgbufp->msg_ptr, msgbufp->msg_size); 89938032Speter msgbufp->msg_bufr = msgbufp->msg_bufx = 0; 90038032Speter msgbuf_clear = 0; 90190792Sgshapiro } 90290792Sgshapiro return (error); 90338032Speter} 90438032Speter 90538032SpeterSYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 90638032Speter CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clear, 0, 90738032Speter sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer"); 90838032Speter 90938032Speter#ifdef DDB 91038032Speter 91138032SpeterDB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 91238032Speter{ 91338032Speter int i, j; 91438032Speter 91538032Speter if (!msgbufmapped) { 91638032Speter db_printf("msgbuf not mapped yet\n"); 91738032Speter return; 91864562Sgshapiro } 91964562Sgshapiro db_printf("msgbufp = %p\n", msgbufp); 92064562Sgshapiro db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n", 92164562Sgshapiro msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, 92264562Sgshapiro msgbufp->msg_bufx, msgbufp->msg_ptr); 92338032Speter for (i = 0; i < msgbufp->msg_size; i++) { 92438032Speter j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; 92564562Sgshapiro db_printf("%c", msgbufp->msg_ptr[j]); 92638032Speter } 92738032Speter db_printf("\n"); 92838032Speter} 92938032Speter 93038032Speter#endif /* DDB */ 93138032Speter