diff options
| -rw-r--r-- | src/util/profile/ChangeLog | 49 | ||||
| -rw-r--r-- | src/util/profile/Makefile.in | 3 | ||||
| -rw-r--r-- | src/util/profile/prof_err.et | 5 | ||||
| -rw-r--r-- | src/util/profile/prof_file.c | 12 | ||||
| -rw-r--r-- | src/util/profile/prof_get.c | 523 | ||||
| -rw-r--r-- | src/util/profile/prof_init.c | 381 | ||||
| -rw-r--r-- | src/util/profile/prof_int.h | 37 | ||||
| -rw-r--r-- | src/util/profile/prof_parse.c | 2 | ||||
| -rw-r--r-- | src/util/profile/prof_section.c | 170 | ||||
| -rw-r--r-- | src/util/profile/prof_tree.c | 90 | ||||
| -rw-r--r-- | src/util/profile/profile.hin | 10 | ||||
| -rw-r--r-- | src/util/profile/test_profile.c | 36 |
12 files changed, 710 insertions, 608 deletions
diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog index e9734a6f9..b01a98eba 100644 --- a/src/util/profile/ChangeLog +++ b/src/util/profile/ChangeLog @@ -1,3 +1,52 @@ +1998-11-03 Theodore Ts'o <tytso@rsts-11.mit.edu> + + * Makefile.in: Added prof_get.c to the list of files to be compiled. + + * profile.hin: Added declarations for profile_free_list(), + profile_get_relation_names(), and + profile_get_subsection_names(). (These are new public + interfaces to the profile library.) + + * prof_int.h: Removed the profile_section_t structure, which was + used only by the now-defunct prof_section.c file. Added + the internal interfaces for the new public interfaces. + Removed unused declarations which were never + implemented(profile_get, profile_update). + + * prof_init.c: Moved all of the profile querying functions + (profile_get_values(), profile_get_value(), etc.) to + prof_get.c. In the process, removed the really + bletcherous (and badly implemented) + profile_get_first_values(), which did nothing like what + the named implied. Also added to prof_get.c new functions + profile_get_subsection_names() and + profile_get_relation_names(). + (profile_ser_internalize): Rewrote error handling to be + clearer, and removed a bug where memory was not freed + correctly in an error case. + (profile_init): If a list of pathnames is passed in, + profile_init will now try to open all of them, now that + we've defined query fallback semantics in prof_get.c + + * prof_parse.c: Fix lint warning. + + * prof_tree.c (profile_find_node_relation, + profile_find_node_subsection): Allow the returned value or + subsection field to be NULL (in case the caller isn't + interested in getting the returned value or subsection, + and only cares about getting the name). + (profile_delete_node_relation, + profile_delete_interior_node_relation): Removed these + functions and replaced it with profile_remove_node(), + which takes a boolean argument section_flag. + (profile_find_node_name): Removed this function. (This + was a Cygnus/Fusion special used by the now removed + profile_find_first_values() function.) + + * test_profile.c: Added commands to test the new + profile_get_subsection_names() and + profile_get_relation_names() interfaces. + 1998-08-06 Theodore Ts'o <tytso@rsts-11.mit.edu> * prof_tree.c (profile_delete_node_relation): Fix bug where diff --git a/src/util/profile/Makefile.in b/src/util/profile/Makefile.in index 7f566d8c2..0889e343c 100644 --- a/src/util/profile/Makefile.in +++ b/src/util/profile/Makefile.in @@ -15,18 +15,21 @@ STLIBOBJS = \ prof_tree.o \ prof_file.o \ prof_parse.o \ + prof_get.o \ prof_err.o \ prof_init.o OBJS = prof_tree.$(OBJEXT) \ prof_file.$(OBJEXT) \ prof_parse.$(OBJEXT) \ + prof_get.$(OBJEXT) \ prof_err.$(OBJEXT) \ prof_init.$(OBJEXT) SRCS = $(srcdir)/prof_tree.c \ $(srcdir)/prof_file.c \ $(srcdir)/prof_parse.c \ + $(srcdir)/prof_get.c \ prof_err.c \ $(srcdir)/prof_init.c diff --git a/src/util/profile/prof_err.et b/src/util/profile/prof_err.et index 311570a7f..6e1dac68f 100644 --- a/src/util/profile/prof_err.et +++ b/src/util/profile/prof_err.et @@ -39,4 +39,9 @@ error_code PROF_END_OF_SECTIONS, "No more sections" error_code PROF_BAD_NAMESET, "Bad nameset passed to query routine" error_code PROF_NO_PROFILE, "No profile file open" +# +# generated by prof_file.c +# +error_code PROF_MAGIC_FILE, "Bad magic value in profile_file_t" + end diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c index b877e4e1e..d2b427e55 100644 --- a/src/util/profile/prof_file.c +++ b/src/util/profile/prof_file.c @@ -40,6 +40,7 @@ errcode_t profile_open_file(filename, ret_prof) return ENOMEM; } strcpy(prf->filename, filename); + prf->magic = PROF_MAGIC_FILE; retval = profile_update_file(prf); if (retval) { @@ -65,8 +66,14 @@ errcode_t profile_update_file(prf) return errno; if (st.st_mtime == prf->timestamp) return 0; - if (prf->root) + if (prf->root) { profile_free_node(prf->root); + prf->root = 0; + } + if (prf->comment) { + free(prf->comment); + prf->comment = 0; + } #else /* * If we don't have the stat() call, assume that our in-core @@ -96,6 +103,9 @@ errcode_t profile_close_file(prf) free(prf->filename); if (prf->root) profile_free_node(prf->root); + if (prf->comment) + free(prf->comment); + prf->magic = 0; free(prf); return 0; diff --git a/src/util/profile/prof_get.c b/src/util/profile/prof_get.c new file mode 100644 index 000000000..adb175afa --- /dev/null +++ b/src/util/profile/prof_get.c @@ -0,0 +1,523 @@ +/* + * prof_get.c --- routines that expose the public interfaces for + * querying items from the profile. + * + * A profile object can contain multiple profile files; each profile + * is composed of hierarchical sections. Sections can contain + * sections, or relations, both of which are named. (Sections roughly + * correspond to directories, and relations to files.) + * + * Relations may contain multiple values; profile_get_values() will + * return all of the values for a particular relation, + * profile_get_value() will return the first such value for a + * relation. + * + * When there are multiple profile files open for a particular + * profile object, the searching algorithms will find the first + * profile file which contains the full section-path, and only look in + * that profile file for the named relation. + * + * An example here may be useful. Consider a profile which is + * initialied to search to profile files, ~/.samplerc and + * /etc/sample.conf, in that order. Let us suppose that the + * system-wide /etc/sample.conf contains the following information: + * + * [realms] + * ATHENA.MIT.EDU = { + * kdc = kerberos.mit.edu:88 + * kdc = kerberos-1.mit.edu:88 + * kdc = kerberos-2.mit.edu:88 + * admin_server = kerberos.mit.edu:88 + * default_domain = mit.edu + * } + * + * [DNS] + * MIT.EDU = { + * strawb = { + * version = 4.8.3 + * location = E40 + * } + * bitsy = { + * version = 4.8.3 + * location = E40 + * } + * } + * + * ... and the user's ~/.samplerc contains the following: + * + * [realms] + * ATHENA.MIT.EDU = { + * kdc = kerberos-test.mit.edu + * admin_server = kerberos-test.mit.edu + * } + * + * [DNS] + * MIT.EDU = { + * w20-ns = { + * version = 4.8.3 + * location = W20 + * } + * bitsy = { + * version = 4.9.4 + * } + * } + * + * In this example, the values for realms/ATHENA.MIT.EDU/kdc and + * realms/ATHENA.MIT.EDU/admin_server will be taken from ~/.samplrc + * exclusively, since the section realms/ATHENA.MIT.EDU was found + * first in ~/.samplerc. + * + * However, in the case of the [DNS] section, queries for + * DNS/MIT.EDU/w20-ns/<*> will be taken from ~/.samplrc, and + * DNS/MIT.EDU/strawb/<*> will be taken from /etc/sample.rc. + * + * DNS/MIT.EDU/BITSY/version will return 4.9.4, since the entry + * in ~/.samplerc will override the one in /etc/sample.conf. Less + * intuitively, a query for DNS/bitsy/location will return no value, + * since the DNS/bitsy section exists in ~/.samplerc. + * + * This can all be summed up using the following rule: a section found + * in an earlier profile file completely shadows a section in a later + * profile file for the purposes of looking up relations, but not when + * looking up subsections contained in the section. + * + */ + +#include <stdio.h> +#include <string.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include <errno.h> + +#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); +} + +/* + * This function searches the profile for a named section, looking in + * each file in the profile. If ret_name is NULL, then this + * function looks at the entire names array; if ret_name is non-NULL, + * then the last entry in the names array is assumed to be the name of + * the relation desired by profile_get_values(), and is returned in + * ret_name. The section looked up in that case will not include the + * last entry in the names array. + */ +static errcode_t lookup_section(profile, names, ret_name, ret_section) + profile_t profile; + const char **names; + const char **ret_name; + struct profile_node **ret_section; +{ + prf_file_t file; + errcode_t retval; + int done_idx = 0; + const char **cpp; + void *state; + struct profile_node *section; + + if (profile == 0) + return PROF_NO_PROFILE; + + if (names == 0 || names[0] == 0 || (ret_name && names[1] == 0)) + return PROF_BAD_NAMESET; + + if (ret_name) + done_idx = 1; + + file = profile->first_file; + if ((retval = profile_update_file(file))) + return retval; + + section = file->root; + cpp = names; + + while (cpp[done_idx]) { + state = 0; + retval = profile_find_node_subsection(section, *cpp, + &state, 0, §ion); + if (retval == PROF_NO_SECTION) { + /* + * OK, we didn't find the section in this + * file; let's try the next file. + */ + file = file->next; + if (!file) + return retval; + if ((retval = profile_update_file(file))) + return retval; + section = file->root; + cpp = names; + continue; + } else if (retval) + return retval; + cpp++; + } + *ret_section = section; + if (ret_name) + *ret_name = *cpp; + return 0; +} + +/* + * This function finds a relation from the profile, and returns all of + * the values from that relation. + */ +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; + struct profile_node *section; + void *state; + const char *name; + char *value; + struct profile_string_list values; + + retval = lookup_section(profile, names, &name, §ion); + if (retval) + return retval; + + init_list(&values); + + state = 0; + do { + if ((retval = profile_find_node_relation(section, name, + &state, 0, &value))) + goto cleanup; + add_to_list(&values, value); + } while (state); + + 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. + */ +static errcode_t profile_get_value(profile, names, ret_value) + profile_t profile; + const char **names; + char **ret_value; +{ + errcode_t retval; + struct profile_node *section; + void *state; + const char *name; + char *value; + + retval = lookup_section(profile, names, &name, §ion); + if (retval) + return retval; + + state = 0; + if ((retval = profile_find_node_relation(section, name, + &state, 0, &value))) + return retval; + + *ret_value = value; + return 0; +} + +errcode_t 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; +} + +errcode_t 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; +{ + 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. + */ +errcode_t profile_get_subsection_names(profile, names, ret_names) + profile_t profile; + const char **names; + char ***ret_names; +{ + prf_file_t file; + errcode_t retval; + char *name; + const char **cpp; + void *state; + struct profile_node *section; + struct profile_string_list values; + + if (profile == 0) + return PROF_NO_PROFILE; + + if (names == 0) + return PROF_BAD_NAMESET; + + init_list(&values); + for (file = profile->first_file; file; file = file->next) { + if ((retval = profile_update_file(file))) + return retval; + section = file->root; + cpp = names; + /* + * Find the correct section in this file, if it + * exists. + */ + while (*cpp) { + state = 0; + retval = profile_find_node_subsection(section, *cpp, + &state, 0, §ion); + if (retval == PROF_NO_SECTION) + continue; + else if (retval) + goto cleanup; + cpp++; + } + /* + * Now find all of the subsections and append them to + * the list. + */ + state = 0; + do { + retval = profile_find_node_subsection(section, 0, + &state, &name, 0); + if (retval == PROF_NO_SECTION) + break; + else if (retval) + goto cleanup; + if (!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; +} + +/* + * This function will return the list of the names of relations in the + * under the specified section name. + */ +errcode_t profile_get_relation_names(profile, names, ret_names) + profile_t profile; + const char **names; + char ***ret_names; +{ + errcode_t retval; + struct profile_node *section; + void *state; + char *name; + struct profile_string_list values; + + retval = lookup_section(profile, names, 0, §ion); + if (retval) + return retval; + + init_list(&values); + + state = 0; + do { + retval = profile_find_node_relation(section, 0, + &state, &name, 0); + if (retval == PROF_NO_RELATION) + break; + else if (retval) + goto cleanup; + if (!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; +} + + + diff --git a/src/util/profile/prof_init.c b/src/util/profile/prof_init.c index f69fa0bb7..cbf2bc2ad 100644 --- a/src/util/profile/prof_init.c +++ b/src/util/profile/prof_init.c @@ -30,7 +30,7 @@ errcode_t profile_init(filenames, ret_profile) const char **fn; profile_t profile; prf_file_t new_file, last = 0; - errcode_t retval; + errcode_t retval = 0; initialize_prof_error_table(); @@ -55,9 +55,6 @@ errcode_t profile_init(filenames, ret_profile) else profile->first_file = new_file; last = new_file; - /* since we actually got something, don't loop again */ - /* (at least until we understand what multiple files mean) */ - break; } /* if the last file was missing, they all were, so report such */ if (retval == ENOENT) { @@ -131,274 +128,9 @@ void profile_release(profile) free(profile); } -struct string_list { - char **list; - int num; - int max; -}; - -static errcode_t init_list(list) - struct 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; -} - -static void free_list(list) - struct string_list *list; -{ - char **cp; - - for (cp = list->list; *cp; cp++) - free(*cp); - free(list->list); - list->num = list->max = 0; - list->list = 0; -} - -static errcode_t add_to_list(list, str) - struct string_list *list; - const char *str; -{ - char *newstr; - - if (list->num+1 >= list->max) { - list->max += 5; - list->list = realloc(list->list, list->max * sizeof(char *)); - if (list->list == 0) - return ENOMEM; - } - 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; -} - /* - * XXX this version only works to get values from the first file. - * To do more than that means we have to implement some "interesting" - * code to do the section searching. + * Here begins the profile serialization functions. */ -KRB5_DLLIMP errcode_t KRB5_CALLCONV -profile_get_values(profile, names, ret_values) - profile_t profile; - const char **names; - char ***ret_values; -{ - prf_file_t file; - errcode_t retval; - struct profile_node *section; - void *state; - char *value; - struct string_list values; - const char **cpp; - - if (profile == 0) - return PROF_NO_PROFILE; - - if (names == 0 || names[0] == 0 || names[1] == 0) - return PROF_BAD_NAMESET; - - init_list(&values); - - file = profile->first_file; - retval = profile_update_file(file); - if (retval) - goto cleanup; - - section = file->root; - - for (cpp = names; cpp[1]; cpp++) { - state = 0; - retval = profile_find_node_subsection(section, *cpp, - &state, 0, §ion); - if (retval) - goto cleanup; - } - - state = 0; - do { - retval = profile_find_node_relation(section, *cpp, &state, 0, &value); - if (retval) - goto cleanup; - add_to_list(&values, value); - } while (state); - - *ret_values = values.list; - return 0; -cleanup: - free_list(&values); - return retval; -} - -/* - * XXX this version only works to get values from the first file. - * To do more than that means we have to implement some "interesting" - * code to do the section searching. - */ -errcode_t profile_get_first_values(profile, names, ret_values) - profile_t profile; - const char **names; - char ***ret_values; -{ - prf_file_t file; - errcode_t retval; - struct profile_node *section; - void *state; - char *value; - struct string_list values; - char *secname; - - if (profile == 0) - return PROF_NO_PROFILE; - - if (names == 0 || names[0] == 0) - return PROF_BAD_NAMESET; - - init_list(&values); - - file = profile->first_file; - retval = profile_update_file(file); - if (retval) - goto cleanup; - - section = file->root; - - state = 0; - retval = profile_find_node_subsection(section, *names, &state, &secname, §ion); - - do { - retval = profile_find_node_name(section, &state, &value); - if (retval) - goto cleanup; - add_to_list(&values, value); - } while (state); - - *ret_values = values.list; - return 0; -cleanup: - free_list(&values); - return retval; -} - -/* - * XXX this version only works to get values from the first file. - */ -static errcode_t profile_get_value(profile, names, ret_value) - profile_t profile; - const char **names; - char **ret_value; -{ - prf_file_t file; - errcode_t retval; - struct profile_node *section; - void *state; - char *value; - const char **cpp; - - if (names == 0 || names[0] == 0 || names[1] == 0) - return PROF_BAD_NAMESET; - - file = profile->first_file; - retval = profile_update_file(file); - if (retval) - goto cleanup; - - section = file->root; - - for (cpp = names; cpp[1]; cpp++) { - state = 0; - retval = profile_find_node_subsection(section, *cpp, - &state, 0, §ion); - if (retval) - goto cleanup; - } - - state = 0; - retval = profile_find_node_relation(section, *cpp, &state, 0, &value); - if (retval) - goto cleanup; - - *ret_value = value; - return 0; -cleanup: - return retval; -} - -errcode_t 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; -} - -errcode_t 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; -{ - 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; -} - errcode_t profile_ser_size(unused, profile, sizep) const char *unused; profile_t profile; @@ -407,14 +139,6 @@ errcode_t profile_ser_size(unused, profile, sizep) size_t required; prf_file_t pfp; - /* - * ARGH - We want to avoid having to include k5-int.h. We ASSuME that - * krb5_int32 is 4 bytes in length. - * - * krb5_int32 for header - * krb5_int32 for number of files. - * krb5_int32 for trailer - */ required = 3*sizeof(prof_int32); for (pfp = profile->first_file; pfp; pfp = pfp->next) { required += sizeof(prof_int32); @@ -502,63 +226,70 @@ static int unpack_int32(intp, bufpp, remainp) } errcode_t profile_ser_internalize(unused, profilep, bufpp, remainp) - const char *unused; - profile_t *profilep; - unsigned char **bufpp; - size_t *remainp; + const char *unused; + profile_t *profilep; + unsigned char **bufpp; + size_t *remainp; { - errcode_t retval; - unsigned char *bp; - size_t remain; - int i; - prof_int32 fcount, tmp; - char **flist; - - bp = *bufpp; - remain = *remainp; - retval = EINVAL; - - if (remain >= 12) - (void) unpack_int32(&tmp, &bp, &remain); - else - tmp = 0; - if (tmp == PROF_MAGIC_PROFILE) { + errcode_t retval; + unsigned char *bp; + size_t remain; + int i; + prof_int32 fcount, tmp; + char **flist = 0; + + bp = *bufpp; + remain = *remainp; + + if (remain >= 12) + (void) unpack_int32(&tmp, &bp, &remain); + else + tmp = 0; + + if (tmp != PROF_MAGIC_PROFILE) { + retval = EINVAL; + goto cleanup; + } + (void) unpack_int32(&fcount, &bp, &remain); retval = ENOMEM; - if (!fcount || - (flist = (char **) malloc(sizeof(char *) * (fcount + 1)))) { - memset(flist, 0, sizeof(char *) * (fcount+1)); - for (i=0; i<fcount; i++) { + + flist = (char **) malloc(sizeof(char *) * (fcount + 1)); + if (!flist) + goto cleanup; + + memset(flist, 0, sizeof(char *) * (fcount+1)); + for (i=0; i<fcount; i++) { if (!unpack_int32(&tmp, &bp, &remain)) { - if ((flist[i] = (char *) malloc((size_t) (tmp+1)))) { + flist[i] = (char *) malloc((size_t) (tmp+1)); + if (!flist[i]) + goto cleanup; memcpy(flist[i], bp, (size_t) tmp); flist[i][tmp] = '\0'; bp += tmp; remain -= (size_t) tmp; - } - else - break; } - else - break; - } - if ((i == fcount) && - !unpack_int32(&tmp, &bp, &remain) && - (tmp == PROF_MAGIC_PROFILE)) - retval = profile_init((const char **)flist, profilep); + } - if (!retval) { - *bufpp = bp; - *remainp = remain; - } + if (unpack_int32(&tmp, &bp, &remain) || + (tmp != PROF_MAGIC_PROFILE)) { + retval = EINVAL; + goto cleanup; + } - for (i=0; i<fcount; i++) { - if (flist[i]) - free(flist[i]); - } - free(flist); + if ((retval = profile_init((const char **)flist, profilep))) + goto cleanup; + + *bufpp = bp; + *remainp = remain; + +cleanup: + if (flist) { + for (i=0; i<fcount; i++) { + if (flist[i]) + free(flist[i]); + } + free(flist); } - } - return(retval); + return(retval); } - diff --git a/src/util/profile/prof_int.h b/src/util/profile/prof_int.h index 2096bd66d..8a45ec423 100644 --- a/src/util/profile/prof_int.h +++ b/src/util/profile/prof_int.h @@ -60,27 +60,7 @@ struct _profile_t { typedef struct _profile_t *profile_t; -/* - * This structure defines the profile_section_t object, which is - * returned to the user when a section is searched. - */ -struct _profile_section_t { - prf_magic_t magic; - int top_lvl:1, top_lvl_search:1; - char *name; - void *state; - struct profile_node *parent, *sect; - profile_t profile; - prf_file_t file_ptr; -}; - -typedef struct _profile_section_t *profile_section_t; - -errcode_t profile_get - PROTOTYPE((const char *filename, prf_file_t *ret_prof)); - -errcode_t profile_update - PROTOTYPE((prf_file_t profile)); +/* profile_parse.c */ errcode_t profile_parse_file PROTOTYPE((FILE *f, struct profile_node **root)); @@ -145,9 +125,15 @@ errcode_t profile_init_path void profile_release PROTOTYPE ((profile_t profile)); +/* prof_get.c */ + +KRB5_DLLIMP void KRB5_CALLCONV profile_free_list + PROTOTYPE ((char **list)); KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_values - PROTOTYPE ((profile_t profile, const char **names, char ***ret_values)); + PROTOTYPE ((profile_t profile, const char **names, + char ***ret_values)); + errcode_t profile_get_string PROTOTYPE((profile_t profile, const char *name, const char *subname, const char *subsubname, const char *def_val, @@ -156,3 +142,10 @@ errcode_t profile_get_integer PROTOTYPE((profile_t profile, const char *name, const char *subname, const char *subsubname, int def_val, int *ret_default)); + +errcode_t profile_get_relation_names + PROTOTYPE((profile_t profile, const char **names, char ***ret_names)); + +errcode_t profile_get_subsection_names + PROTOTYPE((profile_t profile, const char **names, char ***ret_names)); + diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c index 5d92d9706..cc7e36b8f 100644 --- a/src/util/profile/prof_parse.c +++ b/src/util/profile/prof_parse.c @@ -267,7 +267,7 @@ static void output_quoted_string(str, f) fputc('"', f); return; } - while (ch = *str++) { + while ((ch = *str++)) { switch (ch) { case '\\': fputs("\\\\", f); diff --git a/src/util/profile/prof_section.c b/src/util/profile/prof_section.c deleted file mode 100644 index d147b7912..000000000 --- a/src/util/profile/prof_section.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * prof_section.c --- routines that manipulate the profile_section_t - * object - * - * XXX this file is still under construction. - */ - -#include <stdio.h> -#include <string.h> -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#include <errno.h> - -#include "prof_int.h" - -/* - * This routine frees a profile_section - */ -void profile_free_section(sect) - profile_section_t sect; -{ - if (sect->name) - free(sect->name); - sect->magic = 0; - free(sect); -} - -/* - * This routine creates a profile_section from its parent. If the - * parent is NULL, then a top-level profile section is created. - * - * Top-level profile sections are different from normal - * profile_sections in that top-level sections are agregated across - * multiple files, where as subsections are not. - */ -errcode_t profile_get_subsection(profile, parent, name, ret_name, - ret_section) - profile_t profile; - profile_section_t parent; - const char * name; - char ** ret_name; - profile_section_t *ret_section; -{ - profile_section_t section; - prf_file_t file; - errcode_t retval; - - section = malloc(sizeof(struct _profile_section_t)); - if (section == 0) - return ENOMEM; - memset(section, 0, sizeof(struct _profile_section_t)); - section->magic = PROF_MAGIC_SECTION; - section->name = malloc(strlen(name)+1); - if (section->name == 0) { - free(section); - return ENOMEM; - } - strcpy(section->name, name); - section->file_ptr = file = profile->first_file; - section->profile = profile; - - if (parent == 0) { - /* - * If parent is NULL, then we are creating a - * top-level section which hangs off the root. - * - * We make sure that the section exists in least one - * file. - */ - section->top_lvl = 1; - if (name == 0) - return PROF_TOPSECTION_ITER_NOSUPP; - while (file) { - retval = profile_find_node_subsection(file->root, - name, §ion->state, - ret_name, §ion->sect); - file = file->next; - if (retval == 0) - break; - if (retval == PROF_NO_SECTION) - continue; - profile_free_section(section); - return retval; - } - if (section->sect == 0 && file == 0) { - profile_free_section(section); - return PROF_NO_SECTION; - } - *ret_section = section; - return 0; - } - - - section->top_lvl = 0; - if (parent->top_lvl) { - section->top_lvl_search = 1; - - } else { - section->top_lvl_search = 0; - if (parent->sect == 0) { - profile_free_section(section); - return PROF_INVALID_SECTION; - } - section->parent = parent->sect; - retval = profile_find_node_subsection(parent->sect, - name, §ion->state, ret_name, §ion->sect); - if (retval) { - profile_free_section(section); - return retval; - } - } - *ret_section = section; - return 0; -} - -errcode_t profile_next_section(section, ret_name) - profile_section_t section; - char **ret_name; -{ - prf_file_t file; - errcode_t retval; - - if (section->top_lvl) - return PROF_END_OF_SECTIONS; - else { - if (section->sect == 0) - return PROF_INVALID_SECTION; - retval = profile_find_node_subsection(section->parent, - section->name, §ion->state, ret_name, §ion->sect); - if (retval == PROF_NO_SECTION) - retval = PROF_END_OF_SECTIONS; - return retval; - } -} - -errcode_t profile_get_relation(section, name, ret_values) - profile_section_t section; - const char *name; - char ***ret_values; -{ - prf_file_t file; - char **values; - int num_values; - int max_values; - char *value; - errcode_t retval; - - - max_values = 10; - values = malloc(sizeof(char *) * max_values); - - if (section->top_lvl) { - for (file = section->profile->first_file; file; - file = file->next) { - retval = profile_find_node_relation(file->root, - section->name, §ion->state, 0, &value); - if (retval) - continue; - - } - } else { - if (section->sect == 0) - return PROF_INVALID_SECTION; - } - return 0; -} - - - diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c index f4dc9751b..80d633ded 100644 --- a/src/util/profile/prof_tree.c +++ b/src/util/profile/prof_tree.c @@ -56,6 +56,7 @@ void profile_free_node(node) free(node->name); if (node->value) free(node->value); + for (child=node->first_child; child; child = next) { next = child->next; profile_free_node(child); @@ -204,7 +205,8 @@ errcode_t profile_find_node_relation(section, name, state, ret_name, value) while (p) { if (((name == 0) || (strcmp(p->name, name) == 0)) && p->value) { - *value = p->value; + if (value) + *value = p->value; if (ret_name) *ret_name = p->name; break; @@ -259,7 +261,8 @@ errcode_t profile_find_node_subsection(section, name, state, ret_name, while (p) { if (((name == 0) || (strcmp(p->name, name) == 0)) && (p->value == 0)) { - *subsection = p; + if (subsection) + *subsection = p; if (ret_name) *ret_name = p->name; break; @@ -287,12 +290,13 @@ errcode_t profile_find_node_subsection(section, name, state, ret_name, } /* - * This function deletes a relation from a section. Subsections are - * not deleted; if those need to be deleted, they must be done so manually. + * This function deletes a subsection or relation from a section, + * depending whether on the section flag is non-zero or not. */ -errcode_t profile_delete_node_relation(section, name) +errcode_t profile_remove_node(section, name, section_flag) struct profile_node *section; const char *name; + int section_flag; { struct profile_node *p, *next; @@ -303,11 +307,14 @@ errcode_t profile_delete_node_relation(section, name) if (p == 0) return PROF_NO_RELATION; /* - * Now we start deleting the relations... if we find a - * subsection with the same name, delete it and keep going. + * Now we start deleting the relations or subsection. */ while (p && (strcmp(p->name, name) == 0)) { - if (p->value == 0) { + /* + * Skip if it is not the correct type. + */ + if ((section_flag && p->value) || + (!section_flag && !p->value)) { p = p->next; continue; } @@ -325,42 +332,6 @@ errcode_t profile_delete_node_relation(section, name) } /* - * This function deletes a relation from a section. Subsections are - * not deleted; if those need to be deleted, they must be done so manually. - * And sections need not have a value to be delete, this is to enable - * deleting sections which are valueless headers for subsections. - */ -errcode_t profile_delete_interior_node_relation(section, name) - struct profile_node *section; - const char *name; -{ - struct profile_node *p, *next; - - for (p = section->first_child; p; p = p->next) { - if ((strcmp(p->name, name) == 0)) - break; - } - if (p == 0) - return PROF_NO_RELATION; - /* - * Now we start deleting the relations... if we find a - * subsection with the same name, delete it and keep going. - */ - while (p && (strcmp(p->name, name) == 0)) { - if (p->prev) - p->prev->next = p->next; - else - section->first_child = p->next; - next = p->next; - if (p->next) - p->next->prev = p; - profile_free_node(p); - p = next; - } - return 0; -} - -/* * This function returns the parent of a particular node. */ errcode_t profile_get_node_parent(section, parent) @@ -369,34 +340,3 @@ errcode_t profile_get_node_parent(section, parent) *parent = section->parent; return 0; } - - -/* - * Taking the state from another find function, give the name of the - * section and move to the next section. In this case, state can't be null - */ -errcode_t profile_find_node_name(section, state, ret_name) - struct profile_node *section; - void **state; - char **ret_name; -{ - struct profile_node *p; - - CHECK_MAGIC(section); - p = *state; - if (p) { - CHECK_MAGIC(p); - } else - p = section->first_child; - - if (p == 0) { - *state = 0; - return PROF_NO_SECTION; - } -/* give the name back */ - *ret_name = p->name; - p = p->next; - - *state = p; - return 0; -} diff --git a/src/util/profile/profile.hin b/src/util/profile/profile.hin index 6b9f16356..42dc7fa2a 100644 --- a/src/util/profile/profile.hin +++ b/src/util/profile/profile.hin @@ -40,6 +40,10 @@ void profile_release KRB5_DLLIMP long KRB5_CALLCONV profile_get_values PROTOTYPE ((profile_t profile, const char **names, char ***ret_values)); + +KRB5_DLLIMP void KRB5_CALLCONV profile_free_list + PROTOTYPE ((char **list)); + long profile_get_string PROTOTYPE((profile_t profile, const char *name, const char *subname, const char *subsubname, const char *def_val, @@ -49,4 +53,10 @@ long profile_get_integer const char *subsubname, int def_val, int *ret_default)); +long profile_get_relation_names + PROTOTYPE((profile_t profile, const char **names, char ***ret_names)); + +long profile_get_subsection_names + PROTOTYPE((profile_t profile, const char **names, char ***ret_names)); + #endif /* _KRB5_PROFILE_H */ diff --git a/src/util/profile/test_profile.c b/src/util/profile/test_profile.c index 171df93ec..19edbaf3f 100644 --- a/src/util/profile/test_profile.c +++ b/src/util/profile/test_profile.c @@ -20,36 +20,45 @@ void com_err (char *fmt, long err, char *msg) { } #endif +const char *program_name = "test_profile"; + int main(argc, argv) int argc; char **argv; { profile_t profile; long retval; - const char *filenames[2]; char **values, **cpp; const char **names; + char *cmd; - filenames[0] = argv[1]; - filenames[1] = 0; - - if (argc < 2) { - fprintf(stderr, "Usage: %s filename argset\n", argv[0]); + if (argc < 3) { + fprintf(stderr, "Usage: %s filename cmd argset\n", program_name); exit(1); } initialize_prof_error_table(); - retval = profile_init(filenames, &profile); + retval = profile_init_path(argv[1], &profile); if (retval) { - com_err(argv[0], retval, "while initializing profile"); + com_err(program_name, retval, "while initializing profile"); exit(1); } - names = (const char **) argv+2; - retval = profile_get_values(profile, names, &values); + cmd = *(argv+2); + names = (const char **) argv+3; + if (!strcmp(cmd, "query")) { + retval = profile_get_values(profile, names, &values); + } else if (!strcmp(cmd, "list_sections")) { + retval = profile_get_subsection_names(profile, names, &values); + } else if (!strcmp(cmd, "list_relations")) { + retval = profile_get_relation_names(profile, names, &values); + } else { + fprintf(stderr, "Invalid command.\n"); + exit(1); + } if (retval) { - com_err(argv[0], retval, "while getting values"); - exit(1); + com_err(argv[0], retval, "while getting values"); + exit(1); } for (cpp = values; *cpp; cpp++) { printf("%s\n", *cpp); @@ -58,8 +67,7 @@ int main(argc, argv) free(values); profile_release(profile); - return 0; - + return 0; } |
