xref: /illumos-gate/usr/src/lib/libsecdb/common/secdb.c (revision 281eb3a9)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5a126dc1aSTony Nguyen  * Common Development and Distribution License (the "License").
6a126dc1aSTony Nguyen  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
224e1c7343SJan Friedel  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <strings.h>
297c478bd9Sstevel@tonic-gate #include <secdb.h>
307c478bd9Sstevel@tonic-gate #include <ctype.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /* From libnsl */
337c478bd9Sstevel@tonic-gate extern char *_strdup_null(char *);
347c478bd9Sstevel@tonic-gate extern char *_strtok_escape(char *, char *, char **);
357c478bd9Sstevel@tonic-gate extern char *_strpbrk_escape(char *, char *);
367c478bd9Sstevel@tonic-gate extern char *_unescape(char *, char *);
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate char *_do_unescape(char *);
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * kva_match(): Given a key-value array and a key, return a pointer to the
437c478bd9Sstevel@tonic-gate  * value that matches the key.
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate char *
kva_match(kva_t * kva,char * key)467c478bd9Sstevel@tonic-gate kva_match(kva_t *kva, char *key)
477c478bd9Sstevel@tonic-gate {
487c478bd9Sstevel@tonic-gate 	int	i;
497c478bd9Sstevel@tonic-gate 	kv_t	*data;
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate 	if (kva == NULL || key == NULL) {
52f8994074SJan Friedel 		return (NULL);
537c478bd9Sstevel@tonic-gate 	}
547c478bd9Sstevel@tonic-gate 	data = kva->data;
557c478bd9Sstevel@tonic-gate 	for (i = 0; i < kva->length; i++) {
567c478bd9Sstevel@tonic-gate 		if (strcmp(data[i].key, key) == 0) {
577c478bd9Sstevel@tonic-gate 			return (data[i].value);
587c478bd9Sstevel@tonic-gate 		}
597c478bd9Sstevel@tonic-gate 	}
607c478bd9Sstevel@tonic-gate 
61f8994074SJan Friedel 	return (NULL);
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate  * _kva_free(): Free up memory.
667c478bd9Sstevel@tonic-gate  */
677c478bd9Sstevel@tonic-gate void
_kva_free(kva_t * kva)687c478bd9Sstevel@tonic-gate _kva_free(kva_t *kva)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate 	int	i;
717c478bd9Sstevel@tonic-gate 	kv_t	*data;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate 	if (kva == NULL) {
747c478bd9Sstevel@tonic-gate 		return;
757c478bd9Sstevel@tonic-gate 	}
767c478bd9Sstevel@tonic-gate 	data = kva->data;
777c478bd9Sstevel@tonic-gate 	for (i = 0; i < kva->length; i++) {
787c478bd9Sstevel@tonic-gate 		if (data[i].key != NULL) {
797c478bd9Sstevel@tonic-gate 			free(data[i].key);
807c478bd9Sstevel@tonic-gate 			data[i].key = NULL;
817c478bd9Sstevel@tonic-gate 		}
827c478bd9Sstevel@tonic-gate 		if (data[i].value != NULL) {
837c478bd9Sstevel@tonic-gate 			free(data[i].value);
847c478bd9Sstevel@tonic-gate 			data[i].value = NULL;
857c478bd9Sstevel@tonic-gate 		}
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 	free(kva->data);
887c478bd9Sstevel@tonic-gate 	free(kva);
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate 
91f8994074SJan Friedel /*
92f8994074SJan Friedel  * _kva_free_value(): Free up memory (value) for all the occurrences of
93f8994074SJan Friedel  * the given key.
94f8994074SJan Friedel  */
95f8994074SJan Friedel void
_kva_free_value(kva_t * kva,char * key)96f8994074SJan Friedel _kva_free_value(kva_t *kva, char *key)
97f8994074SJan Friedel {
98f8994074SJan Friedel 	int	ctr;
99f8994074SJan Friedel 	kv_t	*data;
100f8994074SJan Friedel 
101f8994074SJan Friedel 	if (kva == NULL) {
102f8994074SJan Friedel 		return;
103f8994074SJan Friedel 	}
104f8994074SJan Friedel 
105f8994074SJan Friedel 	ctr = kva->length;
106f8994074SJan Friedel 	data = kva->data;
107f8994074SJan Friedel 
108f8994074SJan Friedel 	while (ctr--) {
109f8994074SJan Friedel 		if (strcmp(data->key, key) == 0 && data->value != NULL) {
110f8994074SJan Friedel 			free(data->value);
111f8994074SJan Friedel 			data->value = NULL;
112f8994074SJan Friedel 		}
113f8994074SJan Friedel 		data++;
114f8994074SJan Friedel 	}
115f8994074SJan Friedel }
116f8994074SJan Friedel 
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate  * new_kva(): Allocate a key-value array.
1197c478bd9Sstevel@tonic-gate  */
1207c478bd9Sstevel@tonic-gate kva_t  *
_new_kva(int size)1217c478bd9Sstevel@tonic-gate _new_kva(int size)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	kva_t	*new_kva;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	if ((new_kva = (kva_t *)calloc(1, sizeof (kva_t))) == NULL) {
126f8994074SJan Friedel 		return (NULL);
1277c478bd9Sstevel@tonic-gate 	}
1287c478bd9Sstevel@tonic-gate 	if ((new_kva->data = (kv_t *)calloc(1, (size*sizeof (kv_t)))) == NULL) {
1297c478bd9Sstevel@tonic-gate 		free(new_kva);
130f8994074SJan Friedel 		return (NULL);
1317c478bd9Sstevel@tonic-gate 	}
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	return (new_kva);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate  * _str2kva(): Given a string (s) of key-value pairs, separated by delimeter
1387c478bd9Sstevel@tonic-gate  * (del), place the values into the key value array (nkva).
1397c478bd9Sstevel@tonic-gate  */
1407c478bd9Sstevel@tonic-gate kva_t  *
_str2kva(char * s,char * ass,char * del)1417c478bd9Sstevel@tonic-gate _str2kva(char *s, char *ass, char *del)
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	int	n = 0;
1447c478bd9Sstevel@tonic-gate 	int	m;
1457c478bd9Sstevel@tonic-gate 	int	size = KV_ADD_KEYS;
1467c478bd9Sstevel@tonic-gate 	char	*buf;
1477c478bd9Sstevel@tonic-gate 	char	*p;
1487c478bd9Sstevel@tonic-gate 	char	*pair;
1497c478bd9Sstevel@tonic-gate 	char	*key;
1507c478bd9Sstevel@tonic-gate 	char	*last_pair;
1517c478bd9Sstevel@tonic-gate 	char	*last_key;
1527c478bd9Sstevel@tonic-gate 	kv_t	*data;
1537c478bd9Sstevel@tonic-gate 	kva_t	*nkva;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	if (s == NULL ||
1567c478bd9Sstevel@tonic-gate 	    ass == NULL ||
1577c478bd9Sstevel@tonic-gate 	    del == NULL ||
1587c478bd9Sstevel@tonic-gate 	    *s == '\0' ||
1597c478bd9Sstevel@tonic-gate 	    *s == '\n' ||
1607c478bd9Sstevel@tonic-gate 	    (strlen(s) <= 1)) {
161f8994074SJan Friedel 		return (NULL);
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 	p = s;
1647c478bd9Sstevel@tonic-gate 	while ((p = _strpbrk_escape(p, ass)) != NULL) {
1657c478bd9Sstevel@tonic-gate 		n++;
1667c478bd9Sstevel@tonic-gate 		p++;
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate 	if (n > size) {
1697c478bd9Sstevel@tonic-gate 		m = n/size;
1707c478bd9Sstevel@tonic-gate 		if (n%size) {
1717c478bd9Sstevel@tonic-gate 			++m;
1727c478bd9Sstevel@tonic-gate 		}
1737c478bd9Sstevel@tonic-gate 		size = m * KV_ADD_KEYS;
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 	if ((nkva = _new_kva(size)) == NULL) {
176f8994074SJan Friedel 		return (NULL);
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 	data = nkva->data;
1797c478bd9Sstevel@tonic-gate 	nkva->length = 0;
1807c478bd9Sstevel@tonic-gate 	if ((buf = strdup(s)) == NULL) {
181f8994074SJan Friedel 		return (NULL);
1827c478bd9Sstevel@tonic-gate 	}
1837c478bd9Sstevel@tonic-gate 	pair = _strtok_escape(buf, del, &last_pair);
1847c478bd9Sstevel@tonic-gate 	do {
1857c478bd9Sstevel@tonic-gate 		key = _strtok_escape(pair, ass, &last_key);
1867c478bd9Sstevel@tonic-gate 		if (key != NULL) {
1877c478bd9Sstevel@tonic-gate 			data[nkva->length].key = _do_unescape(key);
1887c478bd9Sstevel@tonic-gate 			data[nkva->length].value = _do_unescape(last_key);
1897c478bd9Sstevel@tonic-gate 			nkva->length++;
1907c478bd9Sstevel@tonic-gate 		}
1917c478bd9Sstevel@tonic-gate 	} while ((pair = _strtok_escape(NULL, del, &last_pair)) != NULL);
1927c478bd9Sstevel@tonic-gate 	free(buf);
1937c478bd9Sstevel@tonic-gate 	return (nkva);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate /*
1977c478bd9Sstevel@tonic-gate  * _kva2str(): Given an array of key-value pairs, place them into a string
1987c478bd9Sstevel@tonic-gate  * (buf). Use delimeter (del) to separate pairs.  Use assignment character
1997c478bd9Sstevel@tonic-gate  * (ass) to separate keys and values.
2007c478bd9Sstevel@tonic-gate  *
201f8994074SJan Friedel  * Return Values: 0  Success 1  Buffer too small
2027c478bd9Sstevel@tonic-gate  */
2037c478bd9Sstevel@tonic-gate int
_kva2str(kva_t * kva,char * buf,int buflen,char * ass,char * del)2047c478bd9Sstevel@tonic-gate _kva2str(kva_t *kva, char *buf, int buflen, char *ass, char *del)
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	int	i;
207f8994074SJan Friedel 	int	len;
208f8994074SJan Friedel 	int	off = 0;
2097c478bd9Sstevel@tonic-gate 	kv_t	*data;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	if (kva == NULL) {
2127c478bd9Sstevel@tonic-gate 		return (0);
2137c478bd9Sstevel@tonic-gate 	}
214f8994074SJan Friedel 
215f8994074SJan Friedel 	buf[0] = '\0';
2167c478bd9Sstevel@tonic-gate 	data = kva->data;
217f8994074SJan Friedel 
2187c478bd9Sstevel@tonic-gate 	for (i = 0; i < kva->length; i++) {
2197c478bd9Sstevel@tonic-gate 		if (data[i].value != NULL) {
220f8994074SJan Friedel 			len = snprintf(buf + off, buflen - off, "%s%s%s%s",
221f8994074SJan Friedel 			    data[i].key, ass, data[i].value, del);
222f8994074SJan Friedel 			if (len < 0 || len + off >= buflen) {
223f8994074SJan Friedel 				return (1);
2247c478bd9Sstevel@tonic-gate 			}
225f8994074SJan Friedel 			off += len;
2267c478bd9Sstevel@tonic-gate 		}
2277c478bd9Sstevel@tonic-gate 	}
228f8994074SJan Friedel 
2297c478bd9Sstevel@tonic-gate 	return (0);
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate int
_insert2kva(kva_t * kva,char * key,char * value)2337c478bd9Sstevel@tonic-gate _insert2kva(kva_t *kva, char *key, char *value)
2347c478bd9Sstevel@tonic-gate {
2357c478bd9Sstevel@tonic-gate 	int	i;
2367c478bd9Sstevel@tonic-gate 	kv_t	*data;
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	if (kva == NULL) {
2397c478bd9Sstevel@tonic-gate 		return (0);
2407c478bd9Sstevel@tonic-gate 	}
2417c478bd9Sstevel@tonic-gate 	data = kva->data;
2427c478bd9Sstevel@tonic-gate 	for (i = 0; i < kva->length; i++) {
2437c478bd9Sstevel@tonic-gate 		if (strcmp(data[i].key, key) == 0) {
2447c478bd9Sstevel@tonic-gate 			if (data[i].value != NULL)
2457c478bd9Sstevel@tonic-gate 				free(data[i].value);
2467c478bd9Sstevel@tonic-gate 			data[i].value = _strdup_null(value);
2477c478bd9Sstevel@tonic-gate 			return (0);
2487c478bd9Sstevel@tonic-gate 		}
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 	return (1);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate kva_t  *
_kva_dup(kva_t * old_kva)2547c478bd9Sstevel@tonic-gate _kva_dup(kva_t *old_kva)
2557c478bd9Sstevel@tonic-gate {
2567c478bd9Sstevel@tonic-gate 	int	i;
2577c478bd9Sstevel@tonic-gate 	int	size;
2587c478bd9Sstevel@tonic-gate 	kv_t	*old_data;
2597c478bd9Sstevel@tonic-gate 	kv_t	*new_data;
260*281eb3a9SToomas Soome 	kva_t	*nkva = NULL;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	if (old_kva == NULL) {
263f8994074SJan Friedel 		return (NULL);
2647c478bd9Sstevel@tonic-gate 	}
2657c478bd9Sstevel@tonic-gate 	old_data = old_kva->data;
2667c478bd9Sstevel@tonic-gate 	size = old_kva->length;
2677c478bd9Sstevel@tonic-gate 	if ((nkva = _new_kva(size)) == NULL) {
268f8994074SJan Friedel 		return (NULL);
2697c478bd9Sstevel@tonic-gate 	}
2707c478bd9Sstevel@tonic-gate 	new_data = nkva->data;
2717c478bd9Sstevel@tonic-gate 	nkva->length = old_kva->length;
272c94b466cSJan Friedel 	for (i = 0; i < nkva->length; i++) {
2737c478bd9Sstevel@tonic-gate 		new_data[i].key = _strdup_null(old_data[i].key);
2747c478bd9Sstevel@tonic-gate 		new_data[i].value = _strdup_null(old_data[i].value);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	return (nkva);
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate static void
strip_spaces(char ** valuep)2817c478bd9Sstevel@tonic-gate strip_spaces(char **valuep)
2827c478bd9Sstevel@tonic-gate {
2837c478bd9Sstevel@tonic-gate 	char *p, *start;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	/* Find first non-white space character and return pointer to it */
2867c478bd9Sstevel@tonic-gate 	for (p = *valuep; *p != '\0' && isspace((unsigned char)*p); p++)
2877c478bd9Sstevel@tonic-gate 		;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	*valuep = start = p;
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	if (*p == '\0')
2927c478bd9Sstevel@tonic-gate 		return;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	p = p + strlen(p) - 1;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	/* Remove trailing spaces */
2977c478bd9Sstevel@tonic-gate 	while (p > start && isspace((unsigned char)*p))
2987c478bd9Sstevel@tonic-gate 		p--;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	p[1] = '\0';
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate char *
_do_unescape(char * src)3047c478bd9Sstevel@tonic-gate _do_unescape(char *src)
3057c478bd9Sstevel@tonic-gate {
3067c478bd9Sstevel@tonic-gate 	char *tmp = NULL;
3077c478bd9Sstevel@tonic-gate 	char *dst = NULL;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	if (src == NULL) {
3107c478bd9Sstevel@tonic-gate 		dst = _strdup_null(src);
3117c478bd9Sstevel@tonic-gate 	} else {
3127c478bd9Sstevel@tonic-gate 		strip_spaces(&src);
3137c478bd9Sstevel@tonic-gate 		tmp = _unescape(src, "=;:,\\");
3147c478bd9Sstevel@tonic-gate 		dst = (tmp == NULL) ? _strdup_null(src) : tmp;
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	return (dst);
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate  * Some utilities for handling comma-separated lists.
3237c478bd9Sstevel@tonic-gate  */
3247c478bd9Sstevel@tonic-gate char *
_argv_to_csl(char ** strings)3257c478bd9Sstevel@tonic-gate _argv_to_csl(char **strings)
3267c478bd9Sstevel@tonic-gate {
3277c478bd9Sstevel@tonic-gate 	int len = 0;
3287c478bd9Sstevel@tonic-gate 	int i = 0;
329f8994074SJan Friedel 	char *newstr = NULL;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	if (strings == NULL)
332f8994074SJan Friedel 		return (NULL);
3337c478bd9Sstevel@tonic-gate 	for (i = 0; strings[i] != NULL; i++) {
3347c478bd9Sstevel@tonic-gate 		len += strlen(strings[i]) + 1;
3357c478bd9Sstevel@tonic-gate 	}
336a126dc1aSTony Nguyen 	if ((len > 0) && ((newstr = (char *)malloc(len + 1)) != NULL)) {
337a126dc1aSTony Nguyen 		(void) memset(newstr, 0, len);
338a126dc1aSTony Nguyen 		for (i = 0; strings[i] != NULL; i++) {
339a126dc1aSTony Nguyen 			(void) strcat(newstr, strings[i]);
340a126dc1aSTony Nguyen 			(void) strcat(newstr, ",");
341a126dc1aSTony Nguyen 		}
342*281eb3a9SToomas Soome 		newstr[len-1] = '\0';
343a126dc1aSTony Nguyen 		return (newstr);
344a126dc1aSTony Nguyen 	} else
345f8994074SJan Friedel 		return (NULL);
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate char **
_csl_to_argv(char * csl)3507c478bd9Sstevel@tonic-gate _csl_to_argv(char *csl)
3517c478bd9Sstevel@tonic-gate {
3527c478bd9Sstevel@tonic-gate 	int len = 0;
3537c478bd9Sstevel@tonic-gate 	int ncommas = 0;
3547c478bd9Sstevel@tonic-gate 	int i = 0;
355f8994074SJan Friedel 	char **spc = NULL;
356f8994074SJan Friedel 	char *copy = NULL;
3577c478bd9Sstevel@tonic-gate 	char *pc;
358f8994074SJan Friedel 	char *lasts = NULL;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	len = strlen(csl);
3617c478bd9Sstevel@tonic-gate 	for (i = 0; i < len; i++) {
3627c478bd9Sstevel@tonic-gate 		if (csl[i] == ',')
3637c478bd9Sstevel@tonic-gate 			ncommas++;
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 	if ((spc = (char **)malloc((ncommas + 2) * sizeof (char *))) == NULL) {
366f8994074SJan Friedel 		return (NULL);
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 	copy = strdup(csl);
3697c478bd9Sstevel@tonic-gate 	for (pc = strtok_r(copy, ",", &lasts), i = 0; pc != NULL;
3707c478bd9Sstevel@tonic-gate 	    pc = strtok_r(NULL, ",", &lasts), i++) {
3717c478bd9Sstevel@tonic-gate 		spc[i] = strdup(pc);
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	spc[i] = NULL;
3747c478bd9Sstevel@tonic-gate 	free(copy);
3757c478bd9Sstevel@tonic-gate 	return (spc);
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate void
_free_argv(char ** p_argv)3807c478bd9Sstevel@tonic-gate _free_argv(char **p_argv)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate 	char **p_a;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	for (p_a = p_argv; *p_a != NULL; p_a++)
3857c478bd9Sstevel@tonic-gate 		free(*p_a);
3867c478bd9Sstevel@tonic-gate 	free(p_argv);
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate #ifdef DEBUG
3917c478bd9Sstevel@tonic-gate void
print_kva(kva_t * kva)3927c478bd9Sstevel@tonic-gate print_kva(kva_t *kva)
3937c478bd9Sstevel@tonic-gate {
3947c478bd9Sstevel@tonic-gate 	int	i;
3957c478bd9Sstevel@tonic-gate 	kv_t	*data;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	if (kva == NULL) {
398f8994074SJan Friedel 		(void) printf("  (empty)\n");
3997c478bd9Sstevel@tonic-gate 		return;
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 	data = kva->data;
4027c478bd9Sstevel@tonic-gate 	for (i = 0; i < kva->length; i++) {
403f8994074SJan Friedel 		(void) printf("  %s = %s\n",
404f8994074SJan Friedel 		    data[i].key != NULL ? data[i].key : "NULL",
405f8994074SJan Friedel 		    data[i].value != NULL ? data[i].value : "NULL");
4067c478bd9Sstevel@tonic-gate 	}
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate #endif  /* DEBUG */
409