Remove bogus (void *) casts.
[dragonfly.git] / sys / kern / subr_prf.c
CommitLineData
984263bc
MD
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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
39 * $FreeBSD: src/sys/kern/subr_prf.c,v 1.61.2.5 2002/08/31 18:22:08 dwmalone Exp $
40 */
41
a0a36cfd
SW
42#include "opt_ddb.h"
43
984263bc
MD
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/kernel.h>
47#include <sys/msgbuf.h>
48#include <sys/malloc.h>
49#include <sys/proc.h>
895c1f85 50#include <sys/priv.h>
984263bc
MD
51#include <sys/tty.h>
52#include <sys/tprintf.h>
a0a36cfd 53#include <sys/stdint.h>
984263bc
MD
54#include <sys/syslog.h>
55#include <sys/cons.h>
56#include <sys/uio.h>
57#include <sys/sysctl.h>
8a8d5d85 58#include <sys/lock.h>
a0a36cfd 59#include <sys/ctype.h>
28d7e704
MD
60#include <sys/eventhandler.h>
61#include <sys/kthread.h>
a0a36cfd 62
5fddbda2
MD
63#include <sys/thread2.h>
64#include <sys/spinlock2.h>
65
a0a36cfd
SW
66#ifdef DDB
67#include <ddb/ddb.h>
68#endif
984263bc
MD
69
70/*
71 * Note that stdarg.h and the ANSI style va_start macro is used for both
e2565a42
MD
72 * ANSI and traditional C compilers. We use the __ machine version to stay
73 * within the kernel header file set.
984263bc
MD
74 */
75#include <machine/stdarg.h>
76
28d7e704
MD
77#define TOCONS 0x01
78#define TOTTY 0x02
79#define TOLOG 0x04
80#define TOWAKEUP 0x08
984263bc
MD
81
82/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
a0a36cfd 83#define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
984263bc
MD
84
85struct putchar_arg {
86 int flags;
87 int pri;
88 struct tty *tty;
89};
90
91struct snprintf_arg {
92 char *str;
93 size_t remain;
94};
95
96extern int log_open;
97
98struct tty *constty; /* pointer to console "window" tty */
99
984263bc
MD
100static void msglogchar(int c, int pri);
101static void msgaddchar(int c, void *dummy);
0ced1954 102static void kputchar (int ch, void *arg);
a0a36cfd
SW
103static char *ksprintn (char *nbuf, uintmax_t num, int base, int *lenp,
104 int upper);
402ed7e1 105static void snprintf_func (int ch, void *arg);
984263bc
MD
106
107static int consintr = 1; /* Ok to handle console interrupts? */
108static int msgbufmapped; /* Set when safe to use msgbuf */
5fddbda2 109static struct spinlock cons_spin = SPINLOCK_INITIALIZER(cons_spin);
28d7e704 110static thread_t constty_td = NULL;
5fddbda2 111
984263bc
MD
112int msgbuftrigger;
113
114static int log_console_output = 1;
115TUNABLE_INT("kern.log_console_output", &log_console_output);
116SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
117 &log_console_output, 0, "");
118
d41cbec3 119static int unprivileged_read_msgbuf = 1;
43a0f7ae 120SYSCTL_INT(_security, OID_AUTO, unprivileged_read_msgbuf, CTLFLAG_RW,
d41cbec3
MD
121 &unprivileged_read_msgbuf, 0,
122 "Unprivileged processes may read the kernel message buffer");
123
984263bc
MD
124/*
125 * Warn that a system table is full.
126 */
127void
128tablefull(const char *tab)
129{
130
131 log(LOG_ERR, "%s: table is full\n", tab);
132}
133
134/*
135 * Uprintf prints to the controlling terminal for the current process.
984263bc
MD
136 */
137int
138uprintf(const char *fmt, ...)
139{
140 struct proc *p = curproc;
e2565a42 141 __va_list ap;
984263bc
MD
142 struct putchar_arg pca;
143 int retval = 0;
144
4643740a 145 if (p && (p->p_flags & P_CONTROLT) && p->p_session->s_ttyvp) {
e2565a42 146 __va_start(ap, fmt);
984263bc
MD
147 pca.tty = p->p_session->s_ttyp;
148 pca.flags = TOTTY;
8a8d5d85 149
379210cb 150 retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
e2565a42 151 __va_end(ap);
984263bc 152 }
a0a36cfd 153 return (retval);
984263bc
MD
154}
155
156tpr_t
dadab5e9 157tprintf_open(struct proc *p)
984263bc 158{
4643740a 159 if ((p->p_flags & P_CONTROLT) && p->p_session->s_ttyvp) {
8b90699b 160 sess_hold(p->p_session);
984263bc
MD
161 return ((tpr_t) p->p_session);
162 }
a60655aa 163 return (NULL);
984263bc
MD
164}
165
166void
dadab5e9 167tprintf_close(tpr_t sess)
984263bc 168{
984263bc 169 if (sess)
8b90699b 170 sess_rele((struct session *) sess);
984263bc
MD
171}
172
173/*
174 * tprintf prints on the controlling terminal associated
175 * with the given session.
176 */
177int
178tprintf(tpr_t tpr, const char *fmt, ...)
179{
1fd87d54 180 struct session *sess = (struct session *)tpr;
984263bc
MD
181 struct tty *tp = NULL;
182 int flags = TOLOG;
e2565a42 183 __va_list ap;
984263bc
MD
184 struct putchar_arg pca;
185 int retval;
186
187 if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
188 flags |= TOTTY;
189 tp = sess->s_ttyp;
190 }
e2565a42 191 __va_start(ap, fmt);
984263bc
MD
192 pca.tty = tp;
193 pca.flags = flags;
194 pca.pri = LOG_INFO;
379210cb 195 retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
e2565a42 196 __va_end(ap);
984263bc 197 msgbuftrigger = 1;
a0a36cfd 198 return (retval);
984263bc
MD
199}
200
201/*
202 * Ttyprintf displays a message on a tty; it should be used only by
203 * the tty driver, or anything that knows the underlying tty will not
204 * be revoke(2)'d away. Other callers should use tprintf.
205 */
206int
207ttyprintf(struct tty *tp, const char *fmt, ...)
208{
e2565a42 209 __va_list ap;
984263bc
MD
210 struct putchar_arg pca;
211 int retval;
212
e2565a42 213 __va_start(ap, fmt);
984263bc
MD
214 pca.tty = tp;
215 pca.flags = TOTTY;
379210cb 216 retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
e2565a42 217 __va_end(ap);
a0a36cfd 218 return (retval);
984263bc
MD
219}
220
221/*
222 * Log writes to the log buffer, and guarantees not to sleep (so can be
223 * called by interrupt routines). If there is no process reading the
224 * log yet, it writes to the console also.
225 */
226int
227log(int level, const char *fmt, ...)
228{
e2565a42 229 __va_list ap;
984263bc
MD
230 int retval;
231 struct putchar_arg pca;
232
233 pca.tty = NULL;
234 pca.pri = level;
235 pca.flags = log_open ? TOLOG : TOCONS;
236
e2565a42 237 __va_start(ap, fmt);
379210cb 238 retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
e2565a42 239 __va_end(ap);
984263bc
MD
240
241 msgbuftrigger = 1;
242 return (retval);
243}
244
984263bc
MD
245#define CONSCHUNK 128
246
247void
248log_console(struct uio *uio)
249{
250 int c, i, error, iovlen, nl;
251 struct uio muio;
252 struct iovec *miov = NULL;
253 char *consbuffer;
254 int pri;
255
256 if (!log_console_output)
257 return;
258
259 pri = LOG_INFO | LOG_CONSOLE;
260 muio = *uio;
261 iovlen = uio->uio_iovcnt * sizeof (struct iovec);
884717e1
SW
262 miov = kmalloc(iovlen, M_TEMP, M_WAITOK);
263 consbuffer = kmalloc(CONSCHUNK, M_TEMP, M_WAITOK);
984263bc
MD
264 bcopy((caddr_t)muio.uio_iov, (caddr_t)miov, iovlen);
265 muio.uio_iov = miov;
266 uio = &muio;
267
268 nl = 0;
269 while (uio->uio_resid > 0) {
e54488bb
MD
270 c = (int)szmin(uio->uio_resid, CONSCHUNK);
271 error = uiomove(consbuffer, (size_t)c, uio);
984263bc 272 if (error != 0)
a0a36cfd 273 break;
984263bc
MD
274 for (i = 0; i < c; i++) {
275 msglogchar(consbuffer[i], pri);
276 if (consbuffer[i] == '\n')
277 nl = 1;
278 else
279 nl = 0;
280 }
281 }
282 if (!nl)
283 msglogchar('\n', pri);
284 msgbuftrigger = 1;
884717e1
SW
285 kfree(miov, M_TEMP);
286 kfree(consbuffer, M_TEMP);
984263bc
MD
287 return;
288}
289
e02941a7
MD
290/*
291 * Output to the console.
e02941a7 292 */
984263bc 293int
169276ba
MD
294kprintf(const char *fmt, ...)
295{
296 __va_list ap;
297 int savintr;
298 struct putchar_arg pca;
299 int retval;
300
301 savintr = consintr; /* disable interrupts */
302 consintr = 0;
303 __va_start(ap, fmt);
304 pca.tty = NULL;
305 pca.flags = TOCONS | TOLOG;
306 pca.pri = -1;
169276ba 307 retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
169276ba
MD
308 __va_end(ap);
309 if (!panicstr)
310 msgbuftrigger = 1;
311 consintr = savintr; /* reenable interrupts */
a0a36cfd 312 return (retval);
169276ba
MD
313}
314
984263bc 315int
379210cb 316kvprintf(const char *fmt, __va_list ap)
984263bc
MD
317{
318 int savintr;
319 struct putchar_arg pca;
320 int retval;
321
322 savintr = consintr; /* disable interrupts */
323 consintr = 0;
324 pca.tty = NULL;
325 pca.flags = TOCONS | TOLOG;
326 pca.pri = -1;
379210cb 327 retval = kvcprintf(fmt, kputchar, &pca, 10, ap);
984263bc
MD
328 if (!panicstr)
329 msgbuftrigger = 1;
330 consintr = savintr; /* reenable interrupts */
a0a36cfd 331 return (retval);
984263bc
MD
332}
333
c8dfd00d
MD
334/*
335 * Limited rate kprintf. The passed rate structure must be initialized
336 * with the desired reporting frequency. A frequency of 0 will result in
337 * no output.
448f8e02
MD
338 *
339 * count may be initialized to a negative number to allow an initial
340 * burst.
c8dfd00d
MD
341 */
342void
343krateprintf(struct krate *rate, const char *fmt, ...)
344{
345 __va_list ap;
346
1c9c514a
MD
347 if (rate->ticks != (int)time_second) {
348 rate->ticks = (int)time_second;
448f8e02
MD
349 if (rate->count > 0)
350 rate->count = 0;
c8dfd00d
MD
351 }
352 if (rate->count < rate->freq) {
353 ++rate->count;
354 __va_start(ap, fmt);
355 kvprintf(fmt, ap);
356 __va_end(ap);
357 }
358}
359
984263bc 360/*
137b3005
MD
361 * Print a character to the dmesg log, the console, and/or the user's
362 * terminal.
e02941a7 363 *
28d7e704
MD
364 * NOTE: TOTTY does not require nonblocking operation, but TOCONS
365 * and TOLOG do. When we have a constty we still output to
366 * the real console but we have a monitoring thread which
367 * we wakeup which tracks the log.
984263bc
MD
368 */
369static void
0ced1954 370kputchar(int c, void *arg)
984263bc
MD
371{
372 struct putchar_arg *ap = (struct putchar_arg*) arg;
373 int flags = ap->flags;
374 struct tty *tp = ap->tty;
137b3005 375
984263bc
MD
376 if (panicstr)
377 constty = NULL;
28d7e704
MD
378 if ((flags & TOCONS) && tp == NULL && constty)
379 flags |= TOLOG | TOWAKEUP;
e5104a66
MD
380 if ((flags & TOTTY) && tputchar(c, tp) < 0)
381 ap->flags &= ~TOTTY;
984263bc
MD
382 if ((flags & TOLOG))
383 msglogchar(c, ap->pri);
28d7e704 384 if ((flags & TOCONS) && c)
5fddbda2 385 cnputc(c);
28d7e704
MD
386 if (flags & TOWAKEUP)
387 wakeup(constty_td);
984263bc
MD
388}
389
390/*
391 * Scaled down version of sprintf(3).
392 */
393int
169276ba
MD
394ksprintf(char *buf, const char *cfmt, ...)
395{
396 int retval;
397 __va_list ap;
398
399 __va_start(ap, cfmt);
4e1af74f 400 retval = kvcprintf(cfmt, NULL, buf, 10, ap);
169276ba
MD
401 buf[retval] = '\0';
402 __va_end(ap);
a0a36cfd 403 return (retval);
169276ba
MD
404}
405
984263bc
MD
406/*
407 * Scaled down version of vsprintf(3).
408 */
409int
379210cb 410kvsprintf(char *buf, const char *cfmt, __va_list ap)
984263bc
MD
411{
412 int retval;
413
4e1af74f 414 retval = kvcprintf(cfmt, NULL, buf, 10, ap);
984263bc 415 buf[retval] = '\0';
a0a36cfd 416 return (retval);
984263bc
MD
417}
418
419/*
420 * Scaled down version of snprintf(3).
421 */
422int
169276ba 423ksnprintf(char *str, size_t size, const char *format, ...)
984263bc
MD
424{
425 int retval;
e2565a42 426 __va_list ap;
984263bc 427
e2565a42 428 __va_start(ap, format);
379210cb 429 retval = kvsnprintf(str, size, format, ap);
e2565a42 430 __va_end(ap);
984263bc
MD
431 return(retval);
432}
433
434/*
435 * Scaled down version of vsnprintf(3).
436 */
437int
379210cb 438kvsnprintf(char *str, size_t size, const char *format, __va_list ap)
984263bc
MD
439{
440 struct snprintf_arg info;
441 int retval;
442
443 info.str = str;
444 info.remain = size;
379210cb 445 retval = kvcprintf(format, snprintf_func, &info, 10, ap);
984263bc
MD
446 if (info.remain >= 1)
447 *info.str++ = '\0';
a0a36cfd 448 return (retval);
984263bc
MD
449}
450
93c46bf9
MD
451int
452ksnrprintf(char *str, size_t size, int radix, const char *format, ...)
453{
454 int retval;
455 __va_list ap;
456
457 __va_start(ap, format);
458 retval = kvsnrprintf(str, size, radix, format, ap);
459 __va_end(ap);
460 return(retval);
461}
462
463int
464kvsnrprintf(char *str, size_t size, int radix, const char *format, __va_list ap)
465{
466 struct snprintf_arg info;
467 int retval;
468
469 info.str = str;
470 info.remain = size;
471 retval = kvcprintf(format, snprintf_func, &info, radix, ap);
472 if (info.remain >= 1)
473 *info.str++ = '\0';
474 return (retval);
475}
476
477int
478kvasnrprintf(char **strp, size_t size, int radix,
479 const char *format, __va_list ap)
480{
481 struct snprintf_arg info;
482 int retval;
483
484 *strp = kmalloc(size, M_TEMP, M_WAITOK);
485 info.str = *strp;
486 info.remain = size;
487 retval = kvcprintf(format, snprintf_func, &info, radix, ap);
488 if (info.remain >= 1)
489 *info.str++ = '\0';
490 return (retval);
491}
492
493void
494kvasfree(char **strp)
495{
496 if (*strp) {
497 kfree(*strp, M_TEMP);
498 *strp = NULL;
499 }
500}
501
984263bc
MD
502static void
503snprintf_func(int ch, void *arg)
504{
505 struct snprintf_arg *const info = arg;
506
507 if (info->remain >= 2) {
508 *info->str++ = ch;
509 info->remain--;
510 }
511}
512
513/*
514 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
515 * order; return an optional length and a pointer to the last character
516 * written in the buffer (i.e., the first character of the string).
517 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
518 */
519static char *
a0a36cfd 520ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
984263bc 521{
a0a36cfd 522 char *p, c;
984263bc
MD
523
524 p = nbuf;
525 *p = '\0';
526 do {
a0a36cfd
SW
527 c = hex2ascii(num % base);
528 *++p = upper ? toupper(c) : c;
529 } while (num /= base);
984263bc
MD
530 if (lenp)
531 *lenp = p - nbuf;
532 return (p);
533}
534
535/*
536 * Scaled down version of printf(3).
537 *
538 * Two additional formats:
539 *
540 * The format %b is supported to decode error registers.
541 * Its usage is:
542 *
71681fd7 543 * kprintf("reg=%b\n", regval, "<base><arg>*");
984263bc
MD
544 *
545 * where <base> is the output base expressed as a control character, e.g.
546 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
547 * the first of which gives the bit number to be inspected (origin 1), and
548 * the next characters (up to a control character, i.e. a character <= 32),
549 * give the name of the register. Thus:
550 *
379210cb 551 * kvcprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
984263bc
MD
552 *
553 * would produce output:
554 *
555 * reg=3<BITTWO,BITONE>
556 *
557 * XXX: %D -- Hexdump, takes pointer and separator string:
558 * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
559 * ("%*D", len, ptr, " " -> XX XX XX XX ...
560 */
5fddbda2
MD
561
562#define PCHAR(c) {int cc=(c); if(func) (*func)(cc,arg); else *d++=cc; retval++;}
563
984263bc 564int
5fddbda2
MD
565kvcprintf(char const *fmt, void (*func)(int, void*), void *arg,
566 int radix, __va_list ap)
984263bc 567{
984263bc 568 char nbuf[MAXNBUF];
a0a36cfd
SW
569 char *d;
570 const char *p, *percent, *q;
984263bc
MD
571 u_char *up;
572 int ch, n;
a0a36cfd
SW
573 uintmax_t num;
574 int base, tmp, width, ladjust, sharpflag, neg, sign, dot;
f481fa5d 575 int cflag, hflag, jflag, lflag, qflag, tflag, zflag;
a0a36cfd 576 int dwidth, upper;
984263bc 577 char padc;
a0a36cfd 578 int retval = 0, stop = 0;
438acbcc
MD
579 int usespin;
580
581 /*
582 * Make a supreme effort to avoid reentrant panics or deadlocks.
3dc9b698
MD
583 *
584 * NOTE! Do nothing that would access mycpu/gd/fs unless the
585 * function is the normal kputchar(), which allows us to
586 * use this function for very early debugging with a special
587 * function.
438acbcc
MD
588 */
589 if (func == kputchar) {
590 if (mycpu->gd_flags & GDF_KPRINTF)
591 return(0);
592 atomic_set_long(&mycpu->gd_flags, GDF_KPRINTF);
593 }
984263bc 594
a0a36cfd 595 num = 0;
984263bc
MD
596 if (!func)
597 d = (char *) arg;
598 else
599 d = NULL;
600
601 if (fmt == NULL)
602 fmt = "(fmt null)\n";
603
604 if (radix < 2 || radix > 36)
605 radix = 10;
606
3dc9b698
MD
607 usespin = (func == kputchar &&
608 panic_cpu_gd != mycpu &&
438acbcc
MD
609 (((struct putchar_arg *)arg)->flags & TOTTY) == 0);
610 if (usespin) {
5fddbda2 611 crit_enter_hard();
287a8577 612 spin_lock(&cons_spin);
5fddbda2
MD
613 }
614
984263bc
MD
615 for (;;) {
616 padc = ' ';
617 width = 0;
a0a36cfd
SW
618 while ((ch = (u_char)*fmt++) != '%' || stop) {
619 if (ch == '\0')
5fddbda2 620 goto done;
984263bc
MD
621 PCHAR(ch);
622 }
a0a36cfd
SW
623 percent = fmt - 1;
624 dot = dwidth = ladjust = neg = sharpflag = sign = upper = 0;
f481fa5d 625 cflag = hflag = jflag = lflag = qflag = tflag = zflag = 0;
a0a36cfd
SW
626
627reswitch:
628 switch (ch = (u_char)*fmt++) {
984263bc
MD
629 case '.':
630 dot = 1;
631 goto reswitch;
632 case '#':
633 sharpflag = 1;
634 goto reswitch;
635 case '+':
636 sign = 1;
637 goto reswitch;
638 case '-':
639 ladjust = 1;
640 goto reswitch;
641 case '%':
642 PCHAR(ch);
643 break;
644 case '*':
645 if (!dot) {
e2565a42 646 width = __va_arg(ap, int);
984263bc
MD
647 if (width < 0) {
648 ladjust = !ladjust;
649 width = -width;
650 }
651 } else {
e2565a42 652 dwidth = __va_arg(ap, int);
984263bc
MD
653 }
654 goto reswitch;
655 case '0':
656 if (!dot) {
657 padc = '0';
658 goto reswitch;
659 }
660 case '1': case '2': case '3': case '4':
661 case '5': case '6': case '7': case '8': case '9':
662 for (n = 0;; ++fmt) {
663 n = n * 10 + ch - '0';
664 ch = *fmt;
665 if (ch < '0' || ch > '9')
666 break;
667 }
668 if (dot)
669 dwidth = n;
670 else
671 width = n;
672 goto reswitch;
673 case 'b':
a0a36cfd 674 num = (u_int)__va_arg(ap, int);
e2565a42 675 p = __va_arg(ap, char *);
a0a36cfd 676 for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
984263bc
MD
677 PCHAR(*q--);
678
a0a36cfd 679 if (num == 0)
984263bc
MD
680 break;
681
682 for (tmp = 0; *p;) {
683 n = *p++;
a0a36cfd 684 if (num & (1 << (n - 1))) {
984263bc
MD
685 PCHAR(tmp ? ',' : '<');
686 for (; (n = *p) > ' '; ++p)
687 PCHAR(n);
688 tmp = 1;
689 } else
690 for (; *p > ' '; ++p)
691 continue;
692 }
693 if (tmp)
694 PCHAR('>');
695 break;
696 case 'c':
e2565a42 697 PCHAR(__va_arg(ap, int));
984263bc
MD
698 break;
699 case 'D':
e2565a42
MD
700 up = __va_arg(ap, u_char *);
701 p = __va_arg(ap, char *);
984263bc
MD
702 if (!width)
703 width = 16;
704 while(width--) {
705 PCHAR(hex2ascii(*up >> 4));
706 PCHAR(hex2ascii(*up & 0x0f));
707 up++;
708 if (width)
709 for (q=p;*q;q++)
710 PCHAR(*q);
711 }
712 break;
713 case 'd':
a0a36cfd 714 case 'i':
984263bc 715 base = 10;
a0a36cfd
SW
716 sign = 1;
717 goto handle_sign;
f481fa5d
SW
718 case 'h':
719 if (hflag) {
720 hflag = 0;
721 cflag = 1;
722 } else
723 hflag = 1;
724 goto reswitch;
a0a36cfd
SW
725 case 'j':
726 jflag = 1;
727 goto reswitch;
984263bc
MD
728 case 'l':
729 if (lflag) {
730 lflag = 0;
731 qflag = 1;
732 } else
733 lflag = 1;
734 goto reswitch;
a0a36cfd 735 case 'n':
f481fa5d
SW
736 if (cflag)
737 *(__va_arg(ap, char *)) = retval;
738 else if (hflag)
739 *(__va_arg(ap, short *)) = retval;
740 else if (jflag)
a0a36cfd 741 *(__va_arg(ap, intmax_t *)) = retval;
984263bc 742 else if (lflag)
a0a36cfd
SW
743 *(__va_arg(ap, long *)) = retval;
744 else if (qflag)
745 *(__va_arg(ap, quad_t *)) = retval;
984263bc 746 else
a0a36cfd
SW
747 *(__va_arg(ap, int *)) = retval;
748 break;
749 case 'o':
984263bc 750 base = 8;
a0a36cfd 751 goto handle_nosign;
984263bc 752 case 'p':
984263bc
MD
753 base = 16;
754 sharpflag = (width == 0);
a0a36cfd
SW
755 sign = 0;
756 num = (uintptr_t)__va_arg(ap, void *);
757 goto number;
984263bc
MD
758 case 'q':
759 qflag = 1;
760 goto reswitch;
984263bc 761 case 'r':
984263bc 762 base = radix;
a0a36cfd
SW
763 if (sign)
764 goto handle_sign;
765 goto handle_nosign;
984263bc 766 case 's':
e2565a42 767 p = __va_arg(ap, char *);
984263bc
MD
768 if (p == NULL)
769 p = "(null)";
770 if (!dot)
771 n = strlen (p);
772 else
773 for (n = 0; n < dwidth && p[n]; n++)
774 continue;
775
776 width -= n;
777
778 if (!ladjust && width > 0)
779 while (width--)
780 PCHAR(padc);
781 while (n--)
782 PCHAR(*p++);
783 if (ladjust && width > 0)
784 while (width--)
785 PCHAR(padc);
786 break;
a0a36cfd
SW
787 case 't':
788 tflag = 1;
789 goto reswitch;
984263bc 790 case 'u':
984263bc 791 base = 10;
a0a36cfd 792 goto handle_nosign;
984263bc 793 case 'X':
a0a36cfd
SW
794 upper = 1;
795 /* FALLTHROUGH */
796 case 'x':
984263bc 797 base = 16;
a0a36cfd 798 goto handle_nosign;
984263bc 799 case 'z':
9c7517ab
MD
800 zflag = 1;
801 goto reswitch;
a0a36cfd
SW
802handle_nosign:
803 sign = 0;
f481fa5d
SW
804 if (cflag)
805 num = (u_char)__va_arg(ap, int);
806 else if (hflag)
807 num = (u_short)__va_arg(ap, int);
808 else if (jflag)
a0a36cfd 809 num = __va_arg(ap, uintmax_t);
984263bc 810 else if (lflag)
a0a36cfd
SW
811 num = __va_arg(ap, u_long);
812 else if (qflag)
813 num = __va_arg(ap, u_quad_t);
814 else if (tflag)
815 num = __va_arg(ap, ptrdiff_t);
9c7517ab
MD
816 else if (zflag)
817 num = __va_arg(ap, size_t);
984263bc 818 else
a0a36cfd 819 num = __va_arg(ap, u_int);
984263bc 820 goto number;
a0a36cfd 821handle_sign:
f481fa5d
SW
822 if (cflag)
823 num = (char)__va_arg(ap, int);
824 else if (hflag)
825 num = (short)__va_arg(ap, int);
826 else if (jflag)
a0a36cfd
SW
827 num = __va_arg(ap, intmax_t);
828 else if (lflag)
829 num = __va_arg(ap, long);
830 else if (qflag)
831 num = __va_arg(ap, quad_t);
832 else if (tflag)
833 num = __va_arg(ap, ptrdiff_t);
9c7517ab
MD
834 else if (zflag)
835 num = __va_arg(ap, ssize_t);
a0a36cfd
SW
836 else
837 num = __va_arg(ap, int);
838number:
839 if (sign && (intmax_t)num < 0) {
840 neg = 1;
841 num = -(intmax_t)num;
984263bc 842 }
a0a36cfd
SW
843 p = ksprintn(nbuf, num, base, &tmp, upper);
844 if (sharpflag && num != 0) {
984263bc
MD
845 if (base == 8)
846 tmp++;
847 else if (base == 16)
848 tmp += 2;
849 }
850 if (neg)
851 tmp++;
852
a0a36cfd
SW
853 if (!ladjust && padc != '0' && width &&
854 (width -= tmp) > 0) {
984263bc
MD
855 while (width--)
856 PCHAR(padc);
a0a36cfd 857 }
984263bc
MD
858 if (neg)
859 PCHAR('-');
a0a36cfd 860 if (sharpflag && num != 0) {
984263bc
MD
861 if (base == 8) {
862 PCHAR('0');
863 } else if (base == 16) {
864 PCHAR('0');
865 PCHAR('x');
866 }
867 }
a0a36cfd
SW
868 if (!ladjust && width && (width -= tmp) > 0)
869 while (width--)
870 PCHAR(padc);
984263bc
MD
871
872 while (*p)
873 PCHAR(*p--);
874
875 if (ladjust && width && (width -= tmp) > 0)
876 while (width--)
877 PCHAR(padc);
878
879 break;
880 default:
a0a36cfd
SW
881 while (percent < fmt)
882 PCHAR(*percent++);
883 /*
884 * Since we ignore an formatting argument it is no
885 * longer safe to obey the remaining formatting
886 * arguments as the arguments will no longer match
887 * the format specs.
888 */
889 stop = 1;
984263bc
MD
890 break;
891 }
892 }
5fddbda2 893done:
438acbcc
MD
894 /*
895 * Cleanup reentrancy issues.
896 */
897 if (func == kputchar)
898 atomic_clear_long(&mycpu->gd_flags, GDF_KPRINTF);
899 if (usespin) {
287a8577 900 spin_unlock(&cons_spin);
5fddbda2
MD
901 crit_exit_hard();
902 }
903 return (retval);
904}
905
984263bc 906#undef PCHAR
5fddbda2
MD
907
908/*
438acbcc
MD
909 * Called from the panic code to try to get the console working
910 * again in case we paniced inside a kprintf().
5fddbda2
MD
911 */
912void
913kvcreinitspin(void)
914{
915 spin_init(&cons_spin);
438acbcc 916 atomic_clear_long(&mycpu->gd_flags, GDF_KPRINTF);
984263bc
MD
917}
918
28d7e704
MD
919/*
920 * Console support thread for constty intercepts. This is needed because
921 * console tty intercepts can block. Instead of having kputchar() attempt
922 * to directly write to the console intercept we just force it to log
923 * and wakeup this baby to track and dump the log to constty.
924 */
925static void
926constty_daemon(void)
927{
928 int rindex = -1;
929 int windex = -1;
930 struct msgbuf *mbp;
931 struct tty *tp;
932
933 EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_kproc,
934 constty_td, SHUTDOWN_PRI_FIRST);
935 constty_td->td_flags |= TDF_SYSTHREAD;
936
937 for (;;) {
938 kproc_suspend_loop();
939
940 crit_enter();
941 mbp = msgbufp;
942 if (mbp == NULL || msgbufmapped == 0 ||
943 windex == mbp->msg_bufx) {
944 tsleep(constty_td, 0, "waiting", hz*60);
945 crit_exit();
946 continue;
947 }
948 windex = mbp->msg_bufx;
949 crit_exit();
950
951 /*
952 * Get message buf FIFO indices. rindex is tracking.
953 */
954 if ((tp = constty) == NULL) {
955 rindex = mbp->msg_bufx;
956 continue;
957 }
958
959 /*
960 * Don't blow up if the message buffer is broken
961 */
962 if (windex < 0 || windex >= mbp->msg_size)
963 continue;
964 if (rindex < 0 || rindex >= mbp->msg_size)
965 rindex = windex;
966
967 /*
968 * And dump it. If constty gets stuck will give up.
969 */
970 while (rindex != windex) {
971 if (tputchar((uint8_t)mbp->msg_ptr[rindex], tp) < 0) {
972 constty = NULL;
973 rindex = mbp->msg_bufx;
974 break;
975 }
976 if (++rindex >= mbp->msg_size)
977 rindex = 0;
978 if (tp->t_outq.c_cc >= tp->t_ohiwat) {
979 tsleep(constty_daemon, 0, "blocked", hz / 10);
980 if (tp->t_outq.c_cc >= tp->t_ohiwat) {
981 rindex = windex;
982 break;
983 }
984 }
985 }
986 }
987}
988
989static struct kproc_desc constty_kp = {
990 "consttyd",
991 constty_daemon,
992 &constty_td
993};
994SYSINIT(bufdaemon, SI_SUB_KTHREAD_UPDATE, SI_ORDER_ANY,
995 kproc_start, &constty_kp)
5fddbda2 996
984263bc
MD
997/*
998 * Put character in log buffer with a particular priority.
e02941a7
MD
999 *
1000 * MPSAFE
984263bc
MD
1001 */
1002static void
1003msglogchar(int c, int pri)
1004{
1005 static int lastpri = -1;
1006 static int dangling;
1007 char nbuf[MAXNBUF];
1008 char *p;
1009
1010 if (!msgbufmapped)
1011 return;
1012 if (c == '\0' || c == '\r')
1013 return;
1014 if (pri != -1 && pri != lastpri) {
1015 if (dangling) {
1016 msgaddchar('\n', NULL);
1017 dangling = 0;
1018 }
1019 msgaddchar('<', NULL);
a0a36cfd 1020 for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL, 0); *p;)
984263bc
MD
1021 msgaddchar(*p--, NULL);
1022 msgaddchar('>', NULL);
1023 lastpri = pri;
1024 }
1025 msgaddchar(c, NULL);
1026 if (c == '\n') {
1027 dangling = 0;
1028 lastpri = -1;
1029 } else {
1030 dangling = 1;
1031 }
1032}
1033
1034/*
e02941a7
MD
1035 * Put char in log buffer. Make sure nothing blows up beyond repair if
1036 * we have an MP race.
1037 *
1038 * MPSAFE.
984263bc
MD
1039 */
1040static void
1041msgaddchar(int c, void *dummy)
1042{
1043 struct msgbuf *mbp;
e02941a7
MD
1044 int rindex;
1045 int windex;
984263bc
MD
1046
1047 if (!msgbufmapped)
1048 return;
1049 mbp = msgbufp;
e02941a7
MD
1050 windex = mbp->msg_bufx;
1051 mbp->msg_ptr[windex] = c;
1052 if (++windex >= mbp->msg_size)
1053 windex = 0;
1054 rindex = mbp->msg_bufr;
1055 if (windex == rindex) {
1056 rindex += 32;
1057 if (rindex >= mbp->msg_size)
1058 rindex -= mbp->msg_size;
1059 mbp->msg_bufr = rindex;
984263bc 1060 }
e02941a7 1061 mbp->msg_bufx = windex;
984263bc
MD
1062}
1063
1064static void
1065msgbufcopy(struct msgbuf *oldp)
1066{
1067 int pos;
1068
1069 pos = oldp->msg_bufr;
1070 while (pos != oldp->msg_bufx) {
1071 msglogchar(oldp->msg_ptr[pos], -1);
1072 if (++pos >= oldp->msg_size)
1073 pos = 0;
1074 }
1075}
1076
1077void
1078msgbufinit(void *ptr, size_t size)
1079{
1080 char *cp;
1081 static struct msgbuf *oldp = NULL;
1082
1083 size -= sizeof(*msgbufp);
1084 cp = (char *)ptr;
1085 msgbufp = (struct msgbuf *) (cp + size);
1086 if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_size != size ||
1087 msgbufp->msg_bufx >= size || msgbufp->msg_bufr >= size) {
1088 bzero(cp, size);
1089 bzero(msgbufp, sizeof(*msgbufp));
1090 msgbufp->msg_magic = MSG_MAGIC;
1091 msgbufp->msg_size = (char *)msgbufp - cp;
1092 }
1093 msgbufp->msg_ptr = cp;
1094 if (msgbufmapped && oldp != msgbufp)
1095 msgbufcopy(oldp);
1096 msgbufmapped = 1;
1097 oldp = msgbufp;
1098}
1099
1100/* Sysctls for accessing/clearing the msgbuf */
d41cbec3 1101
984263bc
MD
1102static int
1103sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
1104{
d41cbec3 1105 struct ucred *cred;
984263bc
MD
1106 int error;
1107
d41cbec3
MD
1108 /*
1109 * Only wheel or root can access the message log.
1110 */
1111 if (unprivileged_read_msgbuf == 0) {
1112 KKASSERT(req->td->td_proc);
1113 cred = req->td->td_proc->p_ucred;
1114
1115 if ((cred->cr_prison || groupmember(0, cred) == 0) &&
895c1f85 1116 priv_check(req->td, PRIV_ROOT) != 0
d41cbec3
MD
1117 ) {
1118 return (EPERM);
1119 }
1120 }
1121
984263bc
MD
1122 /*
1123 * Unwind the buffer, so that it's linear (possibly starting with
1124 * some initial nulls).
1125 */
1126 error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr + msgbufp->msg_bufx,
1127 msgbufp->msg_size - msgbufp->msg_bufx, req);
1128 if (error)
1129 return (error);
1130 if (msgbufp->msg_bufx > 0) {
1131 error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr,
1132 msgbufp->msg_bufx, req);
1133 }
1134 return (error);
1135}
1136
1137SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD,
1138 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer");
1139
1140static int msgbuf_clear;
1141
1142static int
1143sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS)
1144{
1145 int error;
1146 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
1147 if (!error && req->newptr) {
1148 /* Clear the buffer and reset write pointer */
1149 bzero(msgbufp->msg_ptr, msgbufp->msg_size);
1150 msgbufp->msg_bufr = msgbufp->msg_bufx = 0;
1151 msgbuf_clear = 0;
1152 }
1153 return (error);
1154}
1155
1156SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear,
a0a36cfd 1157 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clear, 0,
984263bc
MD
1158 sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer");
1159
984263bc 1160#ifdef DDB
984263bc
MD
1161
1162DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
1163{
1164 int i, j;
1165
1166 if (!msgbufmapped) {
1167 db_printf("msgbuf not mapped yet\n");
1168 return;
1169 }
1170 db_printf("msgbufp = %p\n", msgbufp);
1171 db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n",
1172 msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr,
1173 msgbufp->msg_bufx, msgbufp->msg_ptr);
1174 for (i = 0; i < msgbufp->msg_size; i++) {
1175 j = (i + msgbufp->msg_bufr) % msgbufp->msg_size;
1176 db_printf("%c", msgbufp->msg_ptr[j]);
1177 }
1178 db_printf("\n");
1179}
1180
1181#endif /* DDB */
37f44315
SW
1182
1183
1184void
1185hexdump(const void *ptr, int length, const char *hdr, int flags)
1186{
1187 int i, j, k;
1188 int cols;
1189 const unsigned char *cp;
1190 char delim;
1191
1192 if ((flags & HD_DELIM_MASK) != 0)
1193 delim = (flags & HD_DELIM_MASK) >> 8;
1194 else
1195 delim = ' ';
1196
1197 if ((flags & HD_COLUMN_MASK) != 0)
1198 cols = flags & HD_COLUMN_MASK;
1199 else
1200 cols = 16;
1201
1202 cp = ptr;
1203 for (i = 0; i < length; i+= cols) {
1204 if (hdr != NULL)
1205 kprintf("%s", hdr);
1206
1207 if ((flags & HD_OMIT_COUNT) == 0)
1208 kprintf("%04x ", i);
1209
1210 if ((flags & HD_OMIT_HEX) == 0) {
1211 for (j = 0; j < cols; j++) {
1212 k = i + j;
1213 if (k < length)
1214 kprintf("%c%02x", delim, cp[k]);
1215 else
1216 kprintf(" ");
1217 }
1218 }
1219
1220 if ((flags & HD_OMIT_CHARS) == 0) {
1221 kprintf(" |");
1222 for (j = 0; j < cols; j++) {
1223 k = i + j;
1224 if (k >= length)
1225 kprintf(" ");
1226 else if (cp[k] >= ' ' && cp[k] <= '~')
1227 kprintf("%c", cp[k]);
1228 else
1229 kprintf(".");
1230 }
1231 kprintf("|");
1232 }
1233 kprintf("\n");
1234 }
1235}