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