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