From c04da8d90f3548ea66b5968e9a13fcc4a3f7c01f Mon Sep 17 00:00:00 2001 From: Theodore Tso Date: Wed, 3 Mar 1999 01:26:15 +0000 Subject: [PATCH] prof_tree.c: Add new functions profile_get_node_name, profile_get_node_value, profile_find_node, profile_remove_node, profile_set_relation_value, profile_rename_node. Rewrite profile_find_node_relation and profile_find_node_subsection in terms of profile_find_node. prof_set.c, Makefile.in: Add a new file which exports the public interfaces for setting profile entries. prof_get.c, prof_init.c, prof_int.h: Add the KRB5_DLLIMP and KRB5_CALLCONV to all of the various profile routines so they can be properly exported via a Windows DLL. prof_int.h: Add definition for the flags in the profile structure. prof_err.et: Add new error codes PROF_SET_SECTION_VALUE, PROF_EINVAL, PROF_READ_ONLY, and PROF_EXISTS. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11236 dc483132-0cff-0310-8789-dd5450dbe970 --- src/util/profile/ChangeLog | 22 +++ src/util/profile/Makefile.in | 3 + src/util/profile/prof_err.et | 8 + src/util/profile/prof_get.c | 24 ++- src/util/profile/prof_init.c | 9 +- src/util/profile/prof_int.h | 71 ++++++-- src/util/profile/prof_set.c | 252 +++++++++++++++++++++++++++ src/util/profile/prof_tree.c | 327 ++++++++++++++++++++++++----------- src/util/profile/profile.hin | 38 ++-- 9 files changed, 620 insertions(+), 134 deletions(-) create mode 100644 src/util/profile/prof_set.c diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog index db27227cc..983ccb3c6 100644 --- a/src/util/profile/ChangeLog +++ b/src/util/profile/ChangeLog @@ -1,3 +1,25 @@ +Tue Mar 2 18:55:50 1999 Theodore Y. Ts'o + + * prof_tree.c: Add new functions profile_get_node_name, + profile_get_node_value, profile_find_node, + profile_remove_node, profile_set_relation_value, + profile_rename_node. Rewrite profile_find_node_relation + and profile_find_node_subsection in terms of + profile_find_node. + + * prof_set.c, Makefile.in: Add a new file which exports the public + interfaces for setting profile entries. + + * prof_get.c, prof_init.c, prof_int.h: Add the KRB5_DLLIMP and + KRB5_CALLCONV to all of the various profile routines so + they can be properly exported via a Windows DLL. + + * prof_int.h: Add definition for the flags in the profile + structure. + + * prof_err.et: Add new error codes PROF_SET_SECTION_VALUE, + PROF_EINVAL, PROF_READ_ONLY, and PROF_EXISTS. + Fri Feb 19 00:49:10 1999 Theodore Y. Ts'o * test_parse.c (main): Add a call to profile_verify_node so we can diff --git a/src/util/profile/Makefile.in b/src/util/profile/Makefile.in index b17ef17e6..86cd74eb5 100644 --- a/src/util/profile/Makefile.in +++ b/src/util/profile/Makefile.in @@ -18,6 +18,7 @@ STLIBOBJS = \ prof_file.o \ prof_parse.o \ prof_get.o \ + prof_set.o \ prof_err.o \ prof_init.o @@ -25,6 +26,7 @@ OBJS = prof_tree.$(OBJEXT) \ prof_file.$(OBJEXT) \ prof_parse.$(OBJEXT) \ prof_get.$(OBJEXT) \ + prof_set.$(OBJEXT) \ prof_err.$(OBJEXT) \ prof_init.$(OBJEXT) @@ -32,6 +34,7 @@ SRCS = $(srcdir)/prof_tree.c \ $(srcdir)/prof_file.c \ $(srcdir)/prof_parse.c \ $(srcdir)/prof_get.c \ + $(srcdir)/prof_set.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 e424042cb..410bdc6a5 100644 --- a/src/util/profile/prof_err.et +++ b/src/util/profile/prof_err.et @@ -17,6 +17,9 @@ error_code PROF_BAD_GROUP_LVL, "Bad group level in profile strctures" error_code PROF_BAD_PARENT_PTR, "Bad parent pointer in profile strctures" error_code PROF_MAGIC_ITERATOR, "Bad magic value in profile iterator" +error_code PROF_SET_SECTION_VALUE, "Can't set value on section node" +error_code PROF_EINVAL, "Invalid argument passed to profile library" +error_code PROF_READ_ONLY, "Attempt to modify read-only profile" # # generated by prof_parse.c @@ -45,4 +48,9 @@ error_code PROF_NO_PROFILE, "No profile file open" # error_code PROF_MAGIC_FILE, "Bad magic value in profile_file_t" +# +# generated by prof_set.c +# +error_code PROF_EXISTS, "Section already exists" + end diff --git a/src/util/profile/prof_get.c b/src/util/profile/prof_get.c index 094c6a8d3..2589b24e4 100644 --- a/src/util/profile/prof_get.c +++ b/src/util/profile/prof_get.c @@ -206,7 +206,8 @@ cleanup: return retval; } -errcode_t profile_get_string(profile, name, subname, subsubname, +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; @@ -240,7 +241,8 @@ errcode_t profile_get_string(profile, name, subname, subsubname, return 0; } -errcode_t profile_get_integer(profile, name, subname, subsubname, +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; @@ -275,7 +277,8 @@ errcode_t profile_get_integer(profile, name, subname, subsubname, * 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) +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_get_subsection_names(profile, names, ret_names) profile_t profile; const char **names; char ***ret_names; @@ -312,7 +315,8 @@ cleanup: * 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) +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_get_relation_names(profile, names, ret_names) profile_t profile; const char **names; char ***ret_names; @@ -345,7 +349,8 @@ cleanup: return retval; } -errcode_t profile_iterator_create(profile, names, flags, ret_iter) +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_iterator_create(profile, names, flags, ret_iter) profile_t profile; const char **names; int flags; @@ -354,13 +359,15 @@ errcode_t profile_iterator_create(profile, names, flags, ret_iter) return profile_node_iterator_create(profile, names, flags, ret_iter); } -void profile_iterator_free(iter_p) +KRB5_DLLIMP void KRB5_CALLCONV +profile_iterator_free(iter_p) void **iter_p; { profile_node_iterator_free(iter_p); } -errcode_t profile_iterator(iter_p, ret_name, ret_value) +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_iterator(iter_p, ret_name, ret_value) void **iter_p; char **ret_name, **ret_value; { @@ -397,7 +404,8 @@ errcode_t profile_iterator(iter_p, ret_name, ret_value) return 0; } -void profile_release_string(str) +KRB5_DLLIMP void KRB5_CALLCONV +profile_release_string(str) char *str; { free(str); diff --git a/src/util/profile/prof_init.c b/src/util/profile/prof_init.c index 238ee03e8..d88d5f3ac 100644 --- a/src/util/profile/prof_init.c +++ b/src/util/profile/prof_init.c @@ -23,7 +23,8 @@ typedef int prof_int32; error(do not have a 4-byte integer type) #endif /* SIZEOF_LONG == 4 */ -errcode_t profile_init(filenames, ret_profile) +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_init(filenames, ret_profile) const char **filenames; profile_t *ret_profile; { @@ -68,7 +69,8 @@ errcode_t profile_init(filenames, ret_profile) return 0; } -errcode_t profile_init_path(filepath, ret_profile) +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_init_path(filepath, ret_profile) const char *filepath; profile_t *ret_profile; { @@ -118,7 +120,8 @@ errcode_t profile_init_path(filepath, ret_profile) } -void profile_release(profile) +KRB5_DLLIMP void KRB5_CALLCONV +profile_release(profile) profile_t profile; { prf_file_t p, next; diff --git a/src/util/profile/prof_int.h b/src/util/profile/prof_int.h index 1a0304f4c..143bd53e8 100644 --- a/src/util/profile/prof_int.h +++ b/src/util/profile/prof_int.h @@ -49,6 +49,12 @@ struct _prf_file_t { typedef struct _prf_file_t *prf_file_t; +/* + * The profile flags + */ +#define PROFILE_FILE_RW 0x0001 +#define PROFILE_FILE_DIRTY 0x0002 + /* * This structure defines the high-level, user visible profile_t * object, which is used as a handle by users who need to query some @@ -97,7 +103,19 @@ errcode_t profile_make_node_final int profile_is_node_final PROTOTYPE((struct profile_node *node)); - + +const char *profile_get_node_name + PROTOTYPE((struct profile_node *node)); + +const char *profile_get_node_value + PROTOTYPE((struct profile_node *node)); + +errcode_t profile_find_node + PROTOTYPE ((struct profile_node *section, + const char *name, const char *value, + int section_flag, void **state, + struct profile_node **node)); + errcode_t profile_find_node_relation PROTOTYPE ((struct profile_node *section, const char *name, void **state, @@ -130,6 +148,15 @@ errcode_t profile_node_iterator PROTOTYPE((void **iter_p, struct profile_node **ret_node, char **ret_name, char **ret_value)); +errcode_t profile_remove_node + PROTOTYPE((struct profile_node *node)); + +errcode_t profile_set_relation_value + PROTOTYPE((struct profile_node *node, const char *new_value)); + +errcode_t profile_rename_node + PROTOTYPE((struct profile_node *node, const char *new_name)); + /* prof_file.c */ errcode_t profile_open_file @@ -143,13 +170,13 @@ errcode_t profile_close_file /* prof_init.c */ -errcode_t profile_init +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_init PROTOTYPE ((const char **filenames, profile_t *ret_profile)); -errcode_t profile_init_path +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_init_path PROTOTYPE ((const char *filepath, profile_t *ret_profile)); -void profile_release +KRB5_DLLIMP void KRB5_CALLCONV profile_release PROTOTYPE ((profile_t profile)); /* prof_get.c */ @@ -165,28 +192,48 @@ errcode_t profile_get_value PROTOTYPE ((profile_t profile, const char **names, const char **ret_value)); -errcode_t profile_get_string +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_string PROTOTYPE((profile_t profile, const char *name, const char *subname, const char *subsubname, const char *def_val, char **ret_string)); -errcode_t profile_get_integer +KRB5_DLLIMP errcode_t KRB5_CALLCONV 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 +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_relation_names PROTOTYPE((profile_t profile, const char **names, char ***ret_names)); -errcode_t profile_get_subsection_names +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_subsection_names PROTOTYPE((profile_t profile, const char **names, char ***ret_names)); -errcode_t profile_iterator_create +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_iterator_create PROTOTYPE((profile_t profile, const char **names, int flags, void **ret_iter)); -void profile_iterator_free PROTOTYPE((void **iter_p)); +KRB5_DLLIMP void KRB5_CALLCONV profile_iterator_free + PROTOTYPE((void **iter_p)); -errcode_t profile_iterator +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_iterator PROTOTYPE((void **iter_p, char **ret_name, char **ret_value)); -void profile_release_string PROTOTYPE((char *str)); +KRB5_DLLIMP void KRB5_CALLCONV profile_release_string PROTOTYPE((char *str)); + + +/* prof_set.c */ +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_update_relation + PROTOTYPE((profile_t profile, const char **names, + const char *old_value, const char *new_value)); + +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_clear_relation + PROTOTYPE((profile_t profile, const char **names)); + +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_rename_section + PROTOTYPE((profile_t profile, const char **names, + const char *new_name)); + +KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_add_relation + PROTOTYPE((profile_t profile, const char **names, + const char *new_value)); + + diff --git a/src/util/profile/prof_set.c b/src/util/profile/prof_set.c new file mode 100644 index 000000000..0c9bf8997 --- /dev/null +++ b/src/util/profile/prof_set.c @@ -0,0 +1,252 @@ +/* + * prof_set.c --- routines that expose the public interfaces for + * inserting, updating and deleting items from the profile. + * + * WARNING: These routines only look at the first file opened in the + * profile. It's not clear how to handle multiple files, actually. + * In the future it may be necessary to modify this public interface, + * or possibly add higher level functions to support this correctly. + * + * WARNING: We're not yet doing locking yet, either. + * + */ + +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +#include "prof_int.h" + +static errcode_t rw_setup(profile) + profile_t profile; +{ + prf_file_t file; + errcode_t retval; + + if (!profile) + return PROF_NO_PROFILE; + + if (profile->magic != PROF_MAGIC_PROFILE) + return PROF_MAGIC_PROFILE; + + file = profile->first_file; + if (!(file->flags & PROFILE_FILE_RW)) + return PROF_READ_ONLY; + + /* Don't update the file if we've already made modifications */ + if (file->flags & PROFILE_FILE_DIRTY) + return 0; + + retval = profile_update_file(file); + + return retval; +} + + +/* + * Delete or update a particular child node + * + * ADL - 2/23/99, rewritten TYT 2/25/99 + */ +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_update_relation(profile, names, old_value, new_value) + profile_t profile; + const char **names; + const char *old_value; + const char *new_value; +{ + errcode_t retval; + struct profile_node *section, *node; + void *state; + const char **cpp; + + retval = rw_setup(profile); + if (retval) + return retval; + + if (names == 0 || names[0] == 0 || names[1] == 0) + return PROF_BAD_NAMESET; + + if (!old_value || !*old_value) + return PROF_EINVAL; + + section = profile->first_file->root; + for (cpp = names; cpp[1]; cpp++) { + state = 0; + retval = profile_find_node(section, *cpp, 0, 1, + &state, §ion); + if (retval) + return retval; + } + + state = 0; + retval = profile_find_node(section, *cpp, old_value, 0, &state, &node); + if (retval) + return retval; + + if (new_value) + retval = profile_set_relation_value(node, new_value); + else + retval = profile_remove_node(node); + if (retval) + return retval; + + profile->first_file->flags |= PROFILE_FILE_DIRTY; + + return 0; +} + +/* + * Clear a particular all of the relations with a specific name. + * + * TYT - 2/25/99 + */ +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_clear_relation(profile, names) + profile_t profile; + const char **names; +{ + errcode_t retval; + struct profile_node *section, *node; + void *state; + const char **cpp; + + retval = rw_setup(profile); + if (retval) + return retval; + + if (names == 0 || names[0] == 0 || names[1] == 0) + return PROF_BAD_NAMESET; + + section = profile->first_file->root; + for (cpp = names; cpp[1]; cpp++) { + state = 0; + retval = profile_find_node(section, *cpp, 0, 1, + &state, §ion); + if (retval) + return retval; + } + + state = 0; + do { + retval = profile_find_node(section, *cpp, 0, 0, &state, &node); + if (retval) + return retval; + retval = profile_remove_node(node); + if (retval) + return retval; + } while (state); + + profile->first_file->flags |= PROFILE_FILE_DIRTY; + + return 0; +} + +/* + * Rename a particular section; if the new_section name is NULL, + * delete it. + * + * ADL - 2/23/99, rewritten TYT 2/25/99 + */ +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_rename_section(profile, names, new_name) + profile_t profile; + const char **names; + const char *new_name; +{ + errcode_t retval; + struct profile_node *section, *node; + void *state; + const char **cpp; + + retval = rw_setup(profile); + if (retval) + return retval; + + if (names == 0 || names[0] == 0 || names[1] == 0) + return PROF_BAD_NAMESET; + + section = profile->first_file->root; + for (cpp = names; cpp[1]; cpp++) { + state = 0; + retval = profile_find_node(section, *cpp, 0, 1, + &state, §ion); + if (retval) + return retval; + } + + state = 0; + retval = profile_find_node(section, *cpp, 0, 1, &state, &node); + if (retval) + return retval; + + if (new_name) + retval = profile_rename_node(node, new_name); + else + retval = profile_remove_node(node); + if (retval) + return retval; + + profile->first_file->flags |= PROFILE_FILE_DIRTY; + + return 0; +} + +/* + * Insert a new relation. If the new_value argument is NULL, then + * create a new section instead. + * + * Note: if the intermediate sections do not exist, this function will + * automatically create them. + * + * ADL - 2/23/99, rewritten TYT 2/25/99 + */ +KRB5_DLLIMP errcode_t KRB5_CALLCONV +profile_add_relation(profile, names, new_value) + profile_t profile; + const char **names; + const char *new_value; +{ + errcode_t retval; + struct profile_node *section; + const char **cpp; + void *state; + + retval = rw_setup(profile); + if (retval) + return retval; + + if (names == 0 || names[0] == 0 || names[1] == 0) + return PROF_BAD_NAMESET; + + section = profile->first_file->root; + for (cpp = names; cpp[1]; cpp++) { + state = 0; + retval = profile_find_node(section, *cpp, 0, 1, + &state, §ion); + if (retval == PROF_NO_SECTION) + retval = profile_add_node(section, *cpp, 0, §ion); + if (retval) + return retval; + } + + if (new_value == 0) { + retval = profile_find_node(section, *cpp, 0, 1, &state, 0); + if (retval == 0) + return PROF_EXISTS; + else if (retval != PROF_NO_SECTION) + return retval; + } + + retval = profile_add_node(section, *cpp, new_value, 0); + if (retval) + return retval; + + profile->first_file->flags |= PROFILE_FILE_DIRTY; + + return 0; +} + diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c index a95ce213b..5fde5e930 100644 --- a/src/util/profile/prof_tree.c +++ b/src/util/profile/prof_tree.c @@ -200,23 +200,48 @@ int profile_is_node_final(node) } /* - * Iterate through the section, returning the relations which match + * Return the name of a node. (Note: this is for internal functions + * only; if the name needs to be returned from an exported function, + * strdup it first!) + */ +const char *profile_get_node_name(node) + struct profile_node *node; +{ + return node->name; +} + +/* + * Return the value of a node. (Note: this is for internal functions + * only; if the name needs to be returned from an exported function, + * strdup it first!) + */ +const char *profile_get_node_value(node) + struct profile_node *node; +{ + return node->value; +} + +/* + * Iterate through the section, returning the nodes which match * the given name. If name is NULL, then interate through all the - * relations in the section. The first time this routine is called, - * the state pointer must be null. When this profile_find_node_relation() - * returns, if the state pointer is non-NULL, then this routine should - * be called again. + * nodes in the section. If section_flag is non-zero, only return the + * section which matches the name; don't return relations. If value + * is non-NULL, then only return relations which match the requested + * value. (The value argument is ignored if section_flag is non-zero.) + * + * The first time this routine is called, the state pointer must be + * null. When this profile_find_node_relation() returns, if the state + * pointer is non-NULL, then this routine should be called again. + * (This won't happen if section_flag is non-zero, obviously.) * - * The returned character string in value points to the stored - * character string in the parse string. Before this string value is - * returned to a calling application (profile_find_node_relation is not an - * exported interface), it should be strdup()'ed. */ -errcode_t profile_find_node_relation(section, name, state, ret_name, value) +errcode_t profile_find_node(section, name, value, section_flag, state, node) struct profile_node *section; const char *name; + const char *value; + int section_flag; void **state; - char **ret_name, **value; + struct profile_node **node; { struct profile_node *p; @@ -227,131 +252,119 @@ errcode_t profile_find_node_relation(section, name, state, ret_name, value) } else p = section->first_child; - while (p) { - if (((name == 0) || (strcmp(p->name, name) == 0)) && - p->value) { - if (value) - *value = p->value; - if (ret_name) - *ret_name = p->name; - break; + for (; p; p = p->next) { + if (name && (strcmp(p->name, name))) + continue; + if (section_flag) { + if (p->value) + continue; + } else { + if (!p->value) + continue; + if (value && (strcmp(p->value, value))) + continue; } - p = p->next; + /* A match! */ + if (node) + *node = p; + break; } if (p == 0) { *state = 0; - return PROF_NO_RELATION; + return section_flag ? PROF_NO_SECTION : PROF_NO_RELATION; } /* * OK, we've found one match; now let's try to find another * one. This way, if we return a non-zero state pointer, * there's guaranteed to be another match that's returned. */ - p = p->next; - while (p) { - if (((name == 0) || (strcmp(p->name, name) == 0)) && - p->value) - break; - p = p->next; + for (p = p->next; p; p = p->next) { + if (name && (strcmp(p->name, name))) + continue; + if (section_flag) { + if (p->value) + continue; + } else { + if (!p->value) + continue; + if (value && (strcmp(p->value, value))) + continue; + } + /* A match! */ + break; } *state = p; return 0; } + /* - * Iterate through the section, returning the subsections which match + * Iterate through the section, returning the relations which match * the given name. If name is NULL, then interate through all the - * subsections in the section. The first time this routine is called, - * the state pointer must be null. When this profile_find_node_subsection() + * relations in the section. The first time this routine is called, + * the state pointer must be null. When this profile_find_node_relation() * returns, if the state pointer is non-NULL, then this routine should * be called again. + * + * The returned character string in value points to the stored + * character string in the parse string. Before this string value is + * returned to a calling application (profile_find_node_relation is not an + * exported interface), it should be strdup()'ed. */ -errcode_t profile_find_node_subsection(section, name, state, ret_name, - subsection) +errcode_t profile_find_node_relation(section, name, state, ret_name, value) struct profile_node *section; const char *name; void **state; - char **ret_name; - struct profile_node **subsection; + char **ret_name, **value; { struct profile_node *p; + errcode_t retval; + + retval = profile_find_node(section, name, 0, 0, state, &p); + if (retval) + return retval; - CHECK_MAGIC(section); - p = *state; if (p) { - CHECK_MAGIC(p); - } else - p = section->first_child; - - while (p) { - if (((name == 0) || (strcmp(p->name, name) == 0)) && - (p->value == 0)) { - if (subsection) - *subsection = p; - if (ret_name) - *ret_name = p->name; - break; - } - p = p->next; - } - if (p == 0) { - *state = 0; - return PROF_NO_SECTION; - } - /* - * OK, we've found one match; now let's try to find another - * one. This way, if we return a non-zero state pointer, - * there's guaranteed to be another match that's returned. - */ - p = p->next; - while (p) { - if (((name == 0) || (strcmp(p->name, name) == 0)) - && (p->value == 0)) - break; - p = p->next; + if (value) + *value = p->value; + if (ret_name) + *ret_name = p->name; } - *state = p; return 0; } /* - * This function deletes a subsection or relation from a section, - * depending whether on the section flag is non-zero or not. + * Iterate through the section, returning the subsections which match + * the given name. If name is NULL, then interate through all the + * subsections in the section. The first time this routine is called, + * the state pointer must be null. When this profile_find_node_subsection() + * returns, if the state pointer is non-NULL, then this routine should + * be called again. + * + * This is (plus accessor functions for the name and value given a + * profile node) makes this function mostly syntactic sugar for + * profile_find_node. */ -errcode_t profile_remove_node(section, name, section_flag) +errcode_t profile_find_node_subsection(section, name, state, ret_name, + subsection) struct profile_node *section; const char *name; - int section_flag; + void **state; + char **ret_name; + struct profile_node **subsection; { - struct profile_node *p, *next; - - for (p = section->first_child; p; p = p->next) { - if ((strcmp(p->name, name) == 0) && p->value) - break; - } - if (p == 0) - return PROF_NO_RELATION; - /* - * Now we start deleting the relations or subsection. - */ - while (p && (strcmp(p->name, name) == 0)) { - /* - * Skip if it is not the correct type. - */ - if ((section_flag && p->value) || - (!section_flag && !p->value)) { - p = p->next; - continue; - } - if (p->prev) - p->prev->next = p->next; - else - section->first_child = p->next; - next = p->next; - if (p->next) - p->next->prev = p->prev; - profile_free_node(p); - p = next; + struct profile_node *p; + errcode_t retval; + + retval = profile_find_node(section, name, 0, 1, state, &p); + if (retval) + return retval; + + if (p) { + if (subsection) + *subsection = p; + if (ret_name) + *ret_name = p->name; } return 0; } @@ -541,3 +554,117 @@ get_new_file: *ret_value = p->value; return 0; }; + +/* + * Remove a particular node. + * + * TYT, 2/25/99 + */ +errcode_t profile_remove_node(node) + struct profile_node *node; +{ + CHECK_MAGIC(node); + + if (node->parent == 0) + return PROF_EINVAL; /* Can't remove the root! */ + + if (node->prev) + node->prev->next = node->next; + else + node->parent->first_child = node->next; + + if (node->next) + node->next->prev = node->prev; + + profile_free_node(node); + + return 0; +} + +/* + * Set the value of a specific node containing a relation. + * + * TYT, 2/25/99 + */ +errcode_t profile_set_relation_value(node, new_value) + struct profile_node *node; + const char *new_value; +{ + char *cp; + + CHECK_MAGIC(node); + + if (node->value) + return PROF_SET_SECTION_VALUE; + + cp = malloc(strlen(new_value)+1); + if (!cp) + return ENOMEM; + + strcpy(cp, new_value); + free(node->value); + node->value = cp; + + return 0; +} + +/* + * Rename a specific node + * + * TYT 2/25/99 + */ +errcode_t profile_rename_node(node, new_name) + struct profile_node *node; + const char *new_name; +{ + char *new_string; + struct profile_node *p, *last; + + CHECK_MAGIC(node); + + if (strcmp(new_name, node->name) == 0) + return 0; /* It's the same name, return */ + + /* + * Make sure we can allocate memory for the new name, first! + */ + new_string = malloc(strlen(new_name)+1); + if (!new_string) + return ENOMEM; + strcpy(new_string, new_name); + + /* + * Find the place to where the new node should go. We look + * for the place *after* the last match of the node name, + * since order matters. + */ + for (p=node->parent->first_child, last = 0; p; last = p, p = p->next) { + if (strcmp(p->name, new_name) > 0) + break; + } + + /* + * OK, let's detach the node + */ + if (node->prev) + node->prev->next = node->next; + else + node->parent->first_child = node->next; + + if (node->next) + node->next->prev = node->prev; + + /* + * Now let's reattach it in the right place. + */ + if (p) + p->prev = node; + if (last) + last->next = node; + else + node->parent->first_child = node; + + free(node->name); + node->name = new_string; + return 0; +} diff --git a/src/util/profile/profile.hin b/src/util/profile/profile.hin index dadf804a2..581de74ed 100644 --- a/src/util/profile/profile.hin +++ b/src/util/profile/profile.hin @@ -35,13 +35,13 @@ typedef struct _profile_t *profile_t; #define PROFILE_ITER_SECTIONS_ONLY 0x0002 #define PROFILE_ITER_RELATIONS_ONLY 0x0004 -long profile_init +KRB5_DLLIMP long KRB5_CALLCONV profile_init PROTOTYPE ((const char **filenames, profile_t *ret_profile)); -long profile_init_path +KRB5_DLLIMP long KRB5_CALLCONV profile_init_path PROTOTYPE ((const char *filepath, profile_t *ret_profile)); -void profile_release +KRB5_DLLIMP void KRB5_CALLCONV profile_release PROTOTYPE ((profile_t profile)); KRB5_DLLIMP long KRB5_CALLCONV profile_get_values @@ -50,30 +50,46 @@ KRB5_DLLIMP long KRB5_CALLCONV profile_get_values KRB5_DLLIMP void KRB5_CALLCONV profile_free_list PROTOTYPE ((char **list)); -long profile_get_string +KRB5_DLLIMP long KRB5_CALLCONV profile_get_string PROTOTYPE((profile_t profile, const char *name, const char *subname, const char *subsubname, const char *def_val, char **ret_string)); -long profile_get_integer +KRB5_DLLIMP long KRB5_CALLCONV profile_get_integer PROTOTYPE((profile_t profile, const char *name, const char *subname, const char *subsubname, int def_val, int *ret_default)); -long profile_get_relation_names +KRB5_DLLIMP long KRB5_CALLCONV profile_get_relation_names PROTOTYPE((profile_t profile, const char **names, char ***ret_names)); -long profile_get_subsection_names +KRB5_DLLIMP long KRB5_CALLCONV profile_get_subsection_names PROTOTYPE((profile_t profile, const char **names, char ***ret_names)); -long profile_iterator_create +KRB5_DLLIMP long KRB5_CALLCONV profile_iterator_create PROTOTYPE((profile_t profile, const char **names, int flags, void **ret_iter)); -void profile_iterator_free PROTOTYPE((void **iter_p)); +KRB5_DLLIMP void KRB5_CALLCONV profile_iterator_free + PROTOTYPE((void **iter_p)); -long profile_iterator +KRB5_DLLIMP long KRB5_CALLCONV profile_iterator PROTOTYPE((void **iter_p, char **ret_name, char **ret_value)); -void profile_release_string PROTOTYPE((char *str)); +KRB5_DLLIMP void KRB5_CALLCONV profile_release_string PROTOTYPE((char *str)); + +KRB5_DLLIMP long KRB5_CALLCONV profile_update_relation + PROTOTYPE((profile_t profile, const char **names, + const char *old_value, const char *new_value)); + +KRB5_DLLIMP long KRB5_CALLCONV profile_clear_relation + PROTOTYPE((profile_t profile, const char **names)); + +KRB5_DLLIMP long KRB5_CALLCONV profile_rename_section + PROTOTYPE((profile_t profile, const char **names, + const char *new_name)); + +KRB5_DLLIMP long KRB5_CALLCONV profile_add_relation + PROTOTYPE((profile_t profile, const char **names, + const char *new_value)); #endif /* _KRB5_PROFILE_H */ -- 2.26.2