FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_prf.c
1 /*-
2 * Copyright (c) 1986, 1988, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
35 */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD: releng/11.2/sys/kern/subr_prf.c 331722 2018-03-29 02:50:57Z eadler $");
39
40 #ifdef _KERNEL
41 #include "opt_ddb.h"
42 #include "opt_printf.h"
43 #endif /* _KERNEL */
44
45 #include <sys/param.h>
46 #ifdef _KERNEL
47 #include <sys/systm.h>
48 #include <sys/lock.h>
49 #include <sys/kdb.h>
50 #include <sys/mutex.h>
51 #include <sys/sx.h>
52 #include <sys/kernel.h>
53 #include <sys/msgbuf.h>
54 #include <sys/malloc.h>
55 #include <sys/priv.h>
56 #include <sys/proc.h>
57 #include <sys/stddef.h>
58 #include <sys/sysctl.h>
59 #include <sys/tty.h>
60 #include <sys/syslog.h>
61 #include <sys/cons.h>
62 #include <sys/uio.h>
63 #endif
64 #include <sys/ctype.h>
65 #include <sys/sbuf.h>
66
67 #ifdef DDB
68 #include <ddb/ddb.h>
69 #endif
70
71 /*
72 * Note that stdarg.h and the ANSI style va_start macro is used for both
73 * ANSI and traditional C compilers.
74 */
75 #ifdef _KERNEL
76 #include <machine/stdarg.h>
77 #else
78 #include <stdarg.h>
79 #endif
80
81 /*
82 * This is needed for sbuf_putbuf() when compiled into userland. Due to the
83 * shared nature of this file, it's the only place to put it.
84 */
85 #ifndef _KERNEL
86 #include <stdio.h>
87 #endif
88
89 #ifdef _KERNEL
90
91 #define TOCONS 0x01
92 #define TOTTY 0x02
93 #define TOLOG 0x04
94
95 /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
96 #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
97
98 struct putchar_arg {
99 int flags;
100 int pri;
101 struct tty *tty;
102 char *p_bufr;
103 size_t n_bufr;
104 char *p_next;
105 size_t remain;
106 };
107
108 struct snprintf_arg {
109 char *str;
110 size_t remain;
111 };
112
113 extern int log_open;
114
115 static void msglogchar(int c, int pri);
116 static void msglogstr(char *str, int pri, int filter_cr);
117 static void putchar(int ch, void *arg);
118 static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
119 static void snprintf_func(int ch, void *arg);
120
121 static int msgbufmapped; /* Set when safe to use msgbuf */
122 int msgbuftrigger;
123
124 static int log_console_output = 1;
125 SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RWTUN,
126 &log_console_output, 0, "Duplicate console output to the syslog");
127
128 /*
129 * See the comment in log_console() below for more explanation of this.
130 */
131 static int log_console_add_linefeed;
132 SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RWTUN,
133 &log_console_add_linefeed, 0, "log_console() adds extra newlines");
134
135 static int always_console_output;
136 SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RWTUN,
137 &always_console_output, 0, "Always output to console despite TIOCCONS");
138
139 /*
140 * Warn that a system table is full.
141 */
142 void
143 tablefull(const char *tab)
144 {
145
146 log(LOG_ERR, "%s: table is full\n", tab);
147 }
148
149 /*
150 * Uprintf prints to the controlling terminal for the current process.
151 */
152 int
153 uprintf(const char *fmt, ...)
154 {
155 va_list ap;
156 struct putchar_arg pca;
157 struct proc *p;
158 struct thread *td;
159 int retval;
160
161 td = curthread;
162 if (TD_IS_IDLETHREAD(td))
163 return (0);
164
165 sx_slock(&proctree_lock);
166 p = td->td_proc;
167 PROC_LOCK(p);
168 if ((p->p_flag & P_CONTROLT) == 0) {
169 PROC_UNLOCK(p);
170 sx_sunlock(&proctree_lock);
171 return (0);
172 }
173 SESS_LOCK(p->p_session);
174 pca.tty = p->p_session->s_ttyp;
175 SESS_UNLOCK(p->p_session);
176 PROC_UNLOCK(p);
177 if (pca.tty == NULL) {
178 sx_sunlock(&proctree_lock);
179 return (0);
180 }
181 pca.flags = TOTTY;
182 pca.p_bufr = NULL;
183 va_start(ap, fmt);
184 tty_lock(pca.tty);
185 sx_sunlock(&proctree_lock);
186 retval = kvprintf(fmt, putchar, &pca, 10, ap);
187 tty_unlock(pca.tty);
188 va_end(ap);
189 return (retval);
190 }
191
192 /*
193 * tprintf and vtprintf print on the controlling terminal associated with the
194 * given session, possibly to the log as well.
195 */
196 void
197 tprintf(struct proc *p, int pri, const char *fmt, ...)
198 {
199 va_list ap;
200
201 va_start(ap, fmt);
202 vtprintf(p, pri, fmt, ap);
203 va_end(ap);
204 }
205
206 void
207 vtprintf(struct proc *p, int pri, const char *fmt, va_list ap)
208 {
209 struct tty *tp = NULL;
210 int flags = 0;
211 struct putchar_arg pca;
212 struct session *sess = NULL;
213
214 sx_slock(&proctree_lock);
215 if (pri != -1)
216 flags |= TOLOG;
217 if (p != NULL) {
218 PROC_LOCK(p);
219 if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
220 sess = p->p_session;
221 sess_hold(sess);
222 PROC_UNLOCK(p);
223 tp = sess->s_ttyp;
224 if (tp != NULL && tty_checkoutq(tp))
225 flags |= TOTTY;
226 else
227 tp = NULL;
228 } else
229 PROC_UNLOCK(p);
230 }
231 pca.pri = pri;
232 pca.tty = tp;
233 pca.flags = flags;
234 pca.p_bufr = NULL;
235 if (pca.tty != NULL)
236 tty_lock(pca.tty);
237 sx_sunlock(&proctree_lock);
238 kvprintf(fmt, putchar, &pca, 10, ap);
239 if (pca.tty != NULL)
240 tty_unlock(pca.tty);
241 if (sess != NULL)
242 sess_release(sess);
243 msgbuftrigger = 1;
244 }
245
246 /*
247 * Ttyprintf displays a message on a tty; it should be used only by
248 * the tty driver, or anything that knows the underlying tty will not
249 * be revoke(2)'d away. Other callers should use tprintf.
250 */
251 int
252 ttyprintf(struct tty *tp, const char *fmt, ...)
253 {
254 va_list ap;
255 struct putchar_arg pca;
256 int retval;
257
258 va_start(ap, fmt);
259 pca.tty = tp;
260 pca.flags = TOTTY;
261 pca.p_bufr = NULL;
262 retval = kvprintf(fmt, putchar, &pca, 10, ap);
263 va_end(ap);
264 return (retval);
265 }
266
267 static int
268 _vprintf(int level, int flags, const char *fmt, va_list ap)
269 {
270 struct putchar_arg pca;
271 int retval;
272 #ifdef PRINTF_BUFR_SIZE
273 char bufr[PRINTF_BUFR_SIZE];
274 #endif
275
276 pca.tty = NULL;
277 pca.pri = level;
278 pca.flags = flags;
279 #ifdef PRINTF_BUFR_SIZE
280 pca.p_bufr = bufr;
281 pca.p_next = pca.p_bufr;
282 pca.n_bufr = sizeof(bufr);
283 pca.remain = sizeof(bufr);
284 *pca.p_next = '\0';
285 #else
286 /* Don't buffer console output. */
287 pca.p_bufr = NULL;
288 #endif
289
290 retval = kvprintf(fmt, putchar, &pca, 10, ap);
291
292 #ifdef PRINTF_BUFR_SIZE
293 /* Write any buffered console/log output: */
294 if (*pca.p_bufr != '\0') {
295 if (pca.flags & TOLOG)
296 msglogstr(pca.p_bufr, level, /*filter_cr*/1);
297
298 if (pca.flags & TOCONS)
299 cnputs(pca.p_bufr);
300 }
301 #endif
302
303 return (retval);
304 }
305
306 /*
307 * Log writes to the log buffer, and guarantees not to sleep (so can be
308 * called by interrupt routines). If there is no process reading the
309 * log yet, it writes to the console also.
310 */
311 void
312 log(int level, const char *fmt, ...)
313 {
314 va_list ap;
315
316 va_start(ap, fmt);
317 vlog(level, fmt, ap);
318 va_end(ap);
319 }
320
321 void
322 vlog(int level, const char *fmt, va_list ap)
323 {
324
325 (void)_vprintf(level, log_open ? TOLOG : TOCONS | TOLOG, fmt, ap);
326 msgbuftrigger = 1;
327 }
328
329 #define CONSCHUNK 128
330
331 void
332 log_console(struct uio *uio)
333 {
334 int c, error, nl;
335 char *consbuffer;
336 int pri;
337
338 if (!log_console_output)
339 return;
340
341 pri = LOG_INFO | LOG_CONSOLE;
342 uio = cloneuio(uio);
343 consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK);
344
345 nl = 0;
346 while (uio->uio_resid > 0) {
347 c = imin(uio->uio_resid, CONSCHUNK - 1);
348 error = uiomove(consbuffer, c, uio);
349 if (error != 0)
350 break;
351 /* Make sure we're NUL-terminated */
352 consbuffer[c] = '\0';
353 if (consbuffer[c - 1] == '\n')
354 nl = 1;
355 else
356 nl = 0;
357 msglogstr(consbuffer, pri, /*filter_cr*/ 1);
358 }
359 /*
360 * The previous behavior in log_console() is preserved when
361 * log_console_add_linefeed is non-zero. For that behavior, if an
362 * individual console write came in that was not terminated with a
363 * line feed, it would add a line feed.
364 *
365 * This results in different data in the message buffer than
366 * appears on the system console (which doesn't add extra line feed
367 * characters).
368 *
369 * A number of programs and rc scripts write a line feed, or a period
370 * and a line feed when they have completed their operation. On
371 * the console, this looks seamless, but when displayed with
372 * 'dmesg -a', you wind up with output that looks like this:
373 *
374 * Updating motd:
375 * .
376 *
377 * On the console, it looks like this:
378 * Updating motd:.
379 *
380 * We could add logic to detect that situation, or just not insert
381 * the extra newlines. Set the kern.log_console_add_linefeed
382 * sysctl/tunable variable to get the old behavior.
383 */
384 if (!nl && log_console_add_linefeed) {
385 consbuffer[0] = '\n';
386 consbuffer[1] = '\0';
387 msglogstr(consbuffer, pri, /*filter_cr*/ 1);
388 }
389 msgbuftrigger = 1;
390 free(uio, M_IOV);
391 free(consbuffer, M_TEMP);
392 }
393
394 int
395 printf(const char *fmt, ...)
396 {
397 va_list ap;
398 int retval;
399
400 va_start(ap, fmt);
401 retval = vprintf(fmt, ap);
402 va_end(ap);
403
404 return (retval);
405 }
406
407 int
408 vprintf(const char *fmt, va_list ap)
409 {
410 int retval;
411
412 retval = _vprintf(-1, TOCONS | TOLOG, fmt, ap);
413
414 if (!panicstr)
415 msgbuftrigger = 1;
416
417 return (retval);
418 }
419
420 static void
421 prf_putbuf(char *bufr, int flags, int pri)
422 {
423
424 if (flags & TOLOG)
425 msglogstr(bufr, pri, /*filter_cr*/1);
426
427 if (flags & TOCONS) {
428 if ((panicstr == NULL) && (constty != NULL))
429 msgbuf_addstr(&consmsgbuf, -1,
430 bufr, /*filter_cr*/ 0);
431
432 if ((constty == NULL) ||(always_console_output))
433 cnputs(bufr);
434 }
435 }
436
437 static void
438 putbuf(int c, struct putchar_arg *ap)
439 {
440 /* Check if no console output buffer was provided. */
441 if (ap->p_bufr == NULL) {
442 /* Output direct to the console. */
443 if (ap->flags & TOCONS)
444 cnputc(c);
445
446 if (ap->flags & TOLOG)
447 msglogchar(c, ap->pri);
448 } else {
449 /* Buffer the character: */
450 *ap->p_next++ = c;
451 ap->remain--;
452
453 /* Always leave the buffer zero terminated. */
454 *ap->p_next = '\0';
455
456 /* Check if the buffer needs to be flushed. */
457 if (ap->remain == 2 || c == '\n') {
458 prf_putbuf(ap->p_bufr, ap->flags, ap->pri);
459
460 ap->p_next = ap->p_bufr;
461 ap->remain = ap->n_bufr;
462 *ap->p_next = '\0';
463 }
464
465 /*
466 * Since we fill the buffer up one character at a time,
467 * this should not happen. We should always catch it when
468 * ap->remain == 2 (if not sooner due to a newline), flush
469 * the buffer and move on. One way this could happen is
470 * if someone sets PRINTF_BUFR_SIZE to 1 or something
471 * similarly silly.
472 */
473 KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
474 ap->remain));
475 }
476 }
477
478 /*
479 * Print a character on console or users terminal. If destination is
480 * the console then the last bunch of characters are saved in msgbuf for
481 * inspection later.
482 */
483 static void
484 putchar(int c, void *arg)
485 {
486 struct putchar_arg *ap = (struct putchar_arg*) arg;
487 struct tty *tp = ap->tty;
488 int flags = ap->flags;
489
490 /* Don't use the tty code after a panic or while in ddb. */
491 if (kdb_active) {
492 if (c != '\0')
493 cnputc(c);
494 return;
495 }
496
497 if ((flags & TOTTY) && tp != NULL && panicstr == NULL)
498 tty_putchar(tp, c);
499
500 if ((flags & (TOCONS | TOLOG)) && c != '\0')
501 putbuf(c, ap);
502 }
503
504 /*
505 * Scaled down version of sprintf(3).
506 */
507 int
508 sprintf(char *buf, const char *cfmt, ...)
509 {
510 int retval;
511 va_list ap;
512
513 va_start(ap, cfmt);
514 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
515 buf[retval] = '\0';
516 va_end(ap);
517 return (retval);
518 }
519
520 /*
521 * Scaled down version of vsprintf(3).
522 */
523 int
524 vsprintf(char *buf, const char *cfmt, va_list ap)
525 {
526 int retval;
527
528 retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
529 buf[retval] = '\0';
530 return (retval);
531 }
532
533 /*
534 * Scaled down version of snprintf(3).
535 */
536 int
537 snprintf(char *str, size_t size, const char *format, ...)
538 {
539 int retval;
540 va_list ap;
541
542 va_start(ap, format);
543 retval = vsnprintf(str, size, format, ap);
544 va_end(ap);
545 return(retval);
546 }
547
548 /*
549 * Scaled down version of vsnprintf(3).
550 */
551 int
552 vsnprintf(char *str, size_t size, const char *format, va_list ap)
553 {
554 struct snprintf_arg info;
555 int retval;
556
557 info.str = str;
558 info.remain = size;
559 retval = kvprintf(format, snprintf_func, &info, 10, ap);
560 if (info.remain >= 1)
561 *info.str++ = '\0';
562 return (retval);
563 }
564
565 /*
566 * Kernel version which takes radix argument vsnprintf(3).
567 */
568 int
569 vsnrprintf(char *str, size_t size, int radix, const char *format, va_list ap)
570 {
571 struct snprintf_arg info;
572 int retval;
573
574 info.str = str;
575 info.remain = size;
576 retval = kvprintf(format, snprintf_func, &info, radix, ap);
577 if (info.remain >= 1)
578 *info.str++ = '\0';
579 return (retval);
580 }
581
582 static void
583 snprintf_func(int ch, void *arg)
584 {
585 struct snprintf_arg *const info = arg;
586
587 if (info->remain >= 2) {
588 *info->str++ = ch;
589 info->remain--;
590 }
591 }
592
593 /*
594 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
595 * order; return an optional length and a pointer to the last character
596 * written in the buffer (i.e., the first character of the string).
597 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
598 */
599 static char *
600 ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
601 {
602 char *p, c;
603
604 p = nbuf;
605 *p = '\0';
606 do {
607 c = hex2ascii(num % base);
608 *++p = upper ? toupper(c) : c;
609 } while (num /= base);
610 if (lenp)
611 *lenp = p - nbuf;
612 return (p);
613 }
614
615 /*
616 * Scaled down version of printf(3).
617 *
618 * Two additional formats:
619 *
620 * The format %b is supported to decode error registers.
621 * Its usage is:
622 *
623 * printf("reg=%b\n", regval, "<base><arg>*");
624 *
625 * where <base> is the output base expressed as a control character, e.g.
626 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
627 * the first of which gives the bit number to be inspected (origin 1), and
628 * the next characters (up to a control character, i.e. a character <= 32),
629 * give the name of the register. Thus:
630 *
631 * kvprintf("reg=%b\n", 3, "\1\2BITTWO\1BITONE");
632 *
633 * would produce output:
634 *
635 * reg=3<BITTWO,BITONE>
636 *
637 * XXX: %D -- Hexdump, takes pointer and separator string:
638 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
639 * ("%*D", len, ptr, " " -> XX XX XX XX ...
640 */
641 int
642 kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
643 {
644 #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
645 char nbuf[MAXNBUF];
646 char *d;
647 const char *p, *percent, *q;
648 u_char *up;
649 int ch, n;
650 uintmax_t num;
651 int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
652 int cflag, hflag, jflag, tflag, zflag;
653 int dwidth, upper;
654 char padc;
655 int stop = 0, retval = 0;
656
657 num = 0;
658 if (!func)
659 d = (char *) arg;
660 else
661 d = NULL;
662
663 if (fmt == NULL)
664 fmt = "(fmt null)\n";
665
666 if (radix < 2 || radix > 36)
667 radix = 10;
668
669 for (;;) {
670 padc = ' ';
671 width = 0;
672 while ((ch = (u_char)*fmt++) != '%' || stop) {
673 if (ch == '\0')
674 return (retval);
675 PCHAR(ch);
676 }
677 percent = fmt - 1;
678 qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
679 sign = 0; dot = 0; dwidth = 0; upper = 0;
680 cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
681 reswitch: switch (ch = (u_char)*fmt++) {
682 case '.':
683 dot = 1;
684 goto reswitch;
685 case '#':
686 sharpflag = 1;
687 goto reswitch;
688 case '+':
689 sign = 1;
690 goto reswitch;
691 case '-':
692 ladjust = 1;
693 goto reswitch;
694 case '%':
695 PCHAR(ch);
696 break;
697 case '*':
698 if (!dot) {
699 width = va_arg(ap, int);
700 if (width < 0) {
701 ladjust = !ladjust;
702 width = -width;
703 }
704 } else {
705 dwidth = va_arg(ap, int);
706 }
707 goto reswitch;
708 case '':
709 if (!dot) {
710 padc = '';
711 goto reswitch;
712 }
713 case '1': case '2': case '3': case '4':
714 case '5': case '6': case '7': case '8': case '9':
715 for (n = 0;; ++fmt) {
716 n = n * 10 + ch - '';
717 ch = *fmt;
718 if (ch < '' || ch > '9')
719 break;
720 }
721 if (dot)
722 dwidth = n;
723 else
724 width = n;
725 goto reswitch;
726 case 'b':
727 num = (u_int)va_arg(ap, int);
728 p = va_arg(ap, char *);
729 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
730 PCHAR(*q--);
731
732 if (num == 0)
733 break;
734
735 for (tmp = 0; *p;) {
736 n = *p++;
737 if (num & (1 << (n - 1))) {
738 PCHAR(tmp ? ',' : '<');
739 for (; (n = *p) > ' '; ++p)
740 PCHAR(n);
741 tmp = 1;
742 } else
743 for (; *p > ' '; ++p)
744 continue;
745 }
746 if (tmp)
747 PCHAR('>');
748 break;
749 case 'c':
750 width -= 1;
751
752 if (!ladjust && width > 0)
753 while (width--)
754 PCHAR(padc);
755 PCHAR(va_arg(ap, int));
756 if (ladjust && width > 0)
757 while (width--)
758 PCHAR(padc);
759 break;
760 case 'D':
761 up = va_arg(ap, u_char *);
762 p = va_arg(ap, char *);
763 if (!width)
764 width = 16;
765 while(width--) {
766 PCHAR(hex2ascii(*up >> 4));
767 PCHAR(hex2ascii(*up & 0x0f));
768 up++;
769 if (width)
770 for (q=p;*q;q++)
771 PCHAR(*q);
772 }
773 break;
774 case 'd':
775 case 'i':
776 base = 10;
777 sign = 1;
778 goto handle_sign;
779 case 'h':
780 if (hflag) {
781 hflag = 0;
782 cflag = 1;
783 } else
784 hflag = 1;
785 goto reswitch;
786 case 'j':
787 jflag = 1;
788 goto reswitch;
789 case 'l':
790 if (lflag) {
791 lflag = 0;
792 qflag = 1;
793 } else
794 lflag = 1;
795 goto reswitch;
796 case 'n':
797 if (jflag)
798 *(va_arg(ap, intmax_t *)) = retval;
799 else if (qflag)
800 *(va_arg(ap, quad_t *)) = retval;
801 else if (lflag)
802 *(va_arg(ap, long *)) = retval;
803 else if (zflag)
804 *(va_arg(ap, size_t *)) = retval;
805 else if (hflag)
806 *(va_arg(ap, short *)) = retval;
807 else if (cflag)
808 *(va_arg(ap, char *)) = retval;
809 else
810 *(va_arg(ap, int *)) = retval;
811 break;
812 case 'o':
813 base = 8;
814 goto handle_nosign;
815 case 'p':
816 base = 16;
817 sharpflag = (width == 0);
818 sign = 0;
819 num = (uintptr_t)va_arg(ap, void *);
820 goto number;
821 case 'q':
822 qflag = 1;
823 goto reswitch;
824 case 'r':
825 base = radix;
826 if (sign)
827 goto handle_sign;
828 goto handle_nosign;
829 case 's':
830 p = va_arg(ap, char *);
831 if (p == NULL)
832 p = "(null)";
833 if (!dot)
834 n = strlen (p);
835 else
836 for (n = 0; n < dwidth && p[n]; n++)
837 continue;
838
839 width -= n;
840
841 if (!ladjust && width > 0)
842 while (width--)
843 PCHAR(padc);
844 while (n--)
845 PCHAR(*p++);
846 if (ladjust && width > 0)
847 while (width--)
848 PCHAR(padc);
849 break;
850 case 't':
851 tflag = 1;
852 goto reswitch;
853 case 'u':
854 base = 10;
855 goto handle_nosign;
856 case 'X':
857 upper = 1;
858 case 'x':
859 base = 16;
860 goto handle_nosign;
861 case 'y':
862 base = 16;
863 sign = 1;
864 goto handle_sign;
865 case 'z':
866 zflag = 1;
867 goto reswitch;
868 handle_nosign:
869 sign = 0;
870 if (jflag)
871 num = va_arg(ap, uintmax_t);
872 else if (qflag)
873 num = va_arg(ap, u_quad_t);
874 else if (tflag)
875 num = va_arg(ap, ptrdiff_t);
876 else if (lflag)
877 num = va_arg(ap, u_long);
878 else if (zflag)
879 num = va_arg(ap, size_t);
880 else if (hflag)
881 num = (u_short)va_arg(ap, int);
882 else if (cflag)
883 num = (u_char)va_arg(ap, int);
884 else
885 num = va_arg(ap, u_int);
886 goto number;
887 handle_sign:
888 if (jflag)
889 num = va_arg(ap, intmax_t);
890 else if (qflag)
891 num = va_arg(ap, quad_t);
892 else if (tflag)
893 num = va_arg(ap, ptrdiff_t);
894 else if (lflag)
895 num = va_arg(ap, long);
896 else if (zflag)
897 num = va_arg(ap, ssize_t);
898 else if (hflag)
899 num = (short)va_arg(ap, int);
900 else if (cflag)
901 num = (char)va_arg(ap, int);
902 else
903 num = va_arg(ap, int);
904 number:
905 if (sign && (intmax_t)num < 0) {
906 neg = 1;
907 num = -(intmax_t)num;
908 }
909 p = ksprintn(nbuf, num, base, &n, upper);
910 tmp = 0;
911 if (sharpflag && num != 0) {
912 if (base == 8)
913 tmp++;
914 else if (base == 16)
915 tmp += 2;
916 }
917 if (neg)
918 tmp++;
919
920 if (!ladjust && padc == '')
921 dwidth = width - tmp;
922 width -= tmp + imax(dwidth, n);
923 dwidth -= n;
924 if (!ladjust)
925 while (width-- > 0)
926 PCHAR(' ');
927 if (neg)
928 PCHAR('-');
929 if (sharpflag && num != 0) {
930 if (base == 8) {
931 PCHAR('');
932 } else if (base == 16) {
933 PCHAR('');
934 PCHAR('x');
935 }
936 }
937 while (dwidth-- > 0)
938 PCHAR('');
939
940 while (*p)
941 PCHAR(*p--);
942
943 if (ladjust)
944 while (width-- > 0)
945 PCHAR(' ');
946
947 break;
948 default:
949 while (percent < fmt)
950 PCHAR(*percent++);
951 /*
952 * Since we ignore a formatting argument it is no
953 * longer safe to obey the remaining formatting
954 * arguments as the arguments will no longer match
955 * the format specs.
956 */
957 stop = 1;
958 break;
959 }
960 }
961 #undef PCHAR
962 }
963
964 /*
965 * Put character in log buffer with a particular priority.
966 */
967 static void
968 msglogchar(int c, int pri)
969 {
970 static int lastpri = -1;
971 static int dangling;
972 char nbuf[MAXNBUF];
973 char *p;
974
975 if (!msgbufmapped)
976 return;
977 if (c == '\0' || c == '\r')
978 return;
979 if (pri != -1 && pri != lastpri) {
980 if (dangling) {
981 msgbuf_addchar(msgbufp, '\n');
982 dangling = 0;
983 }
984 msgbuf_addchar(msgbufp, '<');
985 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
986 msgbuf_addchar(msgbufp, *p--);
987 msgbuf_addchar(msgbufp, '>');
988 lastpri = pri;
989 }
990 msgbuf_addchar(msgbufp, c);
991 if (c == '\n') {
992 dangling = 0;
993 lastpri = -1;
994 } else {
995 dangling = 1;
996 }
997 }
998
999 static void
1000 msglogstr(char *str, int pri, int filter_cr)
1001 {
1002 if (!msgbufmapped)
1003 return;
1004
1005 msgbuf_addstr(msgbufp, pri, str, filter_cr);
1006 }
1007
1008 void
1009 msgbufinit(void *ptr, int size)
1010 {
1011 char *cp;
1012 static struct msgbuf *oldp = NULL;
1013
1014 size -= sizeof(*msgbufp);
1015 cp = (char *)ptr;
1016 msgbufp = (struct msgbuf *)(cp + size);
1017 msgbuf_reinit(msgbufp, cp, size);
1018 if (msgbufmapped && oldp != msgbufp)
1019 msgbuf_copy(oldp, msgbufp);
1020 msgbufmapped = 1;
1021 oldp = msgbufp;
1022 }
1023
1024 static int unprivileged_read_msgbuf = 1;
1025 SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_read_msgbuf,
1026 CTLFLAG_RW, &unprivileged_read_msgbuf, 0,
1027 "Unprivileged processes may read the kernel message buffer");
1028
1029 /* Sysctls for accessing/clearing the msgbuf */
1030 static int
1031 sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
1032 {
1033 char buf[128];
1034 u_int seq;
1035 int error, len;
1036
1037 if (!unprivileged_read_msgbuf) {
1038 error = priv_check(req->td, PRIV_MSGBUF);
1039 if (error)
1040 return (error);
1041 }
1042
1043 /* Read the whole buffer, one chunk at a time. */
1044 mtx_lock(&msgbuf_lock);
1045 msgbuf_peekbytes(msgbufp, NULL, 0, &seq);
1046 for (;;) {
1047 len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq);
1048 mtx_unlock(&msgbuf_lock);
1049 if (len == 0)
1050 return (SYSCTL_OUT(req, "", 1)); /* add nulterm */
1051
1052 error = sysctl_handle_opaque(oidp, buf, len, req);
1053 if (error)
1054 return (error);
1055
1056 mtx_lock(&msgbuf_lock);
1057 }
1058 }
1059
1060 SYSCTL_PROC(_kern, OID_AUTO, msgbuf,
1061 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
1062 NULL, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
1063
1064 static int msgbuf_clearflag;
1065
1066 static int
1067 sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
1068 {
1069 int error;
1070 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
1071 if (!error && req->newptr) {
1072 mtx_lock(&msgbuf_lock);
1073 msgbuf_clear(msgbufp);
1074 mtx_unlock(&msgbuf_lock);
1075 msgbuf_clearflag = 0;
1076 }
1077 return (error);
1078 }
1079
1080 SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
1081 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE | CTLFLAG_MPSAFE,
1082 &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I",
1083 "Clear kernel message buffer");
1084
1085 #ifdef DDB
1086
1087 DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
1088 {
1089 int i, j;
1090
1091 if (!msgbufmapped) {
1092 db_printf("msgbuf not mapped yet\n");
1093 return;
1094 }
1095 db_printf("msgbufp = %p\n", msgbufp);
1096 db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n",
1097 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq,
1098 msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum);
1099 for (i = 0; i < msgbufp->msg_size && !db_pager_quit; i++) {
1100 j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq);
1101 db_printf("%c", msgbufp->msg_ptr[j]);
1102 }
1103 db_printf("\n");
1104 }
1105
1106 #endif /* DDB */
1107
1108 void
1109 hexdump(const void *ptr, int length, const char *hdr, int flags)
1110 {
1111 int i, j, k;
1112 int cols;
1113 const unsigned char *cp;
1114 char delim;
1115
1116 if ((flags & HD_DELIM_MASK) != 0)
1117 delim = (flags & HD_DELIM_MASK) >> 8;
1118 else
1119 delim = ' ';
1120
1121 if ((flags & HD_COLUMN_MASK) != 0)
1122 cols = flags & HD_COLUMN_MASK;
1123 else
1124 cols = 16;
1125
1126 cp = ptr;
1127 for (i = 0; i < length; i+= cols) {
1128 if (hdr != NULL)
1129 printf("%s", hdr);
1130
1131 if ((flags & HD_OMIT_COUNT) == 0)
1132 printf("%04x ", i);
1133
1134 if ((flags & HD_OMIT_HEX) == 0) {
1135 for (j = 0; j < cols; j++) {
1136 k = i + j;
1137 if (k < length)
1138 printf("%c%02x", delim, cp[k]);
1139 else
1140 printf(" ");
1141 }
1142 }
1143
1144 if ((flags & HD_OMIT_CHARS) == 0) {
1145 printf(" |");
1146 for (j = 0; j < cols; j++) {
1147 k = i + j;
1148 if (k >= length)
1149 printf(" ");
1150 else if (cp[k] >= ' ' && cp[k] <= '~')
1151 printf("%c", cp[k]);
1152 else
1153 printf(".");
1154 }
1155 printf("|");
1156 }
1157 printf("\n");
1158 }
1159 }
1160 #endif /* _KERNEL */
1161
1162 void
1163 sbuf_hexdump(struct sbuf *sb, const void *ptr, int length, const char *hdr,
1164 int flags)
1165 {
1166 int i, j, k;
1167 int cols;
1168 const unsigned char *cp;
1169 char delim;
1170
1171 if ((flags & HD_DELIM_MASK) != 0)
1172 delim = (flags & HD_DELIM_MASK) >> 8;
1173 else
1174 delim = ' ';
1175
1176 if ((flags & HD_COLUMN_MASK) != 0)
1177 cols = flags & HD_COLUMN_MASK;
1178 else
1179 cols = 16;
1180
1181 cp = ptr;
1182 for (i = 0; i < length; i+= cols) {
1183 if (hdr != NULL)
1184 sbuf_printf(sb, "%s", hdr);
1185
1186 if ((flags & HD_OMIT_COUNT) == 0)
1187 sbuf_printf(sb, "%04x ", i);
1188
1189 if ((flags & HD_OMIT_HEX) == 0) {
1190 for (j = 0; j < cols; j++) {
1191 k = i + j;
1192 if (k < length)
1193 sbuf_printf(sb, "%c%02x", delim, cp[k]);
1194 else
1195 sbuf_printf(sb, " ");
1196 }
1197 }
1198
1199 if ((flags & HD_OMIT_CHARS) == 0) {
1200 sbuf_printf(sb, " |");
1201 for (j = 0; j < cols; j++) {
1202 k = i + j;
1203 if (k >= length)
1204 sbuf_printf(sb, " ");
1205 else if (cp[k] >= ' ' && cp[k] <= '~')
1206 sbuf_printf(sb, "%c", cp[k]);
1207 else
1208 sbuf_printf(sb, ".");
1209 }
1210 sbuf_printf(sb, "|");
1211 }
1212 sbuf_printf(sb, "\n");
1213 }
1214 }
1215
1216 #ifdef _KERNEL
1217 void
1218 counted_warning(unsigned *counter, const char *msg)
1219 {
1220 struct thread *td;
1221 unsigned c;
1222
1223 for (;;) {
1224 c = *counter;
1225 if (c == 0)
1226 break;
1227 if (atomic_cmpset_int(counter, c, c - 1)) {
1228 td = curthread;
1229 log(LOG_INFO, "pid %d (%s) %s%s\n",
1230 td->td_proc->p_pid, td->td_name, msg,
1231 c > 1 ? "" : " - not logging anymore");
1232 break;
1233 }
1234 }
1235 }
1236 #endif
1237
1238 #ifdef _KERNEL
1239 void
1240 sbuf_putbuf(struct sbuf *sb)
1241 {
1242
1243 prf_putbuf(sbuf_data(sb), TOLOG | TOCONS, -1);
1244 }
1245 #else
1246 void
1247 sbuf_putbuf(struct sbuf *sb)
1248 {
1249
1250 printf("%s", sbuf_data(sb));
1251 }
1252 #endif
Cache object: 9f7687f61275719afe2b07b16c99c333
|