1*5c51f124SMoriah Waterland /* 2*5c51f124SMoriah Waterland * CDDL HEADER START 3*5c51f124SMoriah Waterland * 4*5c51f124SMoriah Waterland * The contents of this file are subject to the terms of the 5*5c51f124SMoriah Waterland * Common Development and Distribution License (the "License"). 6*5c51f124SMoriah Waterland * You may not use this file except in compliance with the License. 7*5c51f124SMoriah Waterland * 8*5c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing. 10*5c51f124SMoriah Waterland * See the License for the specific language governing permissions 11*5c51f124SMoriah Waterland * and limitations under the License. 12*5c51f124SMoriah Waterland * 13*5c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each 14*5c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the 16*5c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying 17*5c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner] 18*5c51f124SMoriah Waterland * 19*5c51f124SMoriah Waterland * CDDL HEADER END 20*5c51f124SMoriah Waterland */ 21*5c51f124SMoriah Waterland 22*5c51f124SMoriah Waterland /* 23*5c51f124SMoriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*5c51f124SMoriah Waterland * Use is subject to license terms. 25*5c51f124SMoriah Waterland */ 26*5c51f124SMoriah Waterland 27*5c51f124SMoriah Waterland 28*5c51f124SMoriah Waterland /* 29*5c51f124SMoriah Waterland * Module: pkgstr.c 30*5c51f124SMoriah Waterland * Synopsis: general string services 31*5c51f124SMoriah Waterland * Taxonomy: project private 32*5c51f124SMoriah Waterland * Debug Flag: str 33*5c51f124SMoriah Waterland * Description: 34*5c51f124SMoriah Waterland * 35*5c51f124SMoriah Waterland * This module implements general string utility services 36*5c51f124SMoriah Waterland * 37*5c51f124SMoriah Waterland * Public Methods: 38*5c51f124SMoriah Waterland * 39*5c51f124SMoriah Waterland * pkgstrAddToken - Add a token to a string 40*5c51f124SMoriah Waterland * pkgstrContainsToken - Determine if a string contains a specified token 41*5c51f124SMoriah Waterland * pkgstrConvertPathToBasename - Return copy of base name in path string 42*5c51f124SMoriah Waterland * pkgstrConvertPathToDirname - Return copy of directory name in path string 43*5c51f124SMoriah Waterland * pkgstrConvertUllToTimeString_r - convert unsigned long long to time string 44*5c51f124SMoriah Waterland * pkgstrExpandTokens - Expand tokens from string appending tokens to another 45*5c51f124SMoriah Waterland * pkgstrGetToken - Get a token from a string 46*5c51f124SMoriah Waterland * pkgstrGetToken_r - Get a token from a string into a fixed buffer 47*5c51f124SMoriah Waterland * pkgstrLocatePathBasename - Locate position of base name in path string 48*5c51f124SMoriah Waterland * pkgstrNumTokens - Determine number of tokens in string 49*5c51f124SMoriah Waterland * pkgstrPrintf - Create a string from a printf style format and arguments 50*5c51f124SMoriah Waterland * pkgstrPrintf_r - Create a string from a printf style format and arguments 51*5c51f124SMoriah Waterland * into a fixed buffer 52*5c51f124SMoriah Waterland * pkgstrRemoveToken - Remove a token from a string 53*5c51f124SMoriah Waterland * pkgstrRemoveLeadingWhitespace - remove leading whitespace from string 54*5c51f124SMoriah Waterland * pkgstrScaleNumericString - Convert unsigned long long to human 55*5c51f124SMoriah Waterland * readable form 56*5c51f124SMoriah Waterland */ 57*5c51f124SMoriah Waterland 58*5c51f124SMoriah Waterland /* 59*5c51f124SMoriah Waterland * Unix Includes 60*5c51f124SMoriah Waterland */ 61*5c51f124SMoriah Waterland 62*5c51f124SMoriah Waterland #define __EXTENSIONS__ 63*5c51f124SMoriah Waterland 64*5c51f124SMoriah Waterland #include <stdio.h> 65*5c51f124SMoriah Waterland #include <stdlib.h> 66*5c51f124SMoriah Waterland #include <string.h> 67*5c51f124SMoriah Waterland #include <libintl.h> 68*5c51f124SMoriah Waterland #include <limits.h> 69*5c51f124SMoriah Waterland #include <sys/types.h> 70*5c51f124SMoriah Waterland #include <assert.h> 71*5c51f124SMoriah Waterland #include <errno.h> 72*5c51f124SMoriah Waterland #include <libintl.h> 73*5c51f124SMoriah Waterland #include <ctype.h> 74*5c51f124SMoriah Waterland #include <unistd.h> 75*5c51f124SMoriah Waterland #include <strings.h> 76*5c51f124SMoriah Waterland #include <stdarg.h> 77*5c51f124SMoriah Waterland 78*5c51f124SMoriah Waterland /* 79*5c51f124SMoriah Waterland * pkglib Includes 80*5c51f124SMoriah Waterland */ 81*5c51f124SMoriah Waterland 82*5c51f124SMoriah Waterland #include "pkglib.h" 83*5c51f124SMoriah Waterland #include "pkgstrct.h" 84*5c51f124SMoriah Waterland #include "libintl.h" 85*5c51f124SMoriah Waterland #include "pkglocale.h" 86*5c51f124SMoriah Waterland 87*5c51f124SMoriah Waterland /* 88*5c51f124SMoriah Waterland * External definitions 89*5c51f124SMoriah Waterland */ 90*5c51f124SMoriah Waterland 91*5c51f124SMoriah Waterland /* 92*5c51f124SMoriah Waterland * Public methods 93*5c51f124SMoriah Waterland */ 94*5c51f124SMoriah Waterland 95*5c51f124SMoriah Waterland /* 96*5c51f124SMoriah Waterland * Name: pkgstrRemoveLeadingWhitespace 97*5c51f124SMoriah Waterland * Synopsis: Remove leading whitespace from string 98*5c51f124SMoriah Waterland * Description: Remove all leading whitespace characters from a string 99*5c51f124SMoriah Waterland * Arguments: a_str - [RO, *RW] - (char **) 100*5c51f124SMoriah Waterland * Pointer to handle to string (in allocated storage) to 101*5c51f124SMoriah Waterland * remove all leading whitespace from 102*5c51f124SMoriah Waterland * Returns: void 103*5c51f124SMoriah Waterland * The input string is modified as follows: 104*5c51f124SMoriah Waterland * == (char *)NULL: 105*5c51f124SMoriah Waterland * - input string was (char *)NULL 106*5c51f124SMoriah Waterland * - input string is all whitespace 107*5c51f124SMoriah Waterland * != (char *)NULL: 108*5c51f124SMoriah Waterland * - copy of input string with leading 109*5c51f124SMoriah Waterland * whitespace removed 110*5c51f124SMoriah Waterland * CAUTION: The input string must be allocated space (via mem* or 111*5c51f124SMoriah Waterland * pkgstr* methods) - it must not be a static or inline 112*5c51f124SMoriah Waterland * character string 113*5c51f124SMoriah Waterland * NOTE: The input string a_str will be freed with 'free' 114*5c51f124SMoriah Waterland * if it is all whitespace, or if it contains any leading 115*5c51f124SMoriah Waterland * whitespace characters 116*5c51f124SMoriah Waterland * NOTE: Any string returned is placed in new storage for the 117*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 118*5c51f124SMoriah Waterland * of the storage once the string is no longer needed. 119*5c51f124SMoriah Waterland * Errors: If the string cannot be created, the process exits 120*5c51f124SMoriah Waterland */ 121*5c51f124SMoriah Waterland 122*5c51f124SMoriah Waterland void 123*5c51f124SMoriah Waterland pkgstrRemoveLeadingWhitespace(char **a_str) 124*5c51f124SMoriah Waterland { 125*5c51f124SMoriah Waterland char *o_str; 126*5c51f124SMoriah Waterland 127*5c51f124SMoriah Waterland /* entry assertions */ 128*5c51f124SMoriah Waterland 129*5c51f124SMoriah Waterland assert(a_str != (char **)NULL); 130*5c51f124SMoriah Waterland 131*5c51f124SMoriah Waterland /* if string is null, just return */ 132*5c51f124SMoriah Waterland 133*5c51f124SMoriah Waterland if (*a_str == (char *)NULL) { 134*5c51f124SMoriah Waterland return; 135*5c51f124SMoriah Waterland } 136*5c51f124SMoriah Waterland o_str = *a_str; 137*5c51f124SMoriah Waterland 138*5c51f124SMoriah Waterland /* if string is empty, deallocate and return NULL */ 139*5c51f124SMoriah Waterland 140*5c51f124SMoriah Waterland if (*o_str == '\0') { 141*5c51f124SMoriah Waterland /* free string - handle is reset to NULL by free */ 142*5c51f124SMoriah Waterland free(*a_str); 143*5c51f124SMoriah Waterland *a_str = (char *)NULL; 144*5c51f124SMoriah Waterland return; 145*5c51f124SMoriah Waterland } 146*5c51f124SMoriah Waterland 147*5c51f124SMoriah Waterland /* if first character is not a space, just return */ 148*5c51f124SMoriah Waterland 149*5c51f124SMoriah Waterland if (!isspace(*o_str)) { 150*5c51f124SMoriah Waterland return; 151*5c51f124SMoriah Waterland } 152*5c51f124SMoriah Waterland 153*5c51f124SMoriah Waterland /* advance past all space characters */ 154*5c51f124SMoriah Waterland 155*5c51f124SMoriah Waterland while ((*o_str != '\0') && (isspace(*o_str))) { 156*5c51f124SMoriah Waterland o_str++; 157*5c51f124SMoriah Waterland } 158*5c51f124SMoriah Waterland 159*5c51f124SMoriah Waterland /* if string was all space characters, deallocate and return NULL */ 160*5c51f124SMoriah Waterland 161*5c51f124SMoriah Waterland if (*o_str == '\0') { 162*5c51f124SMoriah Waterland /* free string - *a_str is reset to NULL by free */ 163*5c51f124SMoriah Waterland free(*a_str); 164*5c51f124SMoriah Waterland *a_str = (char *)NULL; 165*5c51f124SMoriah Waterland return; 166*5c51f124SMoriah Waterland } 167*5c51f124SMoriah Waterland 168*5c51f124SMoriah Waterland /* have non-space/null byte, return dup, deallocate original */ 169*5c51f124SMoriah Waterland 170*5c51f124SMoriah Waterland o_str = strdup(o_str); 171*5c51f124SMoriah Waterland assert(o_str != (char *)NULL); 172*5c51f124SMoriah Waterland if (o_str != (char *)NULL) { 173*5c51f124SMoriah Waterland free(*a_str); 174*5c51f124SMoriah Waterland *a_str = o_str; 175*5c51f124SMoriah Waterland } 176*5c51f124SMoriah Waterland } 177*5c51f124SMoriah Waterland 178*5c51f124SMoriah Waterland unsigned long 179*5c51f124SMoriah Waterland pkgstrNumTokens(char *a_string, char *a_separators) 180*5c51f124SMoriah Waterland { 181*5c51f124SMoriah Waterland int index; 182*5c51f124SMoriah Waterland 183*5c51f124SMoriah Waterland if (a_string == (char *)NULL) { 184*5c51f124SMoriah Waterland return (0); 185*5c51f124SMoriah Waterland } 186*5c51f124SMoriah Waterland 187*5c51f124SMoriah Waterland if (*a_string == '\0') { 188*5c51f124SMoriah Waterland return (0); 189*5c51f124SMoriah Waterland } 190*5c51f124SMoriah Waterland 191*5c51f124SMoriah Waterland for (index = 0 ; ; index ++) { 192*5c51f124SMoriah Waterland char *p; 193*5c51f124SMoriah Waterland 194*5c51f124SMoriah Waterland p = pkgstrGetToken((char *)NULL, a_string, index, a_separators); 195*5c51f124SMoriah Waterland if (p == (char *)NULL) { 196*5c51f124SMoriah Waterland return (index); 197*5c51f124SMoriah Waterland } 198*5c51f124SMoriah Waterland free(p); 199*5c51f124SMoriah Waterland } 200*5c51f124SMoriah Waterland } 201*5c51f124SMoriah Waterland 202*5c51f124SMoriah Waterland /* 203*5c51f124SMoriah Waterland * Name: pkgstrPrintf_r 204*5c51f124SMoriah Waterland * Synopsis: Create string from printf style format and arguments 205*5c51f124SMoriah Waterland * Description: Call to convert a printf style format and arguments into a 206*5c51f124SMoriah Waterland * string of characters placed in allocated storage 207*5c51f124SMoriah Waterland * Arguments: a_buf - [RO, *RW] - (char *) 208*5c51f124SMoriah Waterland * - Pointer to buffer used as storage space for the 209*5c51f124SMoriah Waterland * returned string created 210*5c51f124SMoriah Waterland * a_bufLen - [RO, *RO] - (int) 211*5c51f124SMoriah Waterland * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1' 212*5c51f124SMoriah Waterland * bytes will be placed in 'a_buf' - the returned 213*5c51f124SMoriah Waterland * string is always null terminated 214*5c51f124SMoriah Waterland * a_format - [RO, RO*] (char *) 215*5c51f124SMoriah Waterland * printf-style format for string to be formatted 216*5c51f124SMoriah Waterland * VARG_LIST - [RO] (?) 217*5c51f124SMoriah Waterland * arguments as appropriate to 'format' specified 218*5c51f124SMoriah Waterland * Returns: void 219*5c51f124SMoriah Waterland */ 220*5c51f124SMoriah Waterland 221*5c51f124SMoriah Waterland /*PRINTFLIKE3*/ 222*5c51f124SMoriah Waterland void 223*5c51f124SMoriah Waterland pkgstrPrintf_r(char *a_buf, int a_bufLen, char *a_format, ...) 224*5c51f124SMoriah Waterland { 225*5c51f124SMoriah Waterland va_list ap; 226*5c51f124SMoriah Waterland size_t vres = 0; 227*5c51f124SMoriah Waterland 228*5c51f124SMoriah Waterland /* entry assertions */ 229*5c51f124SMoriah Waterland 230*5c51f124SMoriah Waterland assert(a_format != (char *)NULL); 231*5c51f124SMoriah Waterland assert(*a_format != '\0'); 232*5c51f124SMoriah Waterland assert(a_buf != (char *)NULL); 233*5c51f124SMoriah Waterland assert(a_bufLen > 1); 234*5c51f124SMoriah Waterland 235*5c51f124SMoriah Waterland /* generate the results of the printf conversion */ 236*5c51f124SMoriah Waterland 237*5c51f124SMoriah Waterland va_start(ap, a_format); 238*5c51f124SMoriah Waterland vres = vsnprintf(a_buf, a_bufLen-1, a_format, ap); 239*5c51f124SMoriah Waterland va_end(ap); 240*5c51f124SMoriah Waterland 241*5c51f124SMoriah Waterland assert(vres > 0); 242*5c51f124SMoriah Waterland assert(vres < a_bufLen); 243*5c51f124SMoriah Waterland 244*5c51f124SMoriah Waterland a_buf[a_bufLen-1] = '\0'; 245*5c51f124SMoriah Waterland } 246*5c51f124SMoriah Waterland 247*5c51f124SMoriah Waterland /* 248*5c51f124SMoriah Waterland * Name: pkgstrPrintf 249*5c51f124SMoriah Waterland * Synopsis: Create string from printf style format and arguments 250*5c51f124SMoriah Waterland * Description: Call to convert a printf style format and arguments into a 251*5c51f124SMoriah Waterland * string of characters placed in allocated storage 252*5c51f124SMoriah Waterland * Arguments: format - [RO, RO*] (char *) 253*5c51f124SMoriah Waterland * printf-style format for string to be formatted 254*5c51f124SMoriah Waterland * VARG_LIST - [RO] (?) 255*5c51f124SMoriah Waterland * arguments as appropriate to 'format' specified 256*5c51f124SMoriah Waterland * Returns: char * 257*5c51f124SMoriah Waterland * A string representing the printf conversion results 258*5c51f124SMoriah Waterland * NOTE: Any string returned is placed in new storage for the 259*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 260*5c51f124SMoriah Waterland * of the storage once the string is no longer needed. 261*5c51f124SMoriah Waterland * Errors: If the string cannot be created, the process exits 262*5c51f124SMoriah Waterland */ 263*5c51f124SMoriah Waterland 264*5c51f124SMoriah Waterland /*PRINTFLIKE1*/ 265*5c51f124SMoriah Waterland char * 266*5c51f124SMoriah Waterland pkgstrPrintf(char *a_format, ...) 267*5c51f124SMoriah Waterland { 268*5c51f124SMoriah Waterland va_list ap; 269*5c51f124SMoriah Waterland size_t vres = 0; 270*5c51f124SMoriah Waterland char bfr[1]; 271*5c51f124SMoriah Waterland char *rstr = (char *)NULL; 272*5c51f124SMoriah Waterland 273*5c51f124SMoriah Waterland /* entry assertions */ 274*5c51f124SMoriah Waterland 275*5c51f124SMoriah Waterland assert(a_format != (char *)NULL); 276*5c51f124SMoriah Waterland assert(*a_format != '\0'); 277*5c51f124SMoriah Waterland 278*5c51f124SMoriah Waterland /* determine size of the message in bytes */ 279*5c51f124SMoriah Waterland 280*5c51f124SMoriah Waterland va_start(ap, a_format); 281*5c51f124SMoriah Waterland vres = vsnprintf(bfr, 1, a_format, ap); 282*5c51f124SMoriah Waterland va_end(ap); 283*5c51f124SMoriah Waterland 284*5c51f124SMoriah Waterland assert(vres > 0); 285*5c51f124SMoriah Waterland assert(vres < LINE_MAX); 286*5c51f124SMoriah Waterland 287*5c51f124SMoriah Waterland /* allocate storage to hold the message */ 288*5c51f124SMoriah Waterland 289*5c51f124SMoriah Waterland rstr = (char *)calloc(1, vres+2); 290*5c51f124SMoriah Waterland assert(rstr != (char *)NULL); 291*5c51f124SMoriah Waterland if (rstr == (char *)NULL) { 292*5c51f124SMoriah Waterland return ((char *)NULL); 293*5c51f124SMoriah Waterland } 294*5c51f124SMoriah Waterland 295*5c51f124SMoriah Waterland /* generate the results of the printf conversion */ 296*5c51f124SMoriah Waterland 297*5c51f124SMoriah Waterland va_start(ap, a_format); 298*5c51f124SMoriah Waterland vres = vsnprintf(rstr, vres+1, a_format, ap); 299*5c51f124SMoriah Waterland va_end(ap); 300*5c51f124SMoriah Waterland 301*5c51f124SMoriah Waterland assert(vres > 0); 302*5c51f124SMoriah Waterland assert(vres < LINE_MAX); 303*5c51f124SMoriah Waterland assert(*rstr != '\0'); 304*5c51f124SMoriah Waterland 305*5c51f124SMoriah Waterland /* return the results */ 306*5c51f124SMoriah Waterland 307*5c51f124SMoriah Waterland return (rstr); 308*5c51f124SMoriah Waterland } 309*5c51f124SMoriah Waterland 310*5c51f124SMoriah Waterland /* 311*5c51f124SMoriah Waterland * Name: pkgstrExpandTokens 312*5c51f124SMoriah Waterland * Synopsis: Expand tokens from string appending tokens to another 313*5c51f124SMoriah Waterland * Description: Given a string and a list of one or more separators, 314*5c51f124SMoriah Waterland * expand each token from the string and append those tokens 315*5c51f124SMoriah Waterland * to a string that is in allocated space - create new string 316*5c51f124SMoriah Waterland * if no string to append to exists. 317*5c51f124SMoriah Waterland * Arguments: a_old - [RO, *RW] - (char **) 318*5c51f124SMoriah Waterland * - Pointer to handle to string to append token to 319*5c51f124SMoriah Waterland * == (char *)NULL - new string is created 320*5c51f124SMoriah Waterland * a_separator - [RO, *RO] - (char *) 321*5c51f124SMoriah Waterland * - separator to end tokens returned 322*5c51f124SMoriah Waterland * a_separators - [RO, *RO] - (char *) 323*5c51f124SMoriah Waterland * - String containing one or more characters that 324*5c51f124SMoriah Waterland * can separate one "token" from a_string from another 325*5c51f124SMoriah Waterland * Returns: void 326*5c51f124SMoriah Waterland * NOTE: Any token string returned is placed in new storage for the 327*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 328*5c51f124SMoriah Waterland * of the storage once the token string is no longer needed. 329*5c51f124SMoriah Waterland */ 330*5c51f124SMoriah Waterland 331*5c51f124SMoriah Waterland void 332*5c51f124SMoriah Waterland pkgstrExpandTokens(char **a_old, char *a_string, char a_separator, 333*5c51f124SMoriah Waterland char *a_separators) 334*5c51f124SMoriah Waterland { 335*5c51f124SMoriah Waterland int i; 336*5c51f124SMoriah Waterland char sep[2] = {'\0', '\0'}; 337*5c51f124SMoriah Waterland 338*5c51f124SMoriah Waterland /* convert single separator character into character string */ 339*5c51f124SMoriah Waterland 340*5c51f124SMoriah Waterland sep[0] = a_separator; 341*5c51f124SMoriah Waterland 342*5c51f124SMoriah Waterland /* 343*5c51f124SMoriah Waterland * iterate extracting tokens from the source string and adding 344*5c51f124SMoriah Waterland * those tokens to the target string when the tokens are not 345*5c51f124SMoriah Waterland * already present in the target string 346*5c51f124SMoriah Waterland */ 347*5c51f124SMoriah Waterland 348*5c51f124SMoriah Waterland for (i = 0; ; i++) { 349*5c51f124SMoriah Waterland char *p; 350*5c51f124SMoriah Waterland 351*5c51f124SMoriah Waterland /* extract the next matching token from the source string */ 352*5c51f124SMoriah Waterland 353*5c51f124SMoriah Waterland p = pkgstrGetToken((char *)NULL, a_string, i, a_separators); 354*5c51f124SMoriah Waterland 355*5c51f124SMoriah Waterland /* return if no token is available */ 356*5c51f124SMoriah Waterland 357*5c51f124SMoriah Waterland if (p == (char *)NULL) { 358*5c51f124SMoriah Waterland return; 359*5c51f124SMoriah Waterland } 360*5c51f124SMoriah Waterland 361*5c51f124SMoriah Waterland /* 362*5c51f124SMoriah Waterland * obtained token from source string: if the token is not 363*5c51f124SMoriah Waterland * in the target string, add the token to the target string 364*5c51f124SMoriah Waterland */ 365*5c51f124SMoriah Waterland 366*5c51f124SMoriah Waterland if (pkgstrContainsToken(*a_old, p, sep) == B_FALSE) { 367*5c51f124SMoriah Waterland pkgstrAddToken(a_old, p, *sep); 368*5c51f124SMoriah Waterland } 369*5c51f124SMoriah Waterland 370*5c51f124SMoriah Waterland /* free up temporary storage used by token from source string */ 371*5c51f124SMoriah Waterland 372*5c51f124SMoriah Waterland free(p); 373*5c51f124SMoriah Waterland } 374*5c51f124SMoriah Waterland /*NOTREACHED*/ 375*5c51f124SMoriah Waterland } 376*5c51f124SMoriah Waterland 377*5c51f124SMoriah Waterland 378*5c51f124SMoriah Waterland /* 379*5c51f124SMoriah Waterland * Name: pkgstrGetToken 380*5c51f124SMoriah Waterland * Synopsis: Get a separator delimited token from a string 381*5c51f124SMoriah Waterland * Description: Given a string and a list of one or more separators, 382*5c51f124SMoriah Waterland * return the position specified token (sequence of one or 383*5c51f124SMoriah Waterland * more characters that do not include any of the separators) 384*5c51f124SMoriah Waterland * Arguments: r_sep - [*RW] - (char *) 385*5c51f124SMoriah Waterland * - separator that ended the token returned 386*5c51f124SMoriah Waterland * - NOTE: this is a pointer to a "char", e.g.: 387*5c51f124SMoriah Waterland * - char a; 388*5c51f124SMoriah Waterland * - pkgstrGetToken(&a, ...) 389*5c51f124SMoriah Waterland * a_string - [RO, *RO] - (char *) 390*5c51f124SMoriah Waterland * - pointer to string to extract token from 391*5c51f124SMoriah Waterland * a_index - [RO, *RO] - (int) 392*5c51f124SMoriah Waterland * - Index of token to return; '0' is first matching 393*5c51f124SMoriah Waterland * token, '1' is second matching token, etc. 394*5c51f124SMoriah Waterland * a_separators - [RO, *RO] - (char *) 395*5c51f124SMoriah Waterland * - String containing one or more characters that 396*5c51f124SMoriah Waterland * can separate one "token" from another 397*5c51f124SMoriah Waterland * Returns: char * 398*5c51f124SMoriah Waterland * == (char *)NULL - no token matching criteria found 399*5c51f124SMoriah Waterland * != (char *)NULL - token matching criteria 400*5c51f124SMoriah Waterland * NOTE: Any token string returned is placed in new storage for the 401*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 402*5c51f124SMoriah Waterland * of the storage once the token string is no longer needed. 403*5c51f124SMoriah Waterland */ 404*5c51f124SMoriah Waterland 405*5c51f124SMoriah Waterland char * 406*5c51f124SMoriah Waterland pkgstrGetToken(char *r_sep, char *a_string, int a_index, char *a_separators) 407*5c51f124SMoriah Waterland { 408*5c51f124SMoriah Waterland char *p; 409*5c51f124SMoriah Waterland char *q; 410*5c51f124SMoriah Waterland char *lasts; 411*5c51f124SMoriah Waterland 412*5c51f124SMoriah Waterland /* entry assertions */ 413*5c51f124SMoriah Waterland 414*5c51f124SMoriah Waterland assert(a_string != (char *)NULL); 415*5c51f124SMoriah Waterland assert(a_index >= 0); 416*5c51f124SMoriah Waterland assert(a_separators != (char *)NULL); 417*5c51f124SMoriah Waterland assert(*a_separators != '\0'); 418*5c51f124SMoriah Waterland 419*5c51f124SMoriah Waterland /* if returned separator requested, reset to null until token found */ 420*5c51f124SMoriah Waterland 421*5c51f124SMoriah Waterland if (r_sep != (char *)NULL) { 422*5c51f124SMoriah Waterland *r_sep = '\0'; 423*5c51f124SMoriah Waterland } 424*5c51f124SMoriah Waterland 425*5c51f124SMoriah Waterland /* duplicate original string before breaking down into tokens */ 426*5c51f124SMoriah Waterland 427*5c51f124SMoriah Waterland p = strdup(a_string); 428*5c51f124SMoriah Waterland assert(p != (char *)NULL); 429*5c51f124SMoriah Waterland if (p == (char *)NULL) { 430*5c51f124SMoriah Waterland return ((char *)NULL); 431*5c51f124SMoriah Waterland } 432*5c51f124SMoriah Waterland lasts = p; 433*5c51f124SMoriah Waterland 434*5c51f124SMoriah Waterland /* scan for separators and return 'index'th token found */ 435*5c51f124SMoriah Waterland 436*5c51f124SMoriah Waterland while (q = strtok_r((char *)NULL, a_separators, &lasts)) { 437*5c51f124SMoriah Waterland /* retrieve separator if requested */ 438*5c51f124SMoriah Waterland 439*5c51f124SMoriah Waterland if (r_sep != (char *)NULL) { 440*5c51f124SMoriah Waterland char *x; 441*5c51f124SMoriah Waterland 442*5c51f124SMoriah Waterland x = strpbrk(a_string, a_separators); 443*5c51f124SMoriah Waterland if (x) { 444*5c51f124SMoriah Waterland *r_sep = *x; 445*5c51f124SMoriah Waterland } 446*5c51f124SMoriah Waterland } 447*5c51f124SMoriah Waterland 448*5c51f124SMoriah Waterland /* if this is the 'index'th token requested return it */ 449*5c51f124SMoriah Waterland 450*5c51f124SMoriah Waterland if (a_index-- == 0) { 451*5c51f124SMoriah Waterland char *tmp; 452*5c51f124SMoriah Waterland 453*5c51f124SMoriah Waterland /* duplicate token into its own storage */ 454*5c51f124SMoriah Waterland 455*5c51f124SMoriah Waterland tmp = strdup(q); 456*5c51f124SMoriah Waterland assert(tmp != (char *)NULL); 457*5c51f124SMoriah Waterland if (tmp == (char *)NULL) { 458*5c51f124SMoriah Waterland return ((char *)NULL); 459*5c51f124SMoriah Waterland } 460*5c51f124SMoriah Waterland 461*5c51f124SMoriah Waterland /* free up copy of original input string */ 462*5c51f124SMoriah Waterland 463*5c51f124SMoriah Waterland free(p); 464*5c51f124SMoriah Waterland 465*5c51f124SMoriah Waterland /* return token found */ 466*5c51f124SMoriah Waterland 467*5c51f124SMoriah Waterland return (tmp); 468*5c51f124SMoriah Waterland } 469*5c51f124SMoriah Waterland } 470*5c51f124SMoriah Waterland 471*5c51f124SMoriah Waterland /* 472*5c51f124SMoriah Waterland * token not found 473*5c51f124SMoriah Waterland */ 474*5c51f124SMoriah Waterland 475*5c51f124SMoriah Waterland /* free up copy of original input string */ 476*5c51f124SMoriah Waterland 477*5c51f124SMoriah Waterland free(p); 478*5c51f124SMoriah Waterland 479*5c51f124SMoriah Waterland /* return NULL pointer (token not found) */ 480*5c51f124SMoriah Waterland 481*5c51f124SMoriah Waterland return ((char *)NULL); 482*5c51f124SMoriah Waterland } 483*5c51f124SMoriah Waterland 484*5c51f124SMoriah Waterland /* 485*5c51f124SMoriah Waterland * Name: pkgstrGetToken 486*5c51f124SMoriah Waterland * Synopsis: Get separator delimited token from a string into a fixed buffer 487*5c51f124SMoriah Waterland * Description: Given a string and a list of one or more separators, 488*5c51f124SMoriah Waterland * return the position specified token (sequence of one or 489*5c51f124SMoriah Waterland * more characters that do not include any of the separators) 490*5c51f124SMoriah Waterland * into a specified buffer of a fixed maximum size 491*5c51f124SMoriah Waterland * Arguments: r_sep - [*RW] - (char *) 492*5c51f124SMoriah Waterland * - separator that ended the token returned 493*5c51f124SMoriah Waterland * - NOTE: this is a pointer to a "char", e.g.: 494*5c51f124SMoriah Waterland * - char a; 495*5c51f124SMoriah Waterland * - pkgstrGetToken(&a, ...) 496*5c51f124SMoriah Waterland * a_string - [RO, *RO] - (char *) 497*5c51f124SMoriah Waterland * - pointer to string to extract token from 498*5c51f124SMoriah Waterland * a_index - [RO, *RO] - (int) 499*5c51f124SMoriah Waterland * - Index of token to return; '0' is first matching 500*5c51f124SMoriah Waterland * token, '1' is second matching token, etc. 501*5c51f124SMoriah Waterland * a_separators - [RO, *RO] - (char *) 502*5c51f124SMoriah Waterland * - String containing one or more characters that 503*5c51f124SMoriah Waterland * can separate one "token" from another 504*5c51f124SMoriah Waterland * a_buf - [RO, *RW] - (char *) 505*5c51f124SMoriah Waterland * - Pointer to buffer used as storage space for the 506*5c51f124SMoriah Waterland * returned token - the returned token is always 507*5c51f124SMoriah Waterland * null terminated 508*5c51f124SMoriah Waterland * a_buf[0] == '\0' - no token meeting criteria found 509*5c51f124SMoriah Waterland * a_buf[0] != '\0' - token meeting criteria returned 510*5c51f124SMoriah Waterland * a_bufLen - [RO, *RO] - (int) 511*5c51f124SMoriah Waterland * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1' 512*5c51f124SMoriah Waterland * bytes will be placed in 'a_buf' - the returned 513*5c51f124SMoriah Waterland * token is always null terminated 514*5c51f124SMoriah Waterland * Returns: void 515*5c51f124SMoriah Waterland */ 516*5c51f124SMoriah Waterland 517*5c51f124SMoriah Waterland void 518*5c51f124SMoriah Waterland pkgstrGetToken_r(char *r_sep, char *a_string, int a_index, 519*5c51f124SMoriah Waterland char *a_separators, char *a_buf, int a_bufLen) 520*5c51f124SMoriah Waterland { 521*5c51f124SMoriah Waterland char *p; 522*5c51f124SMoriah Waterland char *q; 523*5c51f124SMoriah Waterland char *lasts; 524*5c51f124SMoriah Waterland 525*5c51f124SMoriah Waterland /* entry assertions */ 526*5c51f124SMoriah Waterland 527*5c51f124SMoriah Waterland assert(a_string != (char *)NULL); 528*5c51f124SMoriah Waterland assert(a_index >= 0); 529*5c51f124SMoriah Waterland assert(a_separators != (char *)NULL); 530*5c51f124SMoriah Waterland assert(*a_separators != '\0'); 531*5c51f124SMoriah Waterland assert(a_buf != (char *)NULL); 532*5c51f124SMoriah Waterland assert(a_bufLen > 0); 533*5c51f124SMoriah Waterland 534*5c51f124SMoriah Waterland /* reset returned separator */ 535*5c51f124SMoriah Waterland 536*5c51f124SMoriah Waterland if (r_sep != (char *)NULL) { 537*5c51f124SMoriah Waterland *r_sep = '\0'; 538*5c51f124SMoriah Waterland } 539*5c51f124SMoriah Waterland 540*5c51f124SMoriah Waterland /* zero out contents of return buffer */ 541*5c51f124SMoriah Waterland 542*5c51f124SMoriah Waterland bzero(a_buf, a_bufLen); 543*5c51f124SMoriah Waterland 544*5c51f124SMoriah Waterland /* duplicate original string before breaking down into tokens */ 545*5c51f124SMoriah Waterland 546*5c51f124SMoriah Waterland p = strdup(a_string); 547*5c51f124SMoriah Waterland assert(p != (char *)NULL); 548*5c51f124SMoriah Waterland if (p == (char *)NULL) { 549*5c51f124SMoriah Waterland return; 550*5c51f124SMoriah Waterland } 551*5c51f124SMoriah Waterland lasts = p; 552*5c51f124SMoriah Waterland 553*5c51f124SMoriah Waterland /* scan for separators and return 'index'th token found */ 554*5c51f124SMoriah Waterland 555*5c51f124SMoriah Waterland while (q = strtok_r((char *)NULL, a_separators, &lasts)) { 556*5c51f124SMoriah Waterland /* retrieve separator if requested */ 557*5c51f124SMoriah Waterland 558*5c51f124SMoriah Waterland if (r_sep != (char *)NULL) { 559*5c51f124SMoriah Waterland char *x; 560*5c51f124SMoriah Waterland x = strpbrk(a_string, a_separators); 561*5c51f124SMoriah Waterland if (x) { 562*5c51f124SMoriah Waterland *r_sep = *x; 563*5c51f124SMoriah Waterland } 564*5c51f124SMoriah Waterland } 565*5c51f124SMoriah Waterland 566*5c51f124SMoriah Waterland /* if this is the 'index'th token requested return it */ 567*5c51f124SMoriah Waterland 568*5c51f124SMoriah Waterland if (a_index-- == 0) { 569*5c51f124SMoriah Waterland /* copy as many characters as possible to return buf */ 570*5c51f124SMoriah Waterland 571*5c51f124SMoriah Waterland (void) strncpy(a_buf, q, a_bufLen-1); 572*5c51f124SMoriah Waterland break; 573*5c51f124SMoriah Waterland } 574*5c51f124SMoriah Waterland } 575*5c51f124SMoriah Waterland 576*5c51f124SMoriah Waterland /* free up copy of original input string */ 577*5c51f124SMoriah Waterland 578*5c51f124SMoriah Waterland free(p); 579*5c51f124SMoriah Waterland } 580*5c51f124SMoriah Waterland 581*5c51f124SMoriah Waterland /* 582*5c51f124SMoriah Waterland * Name: pkgstrAddToken 583*5c51f124SMoriah Waterland * Synopsis: Add a token to a string 584*5c51f124SMoriah Waterland * Description: Append a token (sequence of one or more characters) to a 585*5c51f124SMoriah Waterland * string that is in allocated space - create new string if 586*5c51f124SMoriah Waterland * no string to append to exists 587*5c51f124SMoriah Waterland * Arguments: a_old - [RO, *RW] - (char **) 588*5c51f124SMoriah Waterland * - Pointer to handle to string to append token to 589*5c51f124SMoriah Waterland * == (char *)NULL - new string is created 590*5c51f124SMoriah Waterland * a_new - [RO, *RO] - (char *) 591*5c51f124SMoriah Waterland * - Pointer to string representing token to append 592*5c51f124SMoriah Waterland * to the end of the "a_old" string 593*5c51f124SMoriah Waterland * == (char *)NULL - no action is performed 594*5c51f124SMoriah Waterland * a_new[0] == '\0' - no action is performed 595*5c51f124SMoriah Waterland * a_separator - [RO, *RO] - (char) 596*5c51f124SMoriah Waterland * - One character placed between the old (existing) 597*5c51f124SMoriah Waterland * string and the new token to be added IF the old 598*5c51f124SMoriah Waterland * string exists and is not empty (zero length) 599*5c51f124SMoriah Waterland * Returns: void 600*5c51f124SMoriah Waterland * CAUTION: The old (existing) string must be allocated space (via lu_mem* 601*5c51f124SMoriah Waterland * or pkgstr* methods) - it must not be a static or inline 602*5c51f124SMoriah Waterland * character string 603*5c51f124SMoriah Waterland * NOTE: The old (existing) string may be freed with 'free' 604*5c51f124SMoriah Waterland * if a token is appended to it 605*5c51f124SMoriah Waterland * NOTE: Any string returned in 'a_old' is placed in new storage for the 606*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 607*5c51f124SMoriah Waterland * of the storage once the token string is no longer needed. 608*5c51f124SMoriah Waterland */ 609*5c51f124SMoriah Waterland 610*5c51f124SMoriah Waterland void 611*5c51f124SMoriah Waterland pkgstrAddToken(char **a_old, char *a_new, char a_separator) 612*5c51f124SMoriah Waterland { 613*5c51f124SMoriah Waterland /* entry assertions */ 614*5c51f124SMoriah Waterland 615*5c51f124SMoriah Waterland assert(a_old != (char **)NULL); 616*5c51f124SMoriah Waterland assert(a_separator != '\0'); 617*5c51f124SMoriah Waterland 618*5c51f124SMoriah Waterland /* if token to add is null, just return */ 619*5c51f124SMoriah Waterland 620*5c51f124SMoriah Waterland if (a_new == (char *)NULL) { 621*5c51f124SMoriah Waterland return; 622*5c51f124SMoriah Waterland } 623*5c51f124SMoriah Waterland 624*5c51f124SMoriah Waterland /* if token to add is empty (zero length), just return */ 625*5c51f124SMoriah Waterland 626*5c51f124SMoriah Waterland if (*a_new == '\0') { 627*5c51f124SMoriah Waterland return; 628*5c51f124SMoriah Waterland } 629*5c51f124SMoriah Waterland 630*5c51f124SMoriah Waterland /* make sure that new token does not contain the separator */ 631*5c51f124SMoriah Waterland 632*5c51f124SMoriah Waterland assert(strchr(a_new, (int)a_separator) == (char *)NULL); 633*5c51f124SMoriah Waterland 634*5c51f124SMoriah Waterland /* if old string is empty (zero length), deallocate */ 635*5c51f124SMoriah Waterland 636*5c51f124SMoriah Waterland if ((*a_old != (char *)NULL) && ((*a_old)[0] == '\0')) { 637*5c51f124SMoriah Waterland /* *a_old is set to NULL by free */ 638*5c51f124SMoriah Waterland free(*a_old); 639*5c51f124SMoriah Waterland *a_old = (char *)NULL; 640*5c51f124SMoriah Waterland } 641*5c51f124SMoriah Waterland 642*5c51f124SMoriah Waterland /* if old string is exists, append separator and token */ 643*5c51f124SMoriah Waterland 644*5c51f124SMoriah Waterland if (*a_old != (char *)NULL) { 645*5c51f124SMoriah Waterland char *p; 646*5c51f124SMoriah Waterland p = pkgstrPrintf("%s%c%s", *a_old, a_separator, a_new); 647*5c51f124SMoriah Waterland free(*a_old); 648*5c51f124SMoriah Waterland *a_old = p; 649*5c51f124SMoriah Waterland return; 650*5c51f124SMoriah Waterland } 651*5c51f124SMoriah Waterland 652*5c51f124SMoriah Waterland /* old string does not exist - return duplicate of token */ 653*5c51f124SMoriah Waterland 654*5c51f124SMoriah Waterland assert(*a_old == (char *)NULL); 655*5c51f124SMoriah Waterland *a_old = strdup(a_new); 656*5c51f124SMoriah Waterland assert(*a_old != (char *)NULL); 657*5c51f124SMoriah Waterland } 658*5c51f124SMoriah Waterland 659*5c51f124SMoriah Waterland /* 660*5c51f124SMoriah Waterland * Name: pkgstrContainsToken 661*5c51f124SMoriah Waterland * Synopsis: Does a given string contain a specified substring 662*5c51f124SMoriah Waterland * Description: Determine if a given substring exists in a larger string 663*5c51f124SMoriah Waterland * Arguments: a_string - [RO, *RO] - (char *) 664*5c51f124SMoriah Waterland * Pointer to string to look for substring in 665*5c51f124SMoriah Waterland * a_token - [RO, *RO] - (char *) 666*5c51f124SMoriah Waterland * Pointer to substring to look for in larger string 667*5c51f124SMoriah Waterland * Results: boolean_t 668*5c51f124SMoriah Waterland * B_TRUE - substring exists in larger string 669*5c51f124SMoriah Waterland * B_FALSE - substring does NOT exist in larger string 670*5c51f124SMoriah Waterland * NOTE: The substring must match on a "token" basis; that is, the 671*5c51f124SMoriah Waterland * substring must exist in the larger string delineated with 672*5c51f124SMoriah Waterland * either spaces or tabs to match. 673*5c51f124SMoriah Waterland */ 674*5c51f124SMoriah Waterland 675*5c51f124SMoriah Waterland boolean_t 676*5c51f124SMoriah Waterland pkgstrContainsToken(char *a_string, char *a_token, char *a_separators) 677*5c51f124SMoriah Waterland { 678*5c51f124SMoriah Waterland char *lasts; 679*5c51f124SMoriah Waterland char *current; 680*5c51f124SMoriah Waterland char *p; 681*5c51f124SMoriah Waterland 682*5c51f124SMoriah Waterland /* entry assertions */ 683*5c51f124SMoriah Waterland 684*5c51f124SMoriah Waterland assert(a_separators != (char *)NULL); 685*5c51f124SMoriah Waterland assert(*a_separators != '\0'); 686*5c51f124SMoriah Waterland 687*5c51f124SMoriah Waterland /* if token is not supplied, return false */ 688*5c51f124SMoriah Waterland 689*5c51f124SMoriah Waterland if (a_token == (char *)NULL) { 690*5c51f124SMoriah Waterland return (B_FALSE); 691*5c51f124SMoriah Waterland } 692*5c51f124SMoriah Waterland 693*5c51f124SMoriah Waterland /* if no string provided, return false */ 694*5c51f124SMoriah Waterland 695*5c51f124SMoriah Waterland if (a_string == (char *)NULL) { 696*5c51f124SMoriah Waterland return (B_FALSE); 697*5c51f124SMoriah Waterland } 698*5c51f124SMoriah Waterland 699*5c51f124SMoriah Waterland /* if string empty (zero length), return false */ 700*5c51f124SMoriah Waterland 701*5c51f124SMoriah Waterland if (*a_string == '\0') { 702*5c51f124SMoriah Waterland return (B_FALSE); 703*5c51f124SMoriah Waterland } 704*5c51f124SMoriah Waterland 705*5c51f124SMoriah Waterland /* duplicate larger string because strtok_r changes it */ 706*5c51f124SMoriah Waterland 707*5c51f124SMoriah Waterland p = strdup(a_string); 708*5c51f124SMoriah Waterland assert(p != (char *)NULL); 709*5c51f124SMoriah Waterland if (p == (char *)NULL) { 710*5c51f124SMoriah Waterland return (B_FALSE); 711*5c51f124SMoriah Waterland } 712*5c51f124SMoriah Waterland 713*5c51f124SMoriah Waterland lasts = p; 714*5c51f124SMoriah Waterland 715*5c51f124SMoriah Waterland /* scan each token looking for a match */ 716*5c51f124SMoriah Waterland 717*5c51f124SMoriah Waterland while ((current = strtok_r((char *)NULL, a_separators, &lasts)) != 718*5c51f124SMoriah Waterland (char *)NULL) { 719*5c51f124SMoriah Waterland if (streq(current, a_token)) { 720*5c51f124SMoriah Waterland free(p); 721*5c51f124SMoriah Waterland return (B_TRUE); 722*5c51f124SMoriah Waterland } 723*5c51f124SMoriah Waterland } 724*5c51f124SMoriah Waterland 725*5c51f124SMoriah Waterland /* free up temporary storage */ 726*5c51f124SMoriah Waterland 727*5c51f124SMoriah Waterland free(p); 728*5c51f124SMoriah Waterland 729*5c51f124SMoriah Waterland /* not found */ 730*5c51f124SMoriah Waterland 731*5c51f124SMoriah Waterland return (B_FALSE); 732*5c51f124SMoriah Waterland } 733*5c51f124SMoriah Waterland 734*5c51f124SMoriah Waterland /* 735*5c51f124SMoriah Waterland * Name: pkgstrRemoveToken 736*5c51f124SMoriah Waterland * Synopsis: Remove a token from a string 737*5c51f124SMoriah Waterland * Description: Remove a token (sequence of one or more characters) from a 738*5c51f124SMoriah Waterland * string that is in allocated space 739*5c51f124SMoriah Waterland * Arguments: r_string - [RO, *RW] - (char **) 740*5c51f124SMoriah Waterland * - Pointer to handle to string to remove token from 741*5c51f124SMoriah Waterland * a_token - [RO, *RO] - (char *) 742*5c51f124SMoriah Waterland * Pointer to token (substring) to look for and remove 743*5c51f124SMoriah Waterland * from r_string provided 744*5c51f124SMoriah Waterland * a_separators - [RO, *RO] - (char *) 745*5c51f124SMoriah Waterland * - String containing one or more characters that 746*5c51f124SMoriah Waterland * separate one "token" from another in r_string 747*5c51f124SMoriah Waterland * a_index - [RO, *RO] - (int) 748*5c51f124SMoriah Waterland * - Index of token to remove; '0' is first matching 749*5c51f124SMoriah Waterland * token, '1' is second matching token, etc. 750*5c51f124SMoriah Waterland * Returns: void 751*5c51f124SMoriah Waterland * CAUTION: The input string must be allocated space (via lu_mem* or 752*5c51f124SMoriah Waterland * pkgstr* methods) - it must not be a static or inline 753*5c51f124SMoriah Waterland * character string 754*5c51f124SMoriah Waterland * NOTE: The input string r_string will be freed with 'free' 755*5c51f124SMoriah Waterland * if the token to be removed is found 756*5c51f124SMoriah Waterland * NOTE: Any token string returned is placed in new storage for the 757*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 758*5c51f124SMoriah Waterland * of the storage once the token string is no longer needed. 759*5c51f124SMoriah Waterland * Errors: If the new token string cannot be created, the process exits 760*5c51f124SMoriah Waterland */ 761*5c51f124SMoriah Waterland 762*5c51f124SMoriah Waterland void 763*5c51f124SMoriah Waterland pkgstrRemoveToken(char **r_string, char *a_token, char *a_separators, 764*5c51f124SMoriah Waterland int a_index) 765*5c51f124SMoriah Waterland { 766*5c51f124SMoriah Waterland char *a_string; 767*5c51f124SMoriah Waterland char *copyString; 768*5c51f124SMoriah Waterland char sep = 0; 769*5c51f124SMoriah Waterland int copyLength; 770*5c51f124SMoriah Waterland int i; 771*5c51f124SMoriah Waterland 772*5c51f124SMoriah Waterland /* entry assertions */ 773*5c51f124SMoriah Waterland 774*5c51f124SMoriah Waterland assert(r_string != (char **)NULL); 775*5c51f124SMoriah Waterland assert(a_token != (char *)NULL); 776*5c51f124SMoriah Waterland assert(*a_token != '\0'); 777*5c51f124SMoriah Waterland assert(a_separators != (char *)NULL); 778*5c51f124SMoriah Waterland assert(*a_separators != '\0'); 779*5c51f124SMoriah Waterland 780*5c51f124SMoriah Waterland /* simple case: input string is null; return empty string */ 781*5c51f124SMoriah Waterland 782*5c51f124SMoriah Waterland a_string = *r_string; 783*5c51f124SMoriah Waterland if (*a_string == '\0') { 784*5c51f124SMoriah Waterland return; 785*5c51f124SMoriah Waterland } 786*5c51f124SMoriah Waterland 787*5c51f124SMoriah Waterland /* simple case: token == input string; return empty string */ 788*5c51f124SMoriah Waterland 789*5c51f124SMoriah Waterland if (streq(a_string, a_token)) { 790*5c51f124SMoriah Waterland /* deallocate input string; free sets *r_string to NULL */ 791*5c51f124SMoriah Waterland 792*5c51f124SMoriah Waterland free(*r_string); 793*5c51f124SMoriah Waterland *r_string = (char *)NULL; 794*5c51f124SMoriah Waterland return; 795*5c51f124SMoriah Waterland } 796*5c51f124SMoriah Waterland 797*5c51f124SMoriah Waterland /* simple case: token not in input string: return */ 798*5c51f124SMoriah Waterland 799*5c51f124SMoriah Waterland if (!pkgstrContainsToken(a_string, a_token, a_separators)) { 800*5c51f124SMoriah Waterland return; 801*5c51f124SMoriah Waterland } 802*5c51f124SMoriah Waterland 803*5c51f124SMoriah Waterland /* 804*5c51f124SMoriah Waterland * Pick apart the old string building the new one as we go along 805*5c51f124SMoriah Waterland * removing the first occurance of the token provided 806*5c51f124SMoriah Waterland */ 807*5c51f124SMoriah Waterland 808*5c51f124SMoriah Waterland copyLength = (strlen(a_string)-strlen(a_token))+2; 809*5c51f124SMoriah Waterland copyString = calloc(1, copyLength); 810*5c51f124SMoriah Waterland assert(copyString != (char *)NULL); 811*5c51f124SMoriah Waterland if (copyString == (char *)NULL) { 812*5c51f124SMoriah Waterland return; 813*5c51f124SMoriah Waterland } 814*5c51f124SMoriah Waterland 815*5c51f124SMoriah Waterland for (i = 0; ; i++) { 816*5c51f124SMoriah Waterland char *p; 817*5c51f124SMoriah Waterland 818*5c51f124SMoriah Waterland p = pkgstrGetToken(&sep, a_string, i, a_separators); 819*5c51f124SMoriah Waterland if (p == (char *)NULL) { 820*5c51f124SMoriah Waterland break; 821*5c51f124SMoriah Waterland } 822*5c51f124SMoriah Waterland 823*5c51f124SMoriah Waterland if (streq(p, a_token) && (a_index-- == 0)) { 824*5c51f124SMoriah Waterland continue; 825*5c51f124SMoriah Waterland } 826*5c51f124SMoriah Waterland 827*5c51f124SMoriah Waterland if (*copyString) { 828*5c51f124SMoriah Waterland assert(sep != '\0'); 829*5c51f124SMoriah Waterland (void) strncat(copyString, &sep, 1); 830*5c51f124SMoriah Waterland } 831*5c51f124SMoriah Waterland 832*5c51f124SMoriah Waterland (void) strcat(copyString, p); 833*5c51f124SMoriah Waterland } 834*5c51f124SMoriah Waterland 835*5c51f124SMoriah Waterland free(*r_string); 836*5c51f124SMoriah Waterland assert(*copyString); 837*5c51f124SMoriah Waterland *r_string = copyString; 838*5c51f124SMoriah Waterland } 839*5c51f124SMoriah Waterland 840*5c51f124SMoriah Waterland /* 841*5c51f124SMoriah Waterland * Name: pkgstrScaleNumericString 842*5c51f124SMoriah Waterland * Synopsis: Convert unsigned long long to human readable form 843*5c51f124SMoriah Waterland * Description: Convert a string containing an unsigned long long representation 844*5c51f124SMoriah Waterland * and convert it into a human readable numeric string. The number 845*5c51f124SMoriah Waterland * is scaled down until it is small enough to be in a good human 846*5c51f124SMoriah Waterland * readable format i.e. in the range 0 thru scale-1. 847*5c51f124SMoriah Waterland * Arguments: a_buf - [RO, *RW] - (char *) 848*5c51f124SMoriah Waterland * Pointer to buffer containing string representation 849*5c51f124SMoriah Waterland * of unsigned long long to convert 850*5c51f124SMoriah Waterland * scale - [RO, *RO] - (unsigned long long) 851*5c51f124SMoriah Waterland * Value to scale the number into 852*5c51f124SMoriah Waterland * Returns: a_buf - contains human readable scaled representation of 853*5c51f124SMoriah Waterland * original value contained in the buffer 854*5c51f124SMoriah Waterland * Note: The value "(unsigned long long)-1" is a special case and 855*5c51f124SMoriah Waterland * is always converted to "-1". 856*5c51f124SMoriah Waterland * Errors: If the string cannot be created, the process exits 857*5c51f124SMoriah Waterland */ 858*5c51f124SMoriah Waterland 859*5c51f124SMoriah Waterland void 860*5c51f124SMoriah Waterland pkgstrScaleNumericString(char *a_buf, unsigned long long scale) 861*5c51f124SMoriah Waterland { 862*5c51f124SMoriah Waterland static char *M = " KMGTPE"; /* Measurement: */ 863*5c51f124SMoriah Waterland /* kilo, mega, giga, tera, peta, exa */ 864*5c51f124SMoriah Waterland 865*5c51f124SMoriah Waterland unsigned long long number = 0; /* convert this number */ 866*5c51f124SMoriah Waterland unsigned long long save = 0; 867*5c51f124SMoriah Waterland char *uom = M; /* unit of measurement, initially ' ' (=M[0]) */ 868*5c51f124SMoriah Waterland 869*5c51f124SMoriah Waterland /* entry assertions */ 870*5c51f124SMoriah Waterland 871*5c51f124SMoriah Waterland assert(scale > (unsigned long long)0); 872*5c51f124SMoriah Waterland assert(scale <= (unsigned long long)1048576); 873*5c51f124SMoriah Waterland 874*5c51f124SMoriah Waterland /* 875*5c51f124SMoriah Waterland * Get the number - if no number of empty number, just return 876*5c51f124SMoriah Waterland */ 877*5c51f124SMoriah Waterland 878*5c51f124SMoriah Waterland if (a_buf == (char *)NULL) { 879*5c51f124SMoriah Waterland return; 880*5c51f124SMoriah Waterland } 881*5c51f124SMoriah Waterland 882*5c51f124SMoriah Waterland if (*a_buf == '\0') { 883*5c51f124SMoriah Waterland (void) strcpy(a_buf, "0"); 884*5c51f124SMoriah Waterland return; 885*5c51f124SMoriah Waterland } 886*5c51f124SMoriah Waterland 887*5c51f124SMoriah Waterland /* convert out the number from the input buffer */ 888*5c51f124SMoriah Waterland 889*5c51f124SMoriah Waterland number = strtoull(a_buf, (char **)NULL, 10); 890*5c51f124SMoriah Waterland 891*5c51f124SMoriah Waterland /* if conversion error, return "-1" */ 892*5c51f124SMoriah Waterland 893*5c51f124SMoriah Waterland if ((long long)number == (long long)-1) { 894*5c51f124SMoriah Waterland (void) strcpy(a_buf, "-1"); 895*5c51f124SMoriah Waterland return; 896*5c51f124SMoriah Waterland } 897*5c51f124SMoriah Waterland 898*5c51f124SMoriah Waterland /* 899*5c51f124SMoriah Waterland * Now have number as a count of scale units. 900*5c51f124SMoriah Waterland * Stop scaling when we reached exa-bytes, then something is 901*5c51f124SMoriah Waterland * probably wrong with our number (it is improbably large) 902*5c51f124SMoriah Waterland */ 903*5c51f124SMoriah Waterland 904*5c51f124SMoriah Waterland while ((number >= scale) && (*uom != 'E')) { 905*5c51f124SMoriah Waterland uom++; /* next unit of measurement */ 906*5c51f124SMoriah Waterland save = number; 907*5c51f124SMoriah Waterland number = (number + (scale / 2)) / scale; 908*5c51f124SMoriah Waterland } 909*5c51f124SMoriah Waterland 910*5c51f124SMoriah Waterland /* check if we should output a decimal place after the point */ 911*5c51f124SMoriah Waterland 912*5c51f124SMoriah Waterland if (save && ((save / scale) < 10)) { 913*5c51f124SMoriah Waterland /* sprintf() will round for us */ 914*5c51f124SMoriah Waterland float fnum = (float)save / scale; 915*5c51f124SMoriah Waterland (void) sprintf(a_buf, "%4.1f%c", fnum, *uom); 916*5c51f124SMoriah Waterland } else { 917*5c51f124SMoriah Waterland (void) sprintf(a_buf, "%4llu%c", number, *uom); 918*5c51f124SMoriah Waterland } 919*5c51f124SMoriah Waterland } 920*5c51f124SMoriah Waterland 921*5c51f124SMoriah Waterland /* 922*5c51f124SMoriah Waterland * Name: pkgstrLocatePathBasename 923*5c51f124SMoriah Waterland * Synopsis: Locate position of base name in path string 924*5c51f124SMoriah Waterland * Description: Locate the base name (last path item) in a path and 925*5c51f124SMoriah Waterland * return a pointer to the first byte of the base name 926*5c51f124SMoriah Waterland * within the given path 927*5c51f124SMoriah Waterland * Arguments: a_path - [RO, *RO] - (char *) 928*5c51f124SMoriah Waterland * - Pointer to string representing path to scan 929*5c51f124SMoriah Waterland * Returns: char * 930*5c51f124SMoriah Waterland * - Pointer into string of first byte of path base name 931*5c51f124SMoriah Waterland * - == (char *)NULL - input path is (char *)NULL 932*5c51f124SMoriah Waterland */ 933*5c51f124SMoriah Waterland 934*5c51f124SMoriah Waterland char * 935*5c51f124SMoriah Waterland pkgstrLocatePathBasename(char *a_path) 936*5c51f124SMoriah Waterland { 937*5c51f124SMoriah Waterland char *p; 938*5c51f124SMoriah Waterland 939*5c51f124SMoriah Waterland /* if path is NULL, return NULL */ 940*5c51f124SMoriah Waterland 941*5c51f124SMoriah Waterland if (!a_path) { 942*5c51f124SMoriah Waterland return (a_path); 943*5c51f124SMoriah Waterland } 944*5c51f124SMoriah Waterland 945*5c51f124SMoriah Waterland /* locate last occurance of '/' in path */ 946*5c51f124SMoriah Waterland 947*5c51f124SMoriah Waterland p = strrchr(a_path, '/'); 948*5c51f124SMoriah Waterland if (p != (char *)NULL) { 949*5c51f124SMoriah Waterland /* base name located - return -> first byte */ 950*5c51f124SMoriah Waterland return (p+1); 951*5c51f124SMoriah Waterland } 952*5c51f124SMoriah Waterland 953*5c51f124SMoriah Waterland /* no occurance of '/' - entry path must be basename */ 954*5c51f124SMoriah Waterland 955*5c51f124SMoriah Waterland return (a_path); 956*5c51f124SMoriah Waterland } 957*5c51f124SMoriah Waterland 958*5c51f124SMoriah Waterland /* 959*5c51f124SMoriah Waterland * Name: pkgstrConvertPathToBasename 960*5c51f124SMoriah Waterland * Synopsis: Return copy of base name in path string 961*5c51f124SMoriah Waterland * Description: Locate the base name (last path item) in a path and 962*5c51f124SMoriah Waterland * return a copy of the base name in allocated storage 963*5c51f124SMoriah Waterland * Arguments: a_path - [RO, *RO] - (char *) 964*5c51f124SMoriah Waterland * - Pointer to string representing path to scan 965*5c51f124SMoriah Waterland * Returns: char * 966*5c51f124SMoriah Waterland * - String containing path base name 967*5c51f124SMoriah Waterland * - == (char *)NULL - input path is (char *)NULL 968*5c51f124SMoriah Waterland * NOTE: Any string returned is placed in new storage for the 969*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 970*5c51f124SMoriah Waterland * of the storage once the string is no longer needed. 971*5c51f124SMoriah Waterland * Errors: If the string cannot be created, the process exits 972*5c51f124SMoriah Waterland */ 973*5c51f124SMoriah Waterland 974*5c51f124SMoriah Waterland char * 975*5c51f124SMoriah Waterland pkgstrConvertPathToBasename(char *a_path) 976*5c51f124SMoriah Waterland { 977*5c51f124SMoriah Waterland char *p; 978*5c51f124SMoriah Waterland 979*5c51f124SMoriah Waterland /* if path is NULL, return NULL */ 980*5c51f124SMoriah Waterland 981*5c51f124SMoriah Waterland if (a_path == (char *)NULL) { 982*5c51f124SMoriah Waterland return ((char *)NULL); 983*5c51f124SMoriah Waterland } 984*5c51f124SMoriah Waterland 985*5c51f124SMoriah Waterland /* if path is empty (zero length), return NULL */ 986*5c51f124SMoriah Waterland 987*5c51f124SMoriah Waterland if (*a_path == '\0') { 988*5c51f124SMoriah Waterland return ((char *)NULL); 989*5c51f124SMoriah Waterland } 990*5c51f124SMoriah Waterland 991*5c51f124SMoriah Waterland /* locate last occurance of '/' in path */ 992*5c51f124SMoriah Waterland 993*5c51f124SMoriah Waterland p = strrchr(a_path, '/'); 994*5c51f124SMoriah Waterland if (p == (char *)NULL) { 995*5c51f124SMoriah Waterland /* no occurance of '/' - entry path must be basename */ 996*5c51f124SMoriah Waterland 997*5c51f124SMoriah Waterland return (strdup(a_path)); 998*5c51f124SMoriah Waterland } 999*5c51f124SMoriah Waterland 1000*5c51f124SMoriah Waterland /* base name located - return string from -> first byte */ 1001*5c51f124SMoriah Waterland 1002*5c51f124SMoriah Waterland return (strdup(p+1)); 1003*5c51f124SMoriah Waterland } 1004*5c51f124SMoriah Waterland 1005*5c51f124SMoriah Waterland /* 1006*5c51f124SMoriah Waterland * Name: pkgstrConvertPathToDirname 1007*5c51f124SMoriah Waterland * Synopsis: Return copy of directory in path string 1008*5c51f124SMoriah Waterland * Description: Locate the directory name (everything but last path item) in a 1009*5c51f124SMoriah Waterland * path and return a copy of the dir name in allocated storage 1010*5c51f124SMoriah Waterland * Arguments: a_path - [RO, *RO] - (char *) 1011*5c51f124SMoriah Waterland * - Pointer to string representing path to scan 1012*5c51f124SMoriah Waterland * Returns: char * 1013*5c51f124SMoriah Waterland * - String containing path directory name 1014*5c51f124SMoriah Waterland * - == (char *)NULL - input path is (char *)NULL, 1015*5c51f124SMoriah Waterland * or a_path is empty (*a_path == '\0'), or the 1016*5c51f124SMoriah Waterland * a_path has no directory name in it. 1017*5c51f124SMoriah Waterland * NOTE: Any string returned is placed in new storage for the 1018*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 1019*5c51f124SMoriah Waterland * of the storage once the string is no longer needed. 1020*5c51f124SMoriah Waterland * Errors: If the string cannot be created, the process exits 1021*5c51f124SMoriah Waterland */ 1022*5c51f124SMoriah Waterland 1023*5c51f124SMoriah Waterland char * 1024*5c51f124SMoriah Waterland pkgstrConvertPathToDirname(char *a_path) 1025*5c51f124SMoriah Waterland { 1026*5c51f124SMoriah Waterland char *p; 1027*5c51f124SMoriah Waterland char *retPath; 1028*5c51f124SMoriah Waterland 1029*5c51f124SMoriah Waterland /* if path is NULL, return NULL */ 1030*5c51f124SMoriah Waterland 1031*5c51f124SMoriah Waterland if (a_path == (char *)NULL) { 1032*5c51f124SMoriah Waterland return ((char *)NULL); 1033*5c51f124SMoriah Waterland } 1034*5c51f124SMoriah Waterland 1035*5c51f124SMoriah Waterland /* if path is empty (zero length), return NULL */ 1036*5c51f124SMoriah Waterland 1037*5c51f124SMoriah Waterland if (*a_path == '\0') { 1038*5c51f124SMoriah Waterland return ((char *)NULL); 1039*5c51f124SMoriah Waterland } 1040*5c51f124SMoriah Waterland 1041*5c51f124SMoriah Waterland /* locate last occurance of '/' in path */ 1042*5c51f124SMoriah Waterland 1043*5c51f124SMoriah Waterland p = strrchr(a_path, '/'); 1044*5c51f124SMoriah Waterland if (p == (char *)NULL) { 1045*5c51f124SMoriah Waterland /* no occurance of '/' - entire path must be basename */ 1046*5c51f124SMoriah Waterland 1047*5c51f124SMoriah Waterland return ((char *)NULL); 1048*5c51f124SMoriah Waterland } 1049*5c51f124SMoriah Waterland 1050*5c51f124SMoriah Waterland /* duplicate original path */ 1051*5c51f124SMoriah Waterland 1052*5c51f124SMoriah Waterland retPath = strdup(a_path); 1053*5c51f124SMoriah Waterland assert(retPath != (char *)NULL); 1054*5c51f124SMoriah Waterland if (retPath == (char *)NULL) { 1055*5c51f124SMoriah Waterland return ((char *)NULL); 1056*5c51f124SMoriah Waterland } 1057*5c51f124SMoriah Waterland 1058*5c51f124SMoriah Waterland /* remove all trailing '/'s from copy of path */ 1059*5c51f124SMoriah Waterland 1060*5c51f124SMoriah Waterland for (p = strrchr(retPath, '/'); (p > retPath) && (*p == '/'); p--) { 1061*5c51f124SMoriah Waterland *p = '\0'; 1062*5c51f124SMoriah Waterland } 1063*5c51f124SMoriah Waterland 1064*5c51f124SMoriah Waterland /* if entire path was '/'s, return null string - no directory present */ 1065*5c51f124SMoriah Waterland 1066*5c51f124SMoriah Waterland if (*retPath == '\0') { 1067*5c51f124SMoriah Waterland free(retPath); 1068*5c51f124SMoriah Waterland return ((char *)NULL); 1069*5c51f124SMoriah Waterland } 1070*5c51f124SMoriah Waterland 1071*5c51f124SMoriah Waterland /* path has at least one non-'/' in it - return -> directory portion */ 1072*5c51f124SMoriah Waterland 1073*5c51f124SMoriah Waterland return (retPath); 1074*5c51f124SMoriah Waterland } 1075*5c51f124SMoriah Waterland 1076*5c51f124SMoriah Waterland /* 1077*5c51f124SMoriah Waterland * Name: pkgstrConvertUllToTimeString_r 1078*5c51f124SMoriah Waterland * Synopsis: Convert an unsigned long long into a "time string" 1079*5c51f124SMoriah Waterland * Description: Given an unsigned long long, return a "time string" which is a 1080*5c51f124SMoriah Waterland * conversion of the unsigned long long interpreted as a number of 1081*5c51f124SMoriah Waterland * nanoseconds into a "hour:minute:second.ns" ascii string 1082*5c51f124SMoriah Waterland * Arguments: a_time - [RO, *RO] - (unsigned long long)n 1083*5c51f124SMoriah Waterland * - value to convert 1084*5c51f124SMoriah Waterland * a_buf - [RO, *RW] - (char *) 1085*5c51f124SMoriah Waterland * - Pointer to buffer used as storage space for the 1086*5c51f124SMoriah Waterland * returned string 1087*5c51f124SMoriah Waterland * a_bufLen - [RO, *RO] - (int) 1088*5c51f124SMoriah Waterland * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1' 1089*5c51f124SMoriah Waterland * bytes will be placed in 'a_buf' 1090*5c51f124SMoriah Waterland * Returns: char * 1091*5c51f124SMoriah Waterland * - String containing converted value 1092*5c51f124SMoriah Waterland * NOTE: Any string returned is placed in new storage for the 1093*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose 1094*5c51f124SMoriah Waterland * of the storage once the string is no longer needed. 1095*5c51f124SMoriah Waterland * Errors: If the string cannot be created, the process exits 1096*5c51f124SMoriah Waterland */ 1097*5c51f124SMoriah Waterland 1098*5c51f124SMoriah Waterland void 1099*5c51f124SMoriah Waterland pkgstrConvertUllToTimeString_r(unsigned long long a_time, 1100*5c51f124SMoriah Waterland char *a_buf, int a_bufLen) 1101*5c51f124SMoriah Waterland { 1102*5c51f124SMoriah Waterland unsigned long long seconds; 1103*5c51f124SMoriah Waterland unsigned long long minutes; 1104*5c51f124SMoriah Waterland unsigned long long hours; 1105*5c51f124SMoriah Waterland unsigned long long ns; 1106*5c51f124SMoriah Waterland 1107*5c51f124SMoriah Waterland /* entry assertions */ 1108*5c51f124SMoriah Waterland 1109*5c51f124SMoriah Waterland assert(a_buf != (char *)NULL); 1110*5c51f124SMoriah Waterland assert(a_bufLen > 0); 1111*5c51f124SMoriah Waterland 1112*5c51f124SMoriah Waterland /* if time is 0, return immediate result */ 1113*5c51f124SMoriah Waterland 1114*5c51f124SMoriah Waterland if (a_time == 0) { 1115*5c51f124SMoriah Waterland pkgstrPrintf_r(a_buf, a_bufLen, "%s", "0:00:00.000000000"); 1116*5c51f124SMoriah Waterland return; 1117*5c51f124SMoriah Waterland } 1118*5c51f124SMoriah Waterland 1119*5c51f124SMoriah Waterland /* break out individual time components */ 1120*5c51f124SMoriah Waterland 1121*5c51f124SMoriah Waterland ns = a_time % 1000000000ll; /* nanoseconds left over from seconds */ 1122*5c51f124SMoriah Waterland seconds = a_time / 1000000000ll; /* total seconds */ 1123*5c51f124SMoriah Waterland minutes = seconds / 60ll; /* total minutes */ 1124*5c51f124SMoriah Waterland seconds = seconds % 60ll; /* seconds left over from minutes */ 1125*5c51f124SMoriah Waterland hours = minutes / 60ll; /* total hours */ 1126*5c51f124SMoriah Waterland minutes = minutes % 60ll; /* minutes left over from hours */ 1127*5c51f124SMoriah Waterland 1128*5c51f124SMoriah Waterland /* return a converted string */ 1129*5c51f124SMoriah Waterland 1130*5c51f124SMoriah Waterland pkgstrPrintf_r(a_buf, a_bufLen, "%llu:%02llu:%02llu.%09llu", 1131*5c51f124SMoriah Waterland hours, minutes, seconds, ns); 1132*5c51f124SMoriah Waterland } 1133