secdb.c revision f89940742f5d14dde79b69b98a414dd7b7f585c7
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <secdb.h>
#include <ctype.h>
/* From libnsl */
extern char *_strdup_null(char *);
extern char *_strtok_escape(char *, char *, char **);
extern char *_strpbrk_escape(char *, char *);
extern char *_unescape(char *, char *);
char *_do_unescape(char *);
/*
* kva_match(): Given a key-value array and a key, return a pointer to the
* value that matches the key.
*/
char *
kva_match(kva_t *kva, char *key)
{
int i;
kv_t *data;
if (kva == NULL || key == NULL) {
return (NULL);
}
data = kva->data;
for (i = 0; i < kva->length; i++) {
if (strcmp(data[i].key, key) == 0) {
return (data[i].value);
}
}
return (NULL);
}
/*
* _kva_free(): Free up memory.
*/
void
_kva_free(kva_t *kva)
{
int i;
kv_t *data;
if (kva == NULL) {
return;
}
data = kva->data;
for (i = 0; i < kva->length; i++) {
if (data[i].key != NULL) {
free(data[i].key);
data[i].key = NULL;
}
if (data[i].value != NULL) {
free(data[i].value);
data[i].value = NULL;
}
}
free(kva->data);
free(kva);
}
/*
* _kva_free_value(): Free up memory (value) for all the occurrences of
* the given key.
*/
void
_kva_free_value(kva_t *kva, char *key)
{
int ctr;
kv_t *data;
if (kva == NULL) {
return;
}
ctr = kva->length;
data = kva->data;
while (ctr--) {
if (strcmp(data->key, key) == 0 && data->value != NULL) {
free(data->value);
data->value = NULL;
}
data++;
}
}
/*
* new_kva(): Allocate a key-value array.
*/
kva_t *
_new_kva(int size)
{
kva_t *new_kva;
if ((new_kva = (kva_t *)calloc(1, sizeof (kva_t))) == NULL) {
return (NULL);
}
if ((new_kva->data = (kv_t *)calloc(1, (size*sizeof (kv_t)))) == NULL) {
free(new_kva);
return (NULL);
}
return (new_kva);
}
/*
* _str2kva(): Given a string (s) of key-value pairs, separated by delimeter
* (del), place the values into the key value array (nkva).
*/
kva_t *
_str2kva(char *s, char *ass, char *del)
{
int n = 0;
int m;
int size = KV_ADD_KEYS;
char *buf;
char *p;
char *pair;
char *key;
char *last_pair;
char *last_key;
kv_t *data;
kva_t *nkva;
if (s == NULL ||
ass == NULL ||
del == NULL ||
*s == '\0' ||
*s == '\n' ||
(strlen(s) <= 1)) {
return (NULL);
}
p = s;
while ((p = _strpbrk_escape(p, ass)) != NULL) {
n++;
p++;
}
if (n > size) {
m = n/size;
if (n%size) {
++m;
}
size = m * KV_ADD_KEYS;
}
if ((nkva = _new_kva(size)) == NULL) {
return (NULL);
}
data = nkva->data;
nkva->length = 0;
if ((buf = strdup(s)) == NULL) {
return (NULL);
}
pair = _strtok_escape(buf, del, &last_pair);
do {
key = _strtok_escape(pair, ass, &last_key);
if (key != NULL) {
data[nkva->length].key = _do_unescape(key);
data[nkva->length].value = _do_unescape(last_key);
nkva->length++;
}
} while ((pair = _strtok_escape(NULL, del, &last_pair)) != NULL);
free(buf);
return (nkva);
}
/*
* _kva2str(): Given an array of key-value pairs, place them into a string
* (buf). Use delimeter (del) to separate pairs. Use assignment character
* (ass) to separate keys and values.
*
* Return Values: 0 Success 1 Buffer too small
*/
int
_kva2str(kva_t *kva, char *buf, int buflen, char *ass, char *del)
{
int i;
int len;
int off = 0;
kv_t *data;
if (kva == NULL) {
return (0);
}
buf[0] = '\0';
data = kva->data;
for (i = 0; i < kva->length; i++) {
if (data[i].value != NULL) {
len = snprintf(buf + off, buflen - off, "%s%s%s%s",
data[i].key, ass, data[i].value, del);
if (len < 0 || len + off >= buflen) {
return (1);
}
off += len;
}
}
return (0);
}
int
_insert2kva(kva_t *kva, char *key, char *value)
{
int i;
kv_t *data;
if (kva == NULL) {
return (0);
}
data = kva->data;
for (i = 0; i < kva->length; i++) {
if (strcmp(data[i].key, key) == 0) {
if (data[i].value != NULL)
free(data[i].value);
data[i].value = _strdup_null(value);
return (0);
}
}
return (1);
}
kva_t *
_kva_dup(kva_t *old_kva)
{
int i;
int size;
kv_t *old_data;
kv_t *new_data;
kva_t *nkva = NULL;
if (old_kva == NULL) {
return (NULL);
}
old_data = old_kva->data;
size = old_kva->length;
if ((nkva = _new_kva(size)) == NULL) {
return (NULL);
}
new_data = nkva->data;
nkva->length = old_kva->length;
for (i = 0; i < nkva->length; i++) {
new_data[i].key = _strdup_null(old_data[i].key);
new_data[i].value = _strdup_null(old_data[i].value);
}
return (nkva);
}
static void
strip_spaces(char **valuep)
{
char *p, *start;
/* Find first non-white space character and return pointer to it */
for (p = *valuep; *p != '\0' && isspace((unsigned char)*p); p++)
;
*valuep = start = p;
if (*p == '\0')
return;
p = p + strlen(p) - 1;
/* Remove trailing spaces */
while (p > start && isspace((unsigned char)*p))
p--;
p[1] = '\0';
}
char *
_do_unescape(char *src)
{
char *tmp = NULL;
char *dst = NULL;
if (src == NULL) {
dst = _strdup_null(src);
} else {
strip_spaces(&src);
tmp = _unescape(src, "=;:,\\");
dst = (tmp == NULL) ? _strdup_null(src) : tmp;
}
return (dst);
}
/*
* Some utilities for handling comma-separated lists.
*/
char *
_argv_to_csl(char **strings)
{
int len = 0;
int i = 0;
char *newstr = NULL;
if (strings == NULL)
return (NULL);
for (i = 0; strings[i] != NULL; i++) {
len += strlen(strings[i]) + 1;
}
if ((len > 0) && ((newstr = (char *)malloc(len + 1)) != NULL)) {
(void) memset(newstr, 0, len);
for (i = 0; strings[i] != NULL; i++) {
(void) strcat(newstr, strings[i]);
(void) strcat(newstr, ",");
}
newstr[len-1] = NULL;
return (newstr);
} else
return (NULL);
}
char **
_csl_to_argv(char *csl)
{
int len = 0;
int ncommas = 0;
int i = 0;
char **spc = NULL;
char *copy = NULL;
char *pc;
char *lasts = NULL;
len = strlen(csl);
for (i = 0; i < len; i++) {
if (csl[i] == ',')
ncommas++;
}
if ((spc = (char **)malloc((ncommas + 2) * sizeof (char *))) == NULL) {
return (NULL);
}
copy = strdup(csl);
for (pc = strtok_r(copy, ",", &lasts), i = 0; pc != NULL;
pc = strtok_r(NULL, ",", &lasts), i++) {
spc[i] = strdup(pc);
}
spc[i] = NULL;
free(copy);
return (spc);
}
void
_free_argv(char **p_argv)
{
char **p_a;
for (p_a = p_argv; *p_a != NULL; p_a++)
free(*p_a);
free(p_argv);
}
#ifdef DEBUG
void
print_kva(kva_t *kva)
{
int i;
kv_t *data;
if (kva == NULL) {
(void) printf(" (empty)\n");
return;
}
data = kva->data;
for (i = 0; i < kva->length; i++) {
(void) printf(" %s = %s\n",
data[i].key != NULL ? data[i].key : "NULL",
data[i].value != NULL ? data[i].value : "NULL");
}
}
#endif /* DEBUG */