4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
31 * Description: Private functions used by zones library functions to manipulate
36 * _z_strAddToken - Add a token to a string
37 * _z_strContainsToken - Does a given string contain a specified substring
38 * _z_strGetToken - Get a separator delimited token from a string
39 * _z_strGetToken_r - Get separator delimited token from string to fixed buffer
40 * _z_strPrintf - Create string from printf style format and arguments
41 * _z_strPrintf_r - Create string from printf style format and arguments
42 * _z_strRemoveLeadingWhitespace - Remove leading whitespace from string
43 * _z_strRemoveToken - Remove a token from a string
54 #include <sys/types.h>
55 #include <sys/param.h>
69 #include "instzones_lib.h"
70 #include "zones_strings.h"
77 * Library Function Prototypes
81 * Local Function Prototypes
85 * Global internal (private) declarations
89 * *****************************************************************************
90 * global external (public) functions
91 * *****************************************************************************
95 * Name: _z_strAddToken
96 * Synopsis: Add a token to a string
97 * Description: Append a token (sequence of one or more characters) to a
98 * string that is in allocated space - create new string if
99 * no string to append to exists
100 * Arguments: a_old - [RO, *RW] - (char **)
101 * - Pointer to handle to string to append token to
102 * == NULL - new string is created
103 * a_new - [RO, *RO] - (char *)
104 * - Pointer to string representing token to append
105 * to the end of the "a_old" string
106 * == NULL - no action is performed
107 * a_new[0] == '\0' - no action is performed
108 * a_separator - [RO, *RO] - (char)
109 * - One character placed between the old (existing)
110 * string and the new token to be added IF the old
111 * string exists and is not empty (zero length)
113 * CAUTION: The old (existing) string must be allocated space (via lu_mem*
114 * or _z_str* methods) - it must not be a static or inline
116 * NOTE: The old (existing) string may be freed with 'free'
117 * if a token is appended to it
118 * NOTE: Any string returned in 'a_old' is placed in new storage for the
119 * calling method. The caller must use 'free' to dispose
120 * of the storage once the token string is no longer needed.
124 _z_strAddToken(char **a_old
, char *a_new
, char a_separator
)
126 /* entry assertions */
128 assert(a_old
!= NULL
);
129 assert(a_separator
!= '\0');
131 /* if token to add is null or token is zero length, just return */
133 if (a_new
== NULL
|| *a_new
== '\0') {
137 /* make sure that new token does not contain the separator */
139 assert(strchr(a_new
, (int)a_separator
) == NULL
);
141 /* if old string is empty (zero length), deallocate */
143 if ((*a_old
!= NULL
) && ((*a_old
)[0] == '\0')) {
144 /* *a_old is set to NULL by free */
149 /* if old string exists, append separator and token */
151 if (*a_old
!= NULL
) {
153 p
= _z_strPrintf("%s%c%s", *a_old
, a_separator
, a_new
);
159 /* old string does not exist - return duplicate of token */
161 assert(*a_old
== NULL
);
162 *a_old
= _z_strdup(a_new
);
166 * Name: _z_strContainsToken
167 * Synopsis: Does a given string contain a specified substring
168 * Description: Determine if a given substring exists in a larger string
169 * Arguments: a_string - [RO, *RO] - (char *)
170 * Pointer to string to look for substring in
171 * a_token - [RO, *RO] - (char *)
172 * Pointer to substring to look for in larger string
174 * B_TRUE - substring exists in larger string
175 * B_FALSE - substring does NOT exist in larger string
176 * NOTE: The substring must match on a "token" basis; that is, the
177 * substring must exist in the larger string delineated with
178 * either spaces or tabs to match.
182 _z_strContainsToken(char *a_string
, char *a_token
, char *a_separators
)
188 /* entry assertions */
190 assert(a_separators
!= NULL
);
191 assert(*a_separators
!= '\0');
194 * if token is not supplied, no string provided,
195 * or the string is an empty string, return false
198 if (a_token
== NULL
|| a_string
== NULL
|| *a_string
== '\0') {
202 /* if no string provided, return false */
204 /* if string empty (zero length), return false */
206 /* duplicate larger string because strtok_r changes it */
208 p
= _z_strdup(a_string
);
212 /* scan each token looking for a match */
214 while ((current
= strtok_r(NULL
, a_separators
, &lasts
)) !=
216 if (strcmp(current
, a_token
) == 0) {
222 /* free up temporary storage */
232 * Name: _z_strGetToken
233 * Synopsis: Get a separator delimited token from a string
234 * Description: Given a string and a list of one or more separators,
235 * return the position specified token (sequence of one or
236 * more characters that do not include any of the separators)
237 * Arguments: r_sep - [*RW] - (char *)
238 * - separator that ended the token returned
239 * - NOTE: this is a pointer to a "char", e.g.:
241 * - _z_strGetToken(&a, ...)
242 * a_string - [RO, *RO] - (char *)
243 * - pointer to string to extract token from
244 * a_index - [RO, *RO] - (int)
245 * - Index of token to return; '0' is first matching
246 * token, '1' is second matching token, etc.
247 * a_separators - [RO, *RO] - (char *)
248 * - String containing one or more characters that
249 * can separate one "token" from another
251 * == NULL - no token matching criteria found
252 * != NULL - token matching criteria
253 * NOTE: Any token string returned is placed in new storage for the
254 * calling method. The caller must use 'free' to dispose
255 * of the storage once the token string is no longer needed.
259 _z_strGetToken(char *r_sep
, char *a_string
, int a_index
, char *a_separators
)
265 /* entry assertions */
267 assert(a_string
!= NULL
);
268 assert(a_index
>= 0);
269 assert(a_separators
!= NULL
);
270 assert(*a_separators
!= '\0');
272 /* if returned separator requested, reset to null until token found */
278 /* duplicate original string before breaking down into tokens */
280 p
= _z_strdup(a_string
);
284 /* scan for separators and return 'index'th token found */
286 while (q
= strtok_r(NULL
, a_separators
, &lasts
)) {
287 /* retrieve separator if requested */
292 x
= strpbrk(a_string
, a_separators
);
298 /* if this is the 'index'th token requested return it */
300 if (a_index
-- == 0) {
303 /* duplicate token into its own storage */
307 /* free up copy of original input string */
311 /* return token found */
321 /* free up copy of original input string */
325 /* return NULL pointer (token not found) */
331 * Name: _z_strGetToken_r
332 * Synopsis: Get separator delimited token from a string into a fixed buffer
333 * Description: Given a string and a list of one or more separators,
334 * return the position specified token (sequence of one or
335 * more characters that do not include any of the separators)
336 * into a specified buffer of a fixed maximum size
337 * Arguments: r_sep - [*RW] - (char *)
338 * - separator that ended the token returned
339 * - NOTE: this is a pointer to a "char", e.g.:
341 * - _z_strGetToken(&a, ...)
342 * a_string - [RO, *RO] - (char *)
343 * - pointer to string to extract token from
344 * a_index - [RO, *RO] - (int)
345 * - Index of token to return; '0' is first matching
346 * token, '1' is second matching token, etc.
347 * a_separators - [RO, *RO] - (char *)
348 * - String containing one or more characters that
349 * can separate one "token" from another
350 * a_buf - [RO, *RW] - (char *)
351 * - Pointer to buffer used as storage space for the
352 * returned token - the returned token is always
354 * a_buf[0] == '\0' - no token meeting criteria found
355 * a_buf[0] != '\0' - token meeting criteria returned
356 * a_bufLen - [RO, *RO] - (int)
357 * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
358 * bytes will be placed in 'a_buf' - the returned
359 * token is always null terminated
364 _z_strGetToken_r(char *r_sep
, char *a_string
, int a_index
,
365 char *a_separators
, char *a_buf
, int a_bufLen
)
371 /* entry assertions */
373 assert(a_string
!= NULL
);
374 assert(a_index
>= 0);
375 assert(a_separators
!= NULL
);
376 assert(*a_separators
!= '\0');
377 assert(a_buf
!= NULL
);
378 assert(a_bufLen
> 0);
380 /* reset returned separator */
386 /* zero out contents of return buffer */
388 bzero(a_buf
, a_bufLen
);
390 /* duplicate original string before breaking down into tokens */
392 p
= _z_strdup(a_string
);
396 /* scan for separators and return 'index'th token found */
398 while (q
= strtok_r(NULL
, a_separators
, &lasts
)) {
399 /* retrieve separator if requested */
403 x
= strpbrk(a_string
, a_separators
);
409 /* if this is the 'index'th token requested return it */
411 if (a_index
-- == 0) {
412 /* copy as many characters as possible to return buf */
414 (void) strncpy(a_buf
, q
, a_bufLen
-1);
419 /* free up copy of original input string */
426 * Synopsis: Create string from printf style format and arguments
427 * Description: Call to convert a printf style format and arguments into a
428 * string of characters placed in allocated storage
429 * Arguments: format - [RO, RO*] (char *)
430 * printf-style format for string to be formatted
431 * VARG_LIST - [RO] (?)
432 * arguments as appropriate to 'format' specified
434 * A string representing the printf conversion results
435 * NOTE: Any string returned is placed in new storage for the
436 * calling method. The caller must use 'free' to dispose
437 * of the storage once the string is no longer needed.
438 * Errors: If the string cannot be created, the process exits
443 _z_strPrintf(char *a_format
, ...)
450 /* entry assertions */
452 assert(a_format
!= NULL
);
453 assert(*a_format
!= '\0');
455 /* determine size of the message in bytes */
457 va_start(ap
, a_format
);
458 vres
= vsnprintf(bfr
, 1, a_format
, ap
);
462 assert(vres
< LINE_MAX
);
464 /* allocate storage to hold the message */
466 rstr
= (char *)_z_calloc(vres
+2);
468 /* generate the results of the printf conversion */
470 va_start(ap
, a_format
);
471 vres
= vsnprintf(rstr
, vres
+1, a_format
, ap
);
475 assert(vres
< LINE_MAX
);
476 assert(*rstr
!= '\0');
478 /* return the results */
484 * Name: _z_strPrintf_r
485 * Synopsis: Create string from printf style format and arguments
486 * Description: Call to convert a printf style format and arguments into a
487 * string of characters placed in allocated storage
488 * Arguments: a_buf - [RO, *RW] - (char *)
489 * - Pointer to buffer used as storage space for the
490 * returned string created
491 * a_bufLen - [RO, *RO] - (int)
492 * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
493 * bytes will be placed in 'a_buf' - the returned
494 * string is always null terminated
495 * a_format - [RO, RO*] (char *)
496 * printf-style format for string to be formatted
497 * VARG_LIST - [RO] (?)
498 * arguments as appropriate to 'format' specified
504 _z_strPrintf_r(char *a_buf
, int a_bufLen
, char *a_format
, ...)
509 /* entry assertions */
511 assert(a_format
!= NULL
);
512 assert(*a_format
!= '\0');
513 assert(a_buf
!= NULL
);
514 assert(a_bufLen
> 1);
516 /* generate the results of the printf conversion */
518 va_start(ap
, a_format
);
519 vres
= vsnprintf(a_buf
, a_bufLen
-1, a_format
, ap
);
523 assert(vres
< a_bufLen
);
525 a_buf
[a_bufLen
-1] = '\0';
529 * Name: _z_strRemoveLeadingWhitespace
530 * Synopsis: Remove leading whitespace from string
531 * Description: Remove all leading whitespace characters from a string
532 * Arguments: a_str - [RO, *RW] - (char **)
533 * Pointer to handle to string (in allocated storage) to
534 * remove all leading whitespace from
536 * The input string is modified as follows:
538 * - input string was NULL
539 * - input string is all whitespace
541 * - copy of input string with leading
543 * CAUTION: The input string must be allocated space (via mem* or
544 * _z_str* methods) - it must not be a static or inline
546 * NOTE: The input string a_str will be freed with 'free'
547 * if it is all whitespace, or if it contains any leading
548 * whitespace characters
549 * NOTE: Any string returned is placed in new storage for the
550 * calling method. The caller must use 'free' to dispose
551 * of the storage once the string is no longer needed.
552 * Errors: If the string cannot be created, the process exits
556 _z_strRemoveLeadingWhitespace(char **a_str
)
560 /* entry assertions */
562 assert(a_str
!= NULL
);
564 /* if string is null, just return */
566 if (*a_str
== NULL
) {
571 /* if string is empty, deallocate and return NULL */
573 if (*o_str
== '\0') {
574 /* free string - handle is not reset to NULL by free */
580 /* if first character is not a space, just return */
582 if (!isspace(*o_str
)) {
586 /* advance past all space characters */
588 while ((*o_str
!= '\0') && (isspace(*o_str
))) {
592 /* if string was all space characters, deallocate and return NULL */
594 if (*o_str
== '\0') {
595 /* free string - *a_str is not reset to NULL by free */
601 /* have non-space/null byte, return dup, deallocate original */
604 *a_str
= _z_strdup(o_str
);
608 * Name: _z_strRemoveToken
609 * Synopsis: Remove a token from a string
610 * Description: Remove a token (sequence of one or more characters) from a
611 * string that is in allocated space
612 * Arguments: r_string - [RO, *RW] - (char **)
613 * - Pointer to handle to string to remove token from
614 * a_token - [RO, *RO] - (char *)
615 * Pointer to token (substring) to look for and remove
616 * from r_string provided
617 * a_separators - [RO, *RO] - (char *)
618 * - String containing one or more characters that
619 * separate one "token" from another in r_string
620 * a_index - [RO, *RO] - (int)
621 * - Index of token to remove; '0' is first matching
622 * token, '1' is second matching token, etc.
624 * CAUTION: The input string must be allocated space (via lu_mem* or
625 * _z_str* methods) - it must not be a static or inline
627 * NOTE: The input string r_string will be freed with 'free'
628 * if the token to be removed is found
629 * NOTE: Any token string returned is placed in new storage for the
630 * calling method. The caller must use 'free' to dispose
631 * of the storage once the token string is no longer needed.
632 * Errors: If the new token string cannot be created, the process exits
636 _z_strRemoveToken(char **r_string
, char *a_token
, char *a_separators
,
645 /* entry assertions */
647 assert(r_string
!= NULL
);
648 assert(a_token
!= NULL
);
649 assert(*a_token
!= '\0');
650 assert(a_separators
!= NULL
);
651 assert(*a_separators
!= '\0');
653 /* simple case: input string is null; return empty string */
655 a_string
= *r_string
;
656 if (*a_string
== '\0') {
660 /* simple case: token == input string; return empty string */
662 if (strcmp(a_string
, a_token
) == 0) {
664 * deallocate input string; free doesn't
665 * set *r_string to NULL
672 /* simple case: token not in input string: return */
674 if (!_z_strContainsToken(a_string
, a_token
, a_separators
)) {
679 * Pick apart the old string building the new one as we go along
680 * removing the first occurance of the token provided
683 copyLength
= (strlen(a_string
)-strlen(a_token
))+2;
684 copyString
= (char *)_z_calloc(copyLength
);
689 p
= _z_strGetToken(&sep
, a_string
, i
, a_separators
);
694 if ((strcmp(p
, a_token
) == 0) && (a_index
-- == 0)) {
701 (void) strncat(copyString
, &sep
, 1);
704 (void) strcat(copyString
, p
);
710 *r_string
= copyString
;