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