1 #pragma ident "%Z%%M% %I% %E% SMI" 2 /* 3 * prof_get.c --- routines that expose the public interfaces for 4 * querying items from the profile. 5 * 6 */ 7 8 #include <stdio.h> 9 #include <string.h> 10 #ifdef HAVE_STDLIB_H 11 #include <stdlib.h> 12 #endif 13 #include <errno.h> 14 15 #include "prof_int.h" 16 17 /* 18 * These functions --- init_list(), end_list(), and add_to_list() are 19 * internal functions used to build up a null-terminated char ** list 20 * of strings to be returned by functions like profile_get_values. 21 * 22 * The profile_string_list structure is used for internal booking 23 * purposes to build up the list, which is returned in *ret_list by 24 * the end_list() function. 25 * 26 * The publicly exported interface for freeing char** list is 27 * profile_free_list(). 28 */ 29 30 struct profile_string_list { 31 char **list; 32 int num; 33 int max; 34 }; 35 36 /* 37 * Initialize the string list abstraction. 38 */ 39 static errcode_t init_list(list) 40 struct profile_string_list *list; 41 { 42 list->num = 0; 43 list->max = 10; 44 list->list = (char **) malloc(list->max * sizeof(char *)); 45 if (list->list == 0) 46 return ENOMEM; 47 list->list[0] = 0; 48 return 0; 49 } 50 51 /* 52 * Free any memory left over in the string abstraction, returning the 53 * built up list in *ret_list if it is non-null. 54 */ 55 static void end_list(list, ret_list) 56 struct profile_string_list *list; 57 char ***ret_list; 58 { 59 char **cp; 60 61 if (list == 0) 62 return; 63 64 if (ret_list) { 65 *ret_list = list->list; 66 return; 67 } else { 68 for (cp = list->list; *cp; cp++) 69 free(*cp); 70 free(list->list); 71 } 72 list->num = list->max = 0; 73 list->list = 0; 74 } 75 76 /* 77 * Add a string to the list. 78 */ 79 static errcode_t add_to_list(list, str) 80 struct profile_string_list *list; 81 const char *str; 82 { 83 char *newstr, **newlist; 84 int newmax; 85 86 if (list->num+1 >= list->max) { 87 newmax = list->max + 10; 88 newlist = (char **)realloc(list->list, newmax * sizeof(char *)); 89 if (newlist == 0) 90 return ENOMEM; 91 list->max = newmax; 92 list->list = newlist; 93 } 94 newstr = (char *) malloc(strlen(str)+1); 95 if (newstr == 0) 96 return ENOMEM; 97 strcpy(newstr, str); 98 99 list->list[list->num++] = newstr; 100 list->list[list->num] = 0; 101 return 0; 102 } 103 104 /* 105 * Return TRUE if the string is already a member of the list. 106 */ 107 static int is_list_member(list, str) 108 struct profile_string_list *list; 109 const char *str; 110 { 111 char **cpp; 112 113 if (!list->list) 114 return 0; 115 116 for (cpp = list->list; *cpp; cpp++) { 117 if (!strcmp(*cpp, str)) 118 return 1; 119 } 120 return 0; 121 } 122 123 /* 124 * This function frees a null-terminated list as returned by 125 * profile_get_values. 126 */ 127 KRB5_DLLIMP void KRB5_CALLCONV profile_free_list(list) 128 char **list; 129 { 130 char **cp; 131 132 if (list == 0) 133 return; 134 135 for (cp = list; *cp; cp++) 136 free(*cp); 137 free(list); 138 } 139 140 KRB5_DLLIMP errcode_t KRB5_CALLCONV 141 profile_get_values(profile, names, ret_values) 142 profile_t profile; 143 const char **names; 144 char ***ret_values; 145 { 146 errcode_t retval; 147 void *state; 148 char *value; 149 struct profile_string_list values; 150 151 if ((retval = profile_node_iterator_create(profile, names, 152 PROFILE_ITER_RELATIONS_ONLY, 153 &state))) 154 return retval; 155 156 if ((retval = init_list(&values))) 157 return retval; 158 159 do { 160 if ((retval = profile_node_iterator(&state, 0, 0, &value))) 161 goto cleanup; 162 if (value) 163 add_to_list(&values, value); 164 } while (state); 165 166 if (values.num == 0) { 167 retval = PROF_NO_RELATION; 168 goto cleanup; 169 } 170 171 end_list(&values, ret_values); 172 return 0; 173 174 cleanup: 175 end_list(&values, (char ***)NULL); 176 return retval; 177 } 178 179 /* 180 * This function only gets the first value from the file; it is a 181 * helper function for profile_get_string, profile_get_integer, etc. 182 */ 183 errcode_t profile_get_value(profile, names, ret_value) 184 profile_t profile; 185 const char **names; 186 const char **ret_value; 187 { 188 errcode_t retval; 189 void *state; 190 char *value; 191 192 if ((retval = profile_node_iterator_create(profile, names, 193 PROFILE_ITER_RELATIONS_ONLY, 194 &state))) 195 return retval; 196 197 if ((retval = profile_node_iterator(&state, 0, 0, &value))) 198 goto cleanup; 199 200 if (value) 201 *ret_value = value; 202 else 203 retval = PROF_NO_RELATION; 204 205 cleanup: 206 profile_node_iterator_free(&state); 207 return retval; 208 } 209 210 KRB5_DLLIMP errcode_t KRB5_CALLCONV 211 profile_get_string(profile, name, subname, subsubname, 212 def_val, ret_string) 213 profile_t profile; 214 const char *name, *subname, *subsubname; 215 const char *def_val; 216 char **ret_string; 217 { 218 const char *value; 219 errcode_t retval; 220 const char *names[4]; 221 222 if (profile) { 223 names[0] = name; 224 names[1] = subname; 225 names[2] = subsubname; 226 names[3] = 0; 227 retval = profile_get_value(profile, names, &value); 228 if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) 229 value = def_val; 230 else if (retval) 231 return retval; 232 } else 233 value = def_val; 234 235 if (value) { 236 *ret_string = (char *) malloc(strlen(value)+1); 237 if (*ret_string == 0) 238 return ENOMEM; 239 strcpy(*ret_string, value); 240 } else 241 *ret_string = 0; 242 return 0; 243 } 244 245 KRB5_DLLIMP errcode_t KRB5_CALLCONV 246 profile_get_integer(profile, name, subname, subsubname, 247 def_val, ret_int) 248 profile_t profile; 249 const char *name, *subname, *subsubname; 250 int def_val; 251 int *ret_int; 252 { 253 const char *value; 254 errcode_t retval; 255 const char *names[4]; 256 257 if (profile == 0) { 258 *ret_int = def_val; 259 return 0; 260 } 261 262 names[0] = name; 263 names[1] = subname; 264 names[2] = subsubname; 265 names[3] = 0; 266 retval = profile_get_value(profile, names, &value); 267 if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { 268 *ret_int = def_val; 269 return 0; 270 } else if (retval) 271 return retval; 272 273 *ret_int = atoi(value); 274 return 0; 275 } 276 277 /* 278 * This function will return the list of the names of subections in the 279 * under the specified section name. 280 */ 281 KRB5_DLLIMP errcode_t KRB5_CALLCONV 282 profile_get_subsection_names(profile, names, ret_names) 283 profile_t profile; 284 const char **names; 285 char ***ret_names; 286 { 287 errcode_t retval; 288 void *state; 289 char *name; 290 struct profile_string_list values; 291 292 if ((retval = profile_node_iterator_create(profile, names, 293 PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, 294 &state))) 295 return retval; 296 297 if ((retval = init_list(&values))) 298 return retval; 299 300 do { 301 if ((retval = profile_node_iterator(&state, 0, &name, 0))) 302 goto cleanup; 303 if (name) 304 add_to_list(&values, name); 305 } while (state); 306 307 end_list(&values, ret_names); 308 return 0; 309 310 cleanup: 311 end_list(&values, (char ***)NULL); 312 return retval; 313 } 314 315 /* 316 * This function will return the list of the names of relations in the 317 * under the specified section name. 318 */ 319 KRB5_DLLIMP errcode_t KRB5_CALLCONV 320 profile_get_relation_names(profile, names, ret_names) 321 profile_t profile; 322 const char **names; 323 char ***ret_names; 324 { 325 errcode_t retval; 326 void *state; 327 char *name; 328 struct profile_string_list values; 329 330 if ((retval = profile_node_iterator_create(profile, names, 331 PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY, 332 &state))) 333 return retval; 334 335 if ((retval = init_list(&values))) 336 return retval; 337 338 do { 339 if ((retval = profile_node_iterator(&state, 0, &name, 0))) 340 goto cleanup; 341 if (name && !is_list_member(&values, name)) 342 add_to_list(&values, name); 343 } while (state); 344 345 end_list(&values, ret_names); 346 return 0; 347 348 cleanup: 349 end_list(&values, (char ***)NULL); 350 return retval; 351 } 352 353 KRB5_DLLIMP errcode_t KRB5_CALLCONV 354 profile_iterator_create(profile, names, flags, ret_iter) 355 profile_t profile; 356 const char **names; 357 int flags; 358 void **ret_iter; 359 { 360 return profile_node_iterator_create(profile, names, flags, ret_iter); 361 } 362 363 KRB5_DLLIMP void KRB5_CALLCONV 364 profile_iterator_free(iter_p) 365 void **iter_p; 366 { 367 profile_node_iterator_free(iter_p); 368 } 369 370 KRB5_DLLIMP errcode_t KRB5_CALLCONV 371 profile_iterator(iter_p, ret_name, ret_value) 372 void **iter_p; 373 char **ret_name, **ret_value; 374 { 375 char *name, *value; 376 errcode_t retval; 377 378 retval = profile_node_iterator(iter_p, 0, &name, &value); 379 if (retval) 380 return retval; 381 382 if (ret_name) { 383 if (name) { 384 *ret_name = (char *) malloc(strlen(name)+1); 385 if (!*ret_name) 386 return ENOMEM; 387 strcpy(*ret_name, name); 388 } else 389 *ret_name = 0; 390 } 391 if (ret_value) { 392 if (value) { 393 *ret_value = (char *) malloc(strlen(value)+1); 394 if (!*ret_value) { 395 if (ret_name) { 396 free(*ret_name); 397 *ret_name = 0; 398 } 399 return ENOMEM; 400 } 401 strcpy(*ret_value, value); 402 } else 403 *ret_value = 0; 404 } 405 return 0; 406 } 407 408 KRB5_DLLIMP void KRB5_CALLCONV 409 profile_release_string(str) 410 char *str; 411 { 412 free(str); 413 } 414