1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Implementations of the functions described in vsnprintf(3C) and string(3C), 31*0Sstevel@tonic-gate * for use by the kernel, the standalone, and kmdb. Unless otherwise specified, 32*0Sstevel@tonic-gate * these functions match the section 3C manpages. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #include <sys/types.h> 36*0Sstevel@tonic-gate #include <sys/varargs.h> 37*0Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB) 38*0Sstevel@tonic-gate #include <string.h> 39*0Sstevel@tonic-gate #else 40*0Sstevel@tonic-gate #include <sys/systm.h> 41*0Sstevel@tonic-gate #endif 42*0Sstevel@tonic-gate #ifdef _KERNEL 43*0Sstevel@tonic-gate #include <sys/debug.h> 44*0Sstevel@tonic-gate #endif /* _KERNEL */ 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate /* 47*0Sstevel@tonic-gate * kmdb has its own *printf routines, and thus doesn't need these versions too. 48*0Sstevel@tonic-gate */ 49*0Sstevel@tonic-gate #if !defined(_KMDB) 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate #define ADDCHAR(c) if (bufp++ - buf < buflen) bufp[-1] = (c) 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate /* 54*0Sstevel@tonic-gate * Given a buffer 'buf' of size 'buflen', render as much of the string 55*0Sstevel@tonic-gate * described by <fmt, args> as possible. The string will always be 56*0Sstevel@tonic-gate * null-terminated, so the maximum string length is 'buflen - 1'. 57*0Sstevel@tonic-gate * Returns the number of bytes that would be necessary to render the 58*0Sstevel@tonic-gate * entire string, not including null terminator (just like vsnprintf(3S)). 59*0Sstevel@tonic-gate * To determine buffer size in advance, use vsnprintf(NULL, 0, fmt, args) + 1. 60*0Sstevel@tonic-gate * 61*0Sstevel@tonic-gate * There is no support for floating point, and the C locale is assumed. 62*0Sstevel@tonic-gate */ 63*0Sstevel@tonic-gate size_t 64*0Sstevel@tonic-gate vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs) 65*0Sstevel@tonic-gate { 66*0Sstevel@tonic-gate uint64_t ul, tmp; 67*0Sstevel@tonic-gate char *bufp = buf; /* current buffer pointer */ 68*0Sstevel@tonic-gate int pad, width, ells, base, sign, c; 69*0Sstevel@tonic-gate char *digits, *sp, *bs; 70*0Sstevel@tonic-gate char numbuf[65]; /* sufficient for a 64-bit binary value */ 71*0Sstevel@tonic-gate va_list args; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* 74*0Sstevel@tonic-gate * Make a copy so that all our callers don't have to make a copy 75*0Sstevel@tonic-gate */ 76*0Sstevel@tonic-gate va_copy(args, aargs); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate if ((ssize_t)buflen < 0) 79*0Sstevel@tonic-gate buflen = 0; 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate while ((c = *fmt++) != '\0') { 82*0Sstevel@tonic-gate if (c != '%') { 83*0Sstevel@tonic-gate ADDCHAR(c); 84*0Sstevel@tonic-gate continue; 85*0Sstevel@tonic-gate } 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate if ((c = *fmt++) == '\0') 88*0Sstevel@tonic-gate break; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate for (pad = ' '; c == '0'; c = *fmt++) 91*0Sstevel@tonic-gate pad = '0'; 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate for (width = 0; c >= '0' && c <= '9'; c = *fmt++) 94*0Sstevel@tonic-gate width = width * 10 + c - '0'; 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate for (ells = 0; c == 'l'; c = *fmt++) 97*0Sstevel@tonic-gate ells++; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate digits = "0123456789abcdef"; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate if (c >= 'A' && c <= 'Z') { 102*0Sstevel@tonic-gate c += 'a' - 'A'; 103*0Sstevel@tonic-gate digits = "0123456789ABCDEF"; 104*0Sstevel@tonic-gate } 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate base = sign = 0; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate switch (c) { 109*0Sstevel@tonic-gate case 'd': 110*0Sstevel@tonic-gate sign = 1; 111*0Sstevel@tonic-gate /*FALLTHROUGH*/ 112*0Sstevel@tonic-gate case 'u': 113*0Sstevel@tonic-gate base = 10; 114*0Sstevel@tonic-gate break; 115*0Sstevel@tonic-gate case 'p': 116*0Sstevel@tonic-gate ells = 1; 117*0Sstevel@tonic-gate /*FALLTHROUGH*/ 118*0Sstevel@tonic-gate case 'x': 119*0Sstevel@tonic-gate base = 16; 120*0Sstevel@tonic-gate break; 121*0Sstevel@tonic-gate case 'o': 122*0Sstevel@tonic-gate base = 8; 123*0Sstevel@tonic-gate break; 124*0Sstevel@tonic-gate case 'b': 125*0Sstevel@tonic-gate ells = 0; 126*0Sstevel@tonic-gate base = 1; 127*0Sstevel@tonic-gate break; 128*0Sstevel@tonic-gate case 'c': 129*0Sstevel@tonic-gate ul = (int64_t)va_arg(args, int); 130*0Sstevel@tonic-gate ADDCHAR((int)ul & 0xff); 131*0Sstevel@tonic-gate break; 132*0Sstevel@tonic-gate case 's': 133*0Sstevel@tonic-gate sp = va_arg(args, char *); 134*0Sstevel@tonic-gate if (sp == NULL) 135*0Sstevel@tonic-gate sp = "<null string>"; 136*0Sstevel@tonic-gate while ((c = *sp++) != 0) 137*0Sstevel@tonic-gate ADDCHAR(c); 138*0Sstevel@tonic-gate break; 139*0Sstevel@tonic-gate case '%': 140*0Sstevel@tonic-gate ADDCHAR('%'); 141*0Sstevel@tonic-gate break; 142*0Sstevel@tonic-gate } 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate if (base == 0) 145*0Sstevel@tonic-gate continue; 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate if (ells == 0) 148*0Sstevel@tonic-gate ul = (int64_t)va_arg(args, int); 149*0Sstevel@tonic-gate else if (ells == 1) 150*0Sstevel@tonic-gate ul = (int64_t)va_arg(args, long); 151*0Sstevel@tonic-gate else 152*0Sstevel@tonic-gate ul = (int64_t)va_arg(args, int64_t); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate if (sign && (int64_t)ul < 0) 155*0Sstevel@tonic-gate ul = -ul; 156*0Sstevel@tonic-gate else 157*0Sstevel@tonic-gate sign = 0; 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate if (ells < 8 / sizeof (long)) 160*0Sstevel@tonic-gate ul &= 0xffffffffU; 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate if (c == 'b') { 163*0Sstevel@tonic-gate bs = va_arg(args, char *); 164*0Sstevel@tonic-gate base = *bs++; 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate tmp = ul; 168*0Sstevel@tonic-gate do { 169*0Sstevel@tonic-gate width--; 170*0Sstevel@tonic-gate } while ((tmp /= base) != 0); 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate if (sign && pad == '0') 173*0Sstevel@tonic-gate ADDCHAR('-'); 174*0Sstevel@tonic-gate while (width-- > sign) 175*0Sstevel@tonic-gate ADDCHAR(pad); 176*0Sstevel@tonic-gate if (sign && pad == ' ') 177*0Sstevel@tonic-gate ADDCHAR('-'); 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate sp = numbuf; 180*0Sstevel@tonic-gate tmp = ul; 181*0Sstevel@tonic-gate do { 182*0Sstevel@tonic-gate *sp++ = digits[tmp % base]; 183*0Sstevel@tonic-gate } while ((tmp /= base) != 0); 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate while (sp > numbuf) { 186*0Sstevel@tonic-gate sp--; 187*0Sstevel@tonic-gate ADDCHAR(*sp); 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate if (c == 'b' && ul != 0) { 191*0Sstevel@tonic-gate int any = 0; 192*0Sstevel@tonic-gate c = *bs++; 193*0Sstevel@tonic-gate while (c != 0) { 194*0Sstevel@tonic-gate if (ul & (1 << (c - 1))) { 195*0Sstevel@tonic-gate if (any++ == 0) 196*0Sstevel@tonic-gate ADDCHAR('<'); 197*0Sstevel@tonic-gate while ((c = *bs++) >= 32) 198*0Sstevel@tonic-gate ADDCHAR(c); 199*0Sstevel@tonic-gate ADDCHAR(','); 200*0Sstevel@tonic-gate } else { 201*0Sstevel@tonic-gate while ((c = *bs++) >= 32) 202*0Sstevel@tonic-gate continue; 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate if (any) { 206*0Sstevel@tonic-gate bufp--; 207*0Sstevel@tonic-gate ADDCHAR('>'); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate if (bufp - buf < buflen) 212*0Sstevel@tonic-gate bufp[0] = c; 213*0Sstevel@tonic-gate else if (buflen != 0) 214*0Sstevel@tonic-gate buf[buflen - 1] = c; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate va_end(args); 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate return (bufp - buf); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate /*PRINTFLIKE1*/ 222*0Sstevel@tonic-gate size_t 223*0Sstevel@tonic-gate snprintf(char *buf, size_t buflen, const char *fmt, ...) 224*0Sstevel@tonic-gate { 225*0Sstevel@tonic-gate va_list args; 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate va_start(args, fmt); 228*0Sstevel@tonic-gate buflen = vsnprintf(buf, buflen, fmt, args); 229*0Sstevel@tonic-gate va_end(args); 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate return (buflen); 232*0Sstevel@tonic-gate } 233*0Sstevel@tonic-gate 234*0Sstevel@tonic-gate #if defined(_BOOT) 235*0Sstevel@tonic-gate /* 236*0Sstevel@tonic-gate * The sprintf() and vsprintf() routines aren't shared with the kernel because 237*0Sstevel@tonic-gate * the DDI mandates that they return the buffer rather than its length. 238*0Sstevel@tonic-gate */ 239*0Sstevel@tonic-gate /*PRINTFLIKE2*/ 240*0Sstevel@tonic-gate int 241*0Sstevel@tonic-gate sprintf(char *buf, const char *fmt, ...) 242*0Sstevel@tonic-gate { 243*0Sstevel@tonic-gate va_list args; 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate va_start(args, fmt); 246*0Sstevel@tonic-gate (void) vsnprintf(buf, INT_MAX, fmt, args); 247*0Sstevel@tonic-gate va_end(args); 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate return (strlen(buf)); 250*0Sstevel@tonic-gate } 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate int 253*0Sstevel@tonic-gate vsprintf(char *buf, const char *fmt, va_list args) 254*0Sstevel@tonic-gate { 255*0Sstevel@tonic-gate (void) vsnprintf(buf, INT_MAX, fmt, args); 256*0Sstevel@tonic-gate return (strlen(buf)); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate #endif 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate #endif /* !_KMDB */ 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate char * 263*0Sstevel@tonic-gate strcat(char *s1, const char *s2) 264*0Sstevel@tonic-gate { 265*0Sstevel@tonic-gate char *os1 = s1; 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate while (*s1++ != '\0') 268*0Sstevel@tonic-gate ; 269*0Sstevel@tonic-gate s1--; 270*0Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') 271*0Sstevel@tonic-gate ; 272*0Sstevel@tonic-gate return (os1); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate char * 276*0Sstevel@tonic-gate strchr(const char *sp, int c) 277*0Sstevel@tonic-gate { 278*0Sstevel@tonic-gate do { 279*0Sstevel@tonic-gate if (*sp == (char)c) 280*0Sstevel@tonic-gate return ((char *)sp); 281*0Sstevel@tonic-gate } while (*sp++); 282*0Sstevel@tonic-gate return (NULL); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate int 286*0Sstevel@tonic-gate strcmp(const char *s1, const char *s2) 287*0Sstevel@tonic-gate { 288*0Sstevel@tonic-gate while (*s1 == *s2++) 289*0Sstevel@tonic-gate if (*s1++ == '\0') 290*0Sstevel@tonic-gate return (0); 291*0Sstevel@tonic-gate return (*(unsigned char *)s1 - *(unsigned char *)--s2); 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate int 295*0Sstevel@tonic-gate strncmp(const char *s1, const char *s2, size_t n) 296*0Sstevel@tonic-gate { 297*0Sstevel@tonic-gate if (s1 == s2) 298*0Sstevel@tonic-gate return (0); 299*0Sstevel@tonic-gate n++; 300*0Sstevel@tonic-gate while (--n != 0 && *s1 == *s2++) 301*0Sstevel@tonic-gate if (*s1++ == '\0') 302*0Sstevel@tonic-gate return (0); 303*0Sstevel@tonic-gate return ((n == 0) ? 0 : *(unsigned char *)s1 - *(unsigned char *)--s2); 304*0Sstevel@tonic-gate } 305*0Sstevel@tonic-gate 306*0Sstevel@tonic-gate static const char charmap[] = { 307*0Sstevel@tonic-gate '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', 308*0Sstevel@tonic-gate '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', 309*0Sstevel@tonic-gate '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', 310*0Sstevel@tonic-gate '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', 311*0Sstevel@tonic-gate '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', 312*0Sstevel@tonic-gate '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', 313*0Sstevel@tonic-gate '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', 314*0Sstevel@tonic-gate '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', 315*0Sstevel@tonic-gate '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 316*0Sstevel@tonic-gate '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 317*0Sstevel@tonic-gate '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 318*0Sstevel@tonic-gate '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', 319*0Sstevel@tonic-gate '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 320*0Sstevel@tonic-gate '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 321*0Sstevel@tonic-gate '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 322*0Sstevel@tonic-gate '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', 323*0Sstevel@tonic-gate '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', 324*0Sstevel@tonic-gate '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', 325*0Sstevel@tonic-gate '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', 326*0Sstevel@tonic-gate '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', 327*0Sstevel@tonic-gate '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', 328*0Sstevel@tonic-gate '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', 329*0Sstevel@tonic-gate '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', 330*0Sstevel@tonic-gate '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', 331*0Sstevel@tonic-gate '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', 332*0Sstevel@tonic-gate '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', 333*0Sstevel@tonic-gate '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', 334*0Sstevel@tonic-gate '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', 335*0Sstevel@tonic-gate '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', 336*0Sstevel@tonic-gate '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', 337*0Sstevel@tonic-gate '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', 338*0Sstevel@tonic-gate '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', 339*0Sstevel@tonic-gate }; 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate int 342*0Sstevel@tonic-gate strcasecmp(const char *s1, const char *s2) 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate const unsigned char *cm = (const unsigned char *)charmap; 345*0Sstevel@tonic-gate const unsigned char *us1 = (const unsigned char *)s1; 346*0Sstevel@tonic-gate const unsigned char *us2 = (const unsigned char *)s2; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate while (cm[*us1] == cm[*us2++]) 349*0Sstevel@tonic-gate if (*us1++ == '\0') 350*0Sstevel@tonic-gate return (0); 351*0Sstevel@tonic-gate return (cm[*us1] - cm[*(us2 - 1)]); 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate int 355*0Sstevel@tonic-gate strncasecmp(const char *s1, const char *s2, size_t n) 356*0Sstevel@tonic-gate { 357*0Sstevel@tonic-gate const unsigned char *cm = (const unsigned char *)charmap; 358*0Sstevel@tonic-gate const unsigned char *us1 = (const unsigned char *)s1; 359*0Sstevel@tonic-gate const unsigned char *us2 = (const unsigned char *)s2; 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate while (n != 0 && cm[*us1] == cm[*us2++]) { 362*0Sstevel@tonic-gate if (*us1++ == '\0') 363*0Sstevel@tonic-gate return (0); 364*0Sstevel@tonic-gate n--; 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate return (n == 0 ? 0 : cm[*us1] - cm[*(us2 - 1)]); 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate char * 370*0Sstevel@tonic-gate strcpy(char *s1, const char *s2) 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate char *os1 = s1; 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') 375*0Sstevel@tonic-gate ; 376*0Sstevel@tonic-gate return (os1); 377*0Sstevel@tonic-gate } 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate char * 380*0Sstevel@tonic-gate strncpy(char *s1, const char *s2, size_t n) 381*0Sstevel@tonic-gate { 382*0Sstevel@tonic-gate char *os1 = s1; 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate n++; 385*0Sstevel@tonic-gate while (--n != 0 && (*s1++ = *s2++) != '\0') 386*0Sstevel@tonic-gate ; 387*0Sstevel@tonic-gate if (n != 0) 388*0Sstevel@tonic-gate while (--n != 0) 389*0Sstevel@tonic-gate *s1++ = '\0'; 390*0Sstevel@tonic-gate return (os1); 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate char * 394*0Sstevel@tonic-gate strrchr(const char *sp, int c) 395*0Sstevel@tonic-gate { 396*0Sstevel@tonic-gate char *r = NULL; 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate do { 399*0Sstevel@tonic-gate if (*sp == (char)c) 400*0Sstevel@tonic-gate r = (char *)sp; 401*0Sstevel@tonic-gate } while (*sp++); 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate return (r); 404*0Sstevel@tonic-gate } 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate char * 407*0Sstevel@tonic-gate strstr(const char *as1, const char *as2) 408*0Sstevel@tonic-gate { 409*0Sstevel@tonic-gate const char *s1, *s2; 410*0Sstevel@tonic-gate const char *tptr; 411*0Sstevel@tonic-gate char c; 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate s1 = as1; 414*0Sstevel@tonic-gate s2 = as2; 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0') 417*0Sstevel@tonic-gate return ((char *)s1); 418*0Sstevel@tonic-gate c = *s2; 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate while (*s1) 421*0Sstevel@tonic-gate if (*s1++ == c) { 422*0Sstevel@tonic-gate tptr = s1; 423*0Sstevel@tonic-gate while ((c = *++s2) == *s1++ && c) 424*0Sstevel@tonic-gate ; 425*0Sstevel@tonic-gate if (c == 0) 426*0Sstevel@tonic-gate return ((char *)tptr - 1); 427*0Sstevel@tonic-gate s1 = tptr; 428*0Sstevel@tonic-gate s2 = as2; 429*0Sstevel@tonic-gate c = *s2; 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate return (NULL); 433*0Sstevel@tonic-gate } 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate char * 436*0Sstevel@tonic-gate strpbrk(const char *string, const char *brkset) 437*0Sstevel@tonic-gate { 438*0Sstevel@tonic-gate const char *p; 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate do { 441*0Sstevel@tonic-gate for (p = brkset; *p != '\0' && *p != *string; ++p) 442*0Sstevel@tonic-gate ; 443*0Sstevel@tonic-gate if (*p != '\0') 444*0Sstevel@tonic-gate return ((char *)string); 445*0Sstevel@tonic-gate } while (*string++); 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate return (NULL); 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate 450*0Sstevel@tonic-gate char * 451*0Sstevel@tonic-gate strncat(char *s1, const char *s2, size_t n) 452*0Sstevel@tonic-gate { 453*0Sstevel@tonic-gate char *os1 = s1; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate n++; 456*0Sstevel@tonic-gate while (*s1++ != '\0') 457*0Sstevel@tonic-gate ; 458*0Sstevel@tonic-gate --s1; 459*0Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') { 460*0Sstevel@tonic-gate if (--n == 0) { 461*0Sstevel@tonic-gate s1[-1] = '\0'; 462*0Sstevel@tonic-gate break; 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate return (os1); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB) 469*0Sstevel@tonic-gate #define bcopy(src, dst, n) (void) memcpy((dst), (src), (n)) 470*0Sstevel@tonic-gate #endif 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate size_t 473*0Sstevel@tonic-gate strlcat(char *dst, const char *src, size_t dstsize) 474*0Sstevel@tonic-gate { 475*0Sstevel@tonic-gate char *df = dst; 476*0Sstevel@tonic-gate size_t left = dstsize; 477*0Sstevel@tonic-gate size_t l1; 478*0Sstevel@tonic-gate size_t l2 = strlen(src); 479*0Sstevel@tonic-gate size_t copied; 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate while (left-- != 0 && *df != '\0') 482*0Sstevel@tonic-gate df++; 483*0Sstevel@tonic-gate l1 = df - dst; 484*0Sstevel@tonic-gate if (dstsize == l1) 485*0Sstevel@tonic-gate return (l1 + l2); 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2; 488*0Sstevel@tonic-gate bcopy(src, dst + l1, copied); 489*0Sstevel@tonic-gate dst[l1+copied] = '\0'; 490*0Sstevel@tonic-gate return (l1 + l2); 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate size_t 494*0Sstevel@tonic-gate strlcpy(char *dst, const char *src, size_t len) 495*0Sstevel@tonic-gate { 496*0Sstevel@tonic-gate size_t slen = strlen(src); 497*0Sstevel@tonic-gate size_t copied; 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate if (len == 0) 500*0Sstevel@tonic-gate return (slen); 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate if (slen >= len) 503*0Sstevel@tonic-gate copied = len - 1; 504*0Sstevel@tonic-gate else 505*0Sstevel@tonic-gate copied = slen; 506*0Sstevel@tonic-gate bcopy(src, dst, copied); 507*0Sstevel@tonic-gate dst[copied] = '\0'; 508*0Sstevel@tonic-gate return (slen); 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate size_t 512*0Sstevel@tonic-gate strspn(const char *string, const char *charset) 513*0Sstevel@tonic-gate { 514*0Sstevel@tonic-gate const char *p, *q; 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate for (q = string; *q != '\0'; ++q) { 517*0Sstevel@tonic-gate for (p = charset; *p != '\0' && *p != *q; ++p) 518*0Sstevel@tonic-gate ; 519*0Sstevel@tonic-gate if (*p == '\0') 520*0Sstevel@tonic-gate break; 521*0Sstevel@tonic-gate } 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate return (q - string); 524*0Sstevel@tonic-gate } 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate /* 527*0Sstevel@tonic-gate * Unless mentioned otherwise, all of the routines below should be added to 528*0Sstevel@tonic-gate * the Solaris DDI as necessary. For now, only provide them to standalone. 529*0Sstevel@tonic-gate */ 530*0Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB) 531*0Sstevel@tonic-gate char * 532*0Sstevel@tonic-gate strtok(char *string, const char *sepset) 533*0Sstevel@tonic-gate { 534*0Sstevel@tonic-gate char *p, *q, *r; 535*0Sstevel@tonic-gate static char *savept; 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate /* 538*0Sstevel@tonic-gate * Set `p' to our current location in the string. 539*0Sstevel@tonic-gate */ 540*0Sstevel@tonic-gate p = (string == NULL) ? savept : string; 541*0Sstevel@tonic-gate if (p == NULL) 542*0Sstevel@tonic-gate return (NULL); 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate /* 545*0Sstevel@tonic-gate * Skip leading separators; bail if no tokens remain. 546*0Sstevel@tonic-gate */ 547*0Sstevel@tonic-gate q = p + strspn(p, sepset); 548*0Sstevel@tonic-gate if (*q == '\0') 549*0Sstevel@tonic-gate return (NULL); 550*0Sstevel@tonic-gate 551*0Sstevel@tonic-gate /* 552*0Sstevel@tonic-gate * Mark the end of the token and set `savept' for the next iteration. 553*0Sstevel@tonic-gate */ 554*0Sstevel@tonic-gate if ((r = strpbrk(q, sepset)) == NULL) 555*0Sstevel@tonic-gate savept = NULL; 556*0Sstevel@tonic-gate else { 557*0Sstevel@tonic-gate *r = '\0'; 558*0Sstevel@tonic-gate savept = ++r; 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate return (q); 562*0Sstevel@tonic-gate } 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate /* 565*0Sstevel@tonic-gate * The strlen() routine isn't shared with the kernel because it has its own 566*0Sstevel@tonic-gate * hand-tuned assembly version. 567*0Sstevel@tonic-gate */ 568*0Sstevel@tonic-gate size_t 569*0Sstevel@tonic-gate strlen(const char *s) 570*0Sstevel@tonic-gate { 571*0Sstevel@tonic-gate size_t n = 0; 572*0Sstevel@tonic-gate 573*0Sstevel@tonic-gate while (*s++) 574*0Sstevel@tonic-gate n++; 575*0Sstevel@tonic-gate return (n); 576*0Sstevel@tonic-gate } 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate #endif /* _BOOT || _KMDB */ 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate #ifdef _KERNEL 581*0Sstevel@tonic-gate /* 582*0Sstevel@tonic-gate * Check for a valid C identifier: 583*0Sstevel@tonic-gate * a letter or underscore, followed by 584*0Sstevel@tonic-gate * zero or more letters, digits and underscores. 585*0Sstevel@tonic-gate */ 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate #define IS_ALPHA(c) \ 590*0Sstevel@tonic-gate (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate int 593*0Sstevel@tonic-gate strident_valid(const char *id) 594*0Sstevel@tonic-gate { 595*0Sstevel@tonic-gate int c = *id++; 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate if (!IS_ALPHA(c) && c != '_') 598*0Sstevel@tonic-gate return (0); 599*0Sstevel@tonic-gate while ((c = *id++) != 0) { 600*0Sstevel@tonic-gate if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_') 601*0Sstevel@tonic-gate return (0); 602*0Sstevel@tonic-gate } 603*0Sstevel@tonic-gate return (1); 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate /* 607*0Sstevel@tonic-gate * Convert a string into a valid C identifier by replacing invalid 608*0Sstevel@tonic-gate * characters with '_'. Also makes sure the string is nul-terminated 609*0Sstevel@tonic-gate * and takes up at most n bytes. 610*0Sstevel@tonic-gate */ 611*0Sstevel@tonic-gate void 612*0Sstevel@tonic-gate strident_canon(char *s, size_t n) 613*0Sstevel@tonic-gate { 614*0Sstevel@tonic-gate char c; 615*0Sstevel@tonic-gate char *end = s + n - 1; 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate ASSERT(n > 0); 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate if ((c = *s) == 0) 620*0Sstevel@tonic-gate return; 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate if (!IS_ALPHA(c) && c != '_') 623*0Sstevel@tonic-gate *s = '_'; 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate while (s < end && ((c = *(++s)) != 0)) { 626*0Sstevel@tonic-gate if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_') 627*0Sstevel@tonic-gate *s = '_'; 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate *s = 0; 630*0Sstevel@tonic-gate } 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate #endif /* _KERNEL */ 633