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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23*5c51f124SMoriah Waterland * Use is subject to license terms.
24*5c51f124SMoriah Waterland */
25*5c51f124SMoriah Waterland
26*5c51f124SMoriah Waterland
27*5c51f124SMoriah Waterland
28*5c51f124SMoriah Waterland /*
29*5c51f124SMoriah Waterland * Module: zones_str.c
30*5c51f124SMoriah Waterland * Group: libinstzones
31*5c51f124SMoriah Waterland * Description: Private functions used by zones library functions to manipulate
32*5c51f124SMoriah Waterland * strings
33*5c51f124SMoriah Waterland *
34*5c51f124SMoriah Waterland * Public Methods:
35*5c51f124SMoriah Waterland *
36*5c51f124SMoriah Waterland * _z_strAddToken - Add a token to a string
37*5c51f124SMoriah Waterland * _z_strContainsToken - Does a given string contain a specified substring
38*5c51f124SMoriah Waterland * _z_strGetToken - Get a separator delimited token from a string
39*5c51f124SMoriah Waterland * _z_strGetToken_r - Get separator delimited token from string to fixed buffer
40*5c51f124SMoriah Waterland * _z_strPrintf - Create string from printf style format and arguments
41*5c51f124SMoriah Waterland * _z_strPrintf_r - Create string from printf style format and arguments
42*5c51f124SMoriah Waterland * _z_strRemoveLeadingWhitespace - Remove leading whitespace from string
43*5c51f124SMoriah Waterland * _z_strRemoveToken - Remove a token from a string
44*5c51f124SMoriah Waterland */
45*5c51f124SMoriah Waterland
46*5c51f124SMoriah Waterland /*
47*5c51f124SMoriah Waterland * System includes
48*5c51f124SMoriah Waterland */
49*5c51f124SMoriah Waterland
50*5c51f124SMoriah Waterland #include <stdio.h>
51*5c51f124SMoriah Waterland #include <stdlib.h>
52*5c51f124SMoriah Waterland #include <unistd.h>
53*5c51f124SMoriah Waterland #include <ctype.h>
54*5c51f124SMoriah Waterland #include <sys/types.h>
55*5c51f124SMoriah Waterland #include <sys/param.h>
56*5c51f124SMoriah Waterland #include <string.h>
57*5c51f124SMoriah Waterland #include <strings.h>
58*5c51f124SMoriah Waterland #include <stdarg.h>
59*5c51f124SMoriah Waterland #include <limits.h>
60*5c51f124SMoriah Waterland #include <stropts.h>
61*5c51f124SMoriah Waterland #include <libintl.h>
62*5c51f124SMoriah Waterland #include <locale.h>
63*5c51f124SMoriah Waterland #include <assert.h>
64*5c51f124SMoriah Waterland
65*5c51f124SMoriah Waterland /*
66*5c51f124SMoriah Waterland * local includes
67*5c51f124SMoriah Waterland */
68*5c51f124SMoriah Waterland
69*5c51f124SMoriah Waterland #include "instzones_lib.h"
70*5c51f124SMoriah Waterland #include "zones_strings.h"
71*5c51f124SMoriah Waterland
72*5c51f124SMoriah Waterland /*
73*5c51f124SMoriah Waterland * Private structures
74*5c51f124SMoriah Waterland */
75*5c51f124SMoriah Waterland
76*5c51f124SMoriah Waterland /*
77*5c51f124SMoriah Waterland * Library Function Prototypes
78*5c51f124SMoriah Waterland */
79*5c51f124SMoriah Waterland
80*5c51f124SMoriah Waterland /*
81*5c51f124SMoriah Waterland * Local Function Prototypes
82*5c51f124SMoriah Waterland */
83*5c51f124SMoriah Waterland
84*5c51f124SMoriah Waterland /*
85*5c51f124SMoriah Waterland * Global internal (private) declarations
86*5c51f124SMoriah Waterland */
87*5c51f124SMoriah Waterland
88*5c51f124SMoriah Waterland /*
89*5c51f124SMoriah Waterland * *****************************************************************************
90*5c51f124SMoriah Waterland * global external (public) functions
91*5c51f124SMoriah Waterland * *****************************************************************************
92*5c51f124SMoriah Waterland */
93*5c51f124SMoriah Waterland
94*5c51f124SMoriah Waterland /*
95*5c51f124SMoriah Waterland * Name: _z_strAddToken
96*5c51f124SMoriah Waterland * Synopsis: Add a token to a string
97*5c51f124SMoriah Waterland * Description: Append a token (sequence of one or more characters) to a
98*5c51f124SMoriah Waterland * string that is in allocated space - create new string if
99*5c51f124SMoriah Waterland * no string to append to exists
100*5c51f124SMoriah Waterland * Arguments: a_old - [RO, *RW] - (char **)
101*5c51f124SMoriah Waterland * - Pointer to handle to string to append token to
102*5c51f124SMoriah Waterland * == NULL - new string is created
103*5c51f124SMoriah Waterland * a_new - [RO, *RO] - (char *)
104*5c51f124SMoriah Waterland * - Pointer to string representing token to append
105*5c51f124SMoriah Waterland * to the end of the "a_old" string
106*5c51f124SMoriah Waterland * == NULL - no action is performed
107*5c51f124SMoriah Waterland * a_new[0] == '\0' - no action is performed
108*5c51f124SMoriah Waterland * a_separator - [RO, *RO] - (char)
109*5c51f124SMoriah Waterland * - One character placed between the old (existing)
110*5c51f124SMoriah Waterland * string and the new token to be added IF the old
111*5c51f124SMoriah Waterland * string exists and is not empty (zero length)
112*5c51f124SMoriah Waterland * Returns: void
113*5c51f124SMoriah Waterland * CAUTION: The old (existing) string must be allocated space (via lu_mem*
114*5c51f124SMoriah Waterland * or _z_str* methods) - it must not be a static or inline
115*5c51f124SMoriah Waterland * character string
116*5c51f124SMoriah Waterland * NOTE: The old (existing) string may be freed with 'free'
117*5c51f124SMoriah Waterland * if a token is appended to it
118*5c51f124SMoriah Waterland * NOTE: Any string returned in 'a_old' is placed in new storage for the
119*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose
120*5c51f124SMoriah Waterland * of the storage once the token string is no longer needed.
121*5c51f124SMoriah Waterland */
122*5c51f124SMoriah Waterland
123*5c51f124SMoriah Waterland void
_z_strAddToken(char ** a_old,char * a_new,char a_separator)124*5c51f124SMoriah Waterland _z_strAddToken(char **a_old, char *a_new, char a_separator)
125*5c51f124SMoriah Waterland {
126*5c51f124SMoriah Waterland /* entry assertions */
127*5c51f124SMoriah Waterland
128*5c51f124SMoriah Waterland assert(a_old != NULL);
129*5c51f124SMoriah Waterland assert(a_separator != '\0');
130*5c51f124SMoriah Waterland
131*5c51f124SMoriah Waterland /* if token to add is null or token is zero length, just return */
132*5c51f124SMoriah Waterland
133*5c51f124SMoriah Waterland if (a_new == NULL || *a_new == '\0') {
134*5c51f124SMoriah Waterland return;
135*5c51f124SMoriah Waterland }
136*5c51f124SMoriah Waterland
137*5c51f124SMoriah Waterland /* make sure that new token does not contain the separator */
138*5c51f124SMoriah Waterland
139*5c51f124SMoriah Waterland assert(strchr(a_new, (int)a_separator) == NULL);
140*5c51f124SMoriah Waterland
141*5c51f124SMoriah Waterland /* if old string is empty (zero length), deallocate */
142*5c51f124SMoriah Waterland
143*5c51f124SMoriah Waterland if ((*a_old != NULL) && ((*a_old)[0] == '\0')) {
144*5c51f124SMoriah Waterland /* *a_old is set to NULL by free */
145*5c51f124SMoriah Waterland free(*a_old);
146*5c51f124SMoriah Waterland *a_old = NULL;
147*5c51f124SMoriah Waterland }
148*5c51f124SMoriah Waterland
149*5c51f124SMoriah Waterland /* if old string exists, append separator and token */
150*5c51f124SMoriah Waterland
151*5c51f124SMoriah Waterland if (*a_old != NULL) {
152*5c51f124SMoriah Waterland char *p;
153*5c51f124SMoriah Waterland p = _z_strPrintf("%s%c%s", *a_old, a_separator, a_new);
154*5c51f124SMoriah Waterland free(*a_old);
155*5c51f124SMoriah Waterland *a_old = p;
156*5c51f124SMoriah Waterland return;
157*5c51f124SMoriah Waterland }
158*5c51f124SMoriah Waterland
159*5c51f124SMoriah Waterland /* old string does not exist - return duplicate of token */
160*5c51f124SMoriah Waterland
161*5c51f124SMoriah Waterland assert(*a_old == NULL);
162*5c51f124SMoriah Waterland *a_old = _z_strdup(a_new);
163*5c51f124SMoriah Waterland }
164*5c51f124SMoriah Waterland
165*5c51f124SMoriah Waterland /*
166*5c51f124SMoriah Waterland * Name: _z_strContainsToken
167*5c51f124SMoriah Waterland * Synopsis: Does a given string contain a specified substring
168*5c51f124SMoriah Waterland * Description: Determine if a given substring exists in a larger string
169*5c51f124SMoriah Waterland * Arguments: a_string - [RO, *RO] - (char *)
170*5c51f124SMoriah Waterland * Pointer to string to look for substring in
171*5c51f124SMoriah Waterland * a_token - [RO, *RO] - (char *)
172*5c51f124SMoriah Waterland * Pointer to substring to look for in larger string
173*5c51f124SMoriah Waterland * Results: boolean_t
174*5c51f124SMoriah Waterland * B_TRUE - substring exists in larger string
175*5c51f124SMoriah Waterland * B_FALSE - substring does NOT exist in larger string
176*5c51f124SMoriah Waterland * NOTE: The substring must match on a "token" basis; that is, the
177*5c51f124SMoriah Waterland * substring must exist in the larger string delineated with
178*5c51f124SMoriah Waterland * either spaces or tabs to match.
179*5c51f124SMoriah Waterland */
180*5c51f124SMoriah Waterland
181*5c51f124SMoriah Waterland boolean_t
_z_strContainsToken(char * a_string,char * a_token,char * a_separators)182*5c51f124SMoriah Waterland _z_strContainsToken(char *a_string, char *a_token, char *a_separators)
183*5c51f124SMoriah Waterland {
184*5c51f124SMoriah Waterland char *lasts;
185*5c51f124SMoriah Waterland char *current;
186*5c51f124SMoriah Waterland char *p;
187*5c51f124SMoriah Waterland
188*5c51f124SMoriah Waterland /* entry assertions */
189*5c51f124SMoriah Waterland
190*5c51f124SMoriah Waterland assert(a_separators != NULL);
191*5c51f124SMoriah Waterland assert(*a_separators != '\0');
192*5c51f124SMoriah Waterland
193*5c51f124SMoriah Waterland /*
194*5c51f124SMoriah Waterland * if token is not supplied, no string provided,
195*5c51f124SMoriah Waterland * or the string is an empty string, return false
196*5c51f124SMoriah Waterland */
197*5c51f124SMoriah Waterland
198*5c51f124SMoriah Waterland if (a_token == NULL || a_string == NULL || *a_string == '\0') {
199*5c51f124SMoriah Waterland return (B_FALSE);
200*5c51f124SMoriah Waterland }
201*5c51f124SMoriah Waterland
202*5c51f124SMoriah Waterland /* if no string provided, return false */
203*5c51f124SMoriah Waterland
204*5c51f124SMoriah Waterland /* if string empty (zero length), return false */
205*5c51f124SMoriah Waterland
206*5c51f124SMoriah Waterland /* duplicate larger string because strtok_r changes it */
207*5c51f124SMoriah Waterland
208*5c51f124SMoriah Waterland p = _z_strdup(a_string);
209*5c51f124SMoriah Waterland
210*5c51f124SMoriah Waterland lasts = p;
211*5c51f124SMoriah Waterland
212*5c51f124SMoriah Waterland /* scan each token looking for a match */
213*5c51f124SMoriah Waterland
214*5c51f124SMoriah Waterland while ((current = strtok_r(NULL, a_separators, &lasts)) !=
215*5c51f124SMoriah Waterland NULL) {
216*5c51f124SMoriah Waterland if (strcmp(current, a_token) == 0) {
217*5c51f124SMoriah Waterland free(p);
218*5c51f124SMoriah Waterland return (B_TRUE);
219*5c51f124SMoriah Waterland }
220*5c51f124SMoriah Waterland }
221*5c51f124SMoriah Waterland
222*5c51f124SMoriah Waterland /* free up temporary storage */
223*5c51f124SMoriah Waterland
224*5c51f124SMoriah Waterland free(p);
225*5c51f124SMoriah Waterland
226*5c51f124SMoriah Waterland /* not found */
227*5c51f124SMoriah Waterland
228*5c51f124SMoriah Waterland return (B_FALSE);
229*5c51f124SMoriah Waterland }
230*5c51f124SMoriah Waterland
231*5c51f124SMoriah Waterland /*
232*5c51f124SMoriah Waterland * Name: _z_strGetToken
233*5c51f124SMoriah Waterland * Synopsis: Get a separator delimited token from a string
234*5c51f124SMoriah Waterland * Description: Given a string and a list of one or more separators,
235*5c51f124SMoriah Waterland * return the position specified token (sequence of one or
236*5c51f124SMoriah Waterland * more characters that do not include any of the separators)
237*5c51f124SMoriah Waterland * Arguments: r_sep - [*RW] - (char *)
238*5c51f124SMoriah Waterland * - separator that ended the token returned
239*5c51f124SMoriah Waterland * - NOTE: this is a pointer to a "char", e.g.:
240*5c51f124SMoriah Waterland * - char a;
241*5c51f124SMoriah Waterland * - _z_strGetToken(&a, ...)
242*5c51f124SMoriah Waterland * a_string - [RO, *RO] - (char *)
243*5c51f124SMoriah Waterland * - pointer to string to extract token from
244*5c51f124SMoriah Waterland * a_index - [RO, *RO] - (int)
245*5c51f124SMoriah Waterland * - Index of token to return; '0' is first matching
246*5c51f124SMoriah Waterland * token, '1' is second matching token, etc.
247*5c51f124SMoriah Waterland * a_separators - [RO, *RO] - (char *)
248*5c51f124SMoriah Waterland * - String containing one or more characters that
249*5c51f124SMoriah Waterland * can separate one "token" from another
250*5c51f124SMoriah Waterland * Returns: char *
251*5c51f124SMoriah Waterland * == NULL - no token matching criteria found
252*5c51f124SMoriah Waterland * != NULL - token matching criteria
253*5c51f124SMoriah Waterland * NOTE: Any token string returned is placed in new storage for the
254*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose
255*5c51f124SMoriah Waterland * of the storage once the token string is no longer needed.
256*5c51f124SMoriah Waterland */
257*5c51f124SMoriah Waterland
258*5c51f124SMoriah Waterland char *
_z_strGetToken(char * r_sep,char * a_string,int a_index,char * a_separators)259*5c51f124SMoriah Waterland _z_strGetToken(char *r_sep, char *a_string, int a_index, char *a_separators)
260*5c51f124SMoriah Waterland {
261*5c51f124SMoriah Waterland char *p;
262*5c51f124SMoriah Waterland char *q;
263*5c51f124SMoriah Waterland char *lasts;
264*5c51f124SMoriah Waterland
265*5c51f124SMoriah Waterland /* entry assertions */
266*5c51f124SMoriah Waterland
267*5c51f124SMoriah Waterland assert(a_string != NULL);
268*5c51f124SMoriah Waterland assert(a_index >= 0);
269*5c51f124SMoriah Waterland assert(a_separators != NULL);
270*5c51f124SMoriah Waterland assert(*a_separators != '\0');
271*5c51f124SMoriah Waterland
272*5c51f124SMoriah Waterland /* if returned separator requested, reset to null until token found */
273*5c51f124SMoriah Waterland
274*5c51f124SMoriah Waterland if (r_sep != NULL) {
275*5c51f124SMoriah Waterland *r_sep = '\0';
276*5c51f124SMoriah Waterland }
277*5c51f124SMoriah Waterland
278*5c51f124SMoriah Waterland /* duplicate original string before breaking down into tokens */
279*5c51f124SMoriah Waterland
280*5c51f124SMoriah Waterland p = _z_strdup(a_string);
281*5c51f124SMoriah Waterland
282*5c51f124SMoriah Waterland lasts = p;
283*5c51f124SMoriah Waterland
284*5c51f124SMoriah Waterland /* scan for separators and return 'index'th token found */
285*5c51f124SMoriah Waterland
286*5c51f124SMoriah Waterland while (q = strtok_r(NULL, a_separators, &lasts)) {
287*5c51f124SMoriah Waterland /* retrieve separator if requested */
288*5c51f124SMoriah Waterland
289*5c51f124SMoriah Waterland if (r_sep != NULL) {
290*5c51f124SMoriah Waterland char *x;
291*5c51f124SMoriah Waterland
292*5c51f124SMoriah Waterland x = strpbrk(a_string, a_separators);
293*5c51f124SMoriah Waterland if (x != NULL) {
294*5c51f124SMoriah Waterland *r_sep = *x;
295*5c51f124SMoriah Waterland }
296*5c51f124SMoriah Waterland }
297*5c51f124SMoriah Waterland
298*5c51f124SMoriah Waterland /* if this is the 'index'th token requested return it */
299*5c51f124SMoriah Waterland
300*5c51f124SMoriah Waterland if (a_index-- == 0) {
301*5c51f124SMoriah Waterland char *tmp;
302*5c51f124SMoriah Waterland
303*5c51f124SMoriah Waterland /* duplicate token into its own storage */
304*5c51f124SMoriah Waterland
305*5c51f124SMoriah Waterland tmp = _z_strdup(q);
306*5c51f124SMoriah Waterland
307*5c51f124SMoriah Waterland /* free up copy of original input string */
308*5c51f124SMoriah Waterland
309*5c51f124SMoriah Waterland free(p);
310*5c51f124SMoriah Waterland
311*5c51f124SMoriah Waterland /* return token found */
312*5c51f124SMoriah Waterland
313*5c51f124SMoriah Waterland return (tmp);
314*5c51f124SMoriah Waterland }
315*5c51f124SMoriah Waterland }
316*5c51f124SMoriah Waterland
317*5c51f124SMoriah Waterland /*
318*5c51f124SMoriah Waterland * token not found
319*5c51f124SMoriah Waterland */
320*5c51f124SMoriah Waterland
321*5c51f124SMoriah Waterland /* free up copy of original input string */
322*5c51f124SMoriah Waterland
323*5c51f124SMoriah Waterland free(p);
324*5c51f124SMoriah Waterland
325*5c51f124SMoriah Waterland /* return NULL pointer (token not found) */
326*5c51f124SMoriah Waterland
327*5c51f124SMoriah Waterland return (NULL);
328*5c51f124SMoriah Waterland }
329*5c51f124SMoriah Waterland
330*5c51f124SMoriah Waterland /*
331*5c51f124SMoriah Waterland * Name: _z_strGetToken_r
332*5c51f124SMoriah Waterland * Synopsis: Get separator delimited token from a string into a fixed buffer
333*5c51f124SMoriah Waterland * Description: Given a string and a list of one or more separators,
334*5c51f124SMoriah Waterland * return the position specified token (sequence of one or
335*5c51f124SMoriah Waterland * more characters that do not include any of the separators)
336*5c51f124SMoriah Waterland * into a specified buffer of a fixed maximum size
337*5c51f124SMoriah Waterland * Arguments: r_sep - [*RW] - (char *)
338*5c51f124SMoriah Waterland * - separator that ended the token returned
339*5c51f124SMoriah Waterland * - NOTE: this is a pointer to a "char", e.g.:
340*5c51f124SMoriah Waterland * - char a;
341*5c51f124SMoriah Waterland * - _z_strGetToken(&a, ...)
342*5c51f124SMoriah Waterland * a_string - [RO, *RO] - (char *)
343*5c51f124SMoriah Waterland * - pointer to string to extract token from
344*5c51f124SMoriah Waterland * a_index - [RO, *RO] - (int)
345*5c51f124SMoriah Waterland * - Index of token to return; '0' is first matching
346*5c51f124SMoriah Waterland * token, '1' is second matching token, etc.
347*5c51f124SMoriah Waterland * a_separators - [RO, *RO] - (char *)
348*5c51f124SMoriah Waterland * - String containing one or more characters that
349*5c51f124SMoriah Waterland * can separate one "token" from another
350*5c51f124SMoriah Waterland * a_buf - [RO, *RW] - (char *)
351*5c51f124SMoriah Waterland * - Pointer to buffer used as storage space for the
352*5c51f124SMoriah Waterland * returned token - the returned token is always
353*5c51f124SMoriah Waterland * null terminated
354*5c51f124SMoriah Waterland * a_buf[0] == '\0' - no token meeting criteria found
355*5c51f124SMoriah Waterland * a_buf[0] != '\0' - token meeting criteria returned
356*5c51f124SMoriah Waterland * a_bufLen - [RO, *RO] - (int)
357*5c51f124SMoriah Waterland * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
358*5c51f124SMoriah Waterland * bytes will be placed in 'a_buf' - the returned
359*5c51f124SMoriah Waterland * token is always null terminated
360*5c51f124SMoriah Waterland * Returns: void
361*5c51f124SMoriah Waterland */
362*5c51f124SMoriah Waterland
363*5c51f124SMoriah Waterland void
_z_strGetToken_r(char * r_sep,char * a_string,int a_index,char * a_separators,char * a_buf,int a_bufLen)364*5c51f124SMoriah Waterland _z_strGetToken_r(char *r_sep, char *a_string, int a_index,
365*5c51f124SMoriah Waterland char *a_separators, char *a_buf, int a_bufLen)
366*5c51f124SMoriah Waterland {
367*5c51f124SMoriah Waterland char *p;
368*5c51f124SMoriah Waterland char *q;
369*5c51f124SMoriah Waterland char *lasts;
370*5c51f124SMoriah Waterland
371*5c51f124SMoriah Waterland /* entry assertions */
372*5c51f124SMoriah Waterland
373*5c51f124SMoriah Waterland assert(a_string != NULL);
374*5c51f124SMoriah Waterland assert(a_index >= 0);
375*5c51f124SMoriah Waterland assert(a_separators != NULL);
376*5c51f124SMoriah Waterland assert(*a_separators != '\0');
377*5c51f124SMoriah Waterland assert(a_buf != NULL);
378*5c51f124SMoriah Waterland assert(a_bufLen > 0);
379*5c51f124SMoriah Waterland
380*5c51f124SMoriah Waterland /* reset returned separator */
381*5c51f124SMoriah Waterland
382*5c51f124SMoriah Waterland if (r_sep != NULL) {
383*5c51f124SMoriah Waterland *r_sep = '\0';
384*5c51f124SMoriah Waterland }
385*5c51f124SMoriah Waterland
386*5c51f124SMoriah Waterland /* zero out contents of return buffer */
387*5c51f124SMoriah Waterland
388*5c51f124SMoriah Waterland bzero(a_buf, a_bufLen);
389*5c51f124SMoriah Waterland
390*5c51f124SMoriah Waterland /* duplicate original string before breaking down into tokens */
391*5c51f124SMoriah Waterland
392*5c51f124SMoriah Waterland p = _z_strdup(a_string);
393*5c51f124SMoriah Waterland
394*5c51f124SMoriah Waterland lasts = p;
395*5c51f124SMoriah Waterland
396*5c51f124SMoriah Waterland /* scan for separators and return 'index'th token found */
397*5c51f124SMoriah Waterland
398*5c51f124SMoriah Waterland while (q = strtok_r(NULL, a_separators, &lasts)) {
399*5c51f124SMoriah Waterland /* retrieve separator if requested */
400*5c51f124SMoriah Waterland
401*5c51f124SMoriah Waterland if (r_sep != NULL) {
402*5c51f124SMoriah Waterland char *x;
403*5c51f124SMoriah Waterland x = strpbrk(a_string, a_separators);
404*5c51f124SMoriah Waterland if (x != NULL) {
405*5c51f124SMoriah Waterland *r_sep = *x;
406*5c51f124SMoriah Waterland }
407*5c51f124SMoriah Waterland }
408*5c51f124SMoriah Waterland
409*5c51f124SMoriah Waterland /* if this is the 'index'th token requested return it */
410*5c51f124SMoriah Waterland
411*5c51f124SMoriah Waterland if (a_index-- == 0) {
412*5c51f124SMoriah Waterland /* copy as many characters as possible to return buf */
413*5c51f124SMoriah Waterland
414*5c51f124SMoriah Waterland (void) strncpy(a_buf, q, a_bufLen-1);
415*5c51f124SMoriah Waterland break;
416*5c51f124SMoriah Waterland }
417*5c51f124SMoriah Waterland }
418*5c51f124SMoriah Waterland
419*5c51f124SMoriah Waterland /* free up copy of original input string */
420*5c51f124SMoriah Waterland
421*5c51f124SMoriah Waterland free(p);
422*5c51f124SMoriah Waterland }
423*5c51f124SMoriah Waterland
424*5c51f124SMoriah Waterland /*
425*5c51f124SMoriah Waterland * Name: _z_strPrintf
426*5c51f124SMoriah Waterland * Synopsis: Create string from printf style format and arguments
427*5c51f124SMoriah Waterland * Description: Call to convert a printf style format and arguments into a
428*5c51f124SMoriah Waterland * string of characters placed in allocated storage
429*5c51f124SMoriah Waterland * Arguments: format - [RO, RO*] (char *)
430*5c51f124SMoriah Waterland * printf-style format for string to be formatted
431*5c51f124SMoriah Waterland * VARG_LIST - [RO] (?)
432*5c51f124SMoriah Waterland * arguments as appropriate to 'format' specified
433*5c51f124SMoriah Waterland * Returns: char *
434*5c51f124SMoriah Waterland * A string representing the printf conversion results
435*5c51f124SMoriah Waterland * NOTE: Any string returned is placed in new storage for the
436*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose
437*5c51f124SMoriah Waterland * of the storage once the string is no longer needed.
438*5c51f124SMoriah Waterland * Errors: If the string cannot be created, the process exits
439*5c51f124SMoriah Waterland */
440*5c51f124SMoriah Waterland
441*5c51f124SMoriah Waterland /*PRINTFLIKE1*/
442*5c51f124SMoriah Waterland char *
_z_strPrintf(char * a_format,...)443*5c51f124SMoriah Waterland _z_strPrintf(char *a_format, ...)
444*5c51f124SMoriah Waterland {
445*5c51f124SMoriah Waterland va_list ap;
446*5c51f124SMoriah Waterland size_t vres = 0;
447*5c51f124SMoriah Waterland char bfr[1];
448*5c51f124SMoriah Waterland char *rstr = NULL;
449*5c51f124SMoriah Waterland
450*5c51f124SMoriah Waterland /* entry assertions */
451*5c51f124SMoriah Waterland
452*5c51f124SMoriah Waterland assert(a_format != NULL);
453*5c51f124SMoriah Waterland assert(*a_format != '\0');
454*5c51f124SMoriah Waterland
455*5c51f124SMoriah Waterland /* determine size of the message in bytes */
456*5c51f124SMoriah Waterland
457*5c51f124SMoriah Waterland va_start(ap, a_format);
458*5c51f124SMoriah Waterland vres = vsnprintf(bfr, 1, a_format, ap);
459*5c51f124SMoriah Waterland va_end(ap);
460*5c51f124SMoriah Waterland
461*5c51f124SMoriah Waterland assert(vres > 0);
462*5c51f124SMoriah Waterland assert(vres < LINE_MAX);
463*5c51f124SMoriah Waterland
464*5c51f124SMoriah Waterland /* allocate storage to hold the message */
465*5c51f124SMoriah Waterland
466*5c51f124SMoriah Waterland rstr = (char *)_z_calloc(vres+2);
467*5c51f124SMoriah Waterland
468*5c51f124SMoriah Waterland /* generate the results of the printf conversion */
469*5c51f124SMoriah Waterland
470*5c51f124SMoriah Waterland va_start(ap, a_format);
471*5c51f124SMoriah Waterland vres = vsnprintf(rstr, vres+1, a_format, ap);
472*5c51f124SMoriah Waterland va_end(ap);
473*5c51f124SMoriah Waterland
474*5c51f124SMoriah Waterland assert(vres > 0);
475*5c51f124SMoriah Waterland assert(vres < LINE_MAX);
476*5c51f124SMoriah Waterland assert(*rstr != '\0');
477*5c51f124SMoriah Waterland
478*5c51f124SMoriah Waterland /* return the results */
479*5c51f124SMoriah Waterland
480*5c51f124SMoriah Waterland return (rstr);
481*5c51f124SMoriah Waterland }
482*5c51f124SMoriah Waterland
483*5c51f124SMoriah Waterland /*
484*5c51f124SMoriah Waterland * Name: _z_strPrintf_r
485*5c51f124SMoriah Waterland * Synopsis: Create string from printf style format and arguments
486*5c51f124SMoriah Waterland * Description: Call to convert a printf style format and arguments into a
487*5c51f124SMoriah Waterland * string of characters placed in allocated storage
488*5c51f124SMoriah Waterland * Arguments: a_buf - [RO, *RW] - (char *)
489*5c51f124SMoriah Waterland * - Pointer to buffer used as storage space for the
490*5c51f124SMoriah Waterland * returned string created
491*5c51f124SMoriah Waterland * a_bufLen - [RO, *RO] - (int)
492*5c51f124SMoriah Waterland * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
493*5c51f124SMoriah Waterland * bytes will be placed in 'a_buf' - the returned
494*5c51f124SMoriah Waterland * string is always null terminated
495*5c51f124SMoriah Waterland * a_format - [RO, RO*] (char *)
496*5c51f124SMoriah Waterland * printf-style format for string to be formatted
497*5c51f124SMoriah Waterland * VARG_LIST - [RO] (?)
498*5c51f124SMoriah Waterland * arguments as appropriate to 'format' specified
499*5c51f124SMoriah Waterland * Returns: void
500*5c51f124SMoriah Waterland */
501*5c51f124SMoriah Waterland
502*5c51f124SMoriah Waterland /*PRINTFLIKE3*/
503*5c51f124SMoriah Waterland void
_z_strPrintf_r(char * a_buf,int a_bufLen,char * a_format,...)504*5c51f124SMoriah Waterland _z_strPrintf_r(char *a_buf, int a_bufLen, char *a_format, ...)
505*5c51f124SMoriah Waterland {
506*5c51f124SMoriah Waterland va_list ap;
507*5c51f124SMoriah Waterland size_t vres = 0;
508*5c51f124SMoriah Waterland
509*5c51f124SMoriah Waterland /* entry assertions */
510*5c51f124SMoriah Waterland
511*5c51f124SMoriah Waterland assert(a_format != NULL);
512*5c51f124SMoriah Waterland assert(*a_format != '\0');
513*5c51f124SMoriah Waterland assert(a_buf != NULL);
514*5c51f124SMoriah Waterland assert(a_bufLen > 1);
515*5c51f124SMoriah Waterland
516*5c51f124SMoriah Waterland /* generate the results of the printf conversion */
517*5c51f124SMoriah Waterland
518*5c51f124SMoriah Waterland va_start(ap, a_format);
519*5c51f124SMoriah Waterland vres = vsnprintf(a_buf, a_bufLen-1, a_format, ap);
520*5c51f124SMoriah Waterland va_end(ap);
521*5c51f124SMoriah Waterland
522*5c51f124SMoriah Waterland assert(vres > 0);
523*5c51f124SMoriah Waterland assert(vres < a_bufLen);
524*5c51f124SMoriah Waterland
525*5c51f124SMoriah Waterland a_buf[a_bufLen-1] = '\0';
526*5c51f124SMoriah Waterland }
527*5c51f124SMoriah Waterland
528*5c51f124SMoriah Waterland /*
529*5c51f124SMoriah Waterland * Name: _z_strRemoveLeadingWhitespace
530*5c51f124SMoriah Waterland * Synopsis: Remove leading whitespace from string
531*5c51f124SMoriah Waterland * Description: Remove all leading whitespace characters from a string
532*5c51f124SMoriah Waterland * Arguments: a_str - [RO, *RW] - (char **)
533*5c51f124SMoriah Waterland * Pointer to handle to string (in allocated storage) to
534*5c51f124SMoriah Waterland * remove all leading whitespace from
535*5c51f124SMoriah Waterland * Returns: void
536*5c51f124SMoriah Waterland * The input string is modified as follows:
537*5c51f124SMoriah Waterland * == NULL:
538*5c51f124SMoriah Waterland * - input string was NULL
539*5c51f124SMoriah Waterland * - input string is all whitespace
540*5c51f124SMoriah Waterland * != NULL:
541*5c51f124SMoriah Waterland * - copy of input string with leading
542*5c51f124SMoriah Waterland * whitespace removed
543*5c51f124SMoriah Waterland * CAUTION: The input string must be allocated space (via mem* or
544*5c51f124SMoriah Waterland * _z_str* methods) - it must not be a static or inline
545*5c51f124SMoriah Waterland * character string
546*5c51f124SMoriah Waterland * NOTE: The input string a_str will be freed with 'free'
547*5c51f124SMoriah Waterland * if it is all whitespace, or if it contains any leading
548*5c51f124SMoriah Waterland * whitespace characters
549*5c51f124SMoriah Waterland * NOTE: Any string returned is placed in new storage for the
550*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose
551*5c51f124SMoriah Waterland * of the storage once the string is no longer needed.
552*5c51f124SMoriah Waterland * Errors: If the string cannot be created, the process exits
553*5c51f124SMoriah Waterland */
554*5c51f124SMoriah Waterland
555*5c51f124SMoriah Waterland void
_z_strRemoveLeadingWhitespace(char ** a_str)556*5c51f124SMoriah Waterland _z_strRemoveLeadingWhitespace(char **a_str)
557*5c51f124SMoriah Waterland {
558*5c51f124SMoriah Waterland char *o_str;
559*5c51f124SMoriah Waterland
560*5c51f124SMoriah Waterland /* entry assertions */
561*5c51f124SMoriah Waterland
562*5c51f124SMoriah Waterland assert(a_str != NULL);
563*5c51f124SMoriah Waterland
564*5c51f124SMoriah Waterland /* if string is null, just return */
565*5c51f124SMoriah Waterland
566*5c51f124SMoriah Waterland if (*a_str == NULL) {
567*5c51f124SMoriah Waterland return;
568*5c51f124SMoriah Waterland }
569*5c51f124SMoriah Waterland o_str = *a_str;
570*5c51f124SMoriah Waterland
571*5c51f124SMoriah Waterland /* if string is empty, deallocate and return NULL */
572*5c51f124SMoriah Waterland
573*5c51f124SMoriah Waterland if (*o_str == '\0') {
574*5c51f124SMoriah Waterland /* free string - handle is not reset to NULL by free */
575*5c51f124SMoriah Waterland free(*a_str);
576*5c51f124SMoriah Waterland *a_str = NULL;
577*5c51f124SMoriah Waterland return;
578*5c51f124SMoriah Waterland }
579*5c51f124SMoriah Waterland
580*5c51f124SMoriah Waterland /* if first character is not a space, just return */
581*5c51f124SMoriah Waterland
582*5c51f124SMoriah Waterland if (!isspace(*o_str)) {
583*5c51f124SMoriah Waterland return;
584*5c51f124SMoriah Waterland }
585*5c51f124SMoriah Waterland
586*5c51f124SMoriah Waterland /* advance past all space characters */
587*5c51f124SMoriah Waterland
588*5c51f124SMoriah Waterland while ((*o_str != '\0') && (isspace(*o_str))) {
589*5c51f124SMoriah Waterland o_str++;
590*5c51f124SMoriah Waterland }
591*5c51f124SMoriah Waterland
592*5c51f124SMoriah Waterland /* if string was all space characters, deallocate and return NULL */
593*5c51f124SMoriah Waterland
594*5c51f124SMoriah Waterland if (*o_str == '\0') {
595*5c51f124SMoriah Waterland /* free string - *a_str is not reset to NULL by free */
596*5c51f124SMoriah Waterland free(*a_str);
597*5c51f124SMoriah Waterland *a_str = NULL;
598*5c51f124SMoriah Waterland return;
599*5c51f124SMoriah Waterland }
600*5c51f124SMoriah Waterland
601*5c51f124SMoriah Waterland /* have non-space/null byte, return dup, deallocate original */
602*5c51f124SMoriah Waterland
603*5c51f124SMoriah Waterland free(*a_str);
604*5c51f124SMoriah Waterland *a_str = _z_strdup(o_str);
605*5c51f124SMoriah Waterland }
606*5c51f124SMoriah Waterland
607*5c51f124SMoriah Waterland /*
608*5c51f124SMoriah Waterland * Name: _z_strRemoveToken
609*5c51f124SMoriah Waterland * Synopsis: Remove a token from a string
610*5c51f124SMoriah Waterland * Description: Remove a token (sequence of one or more characters) from a
611*5c51f124SMoriah Waterland * string that is in allocated space
612*5c51f124SMoriah Waterland * Arguments: r_string - [RO, *RW] - (char **)
613*5c51f124SMoriah Waterland * - Pointer to handle to string to remove token from
614*5c51f124SMoriah Waterland * a_token - [RO, *RO] - (char *)
615*5c51f124SMoriah Waterland * Pointer to token (substring) to look for and remove
616*5c51f124SMoriah Waterland * from r_string provided
617*5c51f124SMoriah Waterland * a_separators - [RO, *RO] - (char *)
618*5c51f124SMoriah Waterland * - String containing one or more characters that
619*5c51f124SMoriah Waterland * separate one "token" from another in r_string
620*5c51f124SMoriah Waterland * a_index - [RO, *RO] - (int)
621*5c51f124SMoriah Waterland * - Index of token to remove; '0' is first matching
622*5c51f124SMoriah Waterland * token, '1' is second matching token, etc.
623*5c51f124SMoriah Waterland * Returns: void
624*5c51f124SMoriah Waterland * CAUTION: The input string must be allocated space (via lu_mem* or
625*5c51f124SMoriah Waterland * _z_str* methods) - it must not be a static or inline
626*5c51f124SMoriah Waterland * character string
627*5c51f124SMoriah Waterland * NOTE: The input string r_string will be freed with 'free'
628*5c51f124SMoriah Waterland * if the token to be removed is found
629*5c51f124SMoriah Waterland * NOTE: Any token string returned is placed in new storage for the
630*5c51f124SMoriah Waterland * calling method. The caller must use 'free' to dispose
631*5c51f124SMoriah Waterland * of the storage once the token string is no longer needed.
632*5c51f124SMoriah Waterland * Errors: If the new token string cannot be created, the process exits
633*5c51f124SMoriah Waterland */
634*5c51f124SMoriah Waterland
635*5c51f124SMoriah Waterland void
_z_strRemoveToken(char ** r_string,char * a_token,char * a_separators,int a_index)636*5c51f124SMoriah Waterland _z_strRemoveToken(char **r_string, char *a_token, char *a_separators,
637*5c51f124SMoriah Waterland int a_index)
638*5c51f124SMoriah Waterland {
639*5c51f124SMoriah Waterland char *a_string;
640*5c51f124SMoriah Waterland char *copyString;
641*5c51f124SMoriah Waterland char sep = 0;
642*5c51f124SMoriah Waterland int copyLength;
643*5c51f124SMoriah Waterland int i;
644*5c51f124SMoriah Waterland
645*5c51f124SMoriah Waterland /* entry assertions */
646*5c51f124SMoriah Waterland
647*5c51f124SMoriah Waterland assert(r_string != NULL);
648*5c51f124SMoriah Waterland assert(a_token != NULL);
649*5c51f124SMoriah Waterland assert(*a_token != '\0');
650*5c51f124SMoriah Waterland assert(a_separators != NULL);
651*5c51f124SMoriah Waterland assert(*a_separators != '\0');
652*5c51f124SMoriah Waterland
653*5c51f124SMoriah Waterland /* simple case: input string is null; return empty string */
654*5c51f124SMoriah Waterland
655*5c51f124SMoriah Waterland a_string = *r_string;
656*5c51f124SMoriah Waterland if (*a_string == '\0') {
657*5c51f124SMoriah Waterland return;
658*5c51f124SMoriah Waterland }
659*5c51f124SMoriah Waterland
660*5c51f124SMoriah Waterland /* simple case: token == input string; return empty string */
661*5c51f124SMoriah Waterland
662*5c51f124SMoriah Waterland if (strcmp(a_string, a_token) == 0) {
663*5c51f124SMoriah Waterland /*
664*5c51f124SMoriah Waterland * deallocate input string; free doesn't
665*5c51f124SMoriah Waterland * set *r_string to NULL
666*5c51f124SMoriah Waterland */
667*5c51f124SMoriah Waterland free(*r_string);
668*5c51f124SMoriah Waterland *r_string = NULL;
669*5c51f124SMoriah Waterland return;
670*5c51f124SMoriah Waterland }
671*5c51f124SMoriah Waterland
672*5c51f124SMoriah Waterland /* simple case: token not in input string: return */
673*5c51f124SMoriah Waterland
674*5c51f124SMoriah Waterland if (!_z_strContainsToken(a_string, a_token, a_separators)) {
675*5c51f124SMoriah Waterland return;
676*5c51f124SMoriah Waterland }
677*5c51f124SMoriah Waterland
678*5c51f124SMoriah Waterland /*
679*5c51f124SMoriah Waterland * Pick apart the old string building the new one as we go along
680*5c51f124SMoriah Waterland * removing the first occurance of the token provided
681*5c51f124SMoriah Waterland */
682*5c51f124SMoriah Waterland
683*5c51f124SMoriah Waterland copyLength = (strlen(a_string)-strlen(a_token))+2;
684*5c51f124SMoriah Waterland copyString = (char *)_z_calloc(copyLength);
685*5c51f124SMoriah Waterland
686*5c51f124SMoriah Waterland for (i = 0; ; i++) {
687*5c51f124SMoriah Waterland char *p;
688*5c51f124SMoriah Waterland
689*5c51f124SMoriah Waterland p = _z_strGetToken(&sep, a_string, i, a_separators);
690*5c51f124SMoriah Waterland if (p == NULL) {
691*5c51f124SMoriah Waterland break;
692*5c51f124SMoriah Waterland }
693*5c51f124SMoriah Waterland
694*5c51f124SMoriah Waterland if ((strcmp(p, a_token) == 0) && (a_index-- == 0)) {
695*5c51f124SMoriah Waterland free(p);
696*5c51f124SMoriah Waterland continue;
697*5c51f124SMoriah Waterland }
698*5c51f124SMoriah Waterland
699*5c51f124SMoriah Waterland if (*copyString) {
700*5c51f124SMoriah Waterland assert(sep != '\0');
701*5c51f124SMoriah Waterland (void) strncat(copyString, &sep, 1);
702*5c51f124SMoriah Waterland }
703*5c51f124SMoriah Waterland
704*5c51f124SMoriah Waterland (void) strcat(copyString, p);
705*5c51f124SMoriah Waterland free(p);
706*5c51f124SMoriah Waterland }
707*5c51f124SMoriah Waterland
708*5c51f124SMoriah Waterland free(*r_string);
709*5c51f124SMoriah Waterland assert(*copyString);
710*5c51f124SMoriah Waterland *r_string = copyString;
711*5c51f124SMoriah Waterland }
712