11541Srgrimes/*- 21541Srgrimes * Copyright (c) 1986, 1988, 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * (c) UNIX System Laboratories, Inc. 51541Srgrimes * All or some portions of this file are derived from material licensed 61541Srgrimes * to the University of California by American Telephone and Telegraph 71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 81541Srgrimes * the permission of UNIX System Laboratories, Inc. 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 4. Neither the name of the University nor the names of its contributors 191541Srgrimes * may be used to endorse or promote products derived from this software 201541Srgrimes * without specific prior written permission. 211541Srgrimes * 221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321541Srgrimes * SUCH DAMAGE. 331541Srgrimes * 341541Srgrimes * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 351541Srgrimes */ 361541Srgrimes 37116182Sobrien#include <sys/cdefs.h> 38116182Sobrien__FBSDID("$FreeBSD: stable/11/sys/kern/subr_prf.c 339446 2018-10-20 16:20:36Z jamie $"); 39116182Sobrien 40284192Sken#ifdef _KERNEL 41108678Sphk#include "opt_ddb.h" 42164760Sjb#include "opt_printf.h" 43284192Sken#endif /* _KERNEL */ 44108678Sphk 451541Srgrimes#include <sys/param.h> 46284192Sken#ifdef _KERNEL 471541Srgrimes#include <sys/systm.h> 4891140Stanimura#include <sys/lock.h> 49131931Smarcel#include <sys/kdb.h> 5091140Stanimura#include <sys/mutex.h> 5191140Stanimura#include <sys/sx.h> 5236441Sphk#include <sys/kernel.h> 531541Srgrimes#include <sys/msgbuf.h> 5430354Sphk#include <sys/malloc.h> 55164033Srwatson#include <sys/priv.h> 561541Srgrimes#include <sys/proc.h> 57106855Smux#include <sys/stddef.h> 5890490Sphk#include <sys/sysctl.h> 591541Srgrimes#include <sys/tty.h> 601541Srgrimes#include <sys/syslog.h> 6149558Sphk#include <sys/cons.h> 6270239Sphk#include <sys/uio.h> 63284192Sken#endif 64156518Sjkim#include <sys/ctype.h> 65284192Sken#include <sys/sbuf.h> 661541Srgrimes 67108678Sphk#ifdef DDB 68108678Sphk#include <ddb/ddb.h> 69108678Sphk#endif 70108678Sphk 711541Srgrimes/* 721541Srgrimes * Note that stdarg.h and the ANSI style va_start macro is used for both 731541Srgrimes * ANSI and traditional C compilers. 741541Srgrimes */ 75321107Sngie#ifdef _KERNEL 761541Srgrimes#include <machine/stdarg.h> 77321107Sngie#else 78321107Sngie#include <stdarg.h> 79321107Sngie#endif 801541Srgrimes 81321107Sngie/* 82321107Sngie * This is needed for sbuf_putbuf() when compiled into userland. Due to the 83321107Sngie * shared nature of this file, it's the only place to put it. 84321107Sngie */ 85321107Sngie#ifndef _KERNEL 86321107Sngie#include <stdio.h> 87321107Sngie#endif 88321107Sngie 89284192Sken#ifdef _KERNEL 90284192Sken 911541Srgrimes#define TOCONS 0x01 921541Srgrimes#define TOTTY 0x02 931541Srgrimes#define TOLOG 0x04 941541Srgrimes 9548728Speter/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 9697749Sdes#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 9747773Sarchie 9841479Sarchiestruct putchar_arg { 9947822Sarchie int flags; 10070239Sphk int pri; 10147822Sarchie struct tty *tty; 102163858Sjb char *p_bufr; 103163858Sjb size_t n_bufr; 104163858Sjb char *p_next; 105163858Sjb size_t remain; 10641479Sarchie}; 10741479Sarchie 10841479Sarchiestruct snprintf_arg { 10947822Sarchie char *str; 11047822Sarchie size_t remain; 11141479Sarchie}; 11241479Sarchie 11370239Sphkextern int log_open; 11470239Sphk 11570239Sphkstatic void msglogchar(int c, int pri); 116222537Skenstatic void msglogstr(char *str, int pri, int filter_cr); 11792723Salfredstatic void putchar(int ch, void *arg); 118156518Sjkimstatic char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper); 11992723Salfredstatic void snprintf_func(int ch, void *arg); 1201541Srgrimes 121338109Skevansstatic bool msgbufmapped; /* Set when safe to use msgbuf */ 12270239Sphkint msgbuftrigger; 1231541Srgrimes 124338109Skevans#ifndef BOOT_TAG_SZ 125338109Skevans#define BOOT_TAG_SZ 32 126338109Skevans#endif 127338109Skevans#ifndef BOOT_TAG 128338109Skevans/* Tag used to mark the start of a boot in dmesg */ 129338109Skevans#define BOOT_TAG "" 130338109Skevans#endif 131338109Skevans 132338109Skevansstatic char current_boot_tag[BOOT_TAG_SZ + 1] = BOOT_TAG; 133338109SkevansSYSCTL_STRING(_kern, OID_AUTO, boot_tag, CTLFLAG_RDTUN | CTLFLAG_NOFETCH, 134338109Skevans current_boot_tag, 0, "Tag added to dmesg at start of boot"); 135338109Skevans 136267992Shselaskystatic int log_console_output = 1; 137267992ShselaskySYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN, 138267992Shselasky &log_console_output, 0, "Duplicate console output to the syslog"); 13995713Sdwmalone 140222537Sken/* 141222537Sken * See the comment in log_console() below for more explanation of this. 142222537Sken */ 143267992Shselaskystatic int log_console_add_linefeed; 144267992ShselaskySYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RWTUN, 145267992Shselasky &log_console_add_linefeed, 0, "log_console() adds extra newlines"); 146222537Sken 147267992Shselaskystatic int always_console_output; 148267992ShselaskySYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RWTUN, 149267992Shselasky &always_console_output, 0, "Always output to console despite TIOCCONS"); 150130700Sgreen 1511541Srgrimes/* 1521541Srgrimes * Warn that a system table is full. 1531541Srgrimes */ 1541541Srgrimesvoid 15570239Sphktablefull(const char *tab) 1561541Srgrimes{ 1571541Srgrimes 1581541Srgrimes log(LOG_ERR, "%s: table is full\n", tab); 1591541Srgrimes} 1601541Srgrimes 1611541Srgrimes/* 1621541Srgrimes * Uprintf prints to the controlling terminal for the current process. 1631541Srgrimes */ 16449047Sdfrint 1651541Srgrimesuprintf(const char *fmt, ...) 1661541Srgrimes{ 1671541Srgrimes va_list ap; 16813446Sphk struct putchar_arg pca; 169189102Sed struct proc *p; 170189102Sed struct thread *td; 17191140Stanimura int retval; 1721541Srgrimes 173189102Sed td = curthread; 174189102Sed if (TD_IS_IDLETHREAD(td)) 17591140Stanimura return (0); 17691140Stanimura 177181905Sed sx_slock(&proctree_lock); 178189102Sed p = td->td_proc; 17991140Stanimura PROC_LOCK(p); 18091140Stanimura if ((p->p_flag & P_CONTROLT) == 0) { 18191140Stanimura PROC_UNLOCK(p); 182255509Skib sx_sunlock(&proctree_lock); 183255509Skib return (0); 1841541Srgrimes } 18591140Stanimura SESS_LOCK(p->p_session); 18691140Stanimura pca.tty = p->p_session->s_ttyp; 18791140Stanimura SESS_UNLOCK(p->p_session); 18891140Stanimura PROC_UNLOCK(p); 189150560Srwatson if (pca.tty == NULL) { 190255509Skib sx_sunlock(&proctree_lock); 191255509Skib return (0); 192150560Srwatson } 19391140Stanimura pca.flags = TOTTY; 194222804Sken pca.p_bufr = NULL; 19591140Stanimura va_start(ap, fmt); 196181905Sed tty_lock(pca.tty); 197255509Skib sx_sunlock(&proctree_lock); 19891140Stanimura retval = kvprintf(fmt, putchar, &pca, 10, ap); 199181905Sed tty_unlock(pca.tty); 20091140Stanimura va_end(ap); 20190490Sphk return (retval); 2021541Srgrimes} 2031541Srgrimes 2041541Srgrimes/* 205255351Snp * tprintf and vtprintf print on the controlling terminal associated with the 206255351Snp * given session, possibly to the log as well. 2071541Srgrimes */ 20869214Sphkvoid 20969214Sphktprintf(struct proc *p, int pri, const char *fmt, ...) 2101541Srgrimes{ 211255351Snp va_list ap; 212255351Snp 213255351Snp va_start(ap, fmt); 214255351Snp vtprintf(p, pri, fmt, ap); 215255351Snp va_end(ap); 216255351Snp} 217255351Snp 218255351Snpvoid 219255351Snpvtprintf(struct proc *p, int pri, const char *fmt, va_list ap) 220255351Snp{ 2211541Srgrimes struct tty *tp = NULL; 222113634Sjhb int flags = 0; 22313446Sphk struct putchar_arg pca; 224113634Sjhb struct session *sess = NULL; 2251541Srgrimes 226181905Sed sx_slock(&proctree_lock); 22770239Sphk if (pri != -1) 22869214Sphk flags |= TOLOG; 22991140Stanimura if (p != NULL) { 23091140Stanimura PROC_LOCK(p); 23191140Stanimura if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 232113634Sjhb sess = p->p_session; 233181905Sed sess_hold(sess); 23491140Stanimura PROC_UNLOCK(p); 235113634Sjhb tp = sess->s_ttyp; 236181905Sed if (tp != NULL && tty_checkoutq(tp)) 23791140Stanimura flags |= TOTTY; 23891140Stanimura else 23991140Stanimura tp = NULL; 24091140Stanimura } else 24191140Stanimura PROC_UNLOCK(p); 24269214Sphk } 24370239Sphk pca.pri = pri; 24413446Sphk pca.tty = tp; 24513446Sphk pca.flags = flags; 246222804Sken pca.p_bufr = NULL; 247181905Sed if (pca.tty != NULL) 248181905Sed tty_lock(pca.tty); 249255509Skib sx_sunlock(&proctree_lock); 250115538Sphk kvprintf(fmt, putchar, &pca, 10, ap); 251181905Sed if (pca.tty != NULL) 252181905Sed tty_unlock(pca.tty); 253143740Sphk if (sess != NULL) 254181905Sed sess_release(sess); 25570239Sphk msgbuftrigger = 1; 2561541Srgrimes} 2571541Srgrimes 2581541Srgrimes/* 2591541Srgrimes * Ttyprintf displays a message on a tty; it should be used only by 2601541Srgrimes * the tty driver, or anything that knows the underlying tty will not 2611541Srgrimes * be revoke(2)'d away. Other callers should use tprintf. 2621541Srgrimes */ 26349047Sdfrint 2641541Srgrimesttyprintf(struct tty *tp, const char *fmt, ...) 2651541Srgrimes{ 2661541Srgrimes va_list ap; 26713446Sphk struct putchar_arg pca; 26849047Sdfr int retval; 26949047Sdfr 2701541Srgrimes va_start(ap, fmt); 27113446Sphk pca.tty = tp; 27213446Sphk pca.flags = TOTTY; 273222804Sken pca.p_bufr = NULL; 27449047Sdfr retval = kvprintf(fmt, putchar, &pca, 10, ap); 2751541Srgrimes va_end(ap); 27690490Sphk return (retval); 2771541Srgrimes} 2781541Srgrimes 279263129Sbdrewerystatic int 280263129Sbdrewery_vprintf(int level, int flags, const char *fmt, va_list ap) 2811541Srgrimes{ 28270239Sphk struct putchar_arg pca; 283263129Sbdrewery int retval; 284222537Sken#ifdef PRINTF_BUFR_SIZE 285222537Sken char bufr[PRINTF_BUFR_SIZE]; 286222537Sken#endif 2871541Srgrimes 28870239Sphk pca.tty = NULL; 28970239Sphk pca.pri = level; 290263129Sbdrewery pca.flags = flags; 291222537Sken#ifdef PRINTF_BUFR_SIZE 292222537Sken pca.p_bufr = bufr; 293222537Sken pca.p_next = pca.p_bufr; 294222537Sken pca.n_bufr = sizeof(bufr); 295222537Sken pca.remain = sizeof(bufr); 296222537Sken *pca.p_next = '\0'; 297222537Sken#else 298263129Sbdrewery /* Don't buffer console output. */ 299163858Sjb pca.p_bufr = NULL; 300222537Sken#endif 30170239Sphk 302263129Sbdrewery retval = kvprintf(fmt, putchar, &pca, 10, ap); 30313446Sphk 304222537Sken#ifdef PRINTF_BUFR_SIZE 305222537Sken /* Write any buffered console/log output: */ 306222537Sken if (*pca.p_bufr != '\0') { 307222537Sken if (pca.flags & TOLOG) 308222537Sken msglogstr(pca.p_bufr, level, /*filter_cr*/1); 309222537Sken 310222537Sken if (pca.flags & TOCONS) 311222537Sken cnputs(pca.p_bufr); 312222537Sken } 313222537Sken#endif 314263129Sbdrewery 315263129Sbdrewery return (retval); 316263129Sbdrewery} 317263129Sbdrewery 318263129Sbdrewery/* 319263129Sbdrewery * Log writes to the log buffer, and guarantees not to sleep (so can be 320263129Sbdrewery * called by interrupt routines). If there is no process reading the 321263129Sbdrewery * log yet, it writes to the console also. 322263129Sbdrewery */ 323263129Sbdreweryvoid 324263129Sbdrewerylog(int level, const char *fmt, ...) 325263129Sbdrewery{ 326263129Sbdrewery va_list ap; 327263129Sbdrewery 328263129Sbdrewery va_start(ap, fmt); 329291058Smarkj vlog(level, fmt, ap); 330263129Sbdrewery va_end(ap); 331291058Smarkj} 332263129Sbdrewery 333291058Smarkjvoid 334291058Smarkjvlog(int level, const char *fmt, va_list ap) 335291058Smarkj{ 336291058Smarkj 337291058Smarkj (void)_vprintf(level, log_open ? TOLOG : TOCONS | TOLOG, fmt, ap); 33870240Sphk msgbuftrigger = 1; 3391541Srgrimes} 3401541Srgrimes 34170239Sphk#define CONSCHUNK 128 34270239Sphk 34370239Sphkvoid 34470239Sphklog_console(struct uio *uio) 3451541Srgrimes{ 346222537Sken int c, error, nl; 34770239Sphk char *consbuffer; 34870239Sphk int pri; 3491541Srgrimes 35095713Sdwmalone if (!log_console_output) 35195713Sdwmalone return; 35295713Sdwmalone 35370239Sphk pri = LOG_INFO | LOG_CONSOLE; 354131897Sphk uio = cloneuio(uio); 355131897Sphk consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK); 35670239Sphk 357186383Sed nl = 0; 35870239Sphk while (uio->uio_resid > 0) { 359222537Sken c = imin(uio->uio_resid, CONSCHUNK - 1); 36070239Sphk error = uiomove(consbuffer, c, uio); 36170239Sphk if (error != 0) 362104114Sphk break; 363222537Sken /* Make sure we're NUL-terminated */ 364222537Sken consbuffer[c] = '\0'; 365222537Sken if (consbuffer[c - 1] == '\n') 366222537Sken nl = 1; 367222537Sken else 368222537Sken nl = 0; 369222537Sken msglogstr(consbuffer, pri, /*filter_cr*/ 1); 37070239Sphk } 371222537Sken /* 372222537Sken * The previous behavior in log_console() is preserved when 373222537Sken * log_console_add_linefeed is non-zero. For that behavior, if an 374222537Sken * individual console write came in that was not terminated with a 375222537Sken * line feed, it would add a line feed. 376222537Sken * 377222537Sken * This results in different data in the message buffer than 378222537Sken * appears on the system console (which doesn't add extra line feed 379222537Sken * characters). 380222537Sken * 381222537Sken * A number of programs and rc scripts write a line feed, or a period 382222537Sken * and a line feed when they have completed their operation. On 383222537Sken * the console, this looks seamless, but when displayed with 384222537Sken * 'dmesg -a', you wind up with output that looks like this: 385222537Sken * 386222537Sken * Updating motd: 387222537Sken * . 388222537Sken * 389222537Sken * On the console, it looks like this: 390222537Sken * Updating motd:. 391222537Sken * 392222537Sken * We could add logic to detect that situation, or just not insert 393222537Sken * the extra newlines. Set the kern.log_console_add_linefeed 394222537Sken * sysctl/tunable variable to get the old behavior. 395222537Sken */ 396222537Sken if (!nl && log_console_add_linefeed) { 397222537Sken consbuffer[0] = '\n'; 398222537Sken consbuffer[1] = '\0'; 399222537Sken msglogstr(consbuffer, pri, /*filter_cr*/ 1); 400222537Sken } 40170240Sphk msgbuftrigger = 1; 402131897Sphk free(uio, M_IOV); 403131897Sphk free(consbuffer, M_TEMP); 4041541Srgrimes} 4051541Srgrimes 40615680Sgpalmerint 4071541Srgrimesprintf(const char *fmt, ...) 4081541Srgrimes{ 4091541Srgrimes va_list ap; 41013694Sgibbs int retval; 4111541Srgrimes 4121541Srgrimes va_start(ap, fmt); 413189104Sed retval = vprintf(fmt, ap); 4141541Srgrimes va_end(ap); 415163858Sjb 41690490Sphk return (retval); 4171541Srgrimes} 4181541Srgrimes 41949047Sdfrint 42013446Sphkvprintf(const char *fmt, va_list ap) 42113446Sphk{ 42249047Sdfr int retval; 42313446Sphk 424263129Sbdrewery retval = _vprintf(-1, TOCONS | TOLOG, fmt, ap); 425163858Sjb 42613446Sphk if (!panicstr) 42770240Sphk msgbuftrigger = 1; 428163858Sjb 42990490Sphk return (retval); 43013446Sphk} 43113446Sphk 432163858Sjbstatic void 433321107Sngieprf_putbuf(char *bufr, int flags, int pri) 434321107Sngie{ 435321107Sngie 436321107Sngie if (flags & TOLOG) 437321107Sngie msglogstr(bufr, pri, /*filter_cr*/1); 438321107Sngie 439321107Sngie if (flags & TOCONS) { 440321107Sngie if ((panicstr == NULL) && (constty != NULL)) 441321107Sngie msgbuf_addstr(&consmsgbuf, -1, 442321107Sngie bufr, /*filter_cr*/ 0); 443321107Sngie 444321107Sngie if ((constty == NULL) ||(always_console_output)) 445321107Sngie cnputs(bufr); 446321107Sngie } 447321107Sngie} 448321107Sngie 449321107Sngiestatic void 450222537Skenputbuf(int c, struct putchar_arg *ap) 451163858Sjb{ 452163858Sjb /* Check if no console output buffer was provided. */ 453222537Sken if (ap->p_bufr == NULL) { 454163858Sjb /* Output direct to the console. */ 455222537Sken if (ap->flags & TOCONS) 456222537Sken cnputc(c); 457222537Sken 458222537Sken if (ap->flags & TOLOG) 459222537Sken msglogchar(c, ap->pri); 460222537Sken } else { 461163858Sjb /* Buffer the character: */ 462163858Sjb *ap->p_next++ = c; 463163858Sjb ap->remain--; 464163858Sjb 465163858Sjb /* Always leave the buffer zero terminated. */ 466163858Sjb *ap->p_next = '\0'; 467163858Sjb 468163858Sjb /* Check if the buffer needs to be flushed. */ 469222537Sken if (ap->remain == 2 || c == '\n') { 470321107Sngie prf_putbuf(ap->p_bufr, ap->flags, ap->pri); 471222537Sken 472163858Sjb ap->p_next = ap->p_bufr; 473163858Sjb ap->remain = ap->n_bufr; 474163858Sjb *ap->p_next = '\0'; 475163858Sjb } 476222537Sken 477222537Sken /* 478222537Sken * Since we fill the buffer up one character at a time, 479222537Sken * this should not happen. We should always catch it when 480222537Sken * ap->remain == 2 (if not sooner due to a newline), flush 481222537Sken * the buffer and move on. One way this could happen is 482222537Sken * if someone sets PRINTF_BUFR_SIZE to 1 or something 483222537Sken * similarly silly. 484222537Sken */ 485222537Sken KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd", 486222537Sken ap->remain)); 487163858Sjb } 488163858Sjb} 489163858Sjb 4901541Srgrimes/* 49113446Sphk * Print a character on console or users terminal. If destination is 49236441Sphk * the console then the last bunch of characters are saved in msgbuf for 49313446Sphk * inspection later. 49413446Sphk */ 49513446Sphkstatic void 49613446Sphkputchar(int c, void *arg) 49713446Sphk{ 49813446Sphk struct putchar_arg *ap = (struct putchar_arg*) arg; 49913446Sphk struct tty *tp = ap->tty; 500163858Sjb int flags = ap->flags; 501116663Siedowse 502116664Siedowse /* Don't use the tty code after a panic or while in ddb. */ 503163858Sjb if (kdb_active) { 504116663Siedowse if (c != '\0') 505116663Siedowse cnputc(c); 506226435Smarcel return; 507226435Smarcel } 508222537Sken 509226435Smarcel if ((flags & TOTTY) && tp != NULL && panicstr == NULL) 510226435Smarcel tty_putchar(tp, c); 511226435Smarcel 512226435Smarcel if ((flags & (TOCONS | TOLOG)) && c != '\0') 513226435Smarcel putbuf(c, ap); 51413446Sphk} 51513446Sphk 51613446Sphk/* 51713446Sphk * Scaled down version of sprintf(3). 51813446Sphk */ 51913446Sphkint 52013446Sphksprintf(char *buf, const char *cfmt, ...) 52113446Sphk{ 52213446Sphk int retval; 52313446Sphk va_list ap; 52413446Sphk 52513446Sphk va_start(ap, cfmt); 52613446Sphk retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 52713494Sphk buf[retval] = '\0'; 52813446Sphk va_end(ap); 52990490Sphk return (retval); 53013446Sphk} 53113446Sphk 53213446Sphk/* 53338874Sache * Scaled down version of vsprintf(3). 53438874Sache */ 53538874Sacheint 53638874Sachevsprintf(char *buf, const char *cfmt, va_list ap) 53738874Sache{ 53838874Sache int retval; 53938874Sache 54038874Sache retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 54138874Sache buf[retval] = '\0'; 54290490Sphk return (retval); 54338874Sache} 54438874Sache 54538874Sache/* 54641479Sarchie * Scaled down version of snprintf(3). 54741479Sarchie */ 54841479Sarchieint 54941479Sarchiesnprintf(char *str, size_t size, const char *format, ...) 55041479Sarchie{ 55141479Sarchie int retval; 55241479Sarchie va_list ap; 55341479Sarchie 55441479Sarchie va_start(ap, format); 55541479Sarchie retval = vsnprintf(str, size, format, ap); 55641479Sarchie va_end(ap); 55741479Sarchie return(retval); 55841479Sarchie} 55941479Sarchie 56041479Sarchie/* 56141479Sarchie * Scaled down version of vsnprintf(3). 56241479Sarchie */ 56341479Sarchieint 56441479Sarchievsnprintf(char *str, size_t size, const char *format, va_list ap) 56541479Sarchie{ 56641479Sarchie struct snprintf_arg info; 56741479Sarchie int retval; 56841479Sarchie 56941479Sarchie info.str = str; 57041479Sarchie info.remain = size; 57141479Sarchie retval = kvprintf(format, snprintf_func, &info, 10, ap); 57241479Sarchie if (info.remain >= 1) 57341479Sarchie *info.str++ = '\0'; 57490490Sphk return (retval); 57541479Sarchie} 57641479Sarchie 577110316Sphk/* 578110316Sphk * Kernel version which takes radix argument vsnprintf(3). 579110316Sphk */ 580110316Sphkint 581110316Sphkvsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap) 582110316Sphk{ 583110316Sphk struct snprintf_arg info; 584110316Sphk int retval; 585110316Sphk 586110316Sphk info.str = str; 587110316Sphk info.remain = size; 588110316Sphk retval = kvprintf(format, snprintf_func, &info, radix, ap); 589110316Sphk if (info.remain >= 1) 590110316Sphk *info.str++ = '\0'; 591110316Sphk return (retval); 592110316Sphk} 593110316Sphk 59441479Sarchiestatic void 59541479Sarchiesnprintf_func(int ch, void *arg) 59641479Sarchie{ 59741479Sarchie struct snprintf_arg *const info = arg; 59841479Sarchie 59941479Sarchie if (info->remain >= 2) { 60041479Sarchie *info->str++ = ch; 60141479Sarchie info->remain--; 60241479Sarchie } 60341479Sarchie} 60441479Sarchie 60541479Sarchie/* 60648728Speter * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 60747822Sarchie * order; return an optional length and a pointer to the last character 60847822Sarchie * written in the buffer (i.e., the first character of the string). 60947822Sarchie * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 61013446Sphk */ 61113446Sphkstatic char * 612156518Sjkimksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 61347822Sarchie{ 614156518Sjkim char *p, c; 61513446Sphk 61647822Sarchie p = nbuf; 61747773Sarchie *p = '\0'; 61813446Sphk do { 619156518Sjkim c = hex2ascii(num % base); 620156518Sjkim *++p = upper ? toupper(c) : c; 62197749Sdes } while (num /= base); 62213446Sphk if (lenp) 62347822Sarchie *lenp = p - nbuf; 62413446Sphk return (p); 62513446Sphk} 62613446Sphk 62713446Sphk/* 6281541Srgrimes * Scaled down version of printf(3). 6291541Srgrimes * 6301541Srgrimes * Two additional formats: 6311541Srgrimes * 6321541Srgrimes * The format %b is supported to decode error registers. 6331541Srgrimes * Its usage is: 6341541Srgrimes * 6351541Srgrimes * printf("reg=%b\n", regval, "<base><arg>*"); 6361541Srgrimes * 6371541Srgrimes * where <base> is the output base expressed as a control character, e.g. 6381541Srgrimes * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 6391541Srgrimes * the first of which gives the bit number to be inspected (origin 1), and 6401541Srgrimes * the next characters (up to a control character, i.e. a character <= 32), 6411541Srgrimes * give the name of the register. Thus: 6421541Srgrimes * 643277560Sdanfe * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE"); 6441541Srgrimes * 6451541Srgrimes * would produce output: 6461541Srgrimes * 6471541Srgrimes * reg=3<BITTWO,BITONE> 6481541Srgrimes * 64913618Sphk * XXX: %D -- Hexdump, takes pointer and separator string: 65013618Sphk * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 65113618Sphk * ("%*D", len, ptr, " " -> XX XX XX XX ... 6521541Srgrimes */ 65313446Sphkint 65413446Sphkkvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 6551541Srgrimes{ 65613446Sphk#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 65747773Sarchie char nbuf[MAXNBUF]; 65897749Sdes char *d; 65997749Sdes const char *p, *percent, *q; 66013618Sphk u_char *up; 66113446Sphk int ch, n; 66297749Sdes uintmax_t num; 66348714Speter int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 664125985Snjl int cflag, hflag, jflag, tflag, zflag; 665156518Sjkim int dwidth, upper; 6661541Srgrimes char padc; 667149756Sphk int stop = 0, retval = 0; 6681541Srgrimes 66997749Sdes num = 0; 67013494Sphk if (!func) 67113446Sphk d = (char *) arg; 67213446Sphk else 67313494Sphk d = NULL; 67413446Sphk 6755261Sdg if (fmt == NULL) 6765288Sbde fmt = "(fmt null)\n"; 67713563Sphk 67813618Sphk if (radix < 2 || radix > 36) 67913563Sphk radix = 10; 68013563Sphk 6811541Srgrimes for (;;) { 6821541Srgrimes padc = ' '; 6831541Srgrimes width = 0; 684149756Sphk while ((ch = (u_char)*fmt++) != '%' || stop) { 68597750Sdes if (ch == '\0') 68690490Sphk return (retval); 68713446Sphk PCHAR(ch); 6881541Srgrimes } 68997749Sdes percent = fmt - 1; 69048714Speter qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 691156518Sjkim sign = 0; dot = 0; dwidth = 0; upper = 0; 692125985Snjl cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 69317974Sbdereswitch: switch (ch = (u_char)*fmt++) { 69413466Sphk case '.': 69513466Sphk dot = 1; 69613466Sphk goto reswitch; 69713446Sphk case '#': 69813446Sphk sharpflag = 1; 69913446Sphk goto reswitch; 70013446Sphk case '+': 70113446Sphk sign = 1; 70213446Sphk goto reswitch; 70313446Sphk case '-': 70413446Sphk ladjust = 1; 70513446Sphk goto reswitch; 70613446Sphk case '%': 70713446Sphk PCHAR(ch); 70813446Sphk break; 70913446Sphk case '*': 71013501Sphk if (!dot) { 71113501Sphk width = va_arg(ap, int); 71213501Sphk if (width < 0) { 71313501Sphk ladjust = !ladjust; 71413501Sphk width = -width; 71513501Sphk } 71613501Sphk } else { 71713501Sphk dwidth = va_arg(ap, int); 71813446Sphk } 71913446Sphk goto reswitch; 7201541Srgrimes case '0': 72113480Sphk if (!dot) { 72213480Sphk padc = '0'; 72313480Sphk goto reswitch; 72413480Sphk } 725336550Smarkj /* FALLTHROUGH */ 7261541Srgrimes case '1': case '2': case '3': case '4': 7271541Srgrimes case '5': case '6': case '7': case '8': case '9': 72813480Sphk for (n = 0;; ++fmt) { 72913480Sphk n = n * 10 + ch - '0'; 73013480Sphk ch = *fmt; 73113480Sphk if (ch < '0' || ch > '9') 73213480Sphk break; 73313480Sphk } 73413480Sphk if (dot) 73513480Sphk dwidth = n; 73613480Sphk else 73713480Sphk width = n; 7381541Srgrimes goto reswitch; 7391541Srgrimes case 'b': 740108890Sjhb num = (u_int)va_arg(ap, int); 7411541Srgrimes p = va_arg(ap, char *); 742156518Sjkim for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 74313446Sphk PCHAR(*q--); 7441541Srgrimes 74597749Sdes if (num == 0) 7461541Srgrimes break; 7471541Srgrimes 7483308Sphk for (tmp = 0; *p;) { 7493308Sphk n = *p++; 75097749Sdes if (num & (1 << (n - 1))) { 75113446Sphk PCHAR(tmp ? ',' : '<'); 7521541Srgrimes for (; (n = *p) > ' '; ++p) 75313446Sphk PCHAR(n); 7541541Srgrimes tmp = 1; 7551541Srgrimes } else 7561541Srgrimes for (; *p > ' '; ++p) 7571541Srgrimes continue; 7581541Srgrimes } 7591541Srgrimes if (tmp) 76013446Sphk PCHAR('>'); 7611541Srgrimes break; 7621541Srgrimes case 'c': 763301750Scem width -= 1; 764301750Scem 765301750Scem if (!ladjust && width > 0) 766301750Scem while (width--) 767301750Scem PCHAR(padc); 76813446Sphk PCHAR(va_arg(ap, int)); 769301750Scem if (ladjust && width > 0) 770301750Scem while (width--) 771301750Scem PCHAR(padc); 7721541Srgrimes break; 77313618Sphk case 'D': 77413618Sphk up = va_arg(ap, u_char *); 77513618Sphk p = va_arg(ap, char *); 77613618Sphk if (!width) 77713618Sphk width = 16; 77813618Sphk while(width--) { 77913618Sphk PCHAR(hex2ascii(*up >> 4)); 78013618Sphk PCHAR(hex2ascii(*up & 0x0f)); 78113618Sphk up++; 78213618Sphk if (width) 78313618Sphk for (q=p;*q;q++) 78413618Sphk PCHAR(*q); 78513618Sphk } 78613618Sphk break; 7871541Srgrimes case 'd': 78899459Simp case 'i': 78997749Sdes base = 10; 79013446Sphk sign = 1; 79197749Sdes goto handle_sign; 792125985Snjl case 'h': 793125985Snjl if (hflag) { 794125985Snjl hflag = 0; 795125985Snjl cflag = 1; 796125985Snjl } else 797125985Snjl hflag = 1; 798125985Snjl goto reswitch; 79997749Sdes case 'j': 80097749Sdes jflag = 1; 80197749Sdes goto reswitch; 80213446Sphk case 'l': 80349502Sgreen if (lflag) { 80449502Sgreen lflag = 0; 80549502Sgreen qflag = 1; 80649502Sgreen } else 80749502Sgreen lflag = 1; 80813446Sphk goto reswitch; 80997749Sdes case 'n': 81097749Sdes if (jflag) 81197749Sdes *(va_arg(ap, intmax_t *)) = retval; 81297749Sdes else if (qflag) 81397749Sdes *(va_arg(ap, quad_t *)) = retval; 81448714Speter else if (lflag) 81597749Sdes *(va_arg(ap, long *)) = retval; 816105954Smux else if (zflag) 817105954Smux *(va_arg(ap, size_t *)) = retval; 818125985Snjl else if (hflag) 819125985Snjl *(va_arg(ap, short *)) = retval; 820125985Snjl else if (cflag) 821125985Snjl *(va_arg(ap, char *)) = retval; 82248714Speter else 82397749Sdes *(va_arg(ap, int *)) = retval; 82497749Sdes break; 82597749Sdes case 'o': 8261541Srgrimes base = 8; 82797749Sdes goto handle_nosign; 8289224Sbde case 'p': 8299224Sbde base = 16; 83038224Sbde sharpflag = (width == 0); 83197749Sdes sign = 0; 83297749Sdes num = (uintptr_t)va_arg(ap, void *); 83397749Sdes goto number; 83448714Speter case 'q': 83548714Speter qflag = 1; 83648714Speter goto reswitch; 83737505Sbde case 'r': 83837505Sbde base = radix; 83997749Sdes if (sign) 84097749Sdes goto handle_sign; 84197749Sdes goto handle_nosign; 84213446Sphk case 's': 84313446Sphk p = va_arg(ap, char *); 84413446Sphk if (p == NULL) 84513446Sphk p = "(null)"; 84613466Sphk if (!dot) 84713466Sphk n = strlen (p); 84813466Sphk else 84913480Sphk for (n = 0; n < dwidth && p[n]; n++) 85013466Sphk continue; 85113480Sphk 85213466Sphk width -= n; 85313480Sphk 85413446Sphk if (!ladjust && width > 0) 85513446Sphk while (width--) 85613446Sphk PCHAR(padc); 85713466Sphk while (n--) 85813446Sphk PCHAR(*p++); 85913446Sphk if (ladjust && width > 0) 86013446Sphk while (width--) 86113446Sphk PCHAR(padc); 86213446Sphk break; 863106855Smux case 't': 864106855Smux tflag = 1; 865106855Smux goto reswitch; 8661541Srgrimes case 'u': 8671541Srgrimes base = 10; 86897749Sdes goto handle_nosign; 869156518Sjkim case 'X': 870156518Sjkim upper = 1; 8711541Srgrimes case 'x': 8721541Srgrimes base = 16; 87397749Sdes goto handle_nosign; 874105954Smux case 'y': 87597749Sdes base = 16; 876104924Sjhb sign = 1; 877104924Sjhb goto handle_sign; 878105954Smux case 'z': 879105954Smux zflag = 1; 880105954Smux goto reswitch; 88197749Sdeshandle_nosign: 88297749Sdes sign = 0; 88397749Sdes if (jflag) 88497749Sdes num = va_arg(ap, uintmax_t); 88597749Sdes else if (qflag) 88697749Sdes num = va_arg(ap, u_quad_t); 887106855Smux else if (tflag) 888106855Smux num = va_arg(ap, ptrdiff_t); 88948714Speter else if (lflag) 89097749Sdes num = va_arg(ap, u_long); 891105954Smux else if (zflag) 892105954Smux num = va_arg(ap, size_t); 893125985Snjl else if (hflag) 894125985Snjl num = (u_short)va_arg(ap, int); 895125985Snjl else if (cflag) 896125985Snjl num = (u_char)va_arg(ap, int); 89748714Speter else 89897749Sdes num = va_arg(ap, u_int); 89937505Sbde goto number; 90097749Sdeshandle_sign: 90197749Sdes if (jflag) 90297749Sdes num = va_arg(ap, intmax_t); 90397749Sdes else if (qflag) 90497749Sdes num = va_arg(ap, quad_t); 905106855Smux else if (tflag) 906106855Smux num = va_arg(ap, ptrdiff_t); 90797749Sdes else if (lflag) 90897749Sdes num = va_arg(ap, long); 909105954Smux else if (zflag) 910185036Sdelphij num = va_arg(ap, ssize_t); 911125985Snjl else if (hflag) 912125985Snjl num = (short)va_arg(ap, int); 913125985Snjl else if (cflag) 914125985Snjl num = (char)va_arg(ap, int); 91597749Sdes else 91697749Sdes num = va_arg(ap, int); 91797749Sdesnumber: 91897749Sdes if (sign && (intmax_t)num < 0) { 91997749Sdes neg = 1; 92097749Sdes num = -(intmax_t)num; 92113446Sphk } 922209836Sjkim p = ksprintn(nbuf, num, base, &n, upper); 923209836Sjkim tmp = 0; 92497749Sdes if (sharpflag && num != 0) { 92513446Sphk if (base == 8) 92613446Sphk tmp++; 92713446Sphk else if (base == 16) 92813446Sphk tmp += 2; 92913446Sphk } 93013446Sphk if (neg) 93113446Sphk tmp++; 93213446Sphk 933209836Sjkim if (!ladjust && padc == '0') 934209836Sjkim dwidth = width - tmp; 935209949Sjkim width -= tmp + imax(dwidth, n); 936209836Sjkim dwidth -= n; 937209836Sjkim if (!ladjust) 938209836Sjkim while (width-- > 0) 939209836Sjkim PCHAR(' '); 94013446Sphk if (neg) 94113446Sphk PCHAR('-'); 94297749Sdes if (sharpflag && num != 0) { 94313446Sphk if (base == 8) { 94413446Sphk PCHAR('0'); 94513446Sphk } else if (base == 16) { 94613446Sphk PCHAR('0'); 94713446Sphk PCHAR('x'); 94813446Sphk } 94913446Sphk } 950209836Sjkim while (dwidth-- > 0) 951209836Sjkim PCHAR('0'); 95213446Sphk 9533308Sphk while (*p) 95413446Sphk PCHAR(*p--); 95513446Sphk 956209836Sjkim if (ladjust) 957209836Sjkim while (width-- > 0) 958209836Sjkim PCHAR(' '); 95913446Sphk 9601541Srgrimes break; 9611541Srgrimes default: 96297749Sdes while (percent < fmt) 96397749Sdes PCHAR(*percent++); 964149756Sphk /* 965277560Sdanfe * Since we ignore a formatting argument it is no 966149756Sphk * longer safe to obey the remaining formatting 967149756Sphk * arguments as the arguments will no longer match 968149756Sphk * the format specs. 969149756Sphk */ 970149756Sphk stop = 1; 97113446Sphk break; 9721541Srgrimes } 9731541Srgrimes } 97413446Sphk#undef PCHAR 9751541Srgrimes} 9761541Srgrimes 9771541Srgrimes/* 97870239Sphk * Put character in log buffer with a particular priority. 9791541Srgrimes */ 9801541Srgrimesstatic void 98170239Sphkmsglogchar(int c, int pri) 9821541Srgrimes{ 98370239Sphk static int lastpri = -1; 98470239Sphk static int dangling; 98570239Sphk char nbuf[MAXNBUF]; 98670239Sphk char *p; 9871541Srgrimes 98870239Sphk if (!msgbufmapped) 98970239Sphk return; 99070239Sphk if (c == '\0' || c == '\r') 99170239Sphk return; 99270239Sphk if (pri != -1 && pri != lastpri) { 99370239Sphk if (dangling) { 994116660Siedowse msgbuf_addchar(msgbufp, '\n'); 99570239Sphk dangling = 0; 9966561Sbde } 997116660Siedowse msgbuf_addchar(msgbufp, '<'); 998156518Sjkim for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;) 999116660Siedowse msgbuf_addchar(msgbufp, *p--); 1000116660Siedowse msgbuf_addchar(msgbufp, '>'); 100170239Sphk lastpri = pri; 10021541Srgrimes } 1003116660Siedowse msgbuf_addchar(msgbufp, c); 100470239Sphk if (c == '\n') { 100570239Sphk dangling = 0; 100670239Sphk lastpri = -1; 100770239Sphk } else { 100870239Sphk dangling = 1; 100970239Sphk } 10101541Srgrimes} 101136441Sphk 1012222537Skenstatic void 1013222537Skenmsglogstr(char *str, int pri, int filter_cr) 1014222537Sken{ 1015222537Sken if (!msgbufmapped) 1016222537Sken return; 1017222537Sken 1018222537Sken msgbuf_addstr(msgbufp, pri, str, filter_cr); 1019222537Sken} 1020222537Sken 102136441Sphkvoid 1022106917Stmmmsgbufinit(void *ptr, int size) 102336441Sphk{ 102436441Sphk char *cp; 102547678Sjlemon static struct msgbuf *oldp = NULL; 1026338109Skevans bool print_boot_tag; 102736441Sphk 102886238Siedowse size -= sizeof(*msgbufp); 102936441Sphk cp = (char *)ptr; 1030338109Skevans print_boot_tag = !msgbufmapped; 1031338109Skevans /* Attempt to fetch kern.boot_tag tunable on first mapping */ 1032338109Skevans if (!msgbufmapped) 1033338109Skevans TUNABLE_STR_FETCH("kern.boot_tag", current_boot_tag, 1034338109Skevans sizeof(current_boot_tag)); 1035116660Siedowse msgbufp = (struct msgbuf *)(cp + size); 1036116660Siedowse msgbuf_reinit(msgbufp, cp, size); 103747678Sjlemon if (msgbufmapped && oldp != msgbufp) 1038116660Siedowse msgbuf_copy(oldp, msgbufp); 1039338109Skevans msgbufmapped = true; 1040338109Skevans if (print_boot_tag && *current_boot_tag != '\0') 1041338109Skevans printf("%s\n", current_boot_tag); 104247678Sjlemon oldp = msgbufp; 104336441Sphk} 104436441Sphk 104579153Stmm/* Sysctls for accessing/clearing the msgbuf */ 104679153Stmmstatic int 104779153Stmmsysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 104879153Stmm{ 1049116660Siedowse char buf[128]; 1050116660Siedowse u_int seq; 1051116660Siedowse int error, len; 105279153Stmm 1053339446Sjamie error = priv_check(req->td, PRIV_MSGBUF); 1054339446Sjamie if (error) 1055339446Sjamie return (error); 105687150Srwatson 1057116660Siedowse /* Read the whole buffer, one chunk at a time. */ 1058198860Sed mtx_lock(&msgbuf_lock); 1059116660Siedowse msgbuf_peekbytes(msgbufp, NULL, 0, &seq); 1060198860Sed for (;;) { 1061198860Sed len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq); 1062198860Sed mtx_unlock(&msgbuf_lock); 1063198860Sed if (len == 0) 1064280016Sian return (SYSCTL_OUT(req, "", 1)); /* add nulterm */ 1065198860Sed 1066116660Siedowse error = sysctl_handle_opaque(oidp, buf, len, req); 1067116660Siedowse if (error) 1068116660Siedowse return (error); 1069198860Sed 1070198860Sed mtx_lock(&msgbuf_lock); 107179153Stmm } 107279153Stmm} 107379153Stmm 1074198860SedSYSCTL_PROC(_kern, OID_AUTO, msgbuf, 1075198860Sed CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 1076188057Simp NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 107779153Stmm 1078116660Siedowsestatic int msgbuf_clearflag; 107979153Stmm 108079153Stmmstatic int 108179153Stmmsysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 108279153Stmm{ 108379153Stmm int error; 108479153Stmm error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 108579153Stmm if (!error && req->newptr) { 1086198860Sed mtx_lock(&msgbuf_lock); 1087116660Siedowse msgbuf_clear(msgbufp); 1088198860Sed mtx_unlock(&msgbuf_lock); 1089116660Siedowse msgbuf_clearflag = 0; 109079153Stmm } 109179153Stmm return (error); 109279153Stmm} 109379153Stmm 109479153StmmSYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 1095198860Sed CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE, 1096198860Sed &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I", 1097198860Sed "Clear kernel message buffer"); 109879153Stmm 109936441Sphk#ifdef DDB 110036441Sphk 110136441SphkDB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 110236441Sphk{ 1103160312Sjhb int i, j; 110436441Sphk 110536441Sphk if (!msgbufmapped) { 110636441Sphk db_printf("msgbuf not mapped yet\n"); 110736441Sphk return; 110836441Sphk } 110936441Sphk db_printf("msgbufp = %p\n", msgbufp); 1110116660Siedowse db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n", 1111116660Siedowse msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq, 1112116660Siedowse msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum); 1113160312Sjhb for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) { 1114116660Siedowse j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq); 111536441Sphk db_printf("%c", msgbufp->msg_ptr[j]); 111636441Sphk } 111736441Sphk db_printf("\n"); 111836441Sphk} 111936441Sphk 112036441Sphk#endif /* DDB */ 1121123215Sscottl 1122123215Sscottlvoid 1123144706Sphkhexdump(const void *ptr, int length, const char *hdr, int flags) 1124123215Sscottl{ 1125123215Sscottl int i, j, k; 1126123215Sscottl int cols; 1127144706Sphk const unsigned char *cp; 1128123215Sscottl char delim; 1129123215Sscottl 1130123215Sscottl if ((flags & HD_DELIM_MASK) != 0) 1131123215Sscottl delim = (flags & HD_DELIM_MASK) >> 8; 1132123215Sscottl else 1133123215Sscottl delim = ' '; 1134123215Sscottl 1135123215Sscottl if ((flags & HD_COLUMN_MASK) != 0) 1136123215Sscottl cols = flags & HD_COLUMN_MASK; 1137123215Sscottl else 1138123215Sscottl cols = 16; 1139123215Sscottl 1140123215Sscottl cp = ptr; 1141123215Sscottl for (i = 0; i < length; i+= cols) { 1142123215Sscottl if (hdr != NULL) 1143123215Sscottl printf("%s", hdr); 1144123215Sscottl 1145123215Sscottl if ((flags & HD_OMIT_COUNT) == 0) 1146123215Sscottl printf("%04x ", i); 1147123215Sscottl 1148123215Sscottl if ((flags & HD_OMIT_HEX) == 0) { 1149123215Sscottl for (j = 0; j < cols; j++) { 1150123215Sscottl k = i + j; 1151123215Sscottl if (k < length) 1152123215Sscottl printf("%c%02x", delim, cp[k]); 1153123215Sscottl else 1154123215Sscottl printf(" "); 1155123215Sscottl } 1156123215Sscottl } 1157123215Sscottl 1158123215Sscottl if ((flags & HD_OMIT_CHARS) == 0) { 1159123215Sscottl printf(" |"); 1160123215Sscottl for (j = 0; j < cols; j++) { 1161123215Sscottl k = i + j; 1162123215Sscottl if (k >= length) 1163123215Sscottl printf(" "); 1164123215Sscottl else if (cp[k] >= ' ' && cp[k] <= '~') 1165123215Sscottl printf("%c", cp[k]); 1166123215Sscottl else 1167123215Sscottl printf("."); 1168123215Sscottl } 1169156001Sscottl printf("|"); 1170123215Sscottl } 1171156001Sscottl printf("\n"); 1172123215Sscottl } 1173123215Sscottl} 1174284192Sken#endif /* _KERNEL */ 1175284192Sken 1176284192Skenvoid 1177284192Skensbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr, 1178284192Sken int flags) 1179284192Sken{ 1180284192Sken int i, j, k; 1181284192Sken int cols; 1182284192Sken const unsigned char *cp; 1183284192Sken char delim; 1184284192Sken 1185284192Sken if ((flags & HD_DELIM_MASK) != 0) 1186284192Sken delim = (flags & HD_DELIM_MASK) >> 8; 1187284192Sken else 1188284192Sken delim = ' '; 1189284192Sken 1190284192Sken if ((flags & HD_COLUMN_MASK) != 0) 1191284192Sken cols = flags & HD_COLUMN_MASK; 1192284192Sken else 1193284192Sken cols = 16; 1194284192Sken 1195284192Sken cp = ptr; 1196284192Sken for (i = 0; i < length; i+= cols) { 1197284192Sken if (hdr != NULL) 1198284192Sken sbuf_printf(sb, "%s", hdr); 1199284192Sken 1200284192Sken if ((flags & HD_OMIT_COUNT) == 0) 1201284192Sken sbuf_printf(sb, "%04x ", i); 1202284192Sken 1203284192Sken if ((flags & HD_OMIT_HEX) == 0) { 1204284192Sken for (j = 0; j < cols; j++) { 1205284192Sken k = i + j; 1206284192Sken if (k < length) 1207284192Sken sbuf_printf(sb, "%c%02x", delim, cp[k]); 1208284192Sken else 1209284192Sken sbuf_printf(sb, " "); 1210284192Sken } 1211284192Sken } 1212284192Sken 1213284192Sken if ((flags & HD_OMIT_CHARS) == 0) { 1214284192Sken sbuf_printf(sb, " |"); 1215284192Sken for (j = 0; j < cols; j++) { 1216284192Sken k = i + j; 1217284192Sken if (k >= length) 1218284192Sken sbuf_printf(sb, " "); 1219284192Sken else if (cp[k] >= ' ' && cp[k] <= '~') 1220284192Sken sbuf_printf(sb, "%c", cp[k]); 1221284192Sken else 1222284192Sken sbuf_printf(sb, "."); 1223284192Sken } 1224284192Sken sbuf_printf(sb, "|"); 1225284192Sken } 1226284192Sken sbuf_printf(sb, "\n"); 1227284192Sken } 1228284192Sken} 1229284192Sken 1230303432Skib#ifdef _KERNEL 1231303432Skibvoid 1232303432Skibcounted_warning(unsigned *counter, const char *msg) 1233303432Skib{ 1234303432Skib struct thread *td; 1235303432Skib unsigned c; 1236303432Skib 1237303432Skib for (;;) { 1238303432Skib c = *counter; 1239303432Skib if (c == 0) 1240303432Skib break; 1241303432Skib if (atomic_cmpset_int(counter, c, c - 1)) { 1242303432Skib td = curthread; 1243303432Skib log(LOG_INFO, "pid %d (%s) %s%s\n", 1244303432Skib td->td_proc->p_pid, td->td_name, msg, 1245303432Skib c > 1 ? "" : " - not logging anymore"); 1246303432Skib break; 1247303432Skib } 1248303432Skib } 1249303432Skib} 1250303432Skib#endif 1251321107Sngie 1252321107Sngie#ifdef _KERNEL 1253321107Sngievoid 1254321107Sngiesbuf_putbuf(struct sbuf *sb) 1255321107Sngie{ 1256321107Sngie 1257321107Sngie prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1); 1258321107Sngie} 1259321107Sngie#else 1260321107Sngievoid 1261321107Sngiesbuf_putbuf(struct sbuf *sb) 1262321107Sngie{ 1263321107Sngie 1264321107Sngie printf("%s", sbuf_data(sb)); 1265321107Sngie} 1266321107Sngie#endif 1267