hexdump.c revision 66530
178342Sbenno/*-
278342Sbenno * Copyright (c) 1986, 1988, 1991, 1993
378342Sbenno *	The Regents of the University of California.  All rights reserved.
478342Sbenno * (c) UNIX System Laboratories, Inc.
578342Sbenno * All or some portions of this file are derived from material licensed
678342Sbenno * to the University of California by American Telephone and Telegraph
778342Sbenno * Co. or Unix System Laboratories, Inc. and are reproduced herein with
878342Sbenno * the permission of UNIX System Laboratories, Inc.
978342Sbenno *
1078342Sbenno * Redistribution and use in source and binary forms, with or without
1178342Sbenno * modification, are permitted provided that the following conditions
1278342Sbenno * are met:
1378342Sbenno * 1. Redistributions of source code must retain the above copyright
1478342Sbenno *    notice, this list of conditions and the following disclaimer.
1578342Sbenno * 2. Redistributions in binary form must reproduce the above copyright
1678342Sbenno *    notice, this list of conditions and the following disclaimer in the
1778342Sbenno *    documentation and/or other materials provided with the distribution.
1878342Sbenno * 3. All advertising materials mentioning features or use of this software
1978342Sbenno *    must display the following acknowledgement:
2078342Sbenno *	This product includes software developed by the University of
2178342Sbenno *	California, Berkeley and its contributors.
2278342Sbenno * 4. Neither the name of the University nor the names of its contributors
2378342Sbenno *    may be used to endorse or promote products derived from this software
2478342Sbenno *    without specific prior written permission.
2578342Sbenno *
2678342Sbenno * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27113038Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28113038Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2978342Sbenno * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3078342Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3178342Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3278342Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3378342Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34103597Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3578342Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36108940Sgrehan * SUCH DAMAGE.
37108940Sgrehan *
38143784Sgrehan *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
3992842Salfred * $FreeBSD: head/sys/kern/subr_prf.c 66530 2000-10-02 07:13:10Z msmith $
40143784Sgrehan */
4178342Sbenno
42143784Sgrehan#include <sys/param.h>
43143784Sgrehan#include <sys/systm.h>
44143784Sgrehan#include <sys/kernel.h>
45143784Sgrehan#include <sys/msgbuf.h>
46143784Sgrehan#include <sys/malloc.h>
47143784Sgrehan#include <sys/proc.h>
4878342Sbenno#include <sys/tty.h>
4978342Sbenno#include <sys/tprintf.h>
5078342Sbenno#include <sys/syslog.h>
5178342Sbenno#include <sys/cons.h>
52143784Sgrehan
53143784Sgrehan/*
54146794Smarcel * Note that stdarg.h and the ANSI style va_start macro is used for both
55146794Smarcel * ANSI and traditional C compilers.
56143784Sgrehan */
57143784Sgrehan#include <machine/stdarg.h>
58143784Sgrehan
5978342Sbenno#define TOCONS	0x01
6078342Sbenno#define TOTTY	0x02
61143784Sgrehan#define TOLOG	0x04
6284855Smp
63143784Sgrehan/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
6484855Smp#define MAXNBUF	(sizeof(quad_t) * NBBY + 1)
65143784Sgrehan
66143784Sgrehanstruct putchar_arg {
67143784Sgrehan	int	flags;
68103597Sgrehan	struct	tty *tty;
69103597Sgrehan};
70103597Sgrehan
71103597Sgrehanstruct snprintf_arg {
72103597Sgrehan	char	*str;
73146792Smarcel	size_t	remain;
74103597Sgrehan};
7578342Sbenno
76143784Sgrehanstruct	tty *constty;			/* pointer to console "window" tty */
77143784Sgrehan
78static void (*v_putc)(int) = cnputc;	/* routine to putc on virtual console */
79static void  logpri __P((int level));
80static void  msglogchar(int c, void *dummyarg);
81static void  putchar __P((int ch, void *arg));
82static char *ksprintn __P((char *nbuf, u_long num, int base, int *len));
83static char *ksprintqn __P((char *nbuf, u_quad_t num, int base, int *len));
84static void  snprintf_func __P((int ch, void *arg));
85
86static int consintr = 1;		/* Ok to handle console interrupts? */
87static int msgbufmapped;		/* Set when safe to use msgbuf */
88
89/*
90 * Warn that a system table is full.
91 */
92void
93tablefull(tab)
94	const char *tab;
95{
96
97	log(LOG_ERR, "%s: table is full\n", tab);
98}
99
100/*
101 * Uprintf prints to the controlling terminal for the current process.
102 * It may block if the tty queue is overfull.  No message is printed if
103 * the queue does not clear in a reasonable time.
104 */
105int
106uprintf(const char *fmt, ...)
107{
108	struct proc *p = curproc;
109	va_list ap;
110	struct putchar_arg pca;
111	int retval = 0;
112
113	if (p && p != idleproc && p->p_flag & P_CONTROLT &&
114	    p->p_session->s_ttyvp) {
115		va_start(ap, fmt);
116		pca.tty = p->p_session->s_ttyp;
117		pca.flags = TOTTY;
118		retval = kvprintf(fmt, putchar, &pca, 10, ap);
119		va_end(ap);
120	}
121	return retval;
122}
123
124tpr_t
125tprintf_open(p)
126	register struct proc *p;
127{
128
129	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
130		SESSHOLD(p->p_session);
131		return ((tpr_t) p->p_session);
132	}
133	return ((tpr_t) NULL);
134}
135
136void
137tprintf_close(sess)
138	tpr_t sess;
139{
140
141	if (sess)
142		SESSRELE((struct session *) sess);
143}
144
145/*
146 * tprintf prints on the controlling terminal associated
147 * with the given session.
148 */
149int
150tprintf(tpr_t tpr, const char *fmt, ...)
151{
152	register struct session *sess = (struct session *)tpr;
153	struct tty *tp = NULL;
154	int flags = TOLOG;
155	va_list ap;
156	struct putchar_arg pca;
157	int retval;
158
159	logpri(LOG_INFO);
160	if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
161		flags |= TOTTY;
162		tp = sess->s_ttyp;
163	}
164	va_start(ap, fmt);
165	pca.tty = tp;
166	pca.flags = flags;
167	retval = kvprintf(fmt, putchar, &pca, 10, ap);
168	va_end(ap);
169	logwakeup();
170	return retval;
171}
172
173/*
174 * Ttyprintf displays a message on a tty; it should be used only by
175 * the tty driver, or anything that knows the underlying tty will not
176 * be revoke(2)'d away.  Other callers should use tprintf.
177 */
178int
179ttyprintf(struct tty *tp, const char *fmt, ...)
180{
181	va_list ap;
182	struct putchar_arg pca;
183	int retval;
184
185	va_start(ap, fmt);
186	pca.tty = tp;
187	pca.flags = TOTTY;
188	retval = kvprintf(fmt, putchar, &pca, 10, ap);
189	va_end(ap);
190	return retval;
191}
192
193extern	int log_open;
194
195/*
196 * Log writes to the log buffer, and guarantees not to sleep (so can be
197 * called by interrupt routines).  If there is no process reading the
198 * log yet, it writes to the console also.
199 */
200int
201log(int level, const char *fmt, ...)
202{
203	register int s;
204	va_list ap;
205	int retval;
206
207	s = splhigh();
208	logpri(level);
209	va_start(ap, fmt);
210
211	retval = kvprintf(fmt, msglogchar, NULL, 10, ap);
212	va_end(ap);
213
214	splx(s);
215	if (!log_open) {
216		struct putchar_arg pca;
217		va_start(ap, fmt);
218		pca.tty = NULL;
219		pca.flags = TOCONS;
220		retval += kvprintf(fmt, putchar, &pca, 10, ap);
221		va_end(ap);
222	}
223	logwakeup();
224	return retval;
225}
226
227static void
228logpri(level)
229	int level;
230{
231	char nbuf[MAXNBUF];
232	register char *p;
233
234	msglogchar('<', NULL);
235	for (p = ksprintn(nbuf, (u_long)level, 10, NULL); *p;)
236		msglogchar(*p--, NULL);
237	msglogchar('>', NULL);
238}
239
240int
241addlog(const char *fmt, ...)
242{
243	register int s;
244	va_list ap;
245	int retval;
246
247	s = splhigh();
248	va_start(ap, fmt);
249	retval = kvprintf(fmt, msglogchar, NULL, 10, ap);
250	splx(s);
251	va_end(ap);
252	if (!log_open) {
253		struct putchar_arg pca;
254		va_start(ap, fmt);
255		pca.tty = NULL;
256		pca.flags = TOCONS;
257		retval += kvprintf(fmt, putchar, &pca, 10, ap);
258		va_end(ap);
259	}
260	logwakeup();
261	return (retval);
262}
263
264int
265printf(const char *fmt, ...)
266{
267	va_list ap;
268	register int savintr;
269	struct putchar_arg pca;
270	int retval;
271
272	savintr = consintr;		/* disable interrupts */
273	consintr = 0;
274	va_start(ap, fmt);
275	pca.tty = NULL;
276	pca.flags = TOCONS | TOLOG;
277	retval = kvprintf(fmt, putchar, &pca, 10, ap);
278	va_end(ap);
279	if (!panicstr)
280		logwakeup();
281	consintr = savintr;		/* reenable interrupts */
282	return retval;
283}
284
285int
286vprintf(const char *fmt, va_list ap)
287{
288	register int savintr;
289	struct putchar_arg pca;
290	int retval;
291
292	savintr = consintr;		/* disable interrupts */
293	consintr = 0;
294	pca.tty = NULL;
295	pca.flags = TOCONS | TOLOG;
296	retval = kvprintf(fmt, putchar, &pca, 10, ap);
297	if (!panicstr)
298		logwakeup();
299	consintr = savintr;		/* reenable interrupts */
300	return retval;
301}
302
303/*
304 * Print a character on console or users terminal.  If destination is
305 * the console then the last bunch of characters are saved in msgbuf for
306 * inspection later.
307 */
308static void
309putchar(int c, void *arg)
310{
311	struct putchar_arg *ap = (struct putchar_arg*) arg;
312	int flags = ap->flags;
313	struct tty *tp = ap->tty;
314	if (panicstr)
315		constty = NULL;
316	if ((flags & TOCONS) && tp == NULL && constty) {
317		tp = constty;
318		flags |= TOTTY;
319	}
320	if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
321	    (flags & TOCONS) && tp == constty)
322		constty = NULL;
323	if ((flags & TOLOG))
324		msglogchar(c, NULL);
325	if ((flags & TOCONS) && constty == NULL && c != '\0')
326		(*v_putc)(c);
327}
328
329/*
330 * Scaled down version of sprintf(3).
331 */
332int
333sprintf(char *buf, const char *cfmt, ...)
334{
335	int retval;
336	va_list ap;
337
338	va_start(ap, cfmt);
339	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
340	buf[retval] = '\0';
341	va_end(ap);
342	return retval;
343}
344
345/*
346 * Scaled down version of vsprintf(3).
347 */
348int
349vsprintf(char *buf, const char *cfmt, va_list ap)
350{
351	int retval;
352
353	retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
354	buf[retval] = '\0';
355	return retval;
356}
357
358/*
359 * Scaled down version of snprintf(3).
360 */
361int
362snprintf(char *str, size_t size, const char *format, ...)
363{
364	int retval;
365	va_list ap;
366
367	va_start(ap, format);
368	retval = vsnprintf(str, size, format, ap);
369	va_end(ap);
370	return(retval);
371}
372
373/*
374 * Scaled down version of vsnprintf(3).
375 */
376int
377vsnprintf(char *str, size_t size, const char *format, va_list ap)
378{
379	struct snprintf_arg info;
380	int retval;
381
382	info.str = str;
383	info.remain = size;
384	retval = kvprintf(format, snprintf_func, &info, 10, ap);
385	if (info.remain >= 1)
386		*info.str++ = '\0';
387	return retval;
388}
389
390static void
391snprintf_func(int ch, void *arg)
392{
393	struct snprintf_arg *const info = arg;
394
395	if (info->remain >= 2) {
396		*info->str++ = ch;
397		info->remain--;
398	}
399}
400
401/*
402 * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
403 * order; return an optional length and a pointer to the last character
404 * written in the buffer (i.e., the first character of the string).
405 * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
406 */
407static char *
408ksprintn(nbuf, ul, base, lenp)
409	char *nbuf;
410	register u_long ul;
411	register int base, *lenp;
412{
413	register char *p;
414
415	p = nbuf;
416	*p = '\0';
417	do {
418		*++p = hex2ascii(ul % base);
419	} while (ul /= base);
420	if (lenp)
421		*lenp = p - nbuf;
422	return (p);
423}
424/* ksprintn, but for a quad_t. */
425static char *
426ksprintqn(nbuf, uq, base, lenp)
427	char *nbuf;
428	register u_quad_t uq;
429	register int base, *lenp;
430{
431	register char *p;
432
433	p = nbuf;
434	*p = '\0';
435	do {
436		*++p = hex2ascii(uq % base);
437	} while (uq /= base);
438	if (lenp)
439		*lenp = p - nbuf;
440	return (p);
441}
442
443/*
444 * Scaled down version of printf(3).
445 *
446 * Two additional formats:
447 *
448 * The format %b is supported to decode error registers.
449 * Its usage is:
450 *
451 *	printf("reg=%b\n", regval, "<base><arg>*");
452 *
453 * where <base> is the output base expressed as a control character, e.g.
454 * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
455 * the first of which gives the bit number to be inspected (origin 1), and
456 * the next characters (up to a control character, i.e. a character <= 32),
457 * give the name of the register.  Thus:
458 *
459 *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
460 *
461 * would produce output:
462 *
463 *	reg=3<BITTWO,BITONE>
464 *
465 * XXX:  %D  -- Hexdump, takes pointer and separator string:
466 *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
467 *		("%*D", len, ptr, " " -> XX XX XX XX ...
468 */
469int
470kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
471{
472#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
473	char nbuf[MAXNBUF];
474	char *p, *q, *d;
475	u_char *up;
476	int ch, n;
477	u_long ul;
478	u_quad_t uq;
479	int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
480	int dwidth;
481	char padc;
482	int retval = 0;
483
484	ul = 0;
485	uq = 0;
486	if (!func)
487		d = (char *) arg;
488	else
489		d = NULL;
490
491	if (fmt == NULL)
492		fmt = "(fmt null)\n";
493
494	if (radix < 2 || radix > 36)
495		radix = 10;
496
497	for (;;) {
498		padc = ' ';
499		width = 0;
500		while ((ch = (u_char)*fmt++) != '%') {
501			if (ch == '\0')
502				return retval;
503			PCHAR(ch);
504		}
505		qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
506		sign = 0; dot = 0; dwidth = 0;
507reswitch:	switch (ch = (u_char)*fmt++) {
508		case '.':
509			dot = 1;
510			goto reswitch;
511		case '#':
512			sharpflag = 1;
513			goto reswitch;
514		case '+':
515			sign = 1;
516			goto reswitch;
517		case '-':
518			ladjust = 1;
519			goto reswitch;
520		case '%':
521			PCHAR(ch);
522			break;
523		case '*':
524			if (!dot) {
525				width = va_arg(ap, int);
526				if (width < 0) {
527					ladjust = !ladjust;
528					width = -width;
529				}
530			} else {
531				dwidth = va_arg(ap, int);
532			}
533			goto reswitch;
534		case '0':
535			if (!dot) {
536				padc = '0';
537				goto reswitch;
538			}
539		case '1': case '2': case '3': case '4':
540		case '5': case '6': case '7': case '8': case '9':
541				for (n = 0;; ++fmt) {
542					n = n * 10 + ch - '0';
543					ch = *fmt;
544					if (ch < '0' || ch > '9')
545						break;
546				}
547			if (dot)
548				dwidth = n;
549			else
550				width = n;
551			goto reswitch;
552		case 'b':
553			ul = va_arg(ap, int);
554			p = va_arg(ap, char *);
555			for (q = ksprintn(nbuf, ul, *p++, NULL); *q;)
556				PCHAR(*q--);
557
558			if (!ul)
559				break;
560
561			for (tmp = 0; *p;) {
562				n = *p++;
563				if (ul & (1 << (n - 1))) {
564					PCHAR(tmp ? ',' : '<');
565					for (; (n = *p) > ' '; ++p)
566						PCHAR(n);
567					tmp = 1;
568				} else
569					for (; *p > ' '; ++p)
570						continue;
571			}
572			if (tmp)
573				PCHAR('>');
574			break;
575		case 'c':
576			PCHAR(va_arg(ap, int));
577			break;
578		case 'D':
579			up = va_arg(ap, u_char *);
580			p = va_arg(ap, char *);
581			if (!width)
582				width = 16;
583			while(width--) {
584				PCHAR(hex2ascii(*up >> 4));
585				PCHAR(hex2ascii(*up & 0x0f));
586				up++;
587				if (width)
588					for (q=p;*q;q++)
589						PCHAR(*q);
590			}
591			break;
592		case 'd':
593			if (qflag)
594				uq = va_arg(ap, quad_t);
595			else if (lflag)
596				ul = va_arg(ap, long);
597			else
598				ul = va_arg(ap, int);
599			sign = 1;
600			base = 10;
601			goto number;
602		case 'l':
603			if (lflag) {
604				lflag = 0;
605				qflag = 1;
606			} else
607				lflag = 1;
608			goto reswitch;
609		case 'o':
610			if (qflag)
611				uq = va_arg(ap, u_quad_t);
612			else if (lflag)
613				ul = va_arg(ap, u_long);
614			else
615				ul = va_arg(ap, u_int);
616			base = 8;
617			goto nosign;
618		case 'p':
619			ul = (uintptr_t)va_arg(ap, void *);
620			base = 16;
621			sharpflag = (width == 0);
622			goto nosign;
623		case 'q':
624			qflag = 1;
625			goto reswitch;
626		case 'n':
627		case 'r':
628			if (qflag)
629				uq = va_arg(ap, u_quad_t);
630			else if (lflag)
631				ul = va_arg(ap, u_long);
632			else
633				ul = sign ?
634				    (u_long)va_arg(ap, int) : va_arg(ap, u_int);
635			base = radix;
636			goto number;
637		case 's':
638			p = va_arg(ap, char *);
639			if (p == NULL)
640				p = "(null)";
641			if (!dot)
642				n = strlen (p);
643			else
644				for (n = 0; n < dwidth && p[n]; n++)
645					continue;
646
647			width -= n;
648
649			if (!ladjust && width > 0)
650				while (width--)
651					PCHAR(padc);
652			while (n--)
653				PCHAR(*p++);
654			if (ladjust && width > 0)
655				while (width--)
656					PCHAR(padc);
657			break;
658		case 'u':
659			if (qflag)
660				uq = va_arg(ap, u_quad_t);
661			else if (lflag)
662				ul = va_arg(ap, u_long);
663			else
664				ul = va_arg(ap, u_int);
665			base = 10;
666			goto nosign;
667		case 'x':
668		case 'X':
669			if (qflag)
670				uq = va_arg(ap, u_quad_t);
671			else if (lflag)
672				ul = va_arg(ap, u_long);
673			else
674				ul = va_arg(ap, u_int);
675			base = 16;
676			goto nosign;
677		case 'z':
678			if (qflag)
679				uq = va_arg(ap, u_quad_t);
680			else if (lflag)
681				ul = va_arg(ap, u_long);
682			else
683				ul = sign ?
684				    (u_long)va_arg(ap, int) : va_arg(ap, u_int);
685			base = 16;
686			goto number;
687nosign:			sign = 0;
688number:
689			if (qflag) {
690				if (sign && (quad_t)uq < 0) {
691					neg = 1;
692					uq = -(quad_t)uq;
693				}
694				p = ksprintqn(nbuf, uq, base, &tmp);
695			} else {
696				if (sign && (long)ul < 0) {
697					neg = 1;
698					ul = -(long)ul;
699				}
700				p = ksprintn(nbuf, ul, base, &tmp);
701			}
702			if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
703				if (base == 8)
704					tmp++;
705				else if (base == 16)
706					tmp += 2;
707			}
708			if (neg)
709				tmp++;
710
711			if (!ladjust && width && (width -= tmp) > 0)
712				while (width--)
713					PCHAR(padc);
714			if (neg)
715				PCHAR('-');
716			if (sharpflag && (qflag ? uq != 0 : ul != 0)) {
717				if (base == 8) {
718					PCHAR('0');
719				} else if (base == 16) {
720					PCHAR('0');
721					PCHAR('x');
722				}
723			}
724
725			while (*p)
726				PCHAR(*p--);
727
728			if (ladjust && width && (width -= tmp) > 0)
729				while (width--)
730					PCHAR(padc);
731
732			break;
733		default:
734			PCHAR('%');
735			if (lflag)
736				PCHAR('l');
737			PCHAR(ch);
738			break;
739		}
740	}
741#undef PCHAR
742}
743
744/*
745 * Put character in log buffer.
746 */
747static void
748msglogchar(int c, void *dummyarg)
749{
750	struct msgbuf *mbp;
751
752	if (c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
753		mbp = msgbufp;
754		mbp->msg_ptr[mbp->msg_bufx++] = c;
755		if (mbp->msg_bufx >= mbp->msg_size)
756			mbp->msg_bufx = 0;
757		/* If the buffer is full, keep the most recent data. */
758		if (mbp->msg_bufr == mbp->msg_bufx) {
759			if (++mbp->msg_bufr >= mbp->msg_size)
760				mbp->msg_bufr = 0;
761		}
762	}
763}
764
765static void
766msgbufcopy(struct msgbuf *oldp)
767{
768	int pos;
769
770	pos = oldp->msg_bufr;
771	while (pos != oldp->msg_bufx) {
772		msglogchar(oldp->msg_ptr[pos], NULL);
773		if (++pos >= oldp->msg_size)
774			pos = 0;
775	}
776}
777
778void
779msgbufinit(void *ptr, size_t size)
780{
781	char *cp;
782	static struct msgbuf *oldp = NULL;
783
784	cp = (char *)ptr;
785	msgbufp = (struct msgbuf *) (cp + size - sizeof(*msgbufp));
786	if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_ptr != cp) {
787		bzero(cp, size);
788		msgbufp->msg_magic = MSG_MAGIC;
789		msgbufp->msg_size = (char *)msgbufp - cp;
790		msgbufp->msg_ptr = cp;
791	}
792	if (msgbufmapped && oldp != msgbufp)
793		msgbufcopy(oldp);
794	msgbufmapped = 1;
795	oldp = msgbufp;
796}
797
798#include "opt_ddb.h"
799#ifdef DDB
800#include <ddb/ddb.h>
801
802DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
803{
804	int i, j;
805
806	if (!msgbufmapped) {
807		db_printf("msgbuf not mapped yet\n");
808		return;
809	}
810	db_printf("msgbufp = %p\n", msgbufp);
811	db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n",
812	    msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr,
813	    msgbufp->msg_bufx, msgbufp->msg_ptr);
814	for (i = 0; i < msgbufp->msg_size; i++) {
815		j = (i + msgbufp->msg_bufr) % msgbufp->msg_size;
816		db_printf("%c", msgbufp->msg_ptr[j]);
817	}
818	db_printf("\n");
819}
820
821#endif /* DDB */
822