hexdump.c revision 9979
1240116Smarcel/*-
2240116Smarcel * Copyright (c) 1986, 1988, 1991, 1993
3240116Smarcel *	The Regents of the University of California.  All rights reserved.
4240116Smarcel * (c) UNIX System Laboratories, Inc.
5240116Smarcel * All or some portions of this file are derived from material licensed
6240116Smarcel * to the University of California by American Telephone and Telegraph
7240116Smarcel * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8240116Smarcel * the permission of UNIX System Laboratories, Inc.
9240116Smarcel *
10240116Smarcel * Redistribution and use in source and binary forms, with or without
11240116Smarcel * modification, are permitted provided that the following conditions
12240116Smarcel * are met:
13240116Smarcel * 1. Redistributions of source code must retain the above copyright
14240116Smarcel *    notice, this list of conditions and the following disclaimer.
15240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright
16240116Smarcel *    notice, this list of conditions and the following disclaimer in the
17240116Smarcel *    documentation and/or other materials provided with the distribution.
18240116Smarcel * 3. All advertising materials mentioning features or use of this software
19240116Smarcel *    must display the following acknowledgement:
20240116Smarcel *	This product includes software developed by the University of
21240116Smarcel *	California, Berkeley and its contributors.
22240116Smarcel * 4. Neither the name of the University nor the names of its contributors
23240116Smarcel *    may be used to endorse or promote products derived from this software
24240116Smarcel *    without specific prior written permission.
25240116Smarcel *
26240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27240116Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28240116Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29272049Srodrigc * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30240116Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32240116Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33258289Sjmmv * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34240116Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35240116Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36240116Smarcel * SUCH DAMAGE.
37240116Smarcel *
38258289Sjmmv *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
39258289Sjmmv * $Id: subr_prf.c,v 1.15 1995/08/06 22:00:17 davidg Exp $
40240116Smarcel */
41240116Smarcel
42240116Smarcel#include <sys/param.h>
43240116Smarcel#include <sys/systm.h>
44240116Smarcel#include <sys/buf.h>
45240116Smarcel#include <sys/conf.h>
46240116Smarcel#include <sys/reboot.h>
47258289Sjmmv#include <sys/msgbuf.h>
48258289Sjmmv#include <sys/proc.h>
49240116Smarcel#include <sys/ioctl.h>
50240116Smarcel#include <sys/vnode.h>
51240116Smarcel#include <sys/file.h>
52240116Smarcel#include <sys/tty.h>
53240116Smarcel#include <sys/tprintf.h>
54240116Smarcel#include <sys/syslog.h>
55240116Smarcel#include <sys/malloc.h>
56240116Smarcel#include <machine/cons.h>
57240116Smarcel
58240116Smarcel/*
59240116Smarcel * Note that stdarg.h and the ANSI style va_start macro is used for both
60240116Smarcel * ANSI and traditional C compilers.
61240116Smarcel */
62240116Smarcel#include <machine/stdarg.h>
63240116Smarcel
64240116Smarcel#ifdef KADB
65240116Smarcel#include <machine/kdbparam.h>
66240116Smarcel#endif
67240116Smarcel
68240116Smarcel
69240116Smarcel#define TOCONS	0x01
70240116Smarcel#define TOTTY	0x02
71240116Smarcel#define TOLOG	0x04
72240116Smarcel
73240116Smarcelstruct	tty *constty;			/* pointer to console "window" tty */
74240116Smarcel
75240116Smarcelvoid	(*v_putc)(int) = cnputc;	/* routine to putc on virtual console */
76240116Smarcel
77240116Smarcelvoid  logpri __P((int level));
78240116Smarcelstatic void  putchar __P((int ch, int flags, struct tty *tp));
79240116Smarcelstatic char *ksprintn __P((u_long num, int base, int *len));
80258289Sjmmv
81258289Sjmmvint consintr = 1;			/* Ok to handle console interrupts? */
82258289Sjmmv
83258289Sjmmv/*
84258289Sjmmv * Variable panicstr contains argument to first call to panic; used as flag
85258289Sjmmv * to indicate that the kernel has already called panic.
86258289Sjmmv */
87258289Sjmmvconst char *panicstr;
88258289Sjmmv
89258289Sjmmv/*
90258289Sjmmv * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
91258289Sjmmv * and then reboots.  If we are called twice, then we avoid trying to sync
92258289Sjmmv * the disks as this often leads to recursive panics.
93240116Smarcel */
94240116Smarcel#ifdef __GNUC__
95240116Smarcel__dead			/* panic() does not return */
96240116Smarcel#endif
97240116Smarcelvoid
98240116Smarcel#ifdef __STDC__
99240116Smarcelpanic(const char *fmt, ...)
100258289Sjmmv#else
101258289Sjmmvpanic(fmt, va_alist)
102240116Smarcel	char *fmt;
103240116Smarcel#endif
104240116Smarcel{
105240116Smarcel	int bootopt;
106240116Smarcel	va_list ap;
107240116Smarcel
108240116Smarcel	bootopt = RB_AUTOBOOT | RB_DUMP;
109258289Sjmmv	if (panicstr)
110258289Sjmmv		bootopt |= RB_NOSYNC;
111240116Smarcel	else
112240116Smarcel		panicstr = fmt;
113240116Smarcel
114240116Smarcel	va_start(ap, fmt);
115240116Smarcel	printf("panic: %r\n", fmt, ap);
116240116Smarcel	va_end(ap);
117240116Smarcel
118240116Smarcel#ifdef KGDB
119240116Smarcel	kgdb_panic();
120240116Smarcel#endif
121240116Smarcel#ifdef KADB
122240116Smarcel	if (boothowto & RB_KDB)
123240116Smarcel		kdbpanic();
124240116Smarcel#endif
125240116Smarcel#ifdef DDB
126240116Smarcel	Debugger ("panic");
127240116Smarcel#endif
128240116Smarcel	boot(bootopt);
129240116Smarcel}
130240116Smarcel
131240116Smarcel/*
132240116Smarcel * Warn that a system table is full.
133240116Smarcel */
134240116Smarcelvoid
135240116Smarceltablefull(tab)
136240116Smarcel	const char *tab;
137240116Smarcel{
138240116Smarcel
139240116Smarcel	log(LOG_ERR, "%s: table is full\n", tab);
140240116Smarcel}
141240116Smarcel
142240116Smarcel/*
143258289Sjmmv * Uprintf prints to the controlling terminal for the current process.
144258289Sjmmv * It may block if the tty queue is overfull.  No message is printed if
145258289Sjmmv * the queue does not clear in a reasonable time.
146258289Sjmmv */
147258289Sjmmvvoid
148258289Sjmmv#ifdef __STDC__
149258289Sjmmvuprintf(const char *fmt, ...)
150258289Sjmmv#else
151258289Sjmmvuprintf(fmt, va_alist)
152258289Sjmmv	char *fmt;
153258289Sjmmv#endif
154258289Sjmmv{
155258289Sjmmv	register struct proc *p = curproc;
156258289Sjmmv	va_list ap;
157258289Sjmmv
158258289Sjmmv	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
159258289Sjmmv		va_start(ap, fmt);
160258289Sjmmv		kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
161258289Sjmmv		va_end(ap);
162258289Sjmmv	}
163258289Sjmmv}
164258289Sjmmv
165258289Sjmmvtpr_t
166258289Sjmmvtprintf_open(p)
167258289Sjmmv	register struct proc *p;
168258289Sjmmv{
169258289Sjmmv
170258289Sjmmv	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
171258289Sjmmv		SESSHOLD(p->p_session);
172258289Sjmmv		return ((tpr_t) p->p_session);
173258289Sjmmv	}
174258289Sjmmv	return ((tpr_t) NULL);
175258289Sjmmv}
176258289Sjmmv
177258289Sjmmvvoid
178258289Sjmmvtprintf_close(sess)
179258289Sjmmv	tpr_t sess;
180258289Sjmmv{
181258289Sjmmv
182258289Sjmmv	if (sess)
183258289Sjmmv		SESSRELE((struct session *) sess);
184258289Sjmmv}
185258289Sjmmv
186258289Sjmmv/*
187258289Sjmmv * tprintf prints on the controlling terminal associated
188258289Sjmmv * with the given session.
189258289Sjmmv */
190258289Sjmmvvoid
191258289Sjmmv#ifdef __STDC__
192258289Sjmmvtprintf(tpr_t tpr, const char *fmt, ...)
193258289Sjmmv#else
194258289Sjmmvtprintf(tpr, fmt, va_alist)
195258289Sjmmv	tpr_t tpr;
196258289Sjmmv	char *fmt;
197258289Sjmmv#endif
198258289Sjmmv{
199258289Sjmmv	register struct session *sess = (struct session *)tpr;
200258289Sjmmv	struct tty *tp = NULL;
201258289Sjmmv	int flags = TOLOG;
202258289Sjmmv	va_list ap;
203258289Sjmmv
204240116Smarcel	logpri(LOG_INFO);
205258289Sjmmv	if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
206258289Sjmmv		flags |= TOTTY;
207240116Smarcel		tp = sess->s_ttyp;
208240116Smarcel	}
209240116Smarcel	va_start(ap, fmt);
210240116Smarcel	kprintf(fmt, flags, tp, ap);
211240116Smarcel	va_end(ap);
212240116Smarcel	logwakeup();
213240116Smarcel}
214240116Smarcel
215240116Smarcel/*
216240116Smarcel * Ttyprintf displays a message on a tty; it should be used only by
217240116Smarcel * the tty driver, or anything that knows the underlying tty will not
218240116Smarcel * be revoke(2)'d away.  Other callers should use tprintf.
219240116Smarcel */
220240116Smarcelvoid
221240116Smarcel#ifdef __STDC__
222240116Smarcelttyprintf(struct tty *tp, const char *fmt, ...)
223240116Smarcel#else
224240116Smarcelttyprintf(tp, fmt, va_alist)
225240116Smarcel	struct tty *tp;
226240116Smarcel	char *fmt;
227240116Smarcel#endif
228240116Smarcel{
229240116Smarcel	va_list ap;
230240116Smarcel
231240116Smarcel	va_start(ap, fmt);
232240116Smarcel	kprintf(fmt, TOTTY, tp, ap);
233240116Smarcel	va_end(ap);
234240116Smarcel}
235240116Smarcel
236240116Smarcelextern	int log_open;
237240116Smarcel
238240116Smarcel/*
239240116Smarcel * Log writes to the log buffer, and guarantees not to sleep (so can be
240240116Smarcel * called by interrupt routines).  If there is no process reading the
241240116Smarcel * log yet, it writes to the console also.
242240116Smarcel */
243240116Smarcelvoid
244240116Smarcel#ifdef __STDC__
245240116Smarcellog(int level, const char *fmt, ...)
246240116Smarcel#else
247240116Smarcellog(level, fmt, va_alist)
248240116Smarcel	int level;
249240116Smarcel	char *fmt;
250240116Smarcel#endif
251240116Smarcel{
252240116Smarcel	register int s;
253240116Smarcel	va_list ap;
254240116Smarcel
255240116Smarcel	s = splhigh();
256240116Smarcel	logpri(level);
257240116Smarcel	va_start(ap, fmt);
258240116Smarcel	kprintf(fmt, TOLOG, NULL, ap);
259240116Smarcel	splx(s);
260240116Smarcel	va_end(ap);
261240116Smarcel	if (!log_open) {
262240116Smarcel		va_start(ap, fmt);
263240116Smarcel		kprintf(fmt, TOCONS, NULL, ap);
264240116Smarcel		va_end(ap);
265240116Smarcel	}
266240116Smarcel	logwakeup();
267240116Smarcel}
268240116Smarcel
269240116Smarcelvoid
270240116Smarcellogpri(level)
271240116Smarcel	int level;
272240116Smarcel{
273240116Smarcel	register char *p;
274240116Smarcel
275240116Smarcel	putchar('<', TOLOG, NULL);
276240116Smarcel	for (p = ksprintn((u_long)level, 10, NULL); *p;)
277240116Smarcel		putchar(*p--, TOLOG, NULL);
278240116Smarcel	putchar('>', TOLOG, NULL);
279240116Smarcel}
280240116Smarcel
281240116Smarcelvoid
282240116Smarcel#ifdef __STDC__
283240116Smarceladdlog(const char *fmt, ...)
284240116Smarcel#else
285240116Smarceladdlog(fmt, va_alist)
286240116Smarcel	char *fmt;
287240116Smarcel#endif
288240116Smarcel{
289240116Smarcel	register int s;
290240116Smarcel	va_list ap;
291240116Smarcel
292240116Smarcel	s = splhigh();
293240116Smarcel	va_start(ap, fmt);
294240116Smarcel	kprintf(fmt, TOLOG, NULL, ap);
295240116Smarcel	splx(s);
296240116Smarcel	va_end(ap);
297240116Smarcel	if (!log_open) {
298240116Smarcel		va_start(ap, fmt);
299240116Smarcel		kprintf(fmt, TOCONS, NULL, ap);
300240116Smarcel		va_end(ap);
301240116Smarcel	}
302240116Smarcel	logwakeup();
303240116Smarcel}
304240116Smarcel
305240116Smarcelvoid
306240116Smarcel#ifdef __STDC__
307240116Smarcelprintf(const char *fmt, ...)
308240116Smarcel#else
309240116Smarcelprintf(fmt, va_alist)
310240116Smarcel	char *fmt;
311240116Smarcel#endif
312240116Smarcel{
313240116Smarcel	va_list ap;
314240116Smarcel	register int savintr;
315240116Smarcel
316240116Smarcel	savintr = consintr;		/* disable interrupts */
317240116Smarcel	consintr = 0;
318240116Smarcel	va_start(ap, fmt);
319240116Smarcel	kprintf(fmt, TOCONS | TOLOG, NULL, ap);
320240116Smarcel	va_end(ap);
321240116Smarcel	if (!panicstr)
322240116Smarcel		logwakeup();
323240116Smarcel	consintr = savintr;		/* reenable interrupts */
324240116Smarcel}
325240116Smarcel
326240116Smarcel/*
327240116Smarcel * Scaled down version of printf(3).
328240116Smarcel *
329240116Smarcel * Two additional formats:
330240116Smarcel *
331240116Smarcel * The format %b is supported to decode error registers.
332240116Smarcel * Its usage is:
333240116Smarcel *
334240116Smarcel *	printf("reg=%b\n", regval, "<base><arg>*");
335240116Smarcel *
336240116Smarcel * where <base> is the output base expressed as a control character, e.g.
337240116Smarcel * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
338240116Smarcel * the first of which gives the bit number to be inspected (origin 1), and
339240116Smarcel * the next characters (up to a control character, i.e. a character <= 32),
340240116Smarcel * give the name of the register.  Thus:
341240116Smarcel *
342240116Smarcel *	kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
343240116Smarcel *
344240116Smarcel * would produce output:
345240116Smarcel *
346240116Smarcel *	reg=3<BITTWO,BITONE>
347240116Smarcel *
348240116Smarcel * The format %r passes an additional format string and argument list
349240116Smarcel * recursively.  Its usage is:
350240116Smarcel *
351240116Smarcel * fn(char *fmt, ...)
352240116Smarcel * {
353240116Smarcel *	va_list ap;
354240116Smarcel *	va_start(ap, fmt);
355240116Smarcel *	printf("prefix: %r: suffix\n", fmt, ap);
356240116Smarcel *	va_end(ap);
357240116Smarcel * }
358240116Smarcel *
359240116Smarcel * Space or zero padding and a field width are supported for the numeric
360240116Smarcel * formats only.
361240116Smarcel */
362240116Smarcelvoid
363240116Smarcelkprintf(fmt, flags, tp, ap)
364240116Smarcel	register const char *fmt;
365240116Smarcel	int flags;
366240116Smarcel	struct tty *tp;
367240116Smarcel	va_list ap;
368240116Smarcel{
369240116Smarcel	register char *p, *q;
370240116Smarcel	register int ch, n;
371240116Smarcel	u_long ul;
372240116Smarcel	int base, lflag, tmp, width;
373240116Smarcel	char padc;
374240116Smarcel
375240116Smarcel	if (fmt == NULL)
376240116Smarcel		fmt = "(fmt null)\n";
377240116Smarcel	for (;;) {
378240116Smarcel		padc = ' ';
379240116Smarcel		width = 0;
380240116Smarcel		while ((ch = *(u_char *)fmt++) != '%') {
381240116Smarcel			if (ch == '\0')
382240116Smarcel				return;
383240116Smarcel			putchar(ch, flags, tp);
384240116Smarcel		}
385240116Smarcel		lflag = 0;
386240116Smarcelreswitch:	switch (ch = *(u_char *)fmt++) {
387240116Smarcel		case '0':
388240116Smarcel			padc = '0';
389240116Smarcel			goto reswitch;
390240116Smarcel		case '1': case '2': case '3': case '4':
391240116Smarcel		case '5': case '6': case '7': case '8': case '9':
392240116Smarcel			for (width = 0;; ++fmt) {
393240116Smarcel				width = width * 10 + ch - '0';
394240116Smarcel				ch = *fmt;
395240116Smarcel				if (ch < '0' || ch > '9')
396240116Smarcel					break;
397240116Smarcel			}
398240116Smarcel			goto reswitch;
399240116Smarcel		case 'l':
400240116Smarcel			lflag = 1;
401240116Smarcel			goto reswitch;
402240116Smarcel		case 'b':
403240116Smarcel			ul = va_arg(ap, int);
404240116Smarcel			p = va_arg(ap, char *);
405240116Smarcel			for (q = ksprintn(ul, *p++, NULL); *q;)
406240116Smarcel				putchar(*q--, flags, tp);
407240116Smarcel
408240116Smarcel			if (!ul)
409240116Smarcel				break;
410240116Smarcel
411240116Smarcel			for (tmp = 0; *p;) {
412272049Srodrigc				n = *p++;
413272049Srodrigc				if (ul & (1 << (n - 1))) {
414240116Smarcel					putchar(tmp ? ',' : '<', flags, tp);
415240116Smarcel					for (; (n = *p) > ' '; ++p)
416240116Smarcel						putchar(n, flags, tp);
417240116Smarcel					tmp = 1;
418240116Smarcel				} else
419240116Smarcel					for (; *p > ' '; ++p)
420240116Smarcel						continue;
421240116Smarcel			}
422240116Smarcel			if (tmp)
423240116Smarcel				putchar('>', flags, tp);
424240116Smarcel			break;
425240116Smarcel		case 'c':
426240116Smarcel			putchar(va_arg(ap, int), flags, tp);
427240116Smarcel			break;
428240116Smarcel		case 'r':
429240116Smarcel			p = va_arg(ap, char *);
430240116Smarcel			kprintf(p, flags, tp, va_arg(ap, va_list));
431240116Smarcel			break;
432240116Smarcel		case 's':
433240116Smarcel			p = va_arg(ap, char *);
434240116Smarcel			if (p == NULL)
435240116Smarcel				p = "(null)";
436240116Smarcel			while (*p)
437240116Smarcel				putchar(*p++, flags, tp);
438240116Smarcel			break;
439240116Smarcel		case 'd':
440240116Smarcel			ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
441240116Smarcel			if ((long)ul < 0) {
442240116Smarcel				putchar('-', flags, tp);
443240116Smarcel				ul = -(long)ul;
444240116Smarcel			}
445272049Srodrigc			base = 10;
446272049Srodrigc			goto number;
447240116Smarcel		case 'o':
448240116Smarcel			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
449240116Smarcel			base = 8;
450240116Smarcel			goto number;
451240116Smarcel		case 'p':
452240116Smarcel			ul = (u_long)va_arg(ap, void *);
453240116Smarcel			base = 16;
454240116Smarcel			putchar('0', flags, tp);
455240116Smarcel			putchar('x', flags, tp);
456240116Smarcel			goto number;
457240116Smarcel		case 'u':
458240116Smarcel			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
459240116Smarcel			base = 10;
460240116Smarcel			goto number;
461240116Smarcel		case 'x':
462240116Smarcel			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
463240116Smarcel			base = 16;
464258289Sjmmvnumber:			p = ksprintn(ul, base, &tmp);
465240116Smarcel			if (width && (width -= tmp) > 0)
466240116Smarcel				while (width--)
467240116Smarcel					putchar(padc, flags, tp);
468240116Smarcel			while (*p)
469240116Smarcel				putchar(*p--, flags, tp);
470240116Smarcel			break;
471240116Smarcel		default:
472240116Smarcel			putchar('%', flags, tp);
473240116Smarcel			if (lflag)
474240116Smarcel				putchar('l', flags, tp);
475240116Smarcel			/* FALLTHROUGH */
476240116Smarcel		case '%':
477240116Smarcel			putchar(ch, flags, tp);
478240116Smarcel		}
479240116Smarcel	}
480240116Smarcel}
481240116Smarcel
482240116Smarcel/*
483240116Smarcel * Print a character on console or users terminal.  If destination is
484240116Smarcel * the console then the last MSGBUFS characters are saved in msgbuf for
485240116Smarcel * inspection later.
486240116Smarcel */
487240116Smarcelstatic void
488240116Smarcelputchar(c, flags, tp)
489240116Smarcel	register int c;
490240116Smarcel	int flags;
491240116Smarcel	struct tty *tp;
492240116Smarcel{
493240116Smarcel	register struct msgbuf *mbp;
494240116Smarcel
495240116Smarcel	if (panicstr)
496240116Smarcel		constty = NULL;
497240116Smarcel	if ((flags & TOCONS) && tp == NULL && constty) {
498240116Smarcel		tp = constty;
499258289Sjmmv		flags |= TOTTY;
500258289Sjmmv	}
501258289Sjmmv	if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
502258289Sjmmv	    (flags & TOCONS) && tp == constty)
503258289Sjmmv		constty = NULL;
504258289Sjmmv	if ((flags & TOLOG) &&
505258289Sjmmv	    c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
506258289Sjmmv		mbp = msgbufp;
507258289Sjmmv		if (mbp->msg_magic != MSG_MAGIC ||
508258289Sjmmv		    mbp->msg_bufx >= MSG_BSIZE ||
509240116Smarcel		    mbp->msg_bufr >= MSG_BSIZE) {
510240116Smarcel			bzero(mbp, sizeof(struct msgbuf));
511240116Smarcel			mbp->msg_magic = MSG_MAGIC;
512240116Smarcel		}
513240116Smarcel		mbp->msg_bufc[mbp->msg_bufx++] = c;
514240116Smarcel		if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
515240116Smarcel			mbp->msg_bufx = 0;
516240116Smarcel		/* If the buffer is full, keep the most recent data. */
517240116Smarcel		if (mbp->msg_bufr == mbp->msg_bufx) {
518240116Smarcel			if (++mbp->msg_bufr >= MSG_BSIZE)
519240116Smarcel				mbp->msg_bufr = 0;
520240116Smarcel		}
521240116Smarcel	}
522240116Smarcel	if ((flags & TOCONS) && constty == NULL && c != '\0')
523240116Smarcel		(*v_putc)(c);
524240116Smarcel}
525258289Sjmmv
526258289Sjmmv/*
527258289Sjmmv * Scaled down version of sprintf(3).
528258289Sjmmv */
529258289Sjmmv#ifdef __STDC__
530258289Sjmmvint
531258289Sjmmvsprintf(char *buf, const char *cfmt, ...)
532258289Sjmmv#else
533258289Sjmmvint
534258289Sjmmvsprintf(buf, cfmt, va_alist)
535258289Sjmmv	char *buf, *cfmt;
536258289Sjmmv#endif
537258289Sjmmv{
538258289Sjmmv	register const char *fmt = cfmt;
539258289Sjmmv	register char *p, *bp;
540258289Sjmmv	register int ch, base;
541258289Sjmmv	u_long ul;
542258289Sjmmv	int lflag;
543258289Sjmmv	va_list ap;
544258289Sjmmv
545258289Sjmmv	va_start(ap, cfmt);
546258289Sjmmv	for (bp = buf; ; ) {
547258289Sjmmv		while ((ch = *(u_char *)fmt++) != '%')
548258289Sjmmv			if ((*bp++ = ch) == '\0')
549258289Sjmmv				return ((bp - buf) - 1);
550258289Sjmmv
551258289Sjmmv		lflag = 0;
552258289Sjmmvreswitch:	switch (ch = *(u_char *)fmt++) {
553258289Sjmmv		case 'l':
554258289Sjmmv			lflag = 1;
555258289Sjmmv			goto reswitch;
556258289Sjmmv		case 'c':
557258289Sjmmv			*bp++ = va_arg(ap, int);
558258289Sjmmv			break;
559258289Sjmmv		case 's':
560258289Sjmmv			p = va_arg(ap, char *);
561258289Sjmmv			while (*p)
562258289Sjmmv				*bp++ = *p++;
563258289Sjmmv			break;
564258289Sjmmv		case 'd':
565258289Sjmmv			ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
566258289Sjmmv			if ((long)ul < 0) {
567258289Sjmmv				*bp++ = '-';
568258289Sjmmv				ul = -(long)ul;
569258289Sjmmv			}
570258289Sjmmv			base = 10;
571258289Sjmmv			goto number;
572258289Sjmmv			break;
573258289Sjmmv		case 'o':
574258289Sjmmv			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
575258289Sjmmv			base = 8;
576258289Sjmmv			goto number;
577258289Sjmmv			break;
578258289Sjmmv		case 'p':
579258289Sjmmv			ul = (u_long)va_arg(ap, void *);
580258289Sjmmv			base = 16;
581258289Sjmmv			*bp++ = '0';
582258289Sjmmv			*bp++ = 'x';
583258289Sjmmv			goto number;
584258289Sjmmv		case 'u':
585258289Sjmmv			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
586258289Sjmmv			base = 10;
587258289Sjmmv			goto number;
588258289Sjmmv			break;
589258289Sjmmv		case 'x':
590258289Sjmmv			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
591258289Sjmmv			base = 16;
592258289Sjmmvnumber:			for (p = ksprintn(ul, base, NULL); *p;)
593258289Sjmmv				*bp++ = *p--;
594258289Sjmmv			break;
595258289Sjmmv		default:
596258289Sjmmv			*bp++ = '%';
597258289Sjmmv			if (lflag)
598258289Sjmmv				*bp++ = 'l';
599258289Sjmmv			/* FALLTHROUGH */
600258289Sjmmv		case '%':
601258289Sjmmv			*bp++ = ch;
602258289Sjmmv		}
603258289Sjmmv	}
604258289Sjmmv	va_end(ap);
605258289Sjmmv}
606258289Sjmmv
607258289Sjmmv/*
608258289Sjmmv * Put a number (base <= 16) in a buffer in reverse order; return an
609258289Sjmmv * optional length and a pointer to the NULL terminated (preceded?)
610258289Sjmmv * buffer.
611258289Sjmmv */
612258289Sjmmvstatic char *
613258289Sjmmvksprintn(ul, base, lenp)
614258289Sjmmv	register u_long ul;
615258289Sjmmv	register int base, *lenp;
616258289Sjmmv{					/* A long in base 8, plus NULL. */
617258289Sjmmv	static char buf[sizeof(long) * NBBY / 3 + 2];
618258289Sjmmv	register char *p;
619258289Sjmmv
620258289Sjmmv	p = buf;
621258289Sjmmv	do {
622258289Sjmmv		*++p = "0123456789abcdef"[ul % base];
623258289Sjmmv	} while (ul /= base);
624258289Sjmmv	if (lenp)
625258289Sjmmv		*lenp = p - buf;
626258289Sjmmv	return (p);
627258289Sjmmv}
628258289Sjmmv