hexdump.c revision 164033
1233237Sjkim/*- 2233237Sjkim * Copyright (c) 1986, 1988, 1991, 1993 3233237Sjkim * The Regents of the University of California. All rights reserved. 4233237Sjkim * (c) UNIX System Laboratories, Inc. 5233237Sjkim * All or some portions of this file are derived from material licensed 6233237Sjkim * to the University of California by American Telephone and Telegraph 7233237Sjkim * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8233237Sjkim * the permission of UNIX System Laboratories, Inc. 9245582Sjkim * 10233237Sjkim * Redistribution and use in source and binary forms, with or without 11233237Sjkim * modification, are permitted provided that the following conditions 12233237Sjkim * are met: 13233237Sjkim * 1. Redistributions of source code must retain the above copyright 14233237Sjkim * notice, this list of conditions and the following disclaimer. 15233237Sjkim * 2. Redistributions in binary form must reproduce the above copyright 16233237Sjkim * notice, this list of conditions and the following disclaimer in the 17233237Sjkim * documentation and/or other materials provided with the distribution. 18233237Sjkim * 4. Neither the name of the University nor the names of its contributors 19233237Sjkim * may be used to endorse or promote products derived from this software 20233237Sjkim * without specific prior written permission. 21233237Sjkim * 22233237Sjkim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23233237Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24233237Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25233237Sjkim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26233237Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27233237Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28233237Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29233237Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30233237Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31233237Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32233237Sjkim * SUCH DAMAGE. 33233237Sjkim * 34233237Sjkim * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 35233237Sjkim */ 36233237Sjkim 37233237Sjkim#include <sys/cdefs.h> 38233237Sjkim__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 164033 2006-11-06 13:42:10Z rwatson $"); 39233237Sjkim 40233237Sjkim#include "opt_ddb.h" 41233237Sjkim 42233237Sjkim#include <sys/param.h> 43233237Sjkim#include <sys/systm.h> 44233237Sjkim#include <sys/lock.h> 45233250Sjkim#include <sys/kdb.h> 46233250Sjkim#include <sys/mutex.h> 47233237Sjkim#include <sys/sx.h> 48233237Sjkim#include <sys/kernel.h> 49233237Sjkim#include <sys/msgbuf.h> 50233237Sjkim#include <sys/malloc.h> 51233237Sjkim#include <sys/priv.h> 52233237Sjkim#include <sys/proc.h> 53233237Sjkim#include <sys/stddef.h> 54233237Sjkim#include <sys/sysctl.h> 55233237Sjkim#include <sys/tty.h> 56233237Sjkim#include <sys/syslog.h> 57233237Sjkim#include <sys/cons.h> 58233237Sjkim#include <sys/uio.h> 59233237Sjkim#include <sys/ctype.h> 60233237Sjkim 61233237Sjkim#ifdef DDB 62233237Sjkim#include <ddb/ddb.h> 63233237Sjkim#endif 64233237Sjkim 65233237Sjkim/* 66233237Sjkim * Note that stdarg.h and the ANSI style va_start macro is used for both 67233237Sjkim * ANSI and traditional C compilers. 68233237Sjkim */ 69233237Sjkim#include <machine/stdarg.h> 70233237Sjkim 71233237Sjkim#define TOCONS 0x01 72233237Sjkim#define TOTTY 0x02 73233237Sjkim#define TOLOG 0x04 74233237Sjkim 75233237Sjkim/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ 76233237Sjkim#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) 77233237Sjkim 78233237Sjkimstruct putchar_arg { 79233237Sjkim int flags; 80233237Sjkim int pri; 81233237Sjkim struct tty *tty; 82233237Sjkim char *p_bufr; 83233237Sjkim size_t n_bufr; 84233237Sjkim char *p_next; 85233237Sjkim size_t remain; 86233237Sjkim}; 87233237Sjkim 88233237Sjkimstruct snprintf_arg { 89233237Sjkim char *str; 90233237Sjkim size_t remain; 91233237Sjkim}; 92233237Sjkim 93233237Sjkimextern int log_open; 94233237Sjkim 95233237Sjkimstatic void msglogchar(int c, int pri); 96233237Sjkimstatic void putchar(int ch, void *arg); 97233237Sjkimstatic char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper); 98233237Sjkimstatic void snprintf_func(int ch, void *arg); 99233237Sjkim 100233237Sjkimstatic int msgbufmapped; /* Set when safe to use msgbuf */ 101233237Sjkimint msgbuftrigger; 102233237Sjkim 103233237Sjkimstatic int log_console_output = 1; 104233237SjkimTUNABLE_INT("kern.log_console_output", &log_console_output); 105233237SjkimSYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW, 106233237Sjkim &log_console_output, 0, "Duplicate console output to the syslog."); 107233237Sjkim 108233237Sjkimstatic int always_console_output = 0; 109233237SjkimTUNABLE_INT("kern.always_console_output", &always_console_output); 110233237SjkimSYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW, 111233237Sjkim &always_console_output, 0, "Always output to console despite TIOCCONS."); 112233237Sjkim 113233237Sjkim/* 114233237Sjkim * Warn that a system table is full. 115233237Sjkim */ 116233237Sjkimvoid 117233237Sjkimtablefull(const char *tab) 118233237Sjkim{ 119233237Sjkim 120233237Sjkim log(LOG_ERR, "%s: table is full\n", tab); 121233237Sjkim} 122233237Sjkim 123233237Sjkim/* 124233237Sjkim * Uprintf prints to the controlling terminal for the current process. 125233237Sjkim */ 126233237Sjkimint 127233237Sjkimuprintf(const char *fmt, ...) 128233237Sjkim{ 129233237Sjkim struct thread *td = curthread; 130233237Sjkim struct proc *p = td->td_proc; 131233237Sjkim va_list ap; 132233237Sjkim struct putchar_arg pca; 133233237Sjkim int retval; 134233237Sjkim 135233237Sjkim if (td == NULL || td == PCPU_GET(idlethread)) 136233237Sjkim return (0); 137233237Sjkim 138233237Sjkim mtx_lock(&Giant); 139233237Sjkim p = td->td_proc; 140233237Sjkim PROC_LOCK(p); 141233237Sjkim if ((p->p_flag & P_CONTROLT) == 0) { 142233237Sjkim PROC_UNLOCK(p); 143233237Sjkim retval = 0; 144233237Sjkim goto out; 145233237Sjkim } 146233237Sjkim SESS_LOCK(p->p_session); 147233237Sjkim pca.tty = p->p_session->s_ttyp; 148233237Sjkim SESS_UNLOCK(p->p_session); 149233237Sjkim PROC_UNLOCK(p); 150233237Sjkim if (pca.tty == NULL) { 151233237Sjkim retval = 0; 152233237Sjkim goto out; 153233237Sjkim } 154233237Sjkim pca.flags = TOTTY; 155233237Sjkim va_start(ap, fmt); 156233237Sjkim retval = kvprintf(fmt, putchar, &pca, 10, ap); 157233237Sjkim va_end(ap); 158233237Sjkimout: 159233237Sjkim mtx_unlock(&Giant); 160233237Sjkim return (retval); 161233237Sjkim} 162233237Sjkim 163233237Sjkim/* 164233237Sjkim * tprintf prints on the controlling terminal associated with the given 165233237Sjkim * session, possibly to the log as well. 166233237Sjkim */ 167233237Sjkimvoid 168233237Sjkimtprintf(struct proc *p, int pri, const char *fmt, ...) 169233237Sjkim{ 170233237Sjkim struct tty *tp = NULL; 171233237Sjkim int flags = 0; 172233237Sjkim va_list ap; 173233237Sjkim struct putchar_arg pca; 174233237Sjkim struct session *sess = NULL; 175233237Sjkim 176233237Sjkim mtx_lock(&Giant); 177233237Sjkim if (pri != -1) 178233237Sjkim flags |= TOLOG; 179233237Sjkim if (p != NULL) { 180233237Sjkim PROC_LOCK(p); 181233237Sjkim if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { 182233237Sjkim sess = p->p_session; 183233237Sjkim SESS_LOCK(sess); 184233237Sjkim PROC_UNLOCK(p); 185233237Sjkim SESSHOLD(sess); 186233237Sjkim tp = sess->s_ttyp; 187233237Sjkim SESS_UNLOCK(sess); 188233237Sjkim if (ttycheckoutq(tp, 0)) 189233237Sjkim flags |= TOTTY; 190233237Sjkim else 191233237Sjkim tp = NULL; 192233237Sjkim } else 193233237Sjkim PROC_UNLOCK(p); 194233237Sjkim } 195233237Sjkim pca.pri = pri; 196233237Sjkim pca.tty = tp; 197233237Sjkim pca.flags = flags; 198233237Sjkim va_start(ap, fmt); 199233237Sjkim kvprintf(fmt, putchar, &pca, 10, ap); 200233237Sjkim va_end(ap); 201233237Sjkim if (sess != NULL) 202233237Sjkim SESSRELE(sess); 203233237Sjkim msgbuftrigger = 1; 204233237Sjkim mtx_unlock(&Giant); 205233237Sjkim} 206233237Sjkim 207233237Sjkim/* 208233237Sjkim * Ttyprintf displays a message on a tty; it should be used only by 209233237Sjkim * the tty driver, or anything that knows the underlying tty will not 210233237Sjkim * be revoke(2)'d away. Other callers should use tprintf. 211233237Sjkim */ 212233237Sjkimint 213233237Sjkimttyprintf(struct tty *tp, const char *fmt, ...) 214233237Sjkim{ 215233237Sjkim va_list ap; 216233237Sjkim struct putchar_arg pca; 217233237Sjkim int retval; 218233237Sjkim 219233237Sjkim va_start(ap, fmt); 220233237Sjkim pca.tty = tp; 221233237Sjkim pca.flags = TOTTY; 222233237Sjkim retval = kvprintf(fmt, putchar, &pca, 10, ap); 223233237Sjkim va_end(ap); 224233237Sjkim return (retval); 225233237Sjkim} 226233237Sjkim 227233237Sjkim/* 228233237Sjkim * Log writes to the log buffer, and guarantees not to sleep (so can be 229233237Sjkim * called by interrupt routines). If there is no process reading the 230233237Sjkim * log yet, it writes to the console also. 231233237Sjkim */ 232233237Sjkimvoid 233233237Sjkimlog(int level, const char *fmt, ...) 234233237Sjkim{ 235233237Sjkim va_list ap; 236233237Sjkim struct putchar_arg pca; 237233237Sjkim 238233237Sjkim pca.tty = NULL; 239233237Sjkim pca.pri = level; 240233237Sjkim pca.flags = log_open ? TOLOG : TOCONS; 241233237Sjkim pca.p_bufr = NULL; 242233237Sjkim 243233237Sjkim va_start(ap, fmt); 244233237Sjkim kvprintf(fmt, putchar, &pca, 10, ap); 245233237Sjkim va_end(ap); 246233237Sjkim 247233237Sjkim msgbuftrigger = 1; 248233237Sjkim} 249233237Sjkim 250233237Sjkim#define CONSCHUNK 128 251233237Sjkim 252233237Sjkimvoid 253233237Sjkimlog_console(struct uio *uio) 254233237Sjkim{ 255233237Sjkim int c, i, error, nl; 256233237Sjkim char *consbuffer; 257233237Sjkim int pri; 258233237Sjkim 259233237Sjkim if (!log_console_output) 260233237Sjkim return; 261233237Sjkim 262233237Sjkim pri = LOG_INFO | LOG_CONSOLE; 263233237Sjkim uio = cloneuio(uio); 264233237Sjkim consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK); 265233237Sjkim 266233237Sjkim nl = 0; 267233237Sjkim while (uio->uio_resid > 0) { 268233237Sjkim c = imin(uio->uio_resid, CONSCHUNK); 269233237Sjkim error = uiomove(consbuffer, c, uio); 270233237Sjkim if (error != 0) 271233237Sjkim break; 272233237Sjkim for (i = 0; i < c; i++) { 273233237Sjkim msglogchar(consbuffer[i], pri); 274233237Sjkim if (consbuffer[i] == '\n') 275233237Sjkim nl = 1; 276233237Sjkim else 277233237Sjkim nl = 0; 278233237Sjkim } 279233237Sjkim } 280233237Sjkim if (!nl) 281233237Sjkim msglogchar('\n', pri); 282233237Sjkim msgbuftrigger = 1; 283233237Sjkim free(uio, M_IOV); 284233237Sjkim free(consbuffer, M_TEMP); 285 return; 286} 287 288int 289printf(const char *fmt, ...) 290{ 291 va_list ap; 292 struct putchar_arg pca; 293 int retval; 294 295 critical_enter(); 296 297 va_start(ap, fmt); 298 pca.tty = NULL; 299 pca.flags = TOCONS | TOLOG; 300 pca.pri = -1; 301 pca.p_bufr = (char *) PCPU_PTR(cons_bufr); 302 pca.p_next = pca.p_bufr; 303 pca.n_bufr = PCPU_CONS_BUFR; 304 pca.remain = PCPU_CONS_BUFR; 305 *pca.p_next = '\0'; 306 307 retval = kvprintf(fmt, putchar, &pca, 10, ap); 308 va_end(ap); 309 310 /* Write any buffered console output: */ 311 if (*pca.p_bufr != '\0') 312 cnputs(pca.p_bufr); 313 314 if (!panicstr) 315 msgbuftrigger = 1; 316 317 critical_exit(); 318 319 return (retval); 320} 321 322int 323vprintf(const char *fmt, va_list ap) 324{ 325 struct putchar_arg pca; 326 int retval; 327 328 critical_enter(); 329 330 pca.tty = NULL; 331 pca.flags = TOCONS | TOLOG; 332 pca.pri = -1; 333 pca.p_bufr = (char *) PCPU_PTR(cons_bufr); 334 pca.p_next = pca.p_bufr; 335 pca.n_bufr = PCPU_CONS_BUFR; 336 pca.remain = PCPU_CONS_BUFR; 337 *pca.p_next = '\0'; 338 339 retval = kvprintf(fmt, putchar, &pca, 10, ap); 340 341 /* Write any buffered console output: */ 342 if (*pca.p_bufr != '\0') 343 cnputs(pca.p_bufr); 344 345 if (!panicstr) 346 msgbuftrigger = 1; 347 348 critical_exit(); 349 350 return (retval); 351} 352 353static void 354putcons(int c, struct putchar_arg *ap) 355{ 356 /* Check if no console output buffer was provided. */ 357 if (ap->p_bufr == NULL) 358 /* Output direct to the console. */ 359 cnputc(c); 360 else { 361 /* Buffer the character: */ 362 if (c == '\n') { 363 *ap->p_next++ = '\r'; 364 ap->remain--; 365 } 366 *ap->p_next++ = c; 367 ap->remain--; 368 369 /* Always leave the buffer zero terminated. */ 370 *ap->p_next = '\0'; 371 372 /* Check if the buffer needs to be flushed. */ 373 if (ap->remain < 3 || c == '\n') { 374 cnputs(ap->p_bufr); 375 ap->p_next = ap->p_bufr; 376 ap->remain = ap->n_bufr; 377 *ap->p_next = '\0'; 378 } 379 } 380} 381 382/* 383 * Print a character on console or users terminal. If destination is 384 * the console then the last bunch of characters are saved in msgbuf for 385 * inspection later. 386 */ 387static void 388putchar(int c, void *arg) 389{ 390 struct putchar_arg *ap = (struct putchar_arg*) arg; 391 struct tty *tp = ap->tty; 392 int flags = ap->flags; 393 394 /* Don't use the tty code after a panic or while in ddb. */ 395 if (kdb_active) { 396 if (c != '\0') 397 cnputc(c); 398 } else if (panicstr || ((flags & TOCONS) && constty == NULL)) { 399 if (c != '\0') 400 putcons(c, ap); 401 } else { 402 if ((flags & TOTTY) && tp != NULL) 403 tputchar(c, tp); 404 if (flags & TOCONS) { 405 if (constty != NULL) 406 msgbuf_addchar(&consmsgbuf, c); 407 if (always_console_output && c != '\0') 408 putcons(c, ap); 409 } 410 } 411 if ((flags & TOLOG)) 412 msglogchar(c, ap->pri); 413} 414 415/* 416 * Scaled down version of sprintf(3). 417 */ 418int 419sprintf(char *buf, const char *cfmt, ...) 420{ 421 int retval; 422 va_list ap; 423 424 va_start(ap, cfmt); 425 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 426 buf[retval] = '\0'; 427 va_end(ap); 428 return (retval); 429} 430 431/* 432 * Scaled down version of vsprintf(3). 433 */ 434int 435vsprintf(char *buf, const char *cfmt, va_list ap) 436{ 437 int retval; 438 439 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 440 buf[retval] = '\0'; 441 return (retval); 442} 443 444/* 445 * Scaled down version of snprintf(3). 446 */ 447int 448snprintf(char *str, size_t size, const char *format, ...) 449{ 450 int retval; 451 va_list ap; 452 453 va_start(ap, format); 454 retval = vsnprintf(str, size, format, ap); 455 va_end(ap); 456 return(retval); 457} 458 459/* 460 * Scaled down version of vsnprintf(3). 461 */ 462int 463vsnprintf(char *str, size_t size, const char *format, va_list ap) 464{ 465 struct snprintf_arg info; 466 int retval; 467 468 info.str = str; 469 info.remain = size; 470 retval = kvprintf(format, snprintf_func, &info, 10, ap); 471 if (info.remain >= 1) 472 *info.str++ = '\0'; 473 return (retval); 474} 475 476/* 477 * Kernel version which takes radix argument vsnprintf(3). 478 */ 479int 480vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap) 481{ 482 struct snprintf_arg info; 483 int retval; 484 485 info.str = str; 486 info.remain = size; 487 retval = kvprintf(format, snprintf_func, &info, radix, ap); 488 if (info.remain >= 1) 489 *info.str++ = '\0'; 490 return (retval); 491} 492 493static void 494snprintf_func(int ch, void *arg) 495{ 496 struct snprintf_arg *const info = arg; 497 498 if (info->remain >= 2) { 499 *info->str++ = ch; 500 info->remain--; 501 } 502} 503 504/* 505 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 506 * order; return an optional length and a pointer to the last character 507 * written in the buffer (i.e., the first character of the string). 508 * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 509 */ 510static char * 511ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 512{ 513 char *p, c; 514 515 p = nbuf; 516 *p = '\0'; 517 do { 518 c = hex2ascii(num % base); 519 *++p = upper ? toupper(c) : c; 520 } while (num /= base); 521 if (lenp) 522 *lenp = p - nbuf; 523 return (p); 524} 525 526/* 527 * Scaled down version of printf(3). 528 * 529 * Two additional formats: 530 * 531 * The format %b is supported to decode error registers. 532 * Its usage is: 533 * 534 * printf("reg=%b\n", regval, "<base><arg>*"); 535 * 536 * where <base> is the output base expressed as a control character, e.g. 537 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 538 * the first of which gives the bit number to be inspected (origin 1), and 539 * the next characters (up to a control character, i.e. a character <= 32), 540 * give the name of the register. Thus: 541 * 542 * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 543 * 544 * would produce output: 545 * 546 * reg=3<BITTWO,BITONE> 547 * 548 * XXX: %D -- Hexdump, takes pointer and separator string: 549 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 550 * ("%*D", len, ptr, " " -> XX XX XX XX ... 551 */ 552int 553kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) 554{ 555#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } 556 char nbuf[MAXNBUF]; 557 char *d; 558 const char *p, *percent, *q; 559 u_char *up; 560 int ch, n; 561 uintmax_t num; 562 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 563 int cflag, hflag, jflag, tflag, zflag; 564 int dwidth, upper; 565 char padc; 566 int stop = 0, retval = 0; 567 568 num = 0; 569 if (!func) 570 d = (char *) arg; 571 else 572 d = NULL; 573 574 if (fmt == NULL) 575 fmt = "(fmt null)\n"; 576 577 if (radix < 2 || radix > 36) 578 radix = 10; 579 580 for (;;) { 581 padc = ' '; 582 width = 0; 583 while ((ch = (u_char)*fmt++) != '%' || stop) { 584 if (ch == '\0') 585 return (retval); 586 PCHAR(ch); 587 } 588 percent = fmt - 1; 589 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 590 sign = 0; dot = 0; dwidth = 0; upper = 0; 591 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 592reswitch: switch (ch = (u_char)*fmt++) { 593 case '.': 594 dot = 1; 595 goto reswitch; 596 case '#': 597 sharpflag = 1; 598 goto reswitch; 599 case '+': 600 sign = 1; 601 goto reswitch; 602 case '-': 603 ladjust = 1; 604 goto reswitch; 605 case '%': 606 PCHAR(ch); 607 break; 608 case '*': 609 if (!dot) { 610 width = va_arg(ap, int); 611 if (width < 0) { 612 ladjust = !ladjust; 613 width = -width; 614 } 615 } else { 616 dwidth = va_arg(ap, int); 617 } 618 goto reswitch; 619 case '0': 620 if (!dot) { 621 padc = '0'; 622 goto reswitch; 623 } 624 case '1': case '2': case '3': case '4': 625 case '5': case '6': case '7': case '8': case '9': 626 for (n = 0;; ++fmt) { 627 n = n * 10 + ch - '0'; 628 ch = *fmt; 629 if (ch < '0' || ch > '9') 630 break; 631 } 632 if (dot) 633 dwidth = n; 634 else 635 width = n; 636 goto reswitch; 637 case 'b': 638 num = (u_int)va_arg(ap, int); 639 p = va_arg(ap, char *); 640 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 641 PCHAR(*q--); 642 643 if (num == 0) 644 break; 645 646 for (tmp = 0; *p;) { 647 n = *p++; 648 if (num & (1 << (n - 1))) { 649 PCHAR(tmp ? ',' : '<'); 650 for (; (n = *p) > ' '; ++p) 651 PCHAR(n); 652 tmp = 1; 653 } else 654 for (; *p > ' '; ++p) 655 continue; 656 } 657 if (tmp) 658 PCHAR('>'); 659 break; 660 case 'c': 661 PCHAR(va_arg(ap, int)); 662 break; 663 case 'D': 664 up = va_arg(ap, u_char *); 665 p = va_arg(ap, char *); 666 if (!width) 667 width = 16; 668 while(width--) { 669 PCHAR(hex2ascii(*up >> 4)); 670 PCHAR(hex2ascii(*up & 0x0f)); 671 up++; 672 if (width) 673 for (q=p;*q;q++) 674 PCHAR(*q); 675 } 676 break; 677 case 'd': 678 case 'i': 679 base = 10; 680 sign = 1; 681 goto handle_sign; 682 case 'h': 683 if (hflag) { 684 hflag = 0; 685 cflag = 1; 686 } else 687 hflag = 1; 688 goto reswitch; 689 case 'j': 690 jflag = 1; 691 goto reswitch; 692 case 'l': 693 if (lflag) { 694 lflag = 0; 695 qflag = 1; 696 } else 697 lflag = 1; 698 goto reswitch; 699 case 'n': 700 if (jflag) 701 *(va_arg(ap, intmax_t *)) = retval; 702 else if (qflag) 703 *(va_arg(ap, quad_t *)) = retval; 704 else if (lflag) 705 *(va_arg(ap, long *)) = retval; 706 else if (zflag) 707 *(va_arg(ap, size_t *)) = retval; 708 else if (hflag) 709 *(va_arg(ap, short *)) = retval; 710 else if (cflag) 711 *(va_arg(ap, char *)) = retval; 712 else 713 *(va_arg(ap, int *)) = retval; 714 break; 715 case 'o': 716 base = 8; 717 goto handle_nosign; 718 case 'p': 719 base = 16; 720 sharpflag = (width == 0); 721 sign = 0; 722 num = (uintptr_t)va_arg(ap, void *); 723 goto number; 724 case 'q': 725 qflag = 1; 726 goto reswitch; 727 case 'r': 728 base = radix; 729 if (sign) 730 goto handle_sign; 731 goto handle_nosign; 732 case 's': 733 p = va_arg(ap, char *); 734 if (p == NULL) 735 p = "(null)"; 736 if (!dot) 737 n = strlen (p); 738 else 739 for (n = 0; n < dwidth && p[n]; n++) 740 continue; 741 742 width -= n; 743 744 if (!ladjust && width > 0) 745 while (width--) 746 PCHAR(padc); 747 while (n--) 748 PCHAR(*p++); 749 if (ladjust && width > 0) 750 while (width--) 751 PCHAR(padc); 752 break; 753 case 't': 754 tflag = 1; 755 goto reswitch; 756 case 'u': 757 base = 10; 758 goto handle_nosign; 759 case 'X': 760 upper = 1; 761 case 'x': 762 base = 16; 763 goto handle_nosign; 764 case 'y': 765 base = 16; 766 sign = 1; 767 goto handle_sign; 768 case 'z': 769 zflag = 1; 770 goto reswitch; 771handle_nosign: 772 sign = 0; 773 if (jflag) 774 num = va_arg(ap, uintmax_t); 775 else if (qflag) 776 num = va_arg(ap, u_quad_t); 777 else if (tflag) 778 num = va_arg(ap, ptrdiff_t); 779 else if (lflag) 780 num = va_arg(ap, u_long); 781 else if (zflag) 782 num = va_arg(ap, size_t); 783 else if (hflag) 784 num = (u_short)va_arg(ap, int); 785 else if (cflag) 786 num = (u_char)va_arg(ap, int); 787 else 788 num = va_arg(ap, u_int); 789 goto number; 790handle_sign: 791 if (jflag) 792 num = va_arg(ap, intmax_t); 793 else if (qflag) 794 num = va_arg(ap, quad_t); 795 else if (tflag) 796 num = va_arg(ap, ptrdiff_t); 797 else if (lflag) 798 num = va_arg(ap, long); 799 else if (zflag) 800 num = va_arg(ap, size_t); 801 else if (hflag) 802 num = (short)va_arg(ap, int); 803 else if (cflag) 804 num = (char)va_arg(ap, int); 805 else 806 num = va_arg(ap, int); 807number: 808 if (sign && (intmax_t)num < 0) { 809 neg = 1; 810 num = -(intmax_t)num; 811 } 812 p = ksprintn(nbuf, num, base, &tmp, upper); 813 if (sharpflag && num != 0) { 814 if (base == 8) 815 tmp++; 816 else if (base == 16) 817 tmp += 2; 818 } 819 if (neg) 820 tmp++; 821 822 if (!ladjust && padc != '0' && width 823 && (width -= tmp) > 0) 824 while (width--) 825 PCHAR(padc); 826 if (neg) 827 PCHAR('-'); 828 if (sharpflag && num != 0) { 829 if (base == 8) { 830 PCHAR('0'); 831 } else if (base == 16) { 832 PCHAR('0'); 833 PCHAR('x'); 834 } 835 } 836 if (!ladjust && width && (width -= tmp) > 0) 837 while (width--) 838 PCHAR(padc); 839 840 while (*p) 841 PCHAR(*p--); 842 843 if (ladjust && width && (width -= tmp) > 0) 844 while (width--) 845 PCHAR(padc); 846 847 break; 848 default: 849 while (percent < fmt) 850 PCHAR(*percent++); 851 /* 852 * Since we ignore an formatting argument it is no 853 * longer safe to obey the remaining formatting 854 * arguments as the arguments will no longer match 855 * the format specs. 856 */ 857 stop = 1; 858 break; 859 } 860 } 861#undef PCHAR 862} 863 864/* 865 * Put character in log buffer with a particular priority. 866 */ 867static void 868msglogchar(int c, int pri) 869{ 870 static int lastpri = -1; 871 static int dangling; 872 char nbuf[MAXNBUF]; 873 char *p; 874 875 if (!msgbufmapped) 876 return; 877 if (c == '\0' || c == '\r') 878 return; 879 if (pri != -1 && pri != lastpri) { 880 if (dangling) { 881 msgbuf_addchar(msgbufp, '\n'); 882 dangling = 0; 883 } 884 msgbuf_addchar(msgbufp, '<'); 885 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;) 886 msgbuf_addchar(msgbufp, *p--); 887 msgbuf_addchar(msgbufp, '>'); 888 lastpri = pri; 889 } 890 msgbuf_addchar(msgbufp, c); 891 if (c == '\n') { 892 dangling = 0; 893 lastpri = -1; 894 } else { 895 dangling = 1; 896 } 897} 898 899void 900msgbufinit(void *ptr, int size) 901{ 902 char *cp; 903 static struct msgbuf *oldp = NULL; 904 905 size -= sizeof(*msgbufp); 906 cp = (char *)ptr; 907 msgbufp = (struct msgbuf *)(cp + size); 908 msgbuf_reinit(msgbufp, cp, size); 909 if (msgbufmapped && oldp != msgbufp) 910 msgbuf_copy(oldp, msgbufp); 911 msgbufmapped = 1; 912 oldp = msgbufp; 913} 914 915static int unprivileged_read_msgbuf = 1; 916SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf, 917 CTLFLAG_RW, &unprivileged_read_msgbuf, 0, 918 "Unprivileged processes may read the kernel message buffer"); 919 920/* Sysctls for accessing/clearing the msgbuf */ 921static int 922sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) 923{ 924 char buf[128]; 925 u_int seq; 926 int error, len; 927 928 if (!unprivileged_read_msgbuf) { 929 error = priv_check(req->td, PRIV_MSGBUF); 930 if (error) 931 return (error); 932 } 933 934 /* Read the whole buffer, one chunk at a time. */ 935 msgbuf_peekbytes(msgbufp, NULL, 0, &seq); 936 while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) { 937 error = sysctl_handle_opaque(oidp, buf, len, req); 938 if (error) 939 return (error); 940 } 941 return (0); 942} 943 944SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD, 945 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); 946 947static int msgbuf_clearflag; 948 949static int 950sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) 951{ 952 int error; 953 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); 954 if (!error && req->newptr) { 955 msgbuf_clear(msgbufp); 956 msgbuf_clearflag = 0; 957 } 958 return (error); 959} 960 961SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, 962 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0, 963 sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer"); 964 965#ifdef DDB 966 967DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) 968{ 969 int i, j; 970 971 if (!msgbufmapped) { 972 db_printf("msgbuf not mapped yet\n"); 973 return; 974 } 975 db_printf("msgbufp = %p\n", msgbufp); 976 db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n", 977 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq, 978 msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum); 979 for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) { 980 j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq); 981 db_printf("%c", msgbufp->msg_ptr[j]); 982 } 983 db_printf("\n"); 984} 985 986#endif /* DDB */ 987 988void 989hexdump(const void *ptr, int length, const char *hdr, int flags) 990{ 991 int i, j, k; 992 int cols; 993 const unsigned char *cp; 994 char delim; 995 996 if ((flags & HD_DELIM_MASK) != 0) 997 delim = (flags & HD_DELIM_MASK) >> 8; 998 else 999 delim = ' '; 1000 1001 if ((flags & HD_COLUMN_MASK) != 0) 1002 cols = flags & HD_COLUMN_MASK; 1003 else 1004 cols = 16; 1005 1006 cp = ptr; 1007 for (i = 0; i < length; i+= cols) { 1008 if (hdr != NULL) 1009 printf("%s", hdr); 1010 1011 if ((flags & HD_OMIT_COUNT) == 0) 1012 printf("%04x ", i); 1013 1014 if ((flags & HD_OMIT_HEX) == 0) { 1015 for (j = 0; j < cols; j++) { 1016 k = i + j; 1017 if (k < length) 1018 printf("%c%02x", delim, cp[k]); 1019 else 1020 printf(" "); 1021 } 1022 } 1023 1024 if ((flags & HD_OMIT_CHARS) == 0) { 1025 printf(" |"); 1026 for (j = 0; j < cols; j++) { 1027 k = i + j; 1028 if (k >= length) 1029 printf(" "); 1030 else if (cp[k] >= ' ' && cp[k] <= '~') 1031 printf("%c", cp[k]); 1032 else 1033 printf("."); 1034 } 1035 printf("|"); 1036 } 1037 printf("\n"); 1038 } 1039} 1040 1041