1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <strings.h> 29 #include <secdb.h> 30 #include <ctype.h> 31 32 /* From libnsl */ 33 extern char *_strdup_null(char *); 34 extern char *_strtok_escape(char *, char *, char **); 35 extern char *_strpbrk_escape(char *, char *); 36 extern char *_unescape(char *, char *); 37 38 char *_do_unescape(char *); 39 40 41 /* 42 * kva_match(): Given a key-value array and a key, return a pointer to the 43 * value that matches the key. 44 */ 45 char * 46 kva_match(kva_t *kva, char *key) 47 { 48 int i; 49 kv_t *data; 50 51 if (kva == NULL || key == NULL) { 52 return ((char *)NULL); 53 } 54 data = kva->data; 55 for (i = 0; i < kva->length; i++) { 56 if (strcmp(data[i].key, key) == 0) { 57 return (data[i].value); 58 } 59 } 60 61 return ((char *)NULL); 62 } 63 64 /* 65 * _kva_free(): Free up memory. 66 */ 67 void 68 _kva_free(kva_t *kva) 69 { 70 int i; 71 kv_t *data; 72 73 if (kva == NULL) { 74 return; 75 } 76 data = kva->data; 77 for (i = 0; i < kva->length; i++) { 78 if (data[i].key != NULL) { 79 free(data[i].key); 80 data[i].key = NULL; 81 } 82 if (data[i].value != NULL) { 83 free(data[i].value); 84 data[i].value = NULL; 85 } 86 } 87 free(kva->data); 88 free(kva); 89 } 90 91 /* 92 * new_kva(): Allocate a key-value array. 93 */ 94 kva_t * 95 _new_kva(int size) 96 { 97 kva_t *new_kva; 98 99 if ((new_kva = (kva_t *)calloc(1, sizeof (kva_t))) == NULL) { 100 return ((kva_t *)NULL); 101 } 102 if ((new_kva->data = (kv_t *)calloc(1, (size*sizeof (kv_t)))) == NULL) { 103 free(new_kva); 104 return ((kva_t *)NULL); 105 } 106 107 return (new_kva); 108 } 109 110 /* 111 * _str2kva(): Given a string (s) of key-value pairs, separated by delimeter 112 * (del), place the values into the key value array (nkva). 113 */ 114 kva_t * 115 _str2kva(char *s, char *ass, char *del) 116 { 117 int n = 0; 118 int m; 119 int size = KV_ADD_KEYS; 120 char *buf; 121 char *p; 122 char *pair; 123 char *key; 124 char *last_pair; 125 char *last_key; 126 kv_t *data; 127 kva_t *nkva; 128 129 if (s == NULL || 130 ass == NULL || 131 del == NULL || 132 *s == '\0' || 133 *s == '\n' || 134 (strlen(s) <= 1)) { 135 return ((kva_t *)NULL); 136 } 137 p = s; 138 while ((p = _strpbrk_escape(p, ass)) != NULL) { 139 n++; 140 p++; 141 } 142 if (n > size) { 143 m = n/size; 144 if (n%size) { 145 ++m; 146 } 147 size = m * KV_ADD_KEYS; 148 } 149 if ((nkva = _new_kva(size)) == NULL) { 150 return ((kva_t *)NULL); 151 } 152 data = nkva->data; 153 nkva->length = 0; 154 if ((buf = strdup(s)) == NULL) { 155 return ((kva_t *)NULL); 156 } 157 pair = _strtok_escape(buf, del, &last_pair); 158 do { 159 key = _strtok_escape(pair, ass, &last_key); 160 if (key != NULL) { 161 data[nkva->length].key = _do_unescape(key); 162 data[nkva->length].value = _do_unescape(last_key); 163 nkva->length++; 164 } 165 } while ((pair = _strtok_escape(NULL, del, &last_pair)) != NULL); 166 free(buf); 167 return (nkva); 168 } 169 170 /* 171 * _kva2str(): Given an array of key-value pairs, place them into a string 172 * (buf). Use delimeter (del) to separate pairs. Use assignment character 173 * (ass) to separate keys and values. 174 * 175 * Return Values: 0 Success 1 Buffer too small 2 Out of memory 176 */ 177 int 178 _kva2str(kva_t *kva, char *buf, int buflen, char *ass, char *del) 179 { 180 int i; 181 int length = 0; 182 char *tmp; 183 kv_t *data; 184 185 if (kva == NULL) { 186 return (0); 187 } 188 data = kva->data; 189 for (i = 0; i < kva->length; i++) { 190 if (data[i].value != NULL) { 191 length += 2 + strlen(data[i].value); 192 } 193 } 194 if (length > buflen) { 195 return (1); 196 } 197 (void) memset(buf, 0, buflen); 198 if ((tmp = (char *)malloc(buflen)) == NULL) { 199 return (2); 200 } 201 for (i = 0; i < kva->length; i++) { 202 if (data[i].value != NULL) { 203 if (snprintf(tmp, buflen, "%s%s%s%s", 204 data[i].key, ass, data[i].value, del) >= buflen) { 205 free((void *)tmp); 206 return (0); 207 } 208 (void) strcat(buf, tmp); 209 } 210 } 211 free((void *)tmp); 212 return (0); 213 } 214 215 int 216 _insert2kva(kva_t *kva, char *key, char *value) 217 { 218 int i; 219 kv_t *data; 220 221 if (kva == NULL) { 222 return (0); 223 } 224 data = kva->data; 225 for (i = 0; i < kva->length; i++) { 226 if (strcmp(data[i].key, key) == 0) { 227 if (data[i].value != NULL) 228 free(data[i].value); 229 data[i].value = _strdup_null(value); 230 return (0); 231 } 232 } 233 return (1); 234 } 235 236 kva_t * 237 _kva_dup(kva_t *old_kva) 238 { 239 int i; 240 int size; 241 kv_t *old_data; 242 kv_t *new_data; 243 kva_t *nkva = (kva_t *)NULL; 244 245 if (old_kva == NULL) { 246 return ((kva_t *)NULL); 247 } 248 old_data = old_kva->data; 249 size = old_kva->length; 250 if ((nkva = _new_kva(size)) == NULL) { 251 return ((kva_t *)NULL); 252 } 253 new_data = nkva->data; 254 nkva->length = old_kva->length; 255 for (i = 0; i < nkva->length; i++) { 256 new_data[i].key = _strdup_null(old_data[i].key); 257 new_data[i].value = _strdup_null(old_data[i].value); 258 } 259 260 return (nkva); 261 } 262 263 static void 264 strip_spaces(char **valuep) 265 { 266 char *p, *start; 267 268 /* Find first non-white space character and return pointer to it */ 269 for (p = *valuep; *p != '\0' && isspace((unsigned char)*p); p++) 270 ; 271 272 *valuep = start = p; 273 274 if (*p == '\0') 275 return; 276 277 p = p + strlen(p) - 1; 278 279 /* Remove trailing spaces */ 280 while (p > start && isspace((unsigned char)*p)) 281 p--; 282 283 p[1] = '\0'; 284 } 285 286 char * 287 _do_unescape(char *src) 288 { 289 char *tmp = NULL; 290 char *dst = NULL; 291 292 if (src == NULL) { 293 dst = _strdup_null(src); 294 } else { 295 strip_spaces(&src); 296 tmp = _unescape(src, "=;:,\\"); 297 dst = (tmp == NULL) ? _strdup_null(src) : tmp; 298 } 299 300 return (dst); 301 } 302 303 304 /* 305 * Some utilities for handling comma-separated lists. 306 */ 307 char * 308 _argv_to_csl(char **strings) 309 { 310 int len = 0; 311 int i = 0; 312 char *newstr = (char *)NULL; 313 314 if (strings == NULL) 315 return ((char *)NULL); 316 for (i = 0; strings[i] != NULL; i++) { 317 len += strlen(strings[i]) + 1; 318 } 319 if ((len > 0) && ((newstr = (char *)malloc(len + 1)) != NULL)) { 320 (void) memset(newstr, 0, len); 321 for (i = 0; strings[i] != NULL; i++) { 322 (void) strcat(newstr, strings[i]); 323 (void) strcat(newstr, ","); 324 } 325 newstr[len-1] = NULL; 326 return (newstr); 327 } else 328 return ((char *)NULL); 329 } 330 331 332 char ** 333 _csl_to_argv(char *csl) 334 { 335 int len = 0; 336 int ncommas = 0; 337 int i = 0; 338 char **spc = (char **)NULL; 339 char *copy = (char *)NULL; 340 char *pc; 341 char *lasts = (char *)NULL; 342 343 len = strlen(csl); 344 for (i = 0; i < len; i++) { 345 if (csl[i] == ',') 346 ncommas++; 347 } 348 if ((spc = (char **)malloc((ncommas + 2) * sizeof (char *))) == NULL) { 349 return ((char **)NULL); 350 } 351 copy = strdup(csl); 352 for (pc = strtok_r(copy, ",", &lasts), i = 0; pc != NULL; 353 pc = strtok_r(NULL, ",", &lasts), i++) { 354 spc[i] = strdup(pc); 355 } 356 spc[i] = NULL; 357 free(copy); 358 return (spc); 359 } 360 361 362 void 363 _free_argv(char **p_argv) 364 { 365 char **p_a; 366 367 for (p_a = p_argv; *p_a != NULL; p_a++) 368 free(*p_a); 369 free(p_argv); 370 } 371 372 373 #ifdef DEBUG 374 void 375 print_kva(kva_t *kva) 376 { 377 int i; 378 kv_t *data; 379 380 if (kva == NULL) { 381 printf(" (empty)\n"); 382 return; 383 } 384 data = kva->data; 385 for (i = 0; i < kva->length; i++) { 386 printf(" %s = %s\n", data[i].key, data[i].value); 387 } 388 } 389 #endif /* DEBUG */ 390