prof_tree.c: Add new functions profile_get_node_name,
authorTheodore Tso <tytso@mit.edu>
Wed, 3 Mar 1999 01:26:15 +0000 (01:26 +0000)
committerTheodore Tso <tytso@mit.edu>
Wed, 3 Mar 1999 01:26:15 +0000 (01:26 +0000)
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
src/util/profile/Makefile.in
src/util/profile/prof_err.et
src/util/profile/prof_get.c
src/util/profile/prof_init.c
src/util/profile/prof_int.h
src/util/profile/prof_set.c [new file with mode: 0644]
src/util/profile/prof_tree.c
src/util/profile/profile.hin

index db27227ccc31448630a63751ee676bc41e393b50..983ccb3c64aed5d66156378527d9b8fc7119b3d7 100644 (file)
@@ -1,3 +1,25 @@
+Tue Mar  2 18:55:50 1999  Theodore Y. Ts'o  <tytso@mit.edu>
+
+       * 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  <tytso@mit.edu>
 
        * test_parse.c (main): Add a call to profile_verify_node so we can
index b17ef17e6ca44d6c7e0cc7d633b9bad095d453e3..86cd74eb59ef8be283185c87753539d85d7f5f94 100644 (file)
@@ -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
 
index e424042cb350770f47e5c3e957f4ce42905be091..410bdc6a54febe019852634e4820abc35db9506e 100644 (file)
@@ -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
index 094c6a8d3cafdf561874f39caa38f20477031b25..2589b24e4b8efe5e504f32666cd3bca581a246df 100644 (file)
@@ -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);
index 238ee03e8533ce4c6aeb6b4549241bb59d32433d..d88d5f3ac349925d7683fa1d7a1d940e437e4cc8 100644 (file)
@@ -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;
index 1a0304f4c8e96dbcfadb21f31ee09e3a9df8d57c..143bd53e82cab30ff37db0d828b5230a982e479e 100644 (file)
@@ -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 (file)
index 0000000..0c9bf89
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <errno.h>
+
+#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, &section);
+               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, &section);
+               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, &section);
+               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, &section);
+               if (retval == PROF_NO_SECTION)
+                       retval = profile_add_node(section, *cpp, 0, &section);
+               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;
+}
+
index a95ce213b5c2ee9cf9e638e0cf7fba6b46cb9068..5fde5e9300f27e02aacea7b36b708e341e40de05 100644 (file)
@@ -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;
+}
index dadf804a27b6cf0d86f092bf86d2ae46bcdf8e1a..581de74ed888f78aef1cff536df060b430a5c731 100644 (file)
@@ -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 */