/* * prof_get.c --- routines that expose the public interfaces for * querying items from the profile. * */ #include #include #ifdef HAVE_STDLIB_H #include #endif #include #include "prof_int.h" /* * These functions --- init_list(), end_list(), and add_to_list() are * internal functions used to build up a null-terminated char ** list * of strings to be returned by functions like profile_get_values. * * The profile_string_list structure is used for internal booking * purposes to build up the list, which is returned in *ret_list by * the end_list() function. * * The publicly exported interface for freeing char** list is * profile_free_list(). */ struct profile_string_list { char **list; int num; int max; }; /* * Initialize the string list abstraction. */ static errcode_t init_list(list) struct profile_string_list *list; { list->num = 0; list->max = 10; list->list = malloc(list->max * sizeof(char *)); if (list->list == 0) return ENOMEM; list->list[0] = 0; return 0; } /* * Free any memory left over in the string abstraction, returning the * built up list in *ret_list if it is non-null. */ static void end_list(list, ret_list) struct profile_string_list *list; char ***ret_list; { char **cp; if (list == 0) return; if (ret_list) { *ret_list = list->list; return; } else { for (cp = list->list; *cp; cp++) free(*cp); free(list->list); } list->num = list->max = 0; list->list = 0; } /* * Add a string to the list. */ static errcode_t add_to_list(list, str) struct profile_string_list *list; const char *str; { char *newstr, **newlist; int newmax; if (list->num+1 >= list->max) { newmax = list->max + 10; newlist = realloc(list->list, newmax * sizeof(char *)); if (newlist == 0) return ENOMEM; list->max = newmax; list->list = newlist; } newstr = malloc(strlen(str)+1); if (newstr == 0) return ENOMEM; strcpy(newstr, str); list->list[list->num++] = newstr; list->list[list->num] = 0; return 0; } /* * Return TRUE if the string is already a member of the list. */ static int is_list_member(list, str) struct profile_string_list *list; const char *str; { char **cpp; if (!list->list) return 0; for (cpp = list->list; *cpp; cpp++) { if (!strcmp(*cpp, str)) return 1; } return 0; } /* * This function frees a null-terminated list as returned by * profile_get_values. */ KRB5_DLLIMP void KRB5_CALLCONV profile_free_list(list) char **list; { char **cp; if (list == 0) return; for (cp = list; *cp; cp++) free(*cp); free(list); } KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_values(profile, names, ret_values) profile_t profile; const char **names; char ***ret_values; { errcode_t retval; void *state; char *value; struct profile_string_list values; if ((retval = profile_node_iterator_create(profile, names, PROFILE_ITER_RELATIONS_ONLY, &state))) return retval; if ((retval = init_list(&values))) return retval; do { if ((retval = profile_node_iterator(&state, 0, 0, &value))) goto cleanup; if (value) add_to_list(&values, value); } while (state); if (values.num == 0) { retval = PROF_NO_RELATION; goto cleanup; } end_list(&values, ret_values); return 0; cleanup: end_list(&values, 0); return retval; } /* * This function only gets the first value from the file; it is a * helper function for profile_get_string, profile_get_integer, etc. */ errcode_t profile_get_value(profile, names, ret_value) profile_t profile; const char **names; const char **ret_value; { errcode_t retval; void *state; char *value; if ((retval = profile_node_iterator_create(profile, names, PROFILE_ITER_RELATIONS_ONLY, &state))) return retval; if ((retval = profile_node_iterator(&state, 0, 0, &value))) goto cleanup; if (value) *ret_value = value; else retval = PROF_NO_RELATION; cleanup: profile_node_iterator_free(&state); return retval; } KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_string(profile, name, subname, subsubname, def_val, ret_string) profile_t profile; const char *name, *subname, *subsubname; const char *def_val; char **ret_string; { const char *value; errcode_t retval; const char *names[4]; if (profile) { names[0] = name; names[1] = subname; names[2] = subsubname; names[3] = 0; retval = profile_get_value(profile, names, &value); if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) value = def_val; else if (retval) return retval; } else value = def_val; if (value) { *ret_string = malloc(strlen(value)+1); if (*ret_string == 0) return ENOMEM; strcpy(*ret_string, value); } else *ret_string = 0; return 0; } KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_integer(profile, name, subname, subsubname, def_val, ret_int) profile_t profile; const char *name, *subname, *subsubname; int def_val; int *ret_int; { const char *value; errcode_t retval; const char *names[4]; if (profile == 0) { *ret_int = def_val; return 0; } names[0] = name; names[1] = subname; names[2] = subsubname; names[3] = 0; retval = profile_get_value(profile, names, &value); if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { *ret_int = def_val; return 0; } else if (retval) return retval; *ret_int = atoi(value); return 0; } /* * This function will return the list of the names of subections in the * under the specified section name. */ KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_subsection_names(profile, names, ret_names) profile_t profile; const char **names; char ***ret_names; { errcode_t retval; void *state; char *name; struct profile_string_list values; if ((retval = profile_node_iterator_create(profile, names, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &state))) return retval; if ((retval = init_list(&values))) return retval; do { if ((retval = profile_node_iterator(&state, 0, &name, 0))) goto cleanup; if (name) add_to_list(&values, name); } while (state); end_list(&values, ret_names); return 0; cleanup: end_list(&values, 0); return retval; } /* * This function will return the list of the names of relations in the * under the specified section name. */ KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_relation_names(profile, names, ret_names) profile_t profile; const char **names; char ***ret_names; { errcode_t retval; void *state; char *name; struct profile_string_list values; if ((retval = profile_node_iterator_create(profile, names, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_RELATIONS_ONLY, &state))) return retval; if ((retval = init_list(&values))) return retval; do { if ((retval = profile_node_iterator(&state, 0, &name, 0))) goto cleanup; if (name && !is_list_member(&values, name)) add_to_list(&values, name); } while (state); end_list(&values, ret_names); return 0; cleanup: end_list(&values, 0); return retval; } KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_iterator_create(profile, names, flags, ret_iter) profile_t profile; const char **names; int flags; void **ret_iter; { return profile_node_iterator_create(profile, names, flags, ret_iter); } KRB5_DLLIMP void KRB5_CALLCONV profile_iterator_free(iter_p) void **iter_p; { profile_node_iterator_free(iter_p); } KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_iterator(iter_p, ret_name, ret_value) void **iter_p; char **ret_name, **ret_value; { char *name, *value; errcode_t retval; retval = profile_node_iterator(iter_p, 0, &name, &value); if (retval) return retval; if (ret_name) { if (name) { *ret_name = malloc(strlen(name)+1); if (!*ret_name) return ENOMEM; strcpy(*ret_name, name); } else *ret_name = 0; } if (ret_value) { if (value) { *ret_value = malloc(strlen(value)+1); if (!*ret_value) { if (ret_name) { free(*ret_name); *ret_name = 0; } return ENOMEM; } strcpy(*ret_value, value); } else *ret_value = 0; } return 0; } KRB5_DLLIMP void KRB5_CALLCONV profile_release_string(str) char *str; { free(str); }