10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*941Smyers * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * Implementations of the functions described in vsnprintf(3C) and string(3C), 310Sstevel@tonic-gate * for use by the kernel, the standalone, and kmdb. Unless otherwise specified, 320Sstevel@tonic-gate * these functions match the section 3C manpages. 330Sstevel@tonic-gate */ 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include <sys/types.h> 360Sstevel@tonic-gate #include <sys/varargs.h> 370Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB) 380Sstevel@tonic-gate #include <string.h> 390Sstevel@tonic-gate #else 400Sstevel@tonic-gate #include <sys/systm.h> 410Sstevel@tonic-gate #endif 420Sstevel@tonic-gate #ifdef _KERNEL 430Sstevel@tonic-gate #include <sys/debug.h> 440Sstevel@tonic-gate #endif /* _KERNEL */ 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * kmdb has its own *printf routines, and thus doesn't need these versions too. 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate #if !defined(_KMDB) 500Sstevel@tonic-gate 510Sstevel@tonic-gate #define ADDCHAR(c) if (bufp++ - buf < buflen) bufp[-1] = (c) 520Sstevel@tonic-gate 530Sstevel@tonic-gate /* 540Sstevel@tonic-gate * Given a buffer 'buf' of size 'buflen', render as much of the string 550Sstevel@tonic-gate * described by <fmt, args> as possible. The string will always be 560Sstevel@tonic-gate * null-terminated, so the maximum string length is 'buflen - 1'. 570Sstevel@tonic-gate * Returns the number of bytes that would be necessary to render the 580Sstevel@tonic-gate * entire string, not including null terminator (just like vsnprintf(3S)). 590Sstevel@tonic-gate * To determine buffer size in advance, use vsnprintf(NULL, 0, fmt, args) + 1. 600Sstevel@tonic-gate * 610Sstevel@tonic-gate * There is no support for floating point, and the C locale is assumed. 620Sstevel@tonic-gate */ 630Sstevel@tonic-gate size_t 640Sstevel@tonic-gate vsnprintf(char *buf, size_t buflen, const char *fmt, va_list aargs) 650Sstevel@tonic-gate { 660Sstevel@tonic-gate uint64_t ul, tmp; 670Sstevel@tonic-gate char *bufp = buf; /* current buffer pointer */ 68*941Smyers int pad, width, base, sign, c, num; 69*941Smyers int prec, h_count, l_count, dot_count; 70*941Smyers int pad_count, transfer_count, left_align; 710Sstevel@tonic-gate char *digits, *sp, *bs; 720Sstevel@tonic-gate char numbuf[65]; /* sufficient for a 64-bit binary value */ 730Sstevel@tonic-gate va_list args; 740Sstevel@tonic-gate 750Sstevel@tonic-gate /* 760Sstevel@tonic-gate * Make a copy so that all our callers don't have to make a copy 770Sstevel@tonic-gate */ 780Sstevel@tonic-gate va_copy(args, aargs); 790Sstevel@tonic-gate 800Sstevel@tonic-gate if ((ssize_t)buflen < 0) 810Sstevel@tonic-gate buflen = 0; 820Sstevel@tonic-gate 830Sstevel@tonic-gate while ((c = *fmt++) != '\0') { 840Sstevel@tonic-gate if (c != '%') { 850Sstevel@tonic-gate ADDCHAR(c); 860Sstevel@tonic-gate continue; 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 89*941Smyers width = prec = 0; 90*941Smyers left_align = base = sign = 0; 91*941Smyers h_count = l_count = dot_count = 0; 92*941Smyers pad = ' '; 93*941Smyers digits = "0123456789abcdef"; 94*941Smyers next_fmt: 950Sstevel@tonic-gate if ((c = *fmt++) == '\0') 960Sstevel@tonic-gate break; 970Sstevel@tonic-gate 980Sstevel@tonic-gate if (c >= 'A' && c <= 'Z') { 990Sstevel@tonic-gate c += 'a' - 'A'; 1000Sstevel@tonic-gate digits = "0123456789ABCDEF"; 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate 103*941Smyers switch (c) { 104*941Smyers case '-': 105*941Smyers left_align++; 106*941Smyers goto next_fmt; 107*941Smyers case '0': 108*941Smyers if (dot_count == 0) 109*941Smyers pad = '0'; 110*941Smyers /*FALLTHROUGH*/ 111*941Smyers case '1': 112*941Smyers case '2': 113*941Smyers case '3': 114*941Smyers case '4': 115*941Smyers case '5': 116*941Smyers case '6': 117*941Smyers case '7': 118*941Smyers case '8': 119*941Smyers case '9': 120*941Smyers num = 0; 121*941Smyers for (;;) { 122*941Smyers num = 10 * num + c - '0'; 123*941Smyers c = *fmt; 124*941Smyers if (c < '0' || c > '9') 125*941Smyers break; 126*941Smyers else 127*941Smyers fmt++; 128*941Smyers } 129*941Smyers if (dot_count > 0) 130*941Smyers prec = num; 131*941Smyers else 132*941Smyers width = num; 1330Sstevel@tonic-gate 134*941Smyers goto next_fmt; 135*941Smyers case '.': 136*941Smyers dot_count++; 137*941Smyers goto next_fmt; 138*941Smyers case '*': 139*941Smyers width = (int)va_arg(args, int); 140*941Smyers goto next_fmt; 141*941Smyers case 'l': 142*941Smyers l_count++; 143*941Smyers goto next_fmt; 144*941Smyers case 'h': 145*941Smyers h_count++; 146*941Smyers goto next_fmt; 1470Sstevel@tonic-gate case 'd': 1480Sstevel@tonic-gate sign = 1; 1490Sstevel@tonic-gate /*FALLTHROUGH*/ 1500Sstevel@tonic-gate case 'u': 1510Sstevel@tonic-gate base = 10; 1520Sstevel@tonic-gate break; 1530Sstevel@tonic-gate case 'p': 154*941Smyers l_count = 1; 1550Sstevel@tonic-gate /*FALLTHROUGH*/ 1560Sstevel@tonic-gate case 'x': 1570Sstevel@tonic-gate base = 16; 1580Sstevel@tonic-gate break; 1590Sstevel@tonic-gate case 'o': 1600Sstevel@tonic-gate base = 8; 1610Sstevel@tonic-gate break; 1620Sstevel@tonic-gate case 'b': 163*941Smyers l_count = 0; 1640Sstevel@tonic-gate base = 1; 1650Sstevel@tonic-gate break; 1660Sstevel@tonic-gate case 'c': 167*941Smyers c = (char)va_arg(args, char); 168*941Smyers ADDCHAR(c); 1690Sstevel@tonic-gate break; 1700Sstevel@tonic-gate case 's': 1710Sstevel@tonic-gate sp = va_arg(args, char *); 172*941Smyers if (sp == NULL) { 1730Sstevel@tonic-gate sp = "<null string>"; 174*941Smyers /* avoid truncation */ 175*941Smyers prec = strlen(sp); 176*941Smyers } 177*941Smyers /* 178*941Smyers * Handle simple case specially to avoid 179*941Smyers * performance hit of strlen() 180*941Smyers */ 181*941Smyers if (prec == 0 && width == 0) { 182*941Smyers while ((c = *sp++) != 0) 183*941Smyers ADDCHAR(c); 184*941Smyers break; 185*941Smyers } 186*941Smyers transfer_count = strlen(sp); 187*941Smyers if (prec > 0) { 188*941Smyers /* trim string if too long */ 189*941Smyers if (transfer_count > prec) 190*941Smyers transfer_count = prec; 191*941Smyers /* widen field if too narrow */ 192*941Smyers if (prec > width) 193*941Smyers width = prec; 194*941Smyers } 195*941Smyers if (width > transfer_count) 196*941Smyers pad_count = width - transfer_count; 197*941Smyers else 198*941Smyers pad_count = 0; 199*941Smyers while ((!left_align) && (pad_count-- > 0)) 200*941Smyers ADDCHAR(' '); 201*941Smyers /* ADDCHAR() evaluates arg at most once */ 202*941Smyers while (transfer_count-- > 0) 203*941Smyers ADDCHAR(*sp++); 204*941Smyers while ((left_align) && (pad_count-- > 0)) 205*941Smyers ADDCHAR(' '); 2060Sstevel@tonic-gate break; 2070Sstevel@tonic-gate case '%': 2080Sstevel@tonic-gate ADDCHAR('%'); 2090Sstevel@tonic-gate break; 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate if (base == 0) 2130Sstevel@tonic-gate continue; 2140Sstevel@tonic-gate 215*941Smyers if (h_count == 0 && l_count == 0) 216*941Smyers if (sign) 217*941Smyers ul = (int64_t)va_arg(args, int); 218*941Smyers else 219*941Smyers ul = (int64_t)va_arg(args, unsigned int); 220*941Smyers else if (l_count > 1) 221*941Smyers if (sign) 222*941Smyers ul = (int64_t)va_arg(args, int64_t); 223*941Smyers else 224*941Smyers ul = (int64_t)va_arg(args, uint64_t); 225*941Smyers else if (l_count > 0) 226*941Smyers if (sign) 227*941Smyers ul = (int64_t)va_arg(args, long); 228*941Smyers else 229*941Smyers ul = (int64_t)va_arg(args, unsigned long); 230*941Smyers else if (h_count > 1) 231*941Smyers if (sign) 232*941Smyers ul = (int64_t)va_arg(args, char); 233*941Smyers else 234*941Smyers ul = (int64_t)va_arg(args, unsigned char); 235*941Smyers else if (h_count > 0) 236*941Smyers if (sign) 237*941Smyers ul = (int64_t)va_arg(args, short); 238*941Smyers else 239*941Smyers ul = (int64_t)va_arg(args, unsigned short); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate if (sign && (int64_t)ul < 0) 2420Sstevel@tonic-gate ul = -ul; 2430Sstevel@tonic-gate else 2440Sstevel@tonic-gate sign = 0; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate if (c == 'b') { 2470Sstevel@tonic-gate bs = va_arg(args, char *); 2480Sstevel@tonic-gate base = *bs++; 2490Sstevel@tonic-gate } 2500Sstevel@tonic-gate 251*941Smyers /* avoid repeated division if width is 0 */ 252*941Smyers if (width > 0) { 253*941Smyers tmp = ul; 254*941Smyers do { 255*941Smyers width--; 256*941Smyers } while ((tmp /= base) != 0); 257*941Smyers } 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate if (sign && pad == '0') 2600Sstevel@tonic-gate ADDCHAR('-'); 2610Sstevel@tonic-gate while (width-- > sign) 2620Sstevel@tonic-gate ADDCHAR(pad); 2630Sstevel@tonic-gate if (sign && pad == ' ') 2640Sstevel@tonic-gate ADDCHAR('-'); 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate sp = numbuf; 2670Sstevel@tonic-gate tmp = ul; 2680Sstevel@tonic-gate do { 2690Sstevel@tonic-gate *sp++ = digits[tmp % base]; 2700Sstevel@tonic-gate } while ((tmp /= base) != 0); 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate while (sp > numbuf) { 2730Sstevel@tonic-gate sp--; 2740Sstevel@tonic-gate ADDCHAR(*sp); 2750Sstevel@tonic-gate } 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate if (c == 'b' && ul != 0) { 2780Sstevel@tonic-gate int any = 0; 2790Sstevel@tonic-gate c = *bs++; 2800Sstevel@tonic-gate while (c != 0) { 2810Sstevel@tonic-gate if (ul & (1 << (c - 1))) { 2820Sstevel@tonic-gate if (any++ == 0) 2830Sstevel@tonic-gate ADDCHAR('<'); 2840Sstevel@tonic-gate while ((c = *bs++) >= 32) 2850Sstevel@tonic-gate ADDCHAR(c); 2860Sstevel@tonic-gate ADDCHAR(','); 2870Sstevel@tonic-gate } else { 2880Sstevel@tonic-gate while ((c = *bs++) >= 32) 2890Sstevel@tonic-gate continue; 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate } 2920Sstevel@tonic-gate if (any) { 2930Sstevel@tonic-gate bufp--; 2940Sstevel@tonic-gate ADDCHAR('>'); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate } 2980Sstevel@tonic-gate if (bufp - buf < buflen) 2990Sstevel@tonic-gate bufp[0] = c; 3000Sstevel@tonic-gate else if (buflen != 0) 3010Sstevel@tonic-gate buf[buflen - 1] = c; 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate va_end(args); 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate return (bufp - buf); 3060Sstevel@tonic-gate } 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /*PRINTFLIKE1*/ 3090Sstevel@tonic-gate size_t 3100Sstevel@tonic-gate snprintf(char *buf, size_t buflen, const char *fmt, ...) 3110Sstevel@tonic-gate { 3120Sstevel@tonic-gate va_list args; 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate va_start(args, fmt); 3150Sstevel@tonic-gate buflen = vsnprintf(buf, buflen, fmt, args); 3160Sstevel@tonic-gate va_end(args); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate return (buflen); 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate #if defined(_BOOT) 3220Sstevel@tonic-gate /* 3230Sstevel@tonic-gate * The sprintf() and vsprintf() routines aren't shared with the kernel because 3240Sstevel@tonic-gate * the DDI mandates that they return the buffer rather than its length. 3250Sstevel@tonic-gate */ 3260Sstevel@tonic-gate /*PRINTFLIKE2*/ 3270Sstevel@tonic-gate int 3280Sstevel@tonic-gate sprintf(char *buf, const char *fmt, ...) 3290Sstevel@tonic-gate { 3300Sstevel@tonic-gate va_list args; 3310Sstevel@tonic-gate 3320Sstevel@tonic-gate va_start(args, fmt); 3330Sstevel@tonic-gate (void) vsnprintf(buf, INT_MAX, fmt, args); 3340Sstevel@tonic-gate va_end(args); 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate return (strlen(buf)); 3370Sstevel@tonic-gate } 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate int 3400Sstevel@tonic-gate vsprintf(char *buf, const char *fmt, va_list args) 3410Sstevel@tonic-gate { 3420Sstevel@tonic-gate (void) vsnprintf(buf, INT_MAX, fmt, args); 3430Sstevel@tonic-gate return (strlen(buf)); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate #endif 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate #endif /* !_KMDB */ 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate char * 3500Sstevel@tonic-gate strcat(char *s1, const char *s2) 3510Sstevel@tonic-gate { 3520Sstevel@tonic-gate char *os1 = s1; 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate while (*s1++ != '\0') 3550Sstevel@tonic-gate ; 3560Sstevel@tonic-gate s1--; 3570Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') 3580Sstevel@tonic-gate ; 3590Sstevel@tonic-gate return (os1); 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate char * 3630Sstevel@tonic-gate strchr(const char *sp, int c) 3640Sstevel@tonic-gate { 3650Sstevel@tonic-gate do { 3660Sstevel@tonic-gate if (*sp == (char)c) 3670Sstevel@tonic-gate return ((char *)sp); 3680Sstevel@tonic-gate } while (*sp++); 3690Sstevel@tonic-gate return (NULL); 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate int 3730Sstevel@tonic-gate strcmp(const char *s1, const char *s2) 3740Sstevel@tonic-gate { 3750Sstevel@tonic-gate while (*s1 == *s2++) 3760Sstevel@tonic-gate if (*s1++ == '\0') 3770Sstevel@tonic-gate return (0); 3780Sstevel@tonic-gate return (*(unsigned char *)s1 - *(unsigned char *)--s2); 3790Sstevel@tonic-gate } 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate int 3820Sstevel@tonic-gate strncmp(const char *s1, const char *s2, size_t n) 3830Sstevel@tonic-gate { 3840Sstevel@tonic-gate if (s1 == s2) 3850Sstevel@tonic-gate return (0); 3860Sstevel@tonic-gate n++; 3870Sstevel@tonic-gate while (--n != 0 && *s1 == *s2++) 3880Sstevel@tonic-gate if (*s1++ == '\0') 3890Sstevel@tonic-gate return (0); 3900Sstevel@tonic-gate return ((n == 0) ? 0 : *(unsigned char *)s1 - *(unsigned char *)--s2); 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate static const char charmap[] = { 3940Sstevel@tonic-gate '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', 3950Sstevel@tonic-gate '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', 3960Sstevel@tonic-gate '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', 3970Sstevel@tonic-gate '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', 3980Sstevel@tonic-gate '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', 3990Sstevel@tonic-gate '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', 4000Sstevel@tonic-gate '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', 4010Sstevel@tonic-gate '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', 4020Sstevel@tonic-gate '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 4030Sstevel@tonic-gate '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 4040Sstevel@tonic-gate '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 4050Sstevel@tonic-gate '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', 4060Sstevel@tonic-gate '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 4070Sstevel@tonic-gate '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 4080Sstevel@tonic-gate '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 4090Sstevel@tonic-gate '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', 4100Sstevel@tonic-gate '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', 4110Sstevel@tonic-gate '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', 4120Sstevel@tonic-gate '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', 4130Sstevel@tonic-gate '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', 4140Sstevel@tonic-gate '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', 4150Sstevel@tonic-gate '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', 4160Sstevel@tonic-gate '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', 4170Sstevel@tonic-gate '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', 4180Sstevel@tonic-gate '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', 4190Sstevel@tonic-gate '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', 4200Sstevel@tonic-gate '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', 4210Sstevel@tonic-gate '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', 4220Sstevel@tonic-gate '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', 4230Sstevel@tonic-gate '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', 4240Sstevel@tonic-gate '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', 4250Sstevel@tonic-gate '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', 4260Sstevel@tonic-gate }; 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate int 4290Sstevel@tonic-gate strcasecmp(const char *s1, const char *s2) 4300Sstevel@tonic-gate { 4310Sstevel@tonic-gate const unsigned char *cm = (const unsigned char *)charmap; 4320Sstevel@tonic-gate const unsigned char *us1 = (const unsigned char *)s1; 4330Sstevel@tonic-gate const unsigned char *us2 = (const unsigned char *)s2; 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate while (cm[*us1] == cm[*us2++]) 4360Sstevel@tonic-gate if (*us1++ == '\0') 4370Sstevel@tonic-gate return (0); 4380Sstevel@tonic-gate return (cm[*us1] - cm[*(us2 - 1)]); 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate int 4420Sstevel@tonic-gate strncasecmp(const char *s1, const char *s2, size_t n) 4430Sstevel@tonic-gate { 4440Sstevel@tonic-gate const unsigned char *cm = (const unsigned char *)charmap; 4450Sstevel@tonic-gate const unsigned char *us1 = (const unsigned char *)s1; 4460Sstevel@tonic-gate const unsigned char *us2 = (const unsigned char *)s2; 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate while (n != 0 && cm[*us1] == cm[*us2++]) { 4490Sstevel@tonic-gate if (*us1++ == '\0') 4500Sstevel@tonic-gate return (0); 4510Sstevel@tonic-gate n--; 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate return (n == 0 ? 0 : cm[*us1] - cm[*(us2 - 1)]); 4540Sstevel@tonic-gate } 4550Sstevel@tonic-gate 4560Sstevel@tonic-gate char * 4570Sstevel@tonic-gate strcpy(char *s1, const char *s2) 4580Sstevel@tonic-gate { 4590Sstevel@tonic-gate char *os1 = s1; 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') 4620Sstevel@tonic-gate ; 4630Sstevel@tonic-gate return (os1); 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate char * 4670Sstevel@tonic-gate strncpy(char *s1, const char *s2, size_t n) 4680Sstevel@tonic-gate { 4690Sstevel@tonic-gate char *os1 = s1; 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate n++; 4720Sstevel@tonic-gate while (--n != 0 && (*s1++ = *s2++) != '\0') 4730Sstevel@tonic-gate ; 4740Sstevel@tonic-gate if (n != 0) 4750Sstevel@tonic-gate while (--n != 0) 4760Sstevel@tonic-gate *s1++ = '\0'; 4770Sstevel@tonic-gate return (os1); 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate char * 4810Sstevel@tonic-gate strrchr(const char *sp, int c) 4820Sstevel@tonic-gate { 4830Sstevel@tonic-gate char *r = NULL; 4840Sstevel@tonic-gate 4850Sstevel@tonic-gate do { 4860Sstevel@tonic-gate if (*sp == (char)c) 4870Sstevel@tonic-gate r = (char *)sp; 4880Sstevel@tonic-gate } while (*sp++); 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate return (r); 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate char * 4940Sstevel@tonic-gate strstr(const char *as1, const char *as2) 4950Sstevel@tonic-gate { 4960Sstevel@tonic-gate const char *s1, *s2; 4970Sstevel@tonic-gate const char *tptr; 4980Sstevel@tonic-gate char c; 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate s1 = as1; 5010Sstevel@tonic-gate s2 = as2; 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate if (s2 == NULL || *s2 == '\0') 5040Sstevel@tonic-gate return ((char *)s1); 5050Sstevel@tonic-gate c = *s2; 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate while (*s1) 5080Sstevel@tonic-gate if (*s1++ == c) { 5090Sstevel@tonic-gate tptr = s1; 5100Sstevel@tonic-gate while ((c = *++s2) == *s1++ && c) 5110Sstevel@tonic-gate ; 5120Sstevel@tonic-gate if (c == 0) 5130Sstevel@tonic-gate return ((char *)tptr - 1); 5140Sstevel@tonic-gate s1 = tptr; 5150Sstevel@tonic-gate s2 = as2; 5160Sstevel@tonic-gate c = *s2; 5170Sstevel@tonic-gate } 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate return (NULL); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate char * 5230Sstevel@tonic-gate strpbrk(const char *string, const char *brkset) 5240Sstevel@tonic-gate { 5250Sstevel@tonic-gate const char *p; 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate do { 5280Sstevel@tonic-gate for (p = brkset; *p != '\0' && *p != *string; ++p) 5290Sstevel@tonic-gate ; 5300Sstevel@tonic-gate if (*p != '\0') 5310Sstevel@tonic-gate return ((char *)string); 5320Sstevel@tonic-gate } while (*string++); 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate return (NULL); 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate char * 5380Sstevel@tonic-gate strncat(char *s1, const char *s2, size_t n) 5390Sstevel@tonic-gate { 5400Sstevel@tonic-gate char *os1 = s1; 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate n++; 5430Sstevel@tonic-gate while (*s1++ != '\0') 5440Sstevel@tonic-gate ; 5450Sstevel@tonic-gate --s1; 5460Sstevel@tonic-gate while ((*s1++ = *s2++) != '\0') { 5470Sstevel@tonic-gate if (--n == 0) { 5480Sstevel@tonic-gate s1[-1] = '\0'; 5490Sstevel@tonic-gate break; 5500Sstevel@tonic-gate } 5510Sstevel@tonic-gate } 5520Sstevel@tonic-gate return (os1); 5530Sstevel@tonic-gate } 5540Sstevel@tonic-gate 5550Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB) 5560Sstevel@tonic-gate #define bcopy(src, dst, n) (void) memcpy((dst), (src), (n)) 5570Sstevel@tonic-gate #endif 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate size_t 5600Sstevel@tonic-gate strlcat(char *dst, const char *src, size_t dstsize) 5610Sstevel@tonic-gate { 5620Sstevel@tonic-gate char *df = dst; 5630Sstevel@tonic-gate size_t left = dstsize; 5640Sstevel@tonic-gate size_t l1; 5650Sstevel@tonic-gate size_t l2 = strlen(src); 5660Sstevel@tonic-gate size_t copied; 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate while (left-- != 0 && *df != '\0') 5690Sstevel@tonic-gate df++; 5700Sstevel@tonic-gate l1 = df - dst; 5710Sstevel@tonic-gate if (dstsize == l1) 5720Sstevel@tonic-gate return (l1 + l2); 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2; 5750Sstevel@tonic-gate bcopy(src, dst + l1, copied); 5760Sstevel@tonic-gate dst[l1+copied] = '\0'; 5770Sstevel@tonic-gate return (l1 + l2); 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate size_t 5810Sstevel@tonic-gate strlcpy(char *dst, const char *src, size_t len) 5820Sstevel@tonic-gate { 5830Sstevel@tonic-gate size_t slen = strlen(src); 5840Sstevel@tonic-gate size_t copied; 5850Sstevel@tonic-gate 5860Sstevel@tonic-gate if (len == 0) 5870Sstevel@tonic-gate return (slen); 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate if (slen >= len) 5900Sstevel@tonic-gate copied = len - 1; 5910Sstevel@tonic-gate else 5920Sstevel@tonic-gate copied = slen; 5930Sstevel@tonic-gate bcopy(src, dst, copied); 5940Sstevel@tonic-gate dst[copied] = '\0'; 5950Sstevel@tonic-gate return (slen); 5960Sstevel@tonic-gate } 5970Sstevel@tonic-gate 5980Sstevel@tonic-gate size_t 5990Sstevel@tonic-gate strspn(const char *string, const char *charset) 6000Sstevel@tonic-gate { 6010Sstevel@tonic-gate const char *p, *q; 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate for (q = string; *q != '\0'; ++q) { 6040Sstevel@tonic-gate for (p = charset; *p != '\0' && *p != *q; ++p) 6050Sstevel@tonic-gate ; 6060Sstevel@tonic-gate if (*p == '\0') 6070Sstevel@tonic-gate break; 6080Sstevel@tonic-gate } 6090Sstevel@tonic-gate 6100Sstevel@tonic-gate return (q - string); 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate /* 6140Sstevel@tonic-gate * Unless mentioned otherwise, all of the routines below should be added to 6150Sstevel@tonic-gate * the Solaris DDI as necessary. For now, only provide them to standalone. 6160Sstevel@tonic-gate */ 6170Sstevel@tonic-gate #if defined(_BOOT) || defined(_KMDB) 6180Sstevel@tonic-gate char * 6190Sstevel@tonic-gate strtok(char *string, const char *sepset) 6200Sstevel@tonic-gate { 6210Sstevel@tonic-gate char *p, *q, *r; 6220Sstevel@tonic-gate static char *savept; 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate /* 6250Sstevel@tonic-gate * Set `p' to our current location in the string. 6260Sstevel@tonic-gate */ 6270Sstevel@tonic-gate p = (string == NULL) ? savept : string; 6280Sstevel@tonic-gate if (p == NULL) 6290Sstevel@tonic-gate return (NULL); 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate /* 6320Sstevel@tonic-gate * Skip leading separators; bail if no tokens remain. 6330Sstevel@tonic-gate */ 6340Sstevel@tonic-gate q = p + strspn(p, sepset); 6350Sstevel@tonic-gate if (*q == '\0') 6360Sstevel@tonic-gate return (NULL); 6370Sstevel@tonic-gate 6380Sstevel@tonic-gate /* 6390Sstevel@tonic-gate * Mark the end of the token and set `savept' for the next iteration. 6400Sstevel@tonic-gate */ 6410Sstevel@tonic-gate if ((r = strpbrk(q, sepset)) == NULL) 6420Sstevel@tonic-gate savept = NULL; 6430Sstevel@tonic-gate else { 6440Sstevel@tonic-gate *r = '\0'; 6450Sstevel@tonic-gate savept = ++r; 6460Sstevel@tonic-gate } 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate return (q); 6490Sstevel@tonic-gate } 6500Sstevel@tonic-gate 6510Sstevel@tonic-gate /* 6520Sstevel@tonic-gate * The strlen() routine isn't shared with the kernel because it has its own 6530Sstevel@tonic-gate * hand-tuned assembly version. 6540Sstevel@tonic-gate */ 6550Sstevel@tonic-gate size_t 6560Sstevel@tonic-gate strlen(const char *s) 6570Sstevel@tonic-gate { 6580Sstevel@tonic-gate size_t n = 0; 6590Sstevel@tonic-gate 6600Sstevel@tonic-gate while (*s++) 6610Sstevel@tonic-gate n++; 6620Sstevel@tonic-gate return (n); 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate #endif /* _BOOT || _KMDB */ 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate #ifdef _KERNEL 6680Sstevel@tonic-gate /* 6690Sstevel@tonic-gate * Check for a valid C identifier: 6700Sstevel@tonic-gate * a letter or underscore, followed by 6710Sstevel@tonic-gate * zero or more letters, digits and underscores. 6720Sstevel@tonic-gate */ 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate #define IS_DIGIT(c) ((c) >= '0' && (c) <= '9') 6750Sstevel@tonic-gate 6760Sstevel@tonic-gate #define IS_ALPHA(c) \ 6770Sstevel@tonic-gate (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z')) 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate int 6800Sstevel@tonic-gate strident_valid(const char *id) 6810Sstevel@tonic-gate { 6820Sstevel@tonic-gate int c = *id++; 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate if (!IS_ALPHA(c) && c != '_') 6850Sstevel@tonic-gate return (0); 6860Sstevel@tonic-gate while ((c = *id++) != 0) { 6870Sstevel@tonic-gate if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_') 6880Sstevel@tonic-gate return (0); 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate return (1); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate /* 6940Sstevel@tonic-gate * Convert a string into a valid C identifier by replacing invalid 6950Sstevel@tonic-gate * characters with '_'. Also makes sure the string is nul-terminated 6960Sstevel@tonic-gate * and takes up at most n bytes. 6970Sstevel@tonic-gate */ 6980Sstevel@tonic-gate void 6990Sstevel@tonic-gate strident_canon(char *s, size_t n) 7000Sstevel@tonic-gate { 7010Sstevel@tonic-gate char c; 7020Sstevel@tonic-gate char *end = s + n - 1; 7030Sstevel@tonic-gate 7040Sstevel@tonic-gate ASSERT(n > 0); 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate if ((c = *s) == 0) 7070Sstevel@tonic-gate return; 7080Sstevel@tonic-gate 7090Sstevel@tonic-gate if (!IS_ALPHA(c) && c != '_') 7100Sstevel@tonic-gate *s = '_'; 7110Sstevel@tonic-gate 7120Sstevel@tonic-gate while (s < end && ((c = *(++s)) != 0)) { 7130Sstevel@tonic-gate if (!IS_ALPHA(c) && !IS_DIGIT(c) && c != '_') 7140Sstevel@tonic-gate *s = '_'; 7150Sstevel@tonic-gate } 7160Sstevel@tonic-gate *s = 0; 7170Sstevel@tonic-gate } 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate #endif /* _KERNEL */ 720