1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
30*7c478bd9Sstevel@tonic-gate #include <limits.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/socket.h>
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h>
35*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_modapi.h>
36*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_lex.h>
37*7c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h>
38*7c478bd9Sstevel@tonic-gate #include <mdb/mdb.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate /*
41*7c478bd9Sstevel@tonic-gate  * Convert the specified integer value to a string represented in the given
42*7c478bd9Sstevel@tonic-gate  * base.  The flags parameter is a bitfield of the formatting flags defined in
43*7c478bd9Sstevel@tonic-gate  * mdb_string.h.  A pointer to a static conversion buffer is returned.
44*7c478bd9Sstevel@tonic-gate  */
45*7c478bd9Sstevel@tonic-gate const char *
46*7c478bd9Sstevel@tonic-gate numtostr(uintmax_t uvalue, int base, uint_t flags)
47*7c478bd9Sstevel@tonic-gate {
48*7c478bd9Sstevel@tonic-gate 	static const char ldigits[] = "0123456789abcdef";
49*7c478bd9Sstevel@tonic-gate 	static const char udigits[] = "0123456789ABCDEF";
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate 	static char buf[68]; /* Enough for ULLONG_MAX in binary plus prefixes */
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate 	const char *digits = (flags & NTOS_UPCASE) ? udigits : ldigits;
54*7c478bd9Sstevel@tonic-gate 	int i = sizeof (buf);
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate 	intmax_t value = (intmax_t)uvalue;
57*7c478bd9Sstevel@tonic-gate 	int neg = (flags & NTOS_UNSIGNED) == 0 && value < 0;
58*7c478bd9Sstevel@tonic-gate 	uintmax_t rem = neg ? -value : value;
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate 	buf[--i] = 0;
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate 	do {
63*7c478bd9Sstevel@tonic-gate 		buf[--i] = digits[rem % base];
64*7c478bd9Sstevel@tonic-gate 		rem /= base;
65*7c478bd9Sstevel@tonic-gate 	} while (rem != 0);
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate 	if (flags & NTOS_SHOWBASE) {
68*7c478bd9Sstevel@tonic-gate 		uintmax_t lim;
69*7c478bd9Sstevel@tonic-gate 		char c = 0;
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 		switch (base) {
72*7c478bd9Sstevel@tonic-gate 		case 2:
73*7c478bd9Sstevel@tonic-gate 			lim = 1;
74*7c478bd9Sstevel@tonic-gate 			c = 'i';
75*7c478bd9Sstevel@tonic-gate 			break;
76*7c478bd9Sstevel@tonic-gate 		case 8:
77*7c478bd9Sstevel@tonic-gate 			lim = 7;
78*7c478bd9Sstevel@tonic-gate 			c = 'o';
79*7c478bd9Sstevel@tonic-gate 			break;
80*7c478bd9Sstevel@tonic-gate 		case 10:
81*7c478bd9Sstevel@tonic-gate 			lim = 9;
82*7c478bd9Sstevel@tonic-gate 			c = 't';
83*7c478bd9Sstevel@tonic-gate 			break;
84*7c478bd9Sstevel@tonic-gate 		case 16:
85*7c478bd9Sstevel@tonic-gate 			lim = 9;
86*7c478bd9Sstevel@tonic-gate 			c = 'x';
87*7c478bd9Sstevel@tonic-gate 			break;
88*7c478bd9Sstevel@tonic-gate 		}
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 		if (c != 0 && uvalue > lim) {
91*7c478bd9Sstevel@tonic-gate 			buf[--i] = c;
92*7c478bd9Sstevel@tonic-gate 			buf[--i] = '0';
93*7c478bd9Sstevel@tonic-gate 		}
94*7c478bd9Sstevel@tonic-gate 	}
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	if (neg)
97*7c478bd9Sstevel@tonic-gate 		buf[--i] = '-';
98*7c478bd9Sstevel@tonic-gate 	else if (flags & NTOS_SIGNPOS)
99*7c478bd9Sstevel@tonic-gate 		buf[--i] = '+';
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 	return ((const char *)(&buf[i]));
102*7c478bd9Sstevel@tonic-gate }
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate #define	CTOI(x)	(((x) >= '0' && (x) <= '9') ? (x) - '0' : \
105*7c478bd9Sstevel@tonic-gate 	((x) >= 'a' && (x) <= 'z') ? (x) + 10 - 'a' : (x) + 10 - 'A')
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate /*
108*7c478bd9Sstevel@tonic-gate  * Convert a string to an unsigned integer value using the specified base.
109*7c478bd9Sstevel@tonic-gate  * In the event of overflow or an invalid character, we generate an
110*7c478bd9Sstevel@tonic-gate  * error message and longjmp back to the main loop using yyerror().
111*7c478bd9Sstevel@tonic-gate  */
112*7c478bd9Sstevel@tonic-gate uintmax_t
113*7c478bd9Sstevel@tonic-gate strtonum(const char *s, int base)
114*7c478bd9Sstevel@tonic-gate {
115*7c478bd9Sstevel@tonic-gate 	uintmax_t multmax = (uintmax_t)ULLONG_MAX / (uintmax_t)(uint_t)base;
116*7c478bd9Sstevel@tonic-gate 	uintmax_t val = 0;
117*7c478bd9Sstevel@tonic-gate 	int c, i, neg = 0;
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	switch (c = *s) {
120*7c478bd9Sstevel@tonic-gate 	case '-':
121*7c478bd9Sstevel@tonic-gate 		neg++;
122*7c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
123*7c478bd9Sstevel@tonic-gate 	case '+':
124*7c478bd9Sstevel@tonic-gate 		c = *++s;
125*7c478bd9Sstevel@tonic-gate 	}
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 	if (c == '\0')
128*7c478bd9Sstevel@tonic-gate 		goto done;
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 	if ((val = CTOI(c)) >= base)
131*7c478bd9Sstevel@tonic-gate 		yyerror("digit '%c' is invalid in current base\n", c);
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	for (c = *++s; c != '\0'; c = *++s) {
134*7c478bd9Sstevel@tonic-gate 		if (val > multmax)
135*7c478bd9Sstevel@tonic-gate 			goto oflow;
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 		if ((i = CTOI(c)) >= base)
138*7c478bd9Sstevel@tonic-gate 			yyerror("digit '%c' is invalid in current base\n", c);
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 		val *= base;
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 		if ((uintmax_t)ULLONG_MAX - val < (uintmax_t)i)
143*7c478bd9Sstevel@tonic-gate 			goto oflow;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 		val += i;
146*7c478bd9Sstevel@tonic-gate 	}
147*7c478bd9Sstevel@tonic-gate done:
148*7c478bd9Sstevel@tonic-gate 	return (neg ? -val : val);
149*7c478bd9Sstevel@tonic-gate oflow:
150*7c478bd9Sstevel@tonic-gate 	yyerror("specified value exceeds maximum immediate value\n");
151*7c478bd9Sstevel@tonic-gate 	return ((uintmax_t)ULLONG_MAX);
152*7c478bd9Sstevel@tonic-gate }
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate /*
155*7c478bd9Sstevel@tonic-gate  * Quick string to unsigned long conversion function.  This function performs
156*7c478bd9Sstevel@tonic-gate  * no overflow checking and is only meant for internal mdb use.  It allows
157*7c478bd9Sstevel@tonic-gate  * the caller to specify the length of the string in bytes and a base.
158*7c478bd9Sstevel@tonic-gate  */
159*7c478bd9Sstevel@tonic-gate ulong_t
160*7c478bd9Sstevel@tonic-gate strntoul(const char *s, size_t nbytes, int base)
161*7c478bd9Sstevel@tonic-gate {
162*7c478bd9Sstevel@tonic-gate 	ulong_t n;
163*7c478bd9Sstevel@tonic-gate 	int c;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	for (n = 0; nbytes != 0 && (c = *s) != '\0'; s++, nbytes--)
166*7c478bd9Sstevel@tonic-gate 		n = n * base + CTOI(c);
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	return (n);
169*7c478bd9Sstevel@tonic-gate }
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate /*
172*7c478bd9Sstevel@tonic-gate  * Return a boolean value indicating whether or not a string consists
173*7c478bd9Sstevel@tonic-gate  * solely of characters which are digits 0..9.
174*7c478bd9Sstevel@tonic-gate  */
175*7c478bd9Sstevel@tonic-gate int
176*7c478bd9Sstevel@tonic-gate strisnum(const char *s)
177*7c478bd9Sstevel@tonic-gate {
178*7c478bd9Sstevel@tonic-gate 	for (; *s != '\0'; s++) {
179*7c478bd9Sstevel@tonic-gate 		if (*s < '0' || *s > '9')
180*7c478bd9Sstevel@tonic-gate 			return (0);
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 	return (1);
184*7c478bd9Sstevel@tonic-gate }
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate /*
187*7c478bd9Sstevel@tonic-gate  * Return a boolean value indicating whether or not a string contains a
188*7c478bd9Sstevel@tonic-gate  * number.  The number may be in the current radix, or it may have an
189*7c478bd9Sstevel@tonic-gate  * explicit radix qualifier.  The number will be validated against the
190*7c478bd9Sstevel@tonic-gate  * legal characters for the given radix.
191*7c478bd9Sstevel@tonic-gate  */
192*7c478bd9Sstevel@tonic-gate int
193*7c478bd9Sstevel@tonic-gate strisbasenum(const char *s)
194*7c478bd9Sstevel@tonic-gate {
195*7c478bd9Sstevel@tonic-gate 	char valid[] = "0123456789aAbBcCdDeEfF";
196*7c478bd9Sstevel@tonic-gate 	int radix = mdb.m_radix;
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 	if (s[0] == '0') {
199*7c478bd9Sstevel@tonic-gate 		switch (s[1]) {
200*7c478bd9Sstevel@tonic-gate 		case 'I':
201*7c478bd9Sstevel@tonic-gate 		case 'i':
202*7c478bd9Sstevel@tonic-gate 			radix = 2;
203*7c478bd9Sstevel@tonic-gate 			s += 2;
204*7c478bd9Sstevel@tonic-gate 			break;
205*7c478bd9Sstevel@tonic-gate 		case 'O':
206*7c478bd9Sstevel@tonic-gate 		case 'o':
207*7c478bd9Sstevel@tonic-gate 			radix = 8;
208*7c478bd9Sstevel@tonic-gate 			s += 2;
209*7c478bd9Sstevel@tonic-gate 			break;
210*7c478bd9Sstevel@tonic-gate 		case 'T':
211*7c478bd9Sstevel@tonic-gate 		case 't':
212*7c478bd9Sstevel@tonic-gate 			radix = 10;
213*7c478bd9Sstevel@tonic-gate 			s += 2;
214*7c478bd9Sstevel@tonic-gate 			break;
215*7c478bd9Sstevel@tonic-gate 		case 'x':
216*7c478bd9Sstevel@tonic-gate 		case 'X':
217*7c478bd9Sstevel@tonic-gate 			radix = 16;
218*7c478bd9Sstevel@tonic-gate 			s += 2;
219*7c478bd9Sstevel@tonic-gate 			break;
220*7c478bd9Sstevel@tonic-gate 		}
221*7c478bd9Sstevel@tonic-gate 	}
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	/* limit `valid' to the digits valid for this base */
224*7c478bd9Sstevel@tonic-gate 	valid[radix > 10 ? 10 + (radix - 10) * 2 : radix] = '\0';
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 	do {
227*7c478bd9Sstevel@tonic-gate 		if (!strchr(valid, *s))
228*7c478bd9Sstevel@tonic-gate 			return (0);
229*7c478bd9Sstevel@tonic-gate 	} while (*++s != '\0');
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	return (1);
232*7c478bd9Sstevel@tonic-gate }
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate /*
235*7c478bd9Sstevel@tonic-gate  * Quick string to integer (base 10) conversion function.  This performs
236*7c478bd9Sstevel@tonic-gate  * no overflow checking and is only meant for internal mdb use.
237*7c478bd9Sstevel@tonic-gate  */
238*7c478bd9Sstevel@tonic-gate int
239*7c478bd9Sstevel@tonic-gate strtoi(const char *s)
240*7c478bd9Sstevel@tonic-gate {
241*7c478bd9Sstevel@tonic-gate 	int c, n;
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	for (n = 0; (c = *s) >= '0' && c <= '9'; s++)
244*7c478bd9Sstevel@tonic-gate 		n = n * 10 + c - '0';
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	return (n);
247*7c478bd9Sstevel@tonic-gate }
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate /*
250*7c478bd9Sstevel@tonic-gate  * Create a copy of string s using the mdb allocator interface.
251*7c478bd9Sstevel@tonic-gate  */
252*7c478bd9Sstevel@tonic-gate char *
253*7c478bd9Sstevel@tonic-gate strdup(const char *s)
254*7c478bd9Sstevel@tonic-gate {
255*7c478bd9Sstevel@tonic-gate 	char *s1 = mdb_alloc(strlen(s) + 1, UM_SLEEP);
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	(void) strcpy(s1, s);
258*7c478bd9Sstevel@tonic-gate 	return (s1);
259*7c478bd9Sstevel@tonic-gate }
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate /*
262*7c478bd9Sstevel@tonic-gate  * Create a copy of string s, but only duplicate the first n bytes.
263*7c478bd9Sstevel@tonic-gate  */
264*7c478bd9Sstevel@tonic-gate char *
265*7c478bd9Sstevel@tonic-gate strndup(const char *s, size_t n)
266*7c478bd9Sstevel@tonic-gate {
267*7c478bd9Sstevel@tonic-gate 	char *s2 = mdb_alloc(n + 1, UM_SLEEP);
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	(void) strncpy(s2, s, n);
270*7c478bd9Sstevel@tonic-gate 	s2[n] = '\0';
271*7c478bd9Sstevel@tonic-gate 	return (s2);
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate /*
275*7c478bd9Sstevel@tonic-gate  * Convenience routine for freeing strings.
276*7c478bd9Sstevel@tonic-gate  */
277*7c478bd9Sstevel@tonic-gate void
278*7c478bd9Sstevel@tonic-gate strfree(char *s)
279*7c478bd9Sstevel@tonic-gate {
280*7c478bd9Sstevel@tonic-gate 	mdb_free(s, strlen(s) + 1);
281*7c478bd9Sstevel@tonic-gate }
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate /*
284*7c478bd9Sstevel@tonic-gate  * Transform string s inline, converting each embedded C escape sequence string
285*7c478bd9Sstevel@tonic-gate  * to the corresponding character.  For example, the substring "\n" is replaced
286*7c478bd9Sstevel@tonic-gate  * by an inline '\n' character.  The length of the resulting string is returned.
287*7c478bd9Sstevel@tonic-gate  */
288*7c478bd9Sstevel@tonic-gate size_t
289*7c478bd9Sstevel@tonic-gate stresc2chr(char *s)
290*7c478bd9Sstevel@tonic-gate {
291*7c478bd9Sstevel@tonic-gate 	char *p, *q, c;
292*7c478bd9Sstevel@tonic-gate 	int esc = 0;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	for (p = q = s; (c = *p) != '\0'; p++) {
295*7c478bd9Sstevel@tonic-gate 		if (esc) {
296*7c478bd9Sstevel@tonic-gate 			switch (c) {
297*7c478bd9Sstevel@tonic-gate 				case '0':
298*7c478bd9Sstevel@tonic-gate 				case '1':
299*7c478bd9Sstevel@tonic-gate 				case '2':
300*7c478bd9Sstevel@tonic-gate 				case '3':
301*7c478bd9Sstevel@tonic-gate 				case '4':
302*7c478bd9Sstevel@tonic-gate 				case '5':
303*7c478bd9Sstevel@tonic-gate 				case '6':
304*7c478bd9Sstevel@tonic-gate 				case '7':
305*7c478bd9Sstevel@tonic-gate 					c -= '0';
306*7c478bd9Sstevel@tonic-gate 					p++;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 					if (*p >= '0' && *p <= '7') {
309*7c478bd9Sstevel@tonic-gate 						c = c * 8 + *p++ - '0';
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 						if (*p >= '0' && *p <= '7')
312*7c478bd9Sstevel@tonic-gate 							c = c * 8 + *p - '0';
313*7c478bd9Sstevel@tonic-gate 						else
314*7c478bd9Sstevel@tonic-gate 							p--;
315*7c478bd9Sstevel@tonic-gate 					} else
316*7c478bd9Sstevel@tonic-gate 						p--;
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 					*q++ = c;
319*7c478bd9Sstevel@tonic-gate 					break;
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 				case 'a':
322*7c478bd9Sstevel@tonic-gate 					*q++ = '\a';
323*7c478bd9Sstevel@tonic-gate 					break;
324*7c478bd9Sstevel@tonic-gate 				case 'b':
325*7c478bd9Sstevel@tonic-gate 					*q++ = '\b';
326*7c478bd9Sstevel@tonic-gate 					break;
327*7c478bd9Sstevel@tonic-gate 				case 'f':
328*7c478bd9Sstevel@tonic-gate 					*q++ = '\f';
329*7c478bd9Sstevel@tonic-gate 					break;
330*7c478bd9Sstevel@tonic-gate 				case 'n':
331*7c478bd9Sstevel@tonic-gate 					*q++ = '\n';
332*7c478bd9Sstevel@tonic-gate 					break;
333*7c478bd9Sstevel@tonic-gate 				case 'r':
334*7c478bd9Sstevel@tonic-gate 					*q++ = '\r';
335*7c478bd9Sstevel@tonic-gate 					break;
336*7c478bd9Sstevel@tonic-gate 				case 't':
337*7c478bd9Sstevel@tonic-gate 					*q++ = '\t';
338*7c478bd9Sstevel@tonic-gate 					break;
339*7c478bd9Sstevel@tonic-gate 				case 'v':
340*7c478bd9Sstevel@tonic-gate 					*q++ = '\v';
341*7c478bd9Sstevel@tonic-gate 					break;
342*7c478bd9Sstevel@tonic-gate 				case '"':
343*7c478bd9Sstevel@tonic-gate 				case '\\':
344*7c478bd9Sstevel@tonic-gate 					*q++ = c;
345*7c478bd9Sstevel@tonic-gate 					break;
346*7c478bd9Sstevel@tonic-gate 				default:
347*7c478bd9Sstevel@tonic-gate 					*q++ = '\\';
348*7c478bd9Sstevel@tonic-gate 					*q++ = c;
349*7c478bd9Sstevel@tonic-gate 			}
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 			esc = 0;
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 		} else {
354*7c478bd9Sstevel@tonic-gate 			if ((esc = c == '\\') == 0)
355*7c478bd9Sstevel@tonic-gate 				*q++ = c;
356*7c478bd9Sstevel@tonic-gate 		}
357*7c478bd9Sstevel@tonic-gate 	}
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 	*q = '\0';
360*7c478bd9Sstevel@tonic-gate 	return ((size_t)(q - s));
361*7c478bd9Sstevel@tonic-gate }
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate /*
364*7c478bd9Sstevel@tonic-gate  * Create a copy of string s in which certain unprintable or special characters
365*7c478bd9Sstevel@tonic-gate  * have been converted to the string representation of their C escape sequence.
366*7c478bd9Sstevel@tonic-gate  * For example, the newline character is expanded to the string "\n".
367*7c478bd9Sstevel@tonic-gate  */
368*7c478bd9Sstevel@tonic-gate char *
369*7c478bd9Sstevel@tonic-gate strchr2esc(const char *s, size_t n)
370*7c478bd9Sstevel@tonic-gate {
371*7c478bd9Sstevel@tonic-gate 	const char *p;
372*7c478bd9Sstevel@tonic-gate 	char *q, *s2, c;
373*7c478bd9Sstevel@tonic-gate 	size_t addl = 0;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	for (p = s; p < s + n; p++) {
376*7c478bd9Sstevel@tonic-gate 		switch (c = *p) {
377*7c478bd9Sstevel@tonic-gate 		case '\0':
378*7c478bd9Sstevel@tonic-gate 		case '\a':
379*7c478bd9Sstevel@tonic-gate 		case '\b':
380*7c478bd9Sstevel@tonic-gate 		case '\f':
381*7c478bd9Sstevel@tonic-gate 		case '\n':
382*7c478bd9Sstevel@tonic-gate 		case '\r':
383*7c478bd9Sstevel@tonic-gate 		case '\t':
384*7c478bd9Sstevel@tonic-gate 		case '\v':
385*7c478bd9Sstevel@tonic-gate 		case '"':
386*7c478bd9Sstevel@tonic-gate 		case '\\':
387*7c478bd9Sstevel@tonic-gate 			addl++;		/* 1 add'l char needed to follow \ */
388*7c478bd9Sstevel@tonic-gate 			break;
389*7c478bd9Sstevel@tonic-gate 		case ' ':
390*7c478bd9Sstevel@tonic-gate 			break;
391*7c478bd9Sstevel@tonic-gate 		default:
392*7c478bd9Sstevel@tonic-gate 			if (c < '!' || c > '~')
393*7c478bd9Sstevel@tonic-gate 				addl += 3; /* 3 add'l chars following \ */
394*7c478bd9Sstevel@tonic-gate 		}
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	s2 = mdb_alloc(n + addl + 1, UM_SLEEP);
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate 	for (p = s, q = s2; p < s + n; p++) {
400*7c478bd9Sstevel@tonic-gate 		switch (c = *p) {
401*7c478bd9Sstevel@tonic-gate 		case '\0':
402*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
403*7c478bd9Sstevel@tonic-gate 			*q++ = '0';
404*7c478bd9Sstevel@tonic-gate 			break;
405*7c478bd9Sstevel@tonic-gate 		case '\a':
406*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
407*7c478bd9Sstevel@tonic-gate 			*q++ = 'a';
408*7c478bd9Sstevel@tonic-gate 			break;
409*7c478bd9Sstevel@tonic-gate 		case '\b':
410*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
411*7c478bd9Sstevel@tonic-gate 			*q++ = 'b';
412*7c478bd9Sstevel@tonic-gate 			break;
413*7c478bd9Sstevel@tonic-gate 		case '\f':
414*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
415*7c478bd9Sstevel@tonic-gate 			*q++ = 'f';
416*7c478bd9Sstevel@tonic-gate 			break;
417*7c478bd9Sstevel@tonic-gate 		case '\n':
418*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
419*7c478bd9Sstevel@tonic-gate 			*q++ = 'n';
420*7c478bd9Sstevel@tonic-gate 			break;
421*7c478bd9Sstevel@tonic-gate 		case '\r':
422*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
423*7c478bd9Sstevel@tonic-gate 			*q++ = 'r';
424*7c478bd9Sstevel@tonic-gate 			break;
425*7c478bd9Sstevel@tonic-gate 		case '\t':
426*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
427*7c478bd9Sstevel@tonic-gate 			*q++ = 't';
428*7c478bd9Sstevel@tonic-gate 			break;
429*7c478bd9Sstevel@tonic-gate 		case '\v':
430*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
431*7c478bd9Sstevel@tonic-gate 			*q++ = 'v';
432*7c478bd9Sstevel@tonic-gate 			break;
433*7c478bd9Sstevel@tonic-gate 		case '"':
434*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
435*7c478bd9Sstevel@tonic-gate 			*q++ = '"';
436*7c478bd9Sstevel@tonic-gate 			break;
437*7c478bd9Sstevel@tonic-gate 		case '\\':
438*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
439*7c478bd9Sstevel@tonic-gate 			*q++ = '\\';
440*7c478bd9Sstevel@tonic-gate 			break;
441*7c478bd9Sstevel@tonic-gate 		case ' ':
442*7c478bd9Sstevel@tonic-gate 			*q++ = c;
443*7c478bd9Sstevel@tonic-gate 			break;
444*7c478bd9Sstevel@tonic-gate 		default:
445*7c478bd9Sstevel@tonic-gate 			if (c < '!' || c > '~') {
446*7c478bd9Sstevel@tonic-gate 				*q++ = '\\';
447*7c478bd9Sstevel@tonic-gate 				*q++ = ((c >> 6) & 3) + '0';
448*7c478bd9Sstevel@tonic-gate 				*q++ = ((c >> 3) & 7) + '0';
449*7c478bd9Sstevel@tonic-gate 				*q++ = (c & 7) + '0';
450*7c478bd9Sstevel@tonic-gate 			} else
451*7c478bd9Sstevel@tonic-gate 				*q++ = c;
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 	}
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 	*q = '\0';
456*7c478bd9Sstevel@tonic-gate 	return (s2);
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate /*
460*7c478bd9Sstevel@tonic-gate  * Create a copy of string s in which certain unprintable or special characters
461*7c478bd9Sstevel@tonic-gate  * have been converted to an odd representation of their escape sequence.
462*7c478bd9Sstevel@tonic-gate  * This algorithm is the old adb convention for representing such sequences.
463*7c478bd9Sstevel@tonic-gate  */
464*7c478bd9Sstevel@tonic-gate char *
465*7c478bd9Sstevel@tonic-gate strchr2adb(const char *s, size_t n)
466*7c478bd9Sstevel@tonic-gate {
467*7c478bd9Sstevel@tonic-gate 	size_t addl = 0;
468*7c478bd9Sstevel@tonic-gate 	const char *p;
469*7c478bd9Sstevel@tonic-gate 	char *q, *s2;
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 	for (p = s; p < s + n; p++) {
472*7c478bd9Sstevel@tonic-gate 		char c = *p & CHAR_MAX;
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 		if (c < ' ' || c == CHAR_MAX)
475*7c478bd9Sstevel@tonic-gate 			addl++; /* 1 add'l char needed for "^" */
476*7c478bd9Sstevel@tonic-gate 	}
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 	s2 = mdb_alloc(n + addl + 1, UM_SLEEP);
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	for (p = s, q = s2; p < s + n; p++) {
481*7c478bd9Sstevel@tonic-gate 		char c = *p & CHAR_MAX;
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 		if (c == CHAR_MAX) {
484*7c478bd9Sstevel@tonic-gate 			*q++ = '^';
485*7c478bd9Sstevel@tonic-gate 			*q++ = '?';
486*7c478bd9Sstevel@tonic-gate 		} else if (c < ' ') {
487*7c478bd9Sstevel@tonic-gate 			*q++ = '^';
488*7c478bd9Sstevel@tonic-gate 			*q++ = c + '@';
489*7c478bd9Sstevel@tonic-gate 		} else
490*7c478bd9Sstevel@tonic-gate 			*q++ = c;
491*7c478bd9Sstevel@tonic-gate 	}
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	*q = '\0';
494*7c478bd9Sstevel@tonic-gate 	return (s2);
495*7c478bd9Sstevel@tonic-gate }
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate /*
498*7c478bd9Sstevel@tonic-gate  * Same as strchr, but we only search the first n characters
499*7c478bd9Sstevel@tonic-gate  */
500*7c478bd9Sstevel@tonic-gate char *
501*7c478bd9Sstevel@tonic-gate strnchr(const char *s, int c, size_t n)
502*7c478bd9Sstevel@tonic-gate {
503*7c478bd9Sstevel@tonic-gate 	int i = 0;
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++) {
506*7c478bd9Sstevel@tonic-gate 		if (*(s + i) == (char)c)
507*7c478bd9Sstevel@tonic-gate 			return ((char *)(s + i));
508*7c478bd9Sstevel@tonic-gate 	}
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	return (NULL);
511*7c478bd9Sstevel@tonic-gate }
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate /*
514*7c478bd9Sstevel@tonic-gate  * Split the string s at the first occurrence of character c.  This character
515*7c478bd9Sstevel@tonic-gate  * is replaced by \0, and a pointer to the remainder of the string is returned.
516*7c478bd9Sstevel@tonic-gate  */
517*7c478bd9Sstevel@tonic-gate char *
518*7c478bd9Sstevel@tonic-gate strsplit(char *s, char c)
519*7c478bd9Sstevel@tonic-gate {
520*7c478bd9Sstevel@tonic-gate 	char *p;
521*7c478bd9Sstevel@tonic-gate 
522*7c478bd9Sstevel@tonic-gate 	if ((p = strchr(s, c)) == NULL)
523*7c478bd9Sstevel@tonic-gate 		return (NULL);
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate 	*p++ = '\0';
526*7c478bd9Sstevel@tonic-gate 	return (p);
527*7c478bd9Sstevel@tonic-gate }
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate /*
530*7c478bd9Sstevel@tonic-gate  * Same as strsplit, but split from the last occurrence of character c.
531*7c478bd9Sstevel@tonic-gate  */
532*7c478bd9Sstevel@tonic-gate char *
533*7c478bd9Sstevel@tonic-gate strrsplit(char *s, char c)
534*7c478bd9Sstevel@tonic-gate {
535*7c478bd9Sstevel@tonic-gate 	char *p;
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate 	if ((p = strrchr(s, c)) == NULL)
538*7c478bd9Sstevel@tonic-gate 		return (NULL);
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	*p++ = '\0';
541*7c478bd9Sstevel@tonic-gate 	return (p);
542*7c478bd9Sstevel@tonic-gate }
543*7c478bd9Sstevel@tonic-gate 
544*7c478bd9Sstevel@tonic-gate /*
545*7c478bd9Sstevel@tonic-gate  * Return the address of the first occurrence of any character from s2
546*7c478bd9Sstevel@tonic-gate  * in the string s1, or NULL if none exists.  This is similar to libc's
547*7c478bd9Sstevel@tonic-gate  * strpbrk, but we add a third parameter to limit the search to the
548*7c478bd9Sstevel@tonic-gate  * specified number of bytes in s1, or a \0 character, whichever is
549*7c478bd9Sstevel@tonic-gate  * encountered first.
550*7c478bd9Sstevel@tonic-gate  */
551*7c478bd9Sstevel@tonic-gate const char *
552*7c478bd9Sstevel@tonic-gate strnpbrk(const char *s1, const char *s2, size_t nbytes)
553*7c478bd9Sstevel@tonic-gate {
554*7c478bd9Sstevel@tonic-gate 	const char *p;
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 	if (nbytes == 0)
557*7c478bd9Sstevel@tonic-gate 		return (NULL);
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	do {
560*7c478bd9Sstevel@tonic-gate 		for (p = s2; *p != '\0' && *p != *s1; p++)
561*7c478bd9Sstevel@tonic-gate 			continue;
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 		if (*p != '\0')
564*7c478bd9Sstevel@tonic-gate 			return (s1);
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	} while (--nbytes != 0 && *s1++ != '\0');
567*7c478bd9Sstevel@tonic-gate 
568*7c478bd9Sstevel@tonic-gate 	return (NULL);
569*7c478bd9Sstevel@tonic-gate }
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate /*
572*7c478bd9Sstevel@tonic-gate  * Abbreviate a string if it meets or exceeds the specified length, including
573*7c478bd9Sstevel@tonic-gate  * the terminating null character.  The string is abbreviated by replacing the
574*7c478bd9Sstevel@tonic-gate  * last four characters with " ...".  strabbr is useful in constructs such as
575*7c478bd9Sstevel@tonic-gate  * this one, where nbytes = sizeof (buf):
576*7c478bd9Sstevel@tonic-gate  *
577*7c478bd9Sstevel@tonic-gate  * if (mdb_snprintf(buf, nbytes, "%s %d %c", ...) >= nbytes)
578*7c478bd9Sstevel@tonic-gate  *         (void) strabbr(buf, nbytes);
579*7c478bd9Sstevel@tonic-gate  *
580*7c478bd9Sstevel@tonic-gate  * No modifications are made if nbytes is too small to hold the suffix itself.
581*7c478bd9Sstevel@tonic-gate  */
582*7c478bd9Sstevel@tonic-gate char *
583*7c478bd9Sstevel@tonic-gate strabbr(char *s, size_t nbytes)
584*7c478bd9Sstevel@tonic-gate {
585*7c478bd9Sstevel@tonic-gate 	static const char suffix[] = " ...";
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate 	if (nbytes > sizeof (suffix) && strlen(s) >= nbytes - 1)
588*7c478bd9Sstevel@tonic-gate 		(void) strcpy(&s[nbytes - sizeof (suffix)], suffix);
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate 	return (s);
591*7c478bd9Sstevel@tonic-gate }
592*7c478bd9Sstevel@tonic-gate 
593*7c478bd9Sstevel@tonic-gate /*
594*7c478bd9Sstevel@tonic-gate  * Return the basename (name after final /) of the given string.  We use
595*7c478bd9Sstevel@tonic-gate  * strbasename rather than basename to avoid conflicting with libgen.h's
596*7c478bd9Sstevel@tonic-gate  * non-const function prototype.
597*7c478bd9Sstevel@tonic-gate  */
598*7c478bd9Sstevel@tonic-gate const char *
599*7c478bd9Sstevel@tonic-gate strbasename(const char *s)
600*7c478bd9Sstevel@tonic-gate {
601*7c478bd9Sstevel@tonic-gate 	const char *p = strrchr(s, '/');
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 	if (p == NULL)
604*7c478bd9Sstevel@tonic-gate 		return (s);
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	return (++p);
607*7c478bd9Sstevel@tonic-gate }
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate /*
610*7c478bd9Sstevel@tonic-gate  * Return the directory name (name prior to the final /) of the given string.
611*7c478bd9Sstevel@tonic-gate  * The string itself is modified.
612*7c478bd9Sstevel@tonic-gate  */
613*7c478bd9Sstevel@tonic-gate char *
614*7c478bd9Sstevel@tonic-gate strdirname(char *s)
615*7c478bd9Sstevel@tonic-gate {
616*7c478bd9Sstevel@tonic-gate 	static char slash[] = "/";
617*7c478bd9Sstevel@tonic-gate 	static char dot[] = ".";
618*7c478bd9Sstevel@tonic-gate 	char *p;
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate 	if (s == NULL || *s == '\0')
621*7c478bd9Sstevel@tonic-gate 		return (dot);
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 	for (p = s + strlen(s); p != s && *--p == '/'; )
624*7c478bd9Sstevel@tonic-gate 		continue;
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	if (p == s && *p == '/')
627*7c478bd9Sstevel@tonic-gate 		return (slash);
628*7c478bd9Sstevel@tonic-gate 
629*7c478bd9Sstevel@tonic-gate 	while (p != s) {
630*7c478bd9Sstevel@tonic-gate 		if (*--p == '/') {
631*7c478bd9Sstevel@tonic-gate 			while (*p == '/' && p != s)
632*7c478bd9Sstevel@tonic-gate 				p--;
633*7c478bd9Sstevel@tonic-gate 			*++p = '\0';
634*7c478bd9Sstevel@tonic-gate 			return (s);
635*7c478bd9Sstevel@tonic-gate 		}
636*7c478bd9Sstevel@tonic-gate 	}
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	return (dot);
639*7c478bd9Sstevel@tonic-gate }
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate /*
642*7c478bd9Sstevel@tonic-gate  * Return a pointer to the first character in the string that makes it an
643*7c478bd9Sstevel@tonic-gate  * invalid identifer (i.e. incompatible with the mdb syntax), or NULL if
644*7c478bd9Sstevel@tonic-gate  * the string is a valid identifier.
645*7c478bd9Sstevel@tonic-gate  */
646*7c478bd9Sstevel@tonic-gate const char *
647*7c478bd9Sstevel@tonic-gate strbadid(const char *s)
648*7c478bd9Sstevel@tonic-gate {
649*7c478bd9Sstevel@tonic-gate 	return (strpbrk(s, "#%^&*-+=,:$/\\?<>;|!`'\"[]\n\t() {}"));
650*7c478bd9Sstevel@tonic-gate }
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate /*
653*7c478bd9Sstevel@tonic-gate  * Return a boolean value indicating if the given string consists solely
654*7c478bd9Sstevel@tonic-gate  * of printable ASCII characters terminated by \0.
655*7c478bd9Sstevel@tonic-gate  */
656*7c478bd9Sstevel@tonic-gate int
657*7c478bd9Sstevel@tonic-gate strisprint(const char *s)
658*7c478bd9Sstevel@tonic-gate {
659*7c478bd9Sstevel@tonic-gate 	for (; *s != '\0'; s++) {
660*7c478bd9Sstevel@tonic-gate 		if (*s < ' ' || *s > '~')
661*7c478bd9Sstevel@tonic-gate 			return (0);
662*7c478bd9Sstevel@tonic-gate 	}
663*7c478bd9Sstevel@tonic-gate 
664*7c478bd9Sstevel@tonic-gate 	return (1);
665*7c478bd9Sstevel@tonic-gate }
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate /*
668*7c478bd9Sstevel@tonic-gate  * This is a near direct copy of the inet_ntop() code in
669*7c478bd9Sstevel@tonic-gate  * uts/common/inet/ip/ipv6.c, duplicated here for kmdb's sake.
670*7c478bd9Sstevel@tonic-gate  */
671*7c478bd9Sstevel@tonic-gate static void
672*7c478bd9Sstevel@tonic-gate convert2ascii(char *buf, const in6_addr_t *addr)
673*7c478bd9Sstevel@tonic-gate {
674*7c478bd9Sstevel@tonic-gate 	int		hexdigits;
675*7c478bd9Sstevel@tonic-gate 	int		head_zero = 0;
676*7c478bd9Sstevel@tonic-gate 	int		tail_zero = 0;
677*7c478bd9Sstevel@tonic-gate 	/* tempbuf must be big enough to hold ffff:\0 */
678*7c478bd9Sstevel@tonic-gate 	char		tempbuf[6];
679*7c478bd9Sstevel@tonic-gate 	char		*ptr;
680*7c478bd9Sstevel@tonic-gate 	uint16_t	*addr_component, host_component;
681*7c478bd9Sstevel@tonic-gate 	size_t		len;
682*7c478bd9Sstevel@tonic-gate 	int		first = FALSE;
683*7c478bd9Sstevel@tonic-gate 	int		med_zero = FALSE;
684*7c478bd9Sstevel@tonic-gate 	int		end_zero = FALSE;
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	addr_component = (uint16_t *)addr;
687*7c478bd9Sstevel@tonic-gate 	ptr = buf;
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	/* First count if trailing zeroes higher in number */
690*7c478bd9Sstevel@tonic-gate 	for (hexdigits = 0; hexdigits < 8; hexdigits++) {
691*7c478bd9Sstevel@tonic-gate 		if (*addr_component == 0) {
692*7c478bd9Sstevel@tonic-gate 			if (hexdigits < 4)
693*7c478bd9Sstevel@tonic-gate 				head_zero++;
694*7c478bd9Sstevel@tonic-gate 			else
695*7c478bd9Sstevel@tonic-gate 				tail_zero++;
696*7c478bd9Sstevel@tonic-gate 		}
697*7c478bd9Sstevel@tonic-gate 		addr_component++;
698*7c478bd9Sstevel@tonic-gate 	}
699*7c478bd9Sstevel@tonic-gate 	addr_component = (uint16_t *)addr;
700*7c478bd9Sstevel@tonic-gate 	if (tail_zero > head_zero && (head_zero + tail_zero) != 7)
701*7c478bd9Sstevel@tonic-gate 		end_zero = TRUE;
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 	for (hexdigits = 0; hexdigits < 8; hexdigits++) {
704*7c478bd9Sstevel@tonic-gate 		/* if entry is a 0 */
705*7c478bd9Sstevel@tonic-gate 		if (*addr_component == 0) {
706*7c478bd9Sstevel@tonic-gate 			if (!first && *(addr_component + 1) == 0) {
707*7c478bd9Sstevel@tonic-gate 				if (end_zero && (hexdigits < 4)) {
708*7c478bd9Sstevel@tonic-gate 					*ptr++ = '0';
709*7c478bd9Sstevel@tonic-gate 					*ptr++ = ':';
710*7c478bd9Sstevel@tonic-gate 				} else {
711*7c478bd9Sstevel@tonic-gate 					if (hexdigits == 0)
712*7c478bd9Sstevel@tonic-gate 						*ptr++ = ':';
713*7c478bd9Sstevel@tonic-gate 					/* add another */
714*7c478bd9Sstevel@tonic-gate 					*ptr++ = ':';
715*7c478bd9Sstevel@tonic-gate 					first = TRUE;
716*7c478bd9Sstevel@tonic-gate 					med_zero = TRUE;
717*7c478bd9Sstevel@tonic-gate 				}
718*7c478bd9Sstevel@tonic-gate 			} else if (first && med_zero) {
719*7c478bd9Sstevel@tonic-gate 				if (hexdigits == 7)
720*7c478bd9Sstevel@tonic-gate 					*ptr++ = ':';
721*7c478bd9Sstevel@tonic-gate 				addr_component++;
722*7c478bd9Sstevel@tonic-gate 				continue;
723*7c478bd9Sstevel@tonic-gate 			} else {
724*7c478bd9Sstevel@tonic-gate 				*ptr++ = '0';
725*7c478bd9Sstevel@tonic-gate 				*ptr++ = ':';
726*7c478bd9Sstevel@tonic-gate 			}
727*7c478bd9Sstevel@tonic-gate 			addr_component++;
728*7c478bd9Sstevel@tonic-gate 			continue;
729*7c478bd9Sstevel@tonic-gate 		}
730*7c478bd9Sstevel@tonic-gate 		if (med_zero)
731*7c478bd9Sstevel@tonic-gate 			med_zero = FALSE;
732*7c478bd9Sstevel@tonic-gate 
733*7c478bd9Sstevel@tonic-gate 		tempbuf[0] = '\0';
734*7c478bd9Sstevel@tonic-gate 		mdb_nhconvert(&host_component, addr_component,
735*7c478bd9Sstevel@tonic-gate 		    sizeof (uint16_t));
736*7c478bd9Sstevel@tonic-gate 		(void) mdb_snprintf(tempbuf, sizeof (tempbuf), "%x:",
737*7c478bd9Sstevel@tonic-gate 		    host_component & 0xffff);
738*7c478bd9Sstevel@tonic-gate 		len = strlen(tempbuf);
739*7c478bd9Sstevel@tonic-gate 		bcopy(tempbuf, ptr, len);
740*7c478bd9Sstevel@tonic-gate 		ptr = ptr + len;
741*7c478bd9Sstevel@tonic-gate 		addr_component++;
742*7c478bd9Sstevel@tonic-gate 	}
743*7c478bd9Sstevel@tonic-gate 	*--ptr = '\0';
744*7c478bd9Sstevel@tonic-gate }
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate char *
747*7c478bd9Sstevel@tonic-gate mdb_inet_ntop(int af, const void *addr, char *buf, size_t buflen)
748*7c478bd9Sstevel@tonic-gate {
749*7c478bd9Sstevel@tonic-gate 	in6_addr_t	*v6addr;
750*7c478bd9Sstevel@tonic-gate 	uchar_t		*v4addr;
751*7c478bd9Sstevel@tonic-gate 	char		*caddr;
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate #define	UC(b)	(((int)b) & 0xff)
754*7c478bd9Sstevel@tonic-gate 	switch (af) {
755*7c478bd9Sstevel@tonic-gate 	case AF_INET:
756*7c478bd9Sstevel@tonic-gate 		ASSERT(buflen >= INET_ADDRSTRLEN);
757*7c478bd9Sstevel@tonic-gate 		v4addr = (uchar_t *)addr;
758*7c478bd9Sstevel@tonic-gate 		(void) mdb_snprintf(buf, buflen, "%d.%d.%d.%d",
759*7c478bd9Sstevel@tonic-gate 		    UC(v4addr[0]), UC(v4addr[1]), UC(v4addr[2]), UC(v4addr[3]));
760*7c478bd9Sstevel@tonic-gate 		return (buf);
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate 	case AF_INET6:
763*7c478bd9Sstevel@tonic-gate 		ASSERT(buflen >= INET6_ADDRSTRLEN);
764*7c478bd9Sstevel@tonic-gate 		v6addr = (in6_addr_t *)addr;
765*7c478bd9Sstevel@tonic-gate 		if (IN6_IS_ADDR_V4MAPPED(v6addr)) {
766*7c478bd9Sstevel@tonic-gate 			caddr = (char *)addr;
767*7c478bd9Sstevel@tonic-gate 			(void) mdb_snprintf(buf, buflen, "::ffff:%d.%d.%d.%d",
768*7c478bd9Sstevel@tonic-gate 			    UC(caddr[12]), UC(caddr[13]),
769*7c478bd9Sstevel@tonic-gate 			    UC(caddr[14]), UC(caddr[15]));
770*7c478bd9Sstevel@tonic-gate 		} else if (IN6_IS_ADDR_V4COMPAT(v6addr)) {
771*7c478bd9Sstevel@tonic-gate 			caddr = (char *)addr;
772*7c478bd9Sstevel@tonic-gate 			(void) mdb_snprintf(buf, buflen, "::%d.%d.%d.%d",
773*7c478bd9Sstevel@tonic-gate 			    UC(caddr[12]), UC(caddr[13]), UC(caddr[14]),
774*7c478bd9Sstevel@tonic-gate 			    UC(caddr[15]));
775*7c478bd9Sstevel@tonic-gate 		} else if (IN6_IS_ADDR_UNSPECIFIED(v6addr)) {
776*7c478bd9Sstevel@tonic-gate 			(void) mdb_snprintf(buf, buflen, "::");
777*7c478bd9Sstevel@tonic-gate 		} else {
778*7c478bd9Sstevel@tonic-gate 			convert2ascii(buf, v6addr);
779*7c478bd9Sstevel@tonic-gate 		}
780*7c478bd9Sstevel@tonic-gate 		return (buf);
781*7c478bd9Sstevel@tonic-gate 	}
782*7c478bd9Sstevel@tonic-gate #undef UC
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 	return (NULL);
785*7c478bd9Sstevel@tonic-gate }
786