1 | /* $NetBSD: subr_prf.c,v 1.160 2016/07/27 09:57:26 skrll Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 1986, 1988, 1991, 1993 |
5 | * The Regents of the University of California. All rights reserved. |
6 | * (c) UNIX System Laboratories, Inc. |
7 | * All or some portions of this file are derived from material licensed |
8 | * to the University of California by American Telephone and Telegraph |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with |
10 | * the permission of UNIX System Laboratories, Inc. |
11 | * |
12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions |
14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions and the following disclaimer. |
17 | * 2. Redistributions in binary form must reproduce the above copyright |
18 | * notice, this list of conditions and the following disclaimer in the |
19 | * documentation and/or other materials provided with the distribution. |
20 | * 3. Neither the name of the University nor the names of its contributors |
21 | * may be used to endorse or promote products derived from this software |
22 | * without specific prior written permission. |
23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 | * SUCH DAMAGE. |
35 | * |
36 | * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95 |
37 | */ |
38 | |
39 | #include <sys/cdefs.h> |
40 | __KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.160 2016/07/27 09:57:26 skrll Exp $" ); |
41 | |
42 | #ifdef _KERNEL_OPT |
43 | #include "opt_ddb.h" |
44 | #include "opt_ipkdb.h" |
45 | #include "opt_kgdb.h" |
46 | #include "opt_dump.h" |
47 | #include "opt_rnd_printf.h" |
48 | #endif |
49 | |
50 | #include <sys/param.h> |
51 | #include <sys/stdint.h> |
52 | #include <sys/systm.h> |
53 | #include <sys/buf.h> |
54 | #include <sys/device.h> |
55 | #include <sys/reboot.h> |
56 | #include <sys/msgbuf.h> |
57 | #include <sys/proc.h> |
58 | #include <sys/ioctl.h> |
59 | #include <sys/vnode.h> |
60 | #include <sys/file.h> |
61 | #include <sys/tty.h> |
62 | #include <sys/tprintf.h> |
63 | #include <sys/spldebug.h> |
64 | #include <sys/syslog.h> |
65 | #include <sys/kprintf.h> |
66 | #include <sys/atomic.h> |
67 | #include <sys/kernel.h> |
68 | #include <sys/cpu.h> |
69 | #include <sys/sha2.h> |
70 | #include <sys/rndsource.h> |
71 | |
72 | #include <dev/cons.h> |
73 | |
74 | #include <net/if.h> |
75 | |
76 | #ifdef IPKDB |
77 | #include <ipkdb/ipkdb.h> |
78 | #endif |
79 | |
80 | static kmutex_t kprintf_mtx; |
81 | static bool kprintf_inited = false; |
82 | |
83 | #ifdef KGDB |
84 | #include <sys/kgdb.h> |
85 | #endif |
86 | |
87 | #ifdef DDB |
88 | #include <ddb/ddbvar.h> /* db_panic */ |
89 | #include <ddb/db_output.h> /* db_printf, db_putchar prototypes */ |
90 | #endif |
91 | |
92 | |
93 | /* |
94 | * defines |
95 | */ |
96 | |
97 | |
98 | /* |
99 | * local prototypes |
100 | */ |
101 | |
102 | static void putchar(int, int, struct tty *); |
103 | |
104 | |
105 | /* |
106 | * globals |
107 | */ |
108 | |
109 | extern struct tty *constty; /* pointer to console "window" tty */ |
110 | extern int log_open; /* subr_log: is /dev/klog open? */ |
111 | extern krndsource_t rnd_printf_source; |
112 | const char *panicstr; /* arg to first call to panic (used as a flag |
113 | to indicate that panic has already been called). */ |
114 | struct cpu_info *paniccpu; /* cpu that first paniced */ |
115 | long panicstart, panicend; /* position in the msgbuf of the start and |
116 | end of the formatted panicstr. */ |
117 | int doing_shutdown; /* set to indicate shutdown in progress */ |
118 | |
119 | #ifdef RND_PRINTF |
120 | static bool kprintf_inited_callout = false; |
121 | static SHA512_CTX kprnd_sha; |
122 | static uint8_t kprnd_accum[SHA512_DIGEST_LENGTH]; |
123 | static int kprnd_added; |
124 | |
125 | static struct callout kprnd_callout; |
126 | #endif |
127 | |
128 | #ifndef DUMP_ON_PANIC |
129 | #define DUMP_ON_PANIC 1 |
130 | #endif |
131 | int dumponpanic = DUMP_ON_PANIC; |
132 | |
133 | /* |
134 | * v_putc: routine to putc on virtual console |
135 | * |
136 | * the v_putc pointer can be used to redirect the console cnputc elsewhere |
137 | * [e.g. to a "virtual console"]. |
138 | */ |
139 | |
140 | void (*v_putc)(int) = cnputc; /* start with cnputc (normal cons) */ |
141 | void (*v_flush)(void) = cnflush; /* start with cnflush (normal cons) */ |
142 | |
143 | const char hexdigits[] = "0123456789abcdef" ; |
144 | const char HEXDIGITS[] = "0123456789ABCDEF" ; |
145 | |
146 | |
147 | /* |
148 | * functions |
149 | */ |
150 | |
151 | #ifdef RND_PRINTF |
152 | static void kprintf_rnd_get(size_t bytes, void *priv) |
153 | { |
154 | if (kprnd_added) { |
155 | KASSERT(kprintf_inited); |
156 | if (mutex_tryenter(&kprintf_mtx)) { |
157 | SHA512_Final(kprnd_accum, &kprnd_sha); |
158 | rnd_add_data(&rnd_printf_source, |
159 | kprnd_accum, sizeof(kprnd_accum), 0); |
160 | kprnd_added = 0; |
161 | /* This, we must do, since we called _Final. */ |
162 | SHA512_Init(&kprnd_sha); |
163 | /* This is optional but seems useful. */ |
164 | SHA512_Update(&kprnd_sha, kprnd_accum, |
165 | sizeof(kprnd_accum)); |
166 | mutex_exit(&kprintf_mtx); |
167 | } |
168 | } |
169 | } |
170 | |
171 | static void kprintf_rnd_callout(void *arg) |
172 | { |
173 | kprintf_rnd_get(0, NULL); |
174 | callout_schedule(&kprnd_callout, hz); |
175 | } |
176 | |
177 | #endif |
178 | |
179 | /* |
180 | * Locking is inited fairly early in MI bootstrap. Before that |
181 | * prints are done unlocked. But that doesn't really matter, |
182 | * since nothing can preempt us before interrupts are enabled. |
183 | */ |
184 | void |
185 | kprintf_init(void) |
186 | { |
187 | |
188 | KASSERT(!kprintf_inited && cold); /* not foolproof, but ... */ |
189 | #ifdef RND_PRINTF |
190 | SHA512_Init(&kprnd_sha); |
191 | #endif |
192 | mutex_init(&kprintf_mtx, MUTEX_DEFAULT, IPL_HIGH); |
193 | kprintf_inited = true; |
194 | } |
195 | |
196 | #ifdef RND_PRINTF |
197 | void |
198 | kprintf_init_callout(void) |
199 | { |
200 | KASSERT(!kprintf_inited_callout); |
201 | callout_init(&kprnd_callout, CALLOUT_MPSAFE); |
202 | callout_setfunc(&kprnd_callout, kprintf_rnd_callout, NULL); |
203 | callout_schedule(&kprnd_callout, hz); |
204 | kprintf_inited_callout = true; |
205 | } |
206 | #endif |
207 | |
208 | void |
209 | kprintf_lock(void) |
210 | { |
211 | |
212 | if (__predict_true(kprintf_inited)) |
213 | mutex_enter(&kprintf_mtx); |
214 | } |
215 | |
216 | void |
217 | kprintf_unlock(void) |
218 | { |
219 | |
220 | if (__predict_true(kprintf_inited)) { |
221 | /* assert kprintf wasn't somehow inited while we were in */ |
222 | KASSERT(mutex_owned(&kprintf_mtx)); |
223 | mutex_exit(&kprintf_mtx); |
224 | } |
225 | } |
226 | |
227 | /* |
228 | * twiddle: spin a little propellor on the console. |
229 | */ |
230 | |
231 | void |
232 | twiddle(void) |
233 | { |
234 | static const char twiddle_chars[] = "|/-\\" ; |
235 | static int pos; |
236 | |
237 | kprintf_lock(); |
238 | |
239 | putchar(twiddle_chars[pos++ & 3], TOCONS, NULL); |
240 | putchar('\b', TOCONS, NULL); |
241 | |
242 | kprintf_unlock(); |
243 | } |
244 | |
245 | /* |
246 | * panic: handle an unresolvable fatal error |
247 | * |
248 | * prints "panic: <message>" and reboots. if called twice (i.e. recursive |
249 | * call) we avoid trying to dump and just reboot (to avoid recursive panics). |
250 | */ |
251 | |
252 | void |
253 | panic(const char *fmt, ...) |
254 | { |
255 | va_list ap; |
256 | |
257 | va_start(ap, fmt); |
258 | vpanic(fmt, ap); |
259 | va_end(ap); |
260 | } |
261 | |
262 | void |
263 | vpanic(const char *fmt, va_list ap) |
264 | { |
265 | CPU_INFO_ITERATOR cii; |
266 | struct cpu_info *ci, *oci; |
267 | int bootopt; |
268 | static char scratchstr[384]; /* stores panic message */ |
269 | |
270 | spldebug_stop(); |
271 | |
272 | if (lwp0.l_cpu && curlwp) { |
273 | /* |
274 | * Disable preemption. If already panicing on another CPU, sit |
275 | * here and spin until the system is rebooted. Allow the CPU that |
276 | * first paniced to panic again. |
277 | */ |
278 | kpreempt_disable(); |
279 | ci = curcpu(); |
280 | oci = atomic_cas_ptr((void *)&paniccpu, NULL, ci); |
281 | if (oci != NULL && oci != ci) { |
282 | /* Give interrupts a chance to try and prevent deadlock. */ |
283 | for (;;) { |
284 | #ifndef _RUMPKERNEL /* XXXpooka: temporary build fix, see kern/40505 */ |
285 | DELAY(10); |
286 | #endif /* _RUMPKERNEL */ |
287 | } |
288 | } |
289 | |
290 | /* |
291 | * Convert the current thread to a bound thread and prevent all |
292 | * CPUs from scheduling unbound jobs. Do so without taking any |
293 | * locks. |
294 | */ |
295 | curlwp->l_pflag |= LP_BOUND; |
296 | for (CPU_INFO_FOREACH(cii, ci)) { |
297 | ci->ci_schedstate.spc_flags |= SPCF_OFFLINE; |
298 | } |
299 | } |
300 | |
301 | bootopt = RB_AUTOBOOT | RB_NOSYNC; |
302 | if (!doing_shutdown) { |
303 | if (dumponpanic) |
304 | bootopt |= RB_DUMP; |
305 | } else |
306 | printf("Skipping crash dump on recursive panic\n" ); |
307 | |
308 | doing_shutdown = 1; |
309 | |
310 | if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC) |
311 | panicstart = msgbufp->msg_bufx; |
312 | |
313 | printf("panic: " ); |
314 | if (panicstr == NULL) { |
315 | /* first time in panic - store fmt first for precaution */ |
316 | panicstr = fmt; |
317 | |
318 | vsnprintf(scratchstr, sizeof(scratchstr), fmt, ap); |
319 | printf("%s" , scratchstr); |
320 | panicstr = scratchstr; |
321 | } else { |
322 | vprintf(fmt, ap); |
323 | } |
324 | printf("\n" ); |
325 | |
326 | if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC) |
327 | panicend = msgbufp->msg_bufx; |
328 | |
329 | #ifdef IPKDB |
330 | ipkdb_panic(); |
331 | #endif |
332 | #ifdef KGDB |
333 | kgdb_panic(); |
334 | #endif |
335 | #ifdef KADB |
336 | if (boothowto & RB_KDB) |
337 | kdbpanic(); |
338 | #endif |
339 | #ifdef DDB |
340 | db_panic(); |
341 | #endif |
342 | cpu_reboot(bootopt, NULL); |
343 | } |
344 | |
345 | /* |
346 | * kernel logging functions: log, logpri, addlog |
347 | */ |
348 | |
349 | /* |
350 | * log: write to the log buffer |
351 | * |
352 | * => will not sleep [so safe to call from interrupt] |
353 | * => will log to console if /dev/klog isn't open |
354 | */ |
355 | |
356 | void |
357 | log(int level, const char *fmt, ...) |
358 | { |
359 | va_list ap; |
360 | |
361 | kprintf_lock(); |
362 | |
363 | klogpri(level); /* log the level first */ |
364 | va_start(ap, fmt); |
365 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
366 | va_end(ap); |
367 | if (!log_open) { |
368 | va_start(ap, fmt); |
369 | kprintf(fmt, TOCONS, NULL, NULL, ap); |
370 | va_end(ap); |
371 | } |
372 | |
373 | kprintf_unlock(); |
374 | |
375 | logwakeup(); /* wake up anyone waiting for log msgs */ |
376 | } |
377 | |
378 | /* |
379 | * vlog: write to the log buffer [already have va_list] |
380 | */ |
381 | |
382 | void |
383 | vlog(int level, const char *fmt, va_list ap) |
384 | { |
385 | va_list cap; |
386 | |
387 | va_copy(cap, ap); |
388 | kprintf_lock(); |
389 | |
390 | klogpri(level); /* log the level first */ |
391 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
392 | if (!log_open) |
393 | kprintf(fmt, TOCONS, NULL, NULL, cap); |
394 | |
395 | kprintf_unlock(); |
396 | va_end(cap); |
397 | |
398 | logwakeup(); /* wake up anyone waiting for log msgs */ |
399 | } |
400 | |
401 | /* |
402 | * logpri: log the priority level to the klog |
403 | */ |
404 | |
405 | void |
406 | logpri(int level) |
407 | { |
408 | |
409 | kprintf_lock(); |
410 | klogpri(level); |
411 | kprintf_unlock(); |
412 | } |
413 | |
414 | /* |
415 | * Note: we must be in the mutex here! |
416 | */ |
417 | void |
418 | klogpri(int level) |
419 | { |
420 | char *p; |
421 | char snbuf[KPRINTF_BUFSIZE]; |
422 | |
423 | putchar('<', TOLOG, NULL); |
424 | snprintf(snbuf, sizeof(snbuf), "%d" , level); |
425 | for (p = snbuf ; *p ; p++) |
426 | putchar(*p, TOLOG, NULL); |
427 | putchar('>', TOLOG, NULL); |
428 | } |
429 | |
430 | /* |
431 | * addlog: add info to previous log message |
432 | */ |
433 | |
434 | void |
435 | addlog(const char *fmt, ...) |
436 | { |
437 | va_list ap; |
438 | |
439 | kprintf_lock(); |
440 | |
441 | va_start(ap, fmt); |
442 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
443 | va_end(ap); |
444 | if (!log_open) { |
445 | va_start(ap, fmt); |
446 | kprintf(fmt, TOCONS, NULL, NULL, ap); |
447 | va_end(ap); |
448 | } |
449 | |
450 | kprintf_unlock(); |
451 | |
452 | logwakeup(); |
453 | } |
454 | |
455 | |
456 | /* |
457 | * putchar: print a single character on console or user terminal. |
458 | * |
459 | * => if console, then the last MSGBUFS chars are saved in msgbuf |
460 | * for inspection later (e.g. dmesg/syslog) |
461 | * => we must already be in the mutex! |
462 | */ |
463 | static void |
464 | putchar(int c, int flags, struct tty *tp) |
465 | { |
466 | #ifdef RND_PRINTF |
467 | uint8_t rbuf[SHA512_BLOCK_LENGTH]; |
468 | static int cursor; |
469 | #endif |
470 | if (panicstr) |
471 | constty = NULL; |
472 | if ((flags & TOCONS) && tp == NULL && constty) { |
473 | tp = constty; |
474 | flags |= TOTTY; |
475 | } |
476 | if ((flags & TOTTY) && tp && |
477 | tputchar(c, flags, tp) < 0 && |
478 | (flags & TOCONS) && tp == constty) |
479 | constty = NULL; |
480 | if ((flags & TOLOG) && |
481 | c != '\0' && c != '\r' && c != 0177) |
482 | logputchar(c); |
483 | if ((flags & TOCONS) && constty == NULL && c != '\0') |
484 | (*v_putc)(c); |
485 | #ifdef DDB |
486 | if (flags & TODDB) { |
487 | db_putchar(c); |
488 | return; |
489 | } |
490 | #endif |
491 | |
492 | #ifdef RND_PRINTF |
493 | if (__predict_true(kprintf_inited)) { |
494 | rbuf[cursor] = c; |
495 | if (cursor == sizeof(rbuf) - 1) { |
496 | SHA512_Update(&kprnd_sha, rbuf, sizeof(rbuf)); |
497 | kprnd_added++; |
498 | cursor = 0; |
499 | } else { |
500 | cursor++; |
501 | } |
502 | } |
503 | #endif |
504 | } |
505 | |
506 | /* |
507 | * tablefull: warn that a system table is full |
508 | */ |
509 | |
510 | void |
511 | tablefull(const char *tab, const char *hint) |
512 | { |
513 | if (hint) |
514 | log(LOG_ERR, "%s: table is full - %s\n" , tab, hint); |
515 | else |
516 | log(LOG_ERR, "%s: table is full\n" , tab); |
517 | } |
518 | |
519 | |
520 | /* |
521 | * uprintf: print to the controlling tty of the current process |
522 | * |
523 | * => we may block if the tty queue is full |
524 | * => no message is printed if the queue doesn't clear in a reasonable |
525 | * time |
526 | */ |
527 | |
528 | void |
529 | uprintf(const char *fmt, ...) |
530 | { |
531 | struct proc *p = curproc; |
532 | va_list ap; |
533 | |
534 | /* mutex_enter(proc_lock); XXXSMP */ |
535 | |
536 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { |
537 | /* No mutex needed; going to process TTY. */ |
538 | va_start(ap, fmt); |
539 | kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap); |
540 | va_end(ap); |
541 | } |
542 | |
543 | /* mutex_exit(proc_lock); XXXSMP */ |
544 | } |
545 | |
546 | void |
547 | uprintf_locked(const char *fmt, ...) |
548 | { |
549 | struct proc *p = curproc; |
550 | va_list ap; |
551 | |
552 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { |
553 | /* No mutex needed; going to process TTY. */ |
554 | va_start(ap, fmt); |
555 | kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap); |
556 | va_end(ap); |
557 | } |
558 | } |
559 | |
560 | /* |
561 | * tprintf functions: used to send messages to a specific process |
562 | * |
563 | * usage: |
564 | * get a tpr_t handle on a process "p" by using "tprintf_open(p)" |
565 | * use the handle when calling "tprintf" |
566 | * when done, do a "tprintf_close" to drop the handle |
567 | */ |
568 | |
569 | /* |
570 | * tprintf_open: get a tprintf handle on a process "p" |
571 | * |
572 | * => returns NULL if process can't be printed to |
573 | */ |
574 | |
575 | tpr_t |
576 | tprintf_open(struct proc *p) |
577 | { |
578 | tpr_t cookie; |
579 | |
580 | cookie = NULL; |
581 | |
582 | mutex_enter(proc_lock); |
583 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { |
584 | proc_sesshold(p->p_session); |
585 | cookie = (tpr_t)p->p_session; |
586 | } |
587 | mutex_exit(proc_lock); |
588 | |
589 | return cookie; |
590 | } |
591 | |
592 | /* |
593 | * tprintf_close: dispose of a tprintf handle obtained with tprintf_open |
594 | */ |
595 | |
596 | void |
597 | tprintf_close(tpr_t sess) |
598 | { |
599 | |
600 | if (sess) { |
601 | mutex_enter(proc_lock); |
602 | /* Releases proc_lock. */ |
603 | proc_sessrele((struct session *)sess); |
604 | } |
605 | } |
606 | |
607 | /* |
608 | * tprintf: given tprintf handle to a process [obtained with tprintf_open], |
609 | * send a message to the controlling tty for that process. |
610 | * |
611 | * => also sends message to /dev/klog |
612 | */ |
613 | void |
614 | tprintf(tpr_t tpr, const char *fmt, ...) |
615 | { |
616 | struct session *sess = (struct session *)tpr; |
617 | struct tty *tp = NULL; |
618 | int flags = TOLOG; |
619 | va_list ap; |
620 | |
621 | /* mutex_enter(proc_lock); XXXSMP */ |
622 | if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { |
623 | flags |= TOTTY; |
624 | tp = sess->s_ttyp; |
625 | } |
626 | |
627 | kprintf_lock(); |
628 | |
629 | klogpri(LOG_INFO); |
630 | va_start(ap, fmt); |
631 | kprintf(fmt, flags, tp, NULL, ap); |
632 | va_end(ap); |
633 | |
634 | kprintf_unlock(); |
635 | /* mutex_exit(proc_lock); XXXSMP */ |
636 | |
637 | logwakeup(); |
638 | } |
639 | |
640 | |
641 | /* |
642 | * ttyprintf: send a message to a specific tty |
643 | * |
644 | * => should be used only by tty driver or anything that knows the |
645 | * underlying tty will not be revoked(2)'d away. [otherwise, |
646 | * use tprintf] |
647 | */ |
648 | void |
649 | ttyprintf(struct tty *tp, const char *fmt, ...) |
650 | { |
651 | va_list ap; |
652 | |
653 | /* No mutex needed; going to process TTY. */ |
654 | va_start(ap, fmt); |
655 | kprintf(fmt, TOTTY, tp, NULL, ap); |
656 | va_end(ap); |
657 | } |
658 | |
659 | #ifdef DDB |
660 | |
661 | /* |
662 | * db_printf: printf for DDB (via db_putchar) |
663 | */ |
664 | |
665 | void |
666 | db_printf(const char *fmt, ...) |
667 | { |
668 | va_list ap; |
669 | |
670 | /* No mutex needed; DDB pauses all processors. */ |
671 | va_start(ap, fmt); |
672 | kprintf(fmt, TODDB, NULL, NULL, ap); |
673 | va_end(ap); |
674 | |
675 | if (db_tee_msgbuf) { |
676 | va_start(ap, fmt); |
677 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
678 | va_end(ap); |
679 | } |
680 | } |
681 | |
682 | void |
683 | db_vprintf(const char *fmt, va_list ap) |
684 | { |
685 | va_list cap; |
686 | |
687 | va_copy(cap, ap); |
688 | /* No mutex needed; DDB pauses all processors. */ |
689 | kprintf(fmt, TODDB, NULL, NULL, ap); |
690 | if (db_tee_msgbuf) |
691 | kprintf(fmt, TOLOG, NULL, NULL, cap); |
692 | va_end(cap); |
693 | } |
694 | |
695 | #endif /* DDB */ |
696 | |
697 | static void |
698 | kprintf_internal(const char *fmt, int oflags, void *vp, char *sbuf, ...) |
699 | { |
700 | va_list ap; |
701 | |
702 | va_start(ap, sbuf); |
703 | (void)kprintf(fmt, oflags, vp, sbuf, ap); |
704 | va_end(ap); |
705 | } |
706 | |
707 | /* |
708 | * Device autoconfiguration printf routines. These change their |
709 | * behavior based on the AB_* flags in boothowto. If AB_SILENT |
710 | * is set, messages never go to the console (but they still always |
711 | * go to the log). AB_VERBOSE overrides AB_SILENT. |
712 | */ |
713 | |
714 | /* |
715 | * aprint_normal: Send to console unless AB_QUIET. Always goes |
716 | * to the log. |
717 | */ |
718 | static void |
719 | aprint_normal_internal(const char *prefix, const char *fmt, va_list ap) |
720 | { |
721 | int flags = TOLOG; |
722 | |
723 | if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 || |
724 | (boothowto & AB_VERBOSE) != 0) |
725 | flags |= TOCONS; |
726 | |
727 | kprintf_lock(); |
728 | |
729 | if (prefix) |
730 | kprintf_internal("%s: " , flags, NULL, NULL, prefix); |
731 | kprintf(fmt, flags, NULL, NULL, ap); |
732 | |
733 | kprintf_unlock(); |
734 | |
735 | if (!panicstr) |
736 | logwakeup(); |
737 | } |
738 | |
739 | void |
740 | aprint_normal(const char *fmt, ...) |
741 | { |
742 | va_list ap; |
743 | |
744 | va_start(ap, fmt); |
745 | aprint_normal_internal(NULL, fmt, ap); |
746 | va_end(ap); |
747 | } |
748 | |
749 | void |
750 | aprint_normal_dev(device_t dv, const char *fmt, ...) |
751 | { |
752 | va_list ap; |
753 | |
754 | va_start(ap, fmt); |
755 | aprint_normal_internal(device_xname(dv), fmt, ap); |
756 | va_end(ap); |
757 | } |
758 | |
759 | void |
760 | aprint_normal_ifnet(struct ifnet *ifp, const char *fmt, ...) |
761 | { |
762 | va_list ap; |
763 | |
764 | va_start(ap, fmt); |
765 | aprint_normal_internal(ifp->if_xname, fmt, ap); |
766 | va_end(ap); |
767 | } |
768 | |
769 | /* |
770 | * aprint_error: Send to console unless AB_QUIET. Always goes |
771 | * to the log. Also counts the number of times called so other |
772 | * parts of the kernel can report the number of errors during a |
773 | * given phase of system startup. |
774 | */ |
775 | static int aprint_error_count; |
776 | |
777 | int |
778 | aprint_get_error_count(void) |
779 | { |
780 | int count; |
781 | |
782 | kprintf_lock(); |
783 | |
784 | count = aprint_error_count; |
785 | aprint_error_count = 0; |
786 | |
787 | kprintf_unlock(); |
788 | |
789 | return (count); |
790 | } |
791 | |
792 | static void |
793 | aprint_error_internal(const char *prefix, const char *fmt, va_list ap) |
794 | { |
795 | int flags = TOLOG; |
796 | |
797 | if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 || |
798 | (boothowto & AB_VERBOSE) != 0) |
799 | flags |= TOCONS; |
800 | |
801 | kprintf_lock(); |
802 | |
803 | aprint_error_count++; |
804 | |
805 | if (prefix) |
806 | kprintf_internal("%s: " , flags, NULL, NULL, prefix); |
807 | kprintf(fmt, flags, NULL, NULL, ap); |
808 | |
809 | kprintf_unlock(); |
810 | |
811 | if (!panicstr) |
812 | logwakeup(); |
813 | } |
814 | |
815 | void |
816 | aprint_error(const char *fmt, ...) |
817 | { |
818 | va_list ap; |
819 | |
820 | va_start(ap, fmt); |
821 | aprint_error_internal(NULL, fmt, ap); |
822 | va_end(ap); |
823 | } |
824 | |
825 | void |
826 | aprint_error_dev(device_t dv, const char *fmt, ...) |
827 | { |
828 | va_list ap; |
829 | |
830 | va_start(ap, fmt); |
831 | aprint_error_internal(device_xname(dv), fmt, ap); |
832 | va_end(ap); |
833 | } |
834 | |
835 | void |
836 | aprint_error_ifnet(struct ifnet *ifp, const char *fmt, ...) |
837 | { |
838 | va_list ap; |
839 | |
840 | va_start(ap, fmt); |
841 | aprint_error_internal(ifp->if_xname, fmt, ap); |
842 | va_end(ap); |
843 | } |
844 | |
845 | /* |
846 | * aprint_naive: Send to console only if AB_QUIET. Never goes |
847 | * to the log. |
848 | */ |
849 | static void |
850 | aprint_naive_internal(const char *prefix, const char *fmt, va_list ap) |
851 | { |
852 | if ((boothowto & (AB_QUIET|AB_SILENT|AB_VERBOSE)) != AB_QUIET) |
853 | return; |
854 | |
855 | kprintf_lock(); |
856 | |
857 | if (prefix) |
858 | kprintf_internal("%s: " , TOCONS, NULL, NULL, prefix); |
859 | kprintf(fmt, TOCONS, NULL, NULL, ap); |
860 | |
861 | kprintf_unlock(); |
862 | } |
863 | |
864 | void |
865 | aprint_naive(const char *fmt, ...) |
866 | { |
867 | va_list ap; |
868 | |
869 | va_start(ap, fmt); |
870 | aprint_naive_internal(NULL, fmt, ap); |
871 | va_end(ap); |
872 | } |
873 | |
874 | void |
875 | aprint_naive_dev(device_t dv, const char *fmt, ...) |
876 | { |
877 | va_list ap; |
878 | |
879 | va_start(ap, fmt); |
880 | aprint_naive_internal(device_xname(dv), fmt, ap); |
881 | va_end(ap); |
882 | } |
883 | |
884 | void |
885 | aprint_naive_ifnet(struct ifnet *ifp, const char *fmt, ...) |
886 | { |
887 | va_list ap; |
888 | |
889 | va_start(ap, fmt); |
890 | aprint_naive_internal(ifp->if_xname, fmt, ap); |
891 | va_end(ap); |
892 | } |
893 | |
894 | /* |
895 | * aprint_verbose: Send to console only if AB_VERBOSE. Always |
896 | * goes to the log. |
897 | */ |
898 | static void |
899 | aprint_verbose_internal(const char *prefix, const char *fmt, va_list ap) |
900 | { |
901 | int flags = TOLOG; |
902 | |
903 | if (boothowto & AB_VERBOSE) |
904 | flags |= TOCONS; |
905 | |
906 | kprintf_lock(); |
907 | |
908 | if (prefix) |
909 | kprintf_internal("%s: " , flags, NULL, NULL, prefix); |
910 | kprintf(fmt, flags, NULL, NULL, ap); |
911 | |
912 | kprintf_unlock(); |
913 | |
914 | if (!panicstr) |
915 | logwakeup(); |
916 | } |
917 | |
918 | void |
919 | aprint_verbose(const char *fmt, ...) |
920 | { |
921 | va_list ap; |
922 | |
923 | va_start(ap, fmt); |
924 | aprint_verbose_internal(NULL, fmt, ap); |
925 | va_end(ap); |
926 | } |
927 | |
928 | void |
929 | aprint_verbose_dev(device_t dv, const char *fmt, ...) |
930 | { |
931 | va_list ap; |
932 | |
933 | va_start(ap, fmt); |
934 | aprint_verbose_internal(device_xname(dv), fmt, ap); |
935 | va_end(ap); |
936 | } |
937 | |
938 | void |
939 | aprint_verbose_ifnet(struct ifnet *ifp, const char *fmt, ...) |
940 | { |
941 | va_list ap; |
942 | |
943 | va_start(ap, fmt); |
944 | aprint_verbose_internal(ifp->if_xname, fmt, ap); |
945 | va_end(ap); |
946 | } |
947 | |
948 | /* |
949 | * aprint_debug: Send to console and log only if AB_DEBUG. |
950 | */ |
951 | static void |
952 | aprint_debug_internal(const char *prefix, const char *fmt, va_list ap) |
953 | { |
954 | if ((boothowto & AB_DEBUG) == 0) |
955 | return; |
956 | |
957 | kprintf_lock(); |
958 | |
959 | if (prefix) |
960 | kprintf_internal("%s: " , TOCONS | TOLOG, NULL, NULL, prefix); |
961 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); |
962 | |
963 | kprintf_unlock(); |
964 | } |
965 | |
966 | void |
967 | aprint_debug(const char *fmt, ...) |
968 | { |
969 | va_list ap; |
970 | |
971 | va_start(ap, fmt); |
972 | aprint_debug_internal(NULL, fmt, ap); |
973 | va_end(ap); |
974 | } |
975 | |
976 | void |
977 | aprint_debug_dev(device_t dv, const char *fmt, ...) |
978 | { |
979 | va_list ap; |
980 | |
981 | va_start(ap, fmt); |
982 | aprint_debug_internal(device_xname(dv), fmt, ap); |
983 | va_end(ap); |
984 | } |
985 | |
986 | void |
987 | aprint_debug_ifnet(struct ifnet *ifp, const char *fmt, ...) |
988 | { |
989 | va_list ap; |
990 | |
991 | va_start(ap, fmt); |
992 | aprint_debug_internal(ifp->if_xname, fmt, ap); |
993 | va_end(ap); |
994 | } |
995 | |
996 | void |
997 | printf_tolog(const char *fmt, ...) |
998 | { |
999 | va_list ap; |
1000 | |
1001 | kprintf_lock(); |
1002 | |
1003 | va_start(ap, fmt); |
1004 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
1005 | va_end(ap); |
1006 | |
1007 | kprintf_unlock(); |
1008 | } |
1009 | |
1010 | /* |
1011 | * printf_nolog: Like printf(), but does not send message to the log. |
1012 | */ |
1013 | |
1014 | void |
1015 | printf_nolog(const char *fmt, ...) |
1016 | { |
1017 | va_list ap; |
1018 | |
1019 | kprintf_lock(); |
1020 | |
1021 | va_start(ap, fmt); |
1022 | kprintf(fmt, TOCONS, NULL, NULL, ap); |
1023 | va_end(ap); |
1024 | |
1025 | kprintf_unlock(); |
1026 | } |
1027 | |
1028 | /* |
1029 | * normal kernel printf functions: printf, vprintf, snprintf, vsnprintf |
1030 | */ |
1031 | |
1032 | /* |
1033 | * printf: print a message to the console and the log |
1034 | */ |
1035 | void |
1036 | printf(const char *fmt, ...) |
1037 | { |
1038 | va_list ap; |
1039 | |
1040 | kprintf_lock(); |
1041 | |
1042 | va_start(ap, fmt); |
1043 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); |
1044 | va_end(ap); |
1045 | |
1046 | kprintf_unlock(); |
1047 | |
1048 | if (!panicstr) |
1049 | logwakeup(); |
1050 | } |
1051 | |
1052 | /* |
1053 | * vprintf: print a message to the console and the log [already have |
1054 | * va_list] |
1055 | */ |
1056 | |
1057 | void |
1058 | vprintf(const char *fmt, va_list ap) |
1059 | { |
1060 | kprintf_lock(); |
1061 | |
1062 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); |
1063 | |
1064 | kprintf_unlock(); |
1065 | |
1066 | if (!panicstr) |
1067 | logwakeup(); |
1068 | } |
1069 | |
1070 | /* |
1071 | * snprintf: print a message to a buffer |
1072 | */ |
1073 | int |
1074 | snprintf(char *bf, size_t size, const char *fmt, ...) |
1075 | { |
1076 | int retval; |
1077 | va_list ap; |
1078 | |
1079 | va_start(ap, fmt); |
1080 | retval = vsnprintf(bf, size, fmt, ap); |
1081 | va_end(ap); |
1082 | |
1083 | return retval; |
1084 | } |
1085 | |
1086 | /* |
1087 | * vsnprintf: print a message to a buffer [already have va_list] |
1088 | */ |
1089 | int |
1090 | vsnprintf(char *bf, size_t size, const char *fmt, va_list ap) |
1091 | { |
1092 | int retval; |
1093 | char *p; |
1094 | |
1095 | p = bf + size; |
1096 | retval = kprintf(fmt, TOBUFONLY, &p, bf, ap); |
1097 | if (bf && size > 0) { |
1098 | /* nul terminate */ |
1099 | if (size <= (size_t)retval) |
1100 | bf[size - 1] = '\0'; |
1101 | else |
1102 | bf[retval] = '\0'; |
1103 | } |
1104 | return retval; |
1105 | } |
1106 | |
1107 | /* |
1108 | * kprintf: scaled down version of printf(3). |
1109 | * |
1110 | * this version based on vfprintf() from libc which was derived from |
1111 | * software contributed to Berkeley by Chris Torek. |
1112 | * |
1113 | * NOTE: The kprintf mutex must be held if we're going TOBUF or TOCONS! |
1114 | */ |
1115 | |
1116 | /* |
1117 | * macros for converting digits to letters and vice versa |
1118 | */ |
1119 | #define to_digit(c) ((c) - '0') |
1120 | #define is_digit(c) ((unsigned)to_digit(c) <= 9) |
1121 | #define to_char(n) ((n) + '0') |
1122 | |
1123 | /* |
1124 | * flags used during conversion. |
1125 | */ |
1126 | #define ALT 0x001 /* alternate form */ |
1127 | #define HEXPREFIX 0x002 /* add 0x or 0X prefix */ |
1128 | #define LADJUST 0x004 /* left adjustment */ |
1129 | #define LONGDBL 0x008 /* long double; unimplemented */ |
1130 | #define LONGINT 0x010 /* long integer */ |
1131 | #define QUADINT 0x020 /* quad integer */ |
1132 | #define SHORTINT 0x040 /* short integer */ |
1133 | #define MAXINT 0x080 /* intmax_t */ |
1134 | #define PTRINT 0x100 /* intptr_t */ |
1135 | #define SIZEINT 0x200 /* size_t */ |
1136 | #define ZEROPAD 0x400 /* zero (as opposed to blank) pad */ |
1137 | #define FPT 0x800 /* Floating point number */ |
1138 | |
1139 | /* |
1140 | * To extend shorts properly, we need both signed and unsigned |
1141 | * argument extraction methods. |
1142 | */ |
1143 | #define SARG() \ |
1144 | (flags&MAXINT ? va_arg(ap, intmax_t) : \ |
1145 | flags&PTRINT ? va_arg(ap, intptr_t) : \ |
1146 | flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \ |
1147 | flags&QUADINT ? va_arg(ap, quad_t) : \ |
1148 | flags&LONGINT ? va_arg(ap, long) : \ |
1149 | flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ |
1150 | (long)va_arg(ap, int)) |
1151 | #define UARG() \ |
1152 | (flags&MAXINT ? va_arg(ap, uintmax_t) : \ |
1153 | flags&PTRINT ? va_arg(ap, uintptr_t) : \ |
1154 | flags&SIZEINT ? va_arg(ap, size_t) : \ |
1155 | flags&QUADINT ? va_arg(ap, u_quad_t) : \ |
1156 | flags&LONGINT ? va_arg(ap, u_long) : \ |
1157 | flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \ |
1158 | (u_long)va_arg(ap, u_int)) |
1159 | |
1160 | #define KPRINTF_PUTCHAR(C) { \ |
1161 | if (oflags == TOBUFONLY) { \ |
1162 | if (sbuf && ((vp == NULL) || (sbuf < tailp))) \ |
1163 | *sbuf++ = (C); \ |
1164 | } else { \ |
1165 | putchar((C), oflags, vp); \ |
1166 | } \ |
1167 | } |
1168 | |
1169 | void |
1170 | device_printf(device_t dev, const char *fmt, ...) |
1171 | { |
1172 | va_list ap; |
1173 | |
1174 | va_start(ap, fmt); |
1175 | printf("%s: " , device_xname(dev)); |
1176 | vprintf(fmt, ap); |
1177 | va_end(ap); |
1178 | return; |
1179 | } |
1180 | |
1181 | /* |
1182 | * Guts of kernel printf. Note, we already expect to be in a mutex! |
1183 | */ |
1184 | int |
1185 | kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap) |
1186 | { |
1187 | const char *fmt; /* format string */ |
1188 | int ch; /* character from fmt */ |
1189 | int n; /* handy integer (short term usage) */ |
1190 | char *cp; /* handy char pointer (short term usage) */ |
1191 | int flags; /* flags as above */ |
1192 | int ret; /* return value accumulator */ |
1193 | int width; /* width from format (%8d), or 0 */ |
1194 | int prec; /* precision from format (%.3d), or -1 */ |
1195 | char sign; /* sign prefix (' ', '+', '-', or \0) */ |
1196 | |
1197 | u_quad_t _uquad; /* integer arguments %[diouxX] */ |
1198 | enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ |
1199 | int dprec; /* a copy of prec if [diouxX], 0 otherwise */ |
1200 | int realsz; /* field size expanded by dprec */ |
1201 | int size; /* size of converted field or string */ |
1202 | const char *xdigs; /* digits for [xX] conversion */ |
1203 | char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */ |
1204 | char *tailp; /* tail pointer for snprintf */ |
1205 | |
1206 | if (oflags == TOBUFONLY && (vp != NULL)) |
1207 | tailp = *(char **)vp; |
1208 | else |
1209 | tailp = NULL; |
1210 | |
1211 | cp = NULL; /* XXX: shutup gcc */ |
1212 | size = 0; /* XXX: shutup gcc */ |
1213 | |
1214 | fmt = fmt0; |
1215 | ret = 0; |
1216 | |
1217 | xdigs = NULL; /* XXX: shut up gcc warning */ |
1218 | |
1219 | /* |
1220 | * Scan the format for conversions (`%' character). |
1221 | */ |
1222 | for (;;) { |
1223 | for (; *fmt != '%' && *fmt; fmt++) { |
1224 | ret++; |
1225 | KPRINTF_PUTCHAR(*fmt); |
1226 | } |
1227 | if (*fmt == 0) |
1228 | goto done; |
1229 | |
1230 | fmt++; /* skip over '%' */ |
1231 | |
1232 | flags = 0; |
1233 | dprec = 0; |
1234 | width = 0; |
1235 | prec = -1; |
1236 | sign = '\0'; |
1237 | |
1238 | rflag: ch = *fmt++; |
1239 | reswitch: switch (ch) { |
1240 | case ' ': |
1241 | /* |
1242 | * ``If the space and + flags both appear, the space |
1243 | * flag will be ignored.'' |
1244 | * -- ANSI X3J11 |
1245 | */ |
1246 | if (!sign) |
1247 | sign = ' '; |
1248 | goto rflag; |
1249 | case '#': |
1250 | flags |= ALT; |
1251 | goto rflag; |
1252 | case '*': |
1253 | /* |
1254 | * ``A negative field width argument is taken as a |
1255 | * - flag followed by a positive field width.'' |
1256 | * -- ANSI X3J11 |
1257 | * They don't exclude field widths read from args. |
1258 | */ |
1259 | if ((width = va_arg(ap, int)) >= 0) |
1260 | goto rflag; |
1261 | width = -width; |
1262 | /* FALLTHROUGH */ |
1263 | case '-': |
1264 | flags |= LADJUST; |
1265 | goto rflag; |
1266 | case '+': |
1267 | sign = '+'; |
1268 | goto rflag; |
1269 | case '.': |
1270 | if ((ch = *fmt++) == '*') { |
1271 | n = va_arg(ap, int); |
1272 | prec = n < 0 ? -1 : n; |
1273 | goto rflag; |
1274 | } |
1275 | n = 0; |
1276 | while (is_digit(ch)) { |
1277 | n = 10 * n + to_digit(ch); |
1278 | ch = *fmt++; |
1279 | } |
1280 | prec = n < 0 ? -1 : n; |
1281 | goto reswitch; |
1282 | case '0': |
1283 | /* |
1284 | * ``Note that 0 is taken as a flag, not as the |
1285 | * beginning of a field width.'' |
1286 | * -- ANSI X3J11 |
1287 | */ |
1288 | flags |= ZEROPAD; |
1289 | goto rflag; |
1290 | case '1': case '2': case '3': case '4': |
1291 | case '5': case '6': case '7': case '8': case '9': |
1292 | n = 0; |
1293 | do { |
1294 | n = 10 * n + to_digit(ch); |
1295 | ch = *fmt++; |
1296 | } while (is_digit(ch)); |
1297 | width = n; |
1298 | goto reswitch; |
1299 | case 'h': |
1300 | flags |= SHORTINT; |
1301 | goto rflag; |
1302 | case 'j': |
1303 | flags |= MAXINT; |
1304 | goto rflag; |
1305 | case 'l': |
1306 | if (*fmt == 'l') { |
1307 | fmt++; |
1308 | flags |= QUADINT; |
1309 | } else { |
1310 | flags |= LONGINT; |
1311 | } |
1312 | goto rflag; |
1313 | case 'q': |
1314 | flags |= QUADINT; |
1315 | goto rflag; |
1316 | case 't': |
1317 | flags |= PTRINT; |
1318 | goto rflag; |
1319 | case 'z': |
1320 | flags |= SIZEINT; |
1321 | goto rflag; |
1322 | case 'c': |
1323 | *(cp = bf) = va_arg(ap, int); |
1324 | size = 1; |
1325 | sign = '\0'; |
1326 | break; |
1327 | case 'D': |
1328 | flags |= LONGINT; |
1329 | /*FALLTHROUGH*/ |
1330 | case 'd': |
1331 | case 'i': |
1332 | _uquad = SARG(); |
1333 | if ((quad_t)_uquad < 0) { |
1334 | _uquad = -_uquad; |
1335 | sign = '-'; |
1336 | } |
1337 | base = DEC; |
1338 | goto number; |
1339 | case 'n': |
1340 | if (flags & MAXINT) |
1341 | *va_arg(ap, intmax_t *) = ret; |
1342 | else if (flags & PTRINT) |
1343 | *va_arg(ap, intptr_t *) = ret; |
1344 | else if (flags & SIZEINT) |
1345 | *va_arg(ap, ssize_t *) = ret; |
1346 | else if (flags & QUADINT) |
1347 | *va_arg(ap, quad_t *) = ret; |
1348 | else if (flags & LONGINT) |
1349 | *va_arg(ap, long *) = ret; |
1350 | else if (flags & SHORTINT) |
1351 | *va_arg(ap, short *) = ret; |
1352 | else |
1353 | *va_arg(ap, int *) = ret; |
1354 | continue; /* no output */ |
1355 | case 'O': |
1356 | flags |= LONGINT; |
1357 | /*FALLTHROUGH*/ |
1358 | case 'o': |
1359 | _uquad = UARG(); |
1360 | base = OCT; |
1361 | goto nosign; |
1362 | case 'p': |
1363 | /* |
1364 | * ``The argument shall be a pointer to void. The |
1365 | * value of the pointer is converted to a sequence |
1366 | * of printable characters, in an implementation- |
1367 | * defined manner.'' |
1368 | * -- ANSI X3J11 |
1369 | */ |
1370 | /* NOSTRICT */ |
1371 | _uquad = (u_long)va_arg(ap, void *); |
1372 | base = HEX; |
1373 | xdigs = hexdigits; |
1374 | flags |= HEXPREFIX; |
1375 | ch = 'x'; |
1376 | goto nosign; |
1377 | case 's': |
1378 | if ((cp = va_arg(ap, char *)) == NULL) |
1379 | /*XXXUNCONST*/ |
1380 | cp = __UNCONST("(null)" ); |
1381 | if (prec >= 0) { |
1382 | /* |
1383 | * can't use strlen; can only look for the |
1384 | * NUL in the first `prec' characters, and |
1385 | * strlen() will go further. |
1386 | */ |
1387 | char *p = memchr(cp, 0, prec); |
1388 | |
1389 | if (p != NULL) { |
1390 | size = p - cp; |
1391 | if (size > prec) |
1392 | size = prec; |
1393 | } else |
1394 | size = prec; |
1395 | } else |
1396 | size = strlen(cp); |
1397 | sign = '\0'; |
1398 | break; |
1399 | case 'U': |
1400 | flags |= LONGINT; |
1401 | /*FALLTHROUGH*/ |
1402 | case 'u': |
1403 | _uquad = UARG(); |
1404 | base = DEC; |
1405 | goto nosign; |
1406 | case 'X': |
1407 | xdigs = HEXDIGITS; |
1408 | goto hex; |
1409 | case 'x': |
1410 | xdigs = hexdigits; |
1411 | hex: _uquad = UARG(); |
1412 | base = HEX; |
1413 | /* leading 0x/X only if non-zero */ |
1414 | if (flags & ALT && _uquad != 0) |
1415 | flags |= HEXPREFIX; |
1416 | |
1417 | /* unsigned conversions */ |
1418 | nosign: sign = '\0'; |
1419 | /* |
1420 | * ``... diouXx conversions ... if a precision is |
1421 | * specified, the 0 flag will be ignored.'' |
1422 | * -- ANSI X3J11 |
1423 | */ |
1424 | number: if ((dprec = prec) >= 0) |
1425 | flags &= ~ZEROPAD; |
1426 | |
1427 | /* |
1428 | * ``The result of converting a zero value with an |
1429 | * explicit precision of zero is no characters.'' |
1430 | * -- ANSI X3J11 |
1431 | */ |
1432 | cp = bf + KPRINTF_BUFSIZE; |
1433 | if (_uquad != 0 || prec != 0) { |
1434 | /* |
1435 | * Unsigned mod is hard, and unsigned mod |
1436 | * by a constant is easier than that by |
1437 | * a variable; hence this switch. |
1438 | */ |
1439 | switch (base) { |
1440 | case OCT: |
1441 | do { |
1442 | *--cp = to_char(_uquad & 7); |
1443 | _uquad >>= 3; |
1444 | } while (_uquad); |
1445 | /* handle octal leading 0 */ |
1446 | if (flags & ALT && *cp != '0') |
1447 | *--cp = '0'; |
1448 | break; |
1449 | |
1450 | case DEC: |
1451 | /* many numbers are 1 digit */ |
1452 | while (_uquad >= 10) { |
1453 | *--cp = to_char(_uquad % 10); |
1454 | _uquad /= 10; |
1455 | } |
1456 | *--cp = to_char(_uquad); |
1457 | break; |
1458 | |
1459 | case HEX: |
1460 | do { |
1461 | *--cp = xdigs[_uquad & 15]; |
1462 | _uquad >>= 4; |
1463 | } while (_uquad); |
1464 | break; |
1465 | |
1466 | default: |
1467 | /*XXXUNCONST*/ |
1468 | cp = __UNCONST("bug in kprintf: bad base" ); |
1469 | size = strlen(cp); |
1470 | goto skipsize; |
1471 | } |
1472 | } |
1473 | size = bf + KPRINTF_BUFSIZE - cp; |
1474 | skipsize: |
1475 | break; |
1476 | default: /* "%?" prints ?, unless ? is NUL */ |
1477 | if (ch == '\0') |
1478 | goto done; |
1479 | /* pretend it was %c with argument ch */ |
1480 | cp = bf; |
1481 | *cp = ch; |
1482 | size = 1; |
1483 | sign = '\0'; |
1484 | break; |
1485 | } |
1486 | |
1487 | /* |
1488 | * All reasonable formats wind up here. At this point, `cp' |
1489 | * points to a string which (if not flags&LADJUST) should be |
1490 | * padded out to `width' places. If flags&ZEROPAD, it should |
1491 | * first be prefixed by any sign or other prefix; otherwise, |
1492 | * it should be blank padded before the prefix is emitted. |
1493 | * After any left-hand padding and prefixing, emit zeroes |
1494 | * required by a decimal [diouxX] precision, then print the |
1495 | * string proper, then emit zeroes required by any leftover |
1496 | * floating precision; finally, if LADJUST, pad with blanks. |
1497 | * |
1498 | * Compute actual size, so we know how much to pad. |
1499 | * size excludes decimal prec; realsz includes it. |
1500 | */ |
1501 | realsz = dprec > size ? dprec : size; |
1502 | if (sign) |
1503 | realsz++; |
1504 | else if (flags & HEXPREFIX) |
1505 | realsz+= 2; |
1506 | |
1507 | /* adjust ret */ |
1508 | ret += width > realsz ? width : realsz; |
1509 | |
1510 | /* right-adjusting blank padding */ |
1511 | if ((flags & (LADJUST|ZEROPAD)) == 0) { |
1512 | n = width - realsz; |
1513 | while (n-- > 0) |
1514 | KPRINTF_PUTCHAR(' '); |
1515 | } |
1516 | |
1517 | /* prefix */ |
1518 | if (sign) { |
1519 | KPRINTF_PUTCHAR(sign); |
1520 | } else if (flags & HEXPREFIX) { |
1521 | KPRINTF_PUTCHAR('0'); |
1522 | KPRINTF_PUTCHAR(ch); |
1523 | } |
1524 | |
1525 | /* right-adjusting zero padding */ |
1526 | if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) { |
1527 | n = width - realsz; |
1528 | while (n-- > 0) |
1529 | KPRINTF_PUTCHAR('0'); |
1530 | } |
1531 | |
1532 | /* leading zeroes from decimal precision */ |
1533 | n = dprec - size; |
1534 | while (n-- > 0) |
1535 | KPRINTF_PUTCHAR('0'); |
1536 | |
1537 | /* the string or number proper */ |
1538 | for (; size--; cp++) |
1539 | KPRINTF_PUTCHAR(*cp); |
1540 | /* left-adjusting padding (always blank) */ |
1541 | if (flags & LADJUST) { |
1542 | n = width - realsz; |
1543 | while (n-- > 0) |
1544 | KPRINTF_PUTCHAR(' '); |
1545 | } |
1546 | } |
1547 | |
1548 | done: |
1549 | if ((oflags == TOBUFONLY) && (vp != NULL)) |
1550 | *(char **)vp = sbuf; |
1551 | (*v_flush)(); |
1552 | |
1553 | #ifdef RND_PRINTF |
1554 | if (!cold) { |
1555 | struct timespec ts; |
1556 | (void)nanotime(&ts); |
1557 | SHA512_Update(&kprnd_sha, (char *)&ts, sizeof(ts)); |
1558 | } |
1559 | #endif |
1560 | return ret; |
1561 | } |
1562 | |