From: Theodore Tso Date: Tue, 3 Nov 1998 22:49:25 +0000 (+0000) Subject: Makefile.in: Added prof_get.c to the list of files to be compiled X-Git-Tag: krb5-1.1-beta1~505 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=a77feae4293dbdba211ca39a275da85e7c3b655f;p=krb5.git 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. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11011 dc483132-0cff-0310-8789-dd5450dbe970 --- 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 + + * 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 * 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 +#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); +} + +/* + * 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 -#include -#ifdef HAVE_STDLIB_H -#include -#endif -#include - -#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; } @@ -324,42 +331,6 @@ errcode_t profile_delete_node_relation(section, name) return 0; } -/* - * 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. */ @@ -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; }