Makefile.in: Added prof_get.c to the list of files to be compiled
authorTheodore Tso <tytso@mit.edu>
Tue, 3 Nov 1998 22:49:25 +0000 (22:49 +0000)
committerTheodore Tso <tytso@mit.edu>
Tue, 3 Nov 1998 22:49:25 +0000 (22:49 +0000)
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

12 files changed:
src/util/profile/ChangeLog
src/util/profile/Makefile.in
src/util/profile/prof_err.et
src/util/profile/prof_file.c
src/util/profile/prof_get.c [new file with mode: 0644]
src/util/profile/prof_init.c
src/util/profile/prof_int.h
src/util/profile/prof_parse.c
src/util/profile/prof_section.c [deleted file]
src/util/profile/prof_tree.c
src/util/profile/profile.hin
src/util/profile/test_profile.c

index e9734a6f950e609d9baff5cb0e041af7ede546b5..b01a98eba0acdc61b092744837cac0acd7a3dbc0 100644 (file)
@@ -1,3 +1,52 @@
+1998-11-03  Theodore Ts'o  <tytso@rsts-11.mit.edu>
+
+       * Makefile.in: Added prof_get.c to the list of files to be compiled.
+       
+       * profile.hin: Added declarations for profile_free_list(),
+               profile_get_relation_names(), and
+               profile_get_subsection_names().  (These are new public
+               interfaces to the profile library.)
+
+       * prof_int.h: Removed the profile_section_t structure, which was
+               used only by the now-defunct prof_section.c file.  Added
+               the internal interfaces for the new public interfaces.
+               Removed unused declarations which were never
+               implemented(profile_get, profile_update).
+
+       * prof_init.c: Moved all of the profile querying functions
+               (profile_get_values(), profile_get_value(), etc.) to
+               prof_get.c.  In the process, removed the really
+               bletcherous (and badly implemented)
+               profile_get_first_values(), which did nothing like what
+               the named implied.  Also added to prof_get.c new functions
+               profile_get_subsection_names() and
+               profile_get_relation_names(). 
+               (profile_ser_internalize): Rewrote error handling to be
+               clearer, and removed a bug where memory was not freed
+               correctly in an error case.  
+               (profile_init): If a list of pathnames is passed in,
+               profile_init will now try to open all of them, now that
+               we've defined query fallback semantics in prof_get.c
+
+       * prof_parse.c: Fix lint warning.
+
+       * prof_tree.c (profile_find_node_relation,
+               profile_find_node_subsection): Allow the returned value or
+               subsection field to be NULL (in case the caller isn't
+               interested in getting the returned value or subsection,
+               and only cares about getting the name).
+               (profile_delete_node_relation,
+               profile_delete_interior_node_relation): Removed these
+               functions and replaced it with profile_remove_node(),
+               which takes a boolean argument section_flag. 
+               (profile_find_node_name): Removed this function.  (This
+               was a Cygnus/Fusion special used by the now removed
+               profile_find_first_values() function.)
+
+       * test_profile.c: Added commands to test the new
+               profile_get_subsection_names() and
+               profile_get_relation_names() interfaces.
+
 1998-08-06  Theodore Ts'o  <tytso@rsts-11.mit.edu>
 
        * prof_tree.c (profile_delete_node_relation): Fix bug where
index 7f566d8c209ae8bf134c5d497ffb797dd7430968..0889e343c5c1b87a270d3fad14f970a33c780706 100644 (file)
@@ -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
 
index 311570a7f9f8199092e49df869098e618c73341a..6e1dac68f4f5e97a78e797c3df6e662b0580ca49 100644 (file)
@@ -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
index b877e4e1e299879d8d98edb9438814971d050696..d2b427e559ddd36d7311e559146d6740483eb1f5 100644 (file)
@@ -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 (file)
index 0000000..adb175a
--- /dev/null
@@ -0,0 +1,523 @@
+/*
+ * prof_get.c --- routines that expose the public interfaces for
+ *     querying items from the profile.
+ *
+ * A profile object can contain multiple profile files; each profile
+ * is composed of hierarchical sections.  Sections can contain
+ * sections, or relations, both of which are named.  (Sections roughly
+ * correspond to directories, and relations to files.)
+ * 
+ * Relations may contain multiple values; profile_get_values() will
+ * return all of the values for a particular relation,
+ * profile_get_value() will return the first such value for a
+ * relation.
+ *
+ * When there are multiple profile files open for a particular
+ * profile object, the searching algorithms will find the first
+ * profile file which contains the full section-path, and only look in
+ * that profile file for the named relation.
+ *
+ * An example here may be useful.  Consider a profile which is
+ * initialied to search to profile files, ~/.samplerc and
+ * /etc/sample.conf, in that order.  Let us suppose that the
+ * system-wide /etc/sample.conf contains the following information:
+ *
+ * [realms]
+ *     ATHENA.MIT.EDU = {
+ *             kdc = kerberos.mit.edu:88
+ *             kdc = kerberos-1.mit.edu:88
+ *             kdc = kerberos-2.mit.edu:88
+ *             admin_server = kerberos.mit.edu:88
+ *             default_domain = mit.edu
+ *     }
+ *
+ * [DNS]
+ *     MIT.EDU = {
+ *             strawb = {
+ *                     version = 4.8.3
+ *                     location = E40
+ *             }
+ *             bitsy = {
+ *                     version = 4.8.3
+ *                     location = E40
+ *             }
+ *     }
+ *
+ * ... and the user's ~/.samplerc contains the following:
+ *
+ * [realms]
+ *     ATHENA.MIT.EDU = {
+ *             kdc = kerberos-test.mit.edu
+ *             admin_server = kerberos-test.mit.edu
+ *     }
+ *
+ * [DNS]
+ *     MIT.EDU = {
+ *             w20-ns = {
+ *                     version = 4.8.3
+ *                     location = W20
+ *             }
+ *             bitsy = {
+ *                     version = 4.9.4
+ *             }
+ *     }
+ * 
+ * In this example, the values for realms/ATHENA.MIT.EDU/kdc and
+ * realms/ATHENA.MIT.EDU/admin_server will be taken from ~/.samplrc
+ * exclusively, since the section realms/ATHENA.MIT.EDU was found
+ * first in ~/.samplerc.
+ * 
+ * However, in the case of the [DNS] section, queries for
+ * DNS/MIT.EDU/w20-ns/<*> will be taken from ~/.samplrc, and
+ * DNS/MIT.EDU/strawb/<*> will be taken from /etc/sample.rc.
+ * 
+ * DNS/MIT.EDU/BITSY/version will return 4.9.4, since the entry
+ * in ~/.samplerc will override the one in /etc/sample.conf.  Less
+ * intuitively, a query for DNS/bitsy/location will return no value,
+ * since the DNS/bitsy section exists in ~/.samplerc.
+ * 
+ * This can all be summed up using the following rule: a section found
+ * in an earlier profile file completely shadows a section in a later
+ * profile file for the purposes of looking up relations, but not when
+ * looking up subsections contained in the section.
+ * 
+ */
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <errno.h>
+
+#include "prof_int.h"
+
+/*
+ * These functions --- init_list(), end_list(), and add_to_list() are
+ * internal functions used to build up a null-terminated char ** list
+ * of strings to be returned by functions like profile_get_values.
+ *
+ * The profile_string_list structure is used for internal booking
+ * purposes to build up the list, which is returned in *ret_list by
+ * the end_list() function.
+ *
+ * The publicly exported interface for freeing char** list is
+ * profile_free_list().
+ */
+
+struct profile_string_list {
+       char    **list;
+       int     num;
+       int     max;
+};
+
+/*
+ * Initialize the string list abstraction.
+ */
+static errcode_t init_list(list)
+       struct profile_string_list *list;
+{
+       list->num = 0;
+       list->max = 10;
+       list->list = malloc(list->max * sizeof(char *));
+       if (list->list == 0)
+               return ENOMEM;
+       list->list[0] = 0;
+       return 0;
+}
+
+/*
+ * Free any memory left over in the string abstraction, returning the
+ * built up list in *ret_list if it is non-null.
+ */
+static void end_list(list, ret_list)
+    struct profile_string_list *list;
+    char ***ret_list;
+{
+       char    **cp;
+
+       if (list == 0)
+               return;
+
+       if (ret_list) {
+               *ret_list = list->list;
+               return;
+       } else {
+               for (cp = list->list; *cp; cp++)
+                       free(*cp);
+               free(list->list);
+       }
+       list->num = list->max = 0;
+       list->list = 0;
+}
+
+/*
+ * Add a string to the list.
+ */
+static errcode_t add_to_list(list, str)
+       struct profile_string_list *list;
+       const char      *str;
+{
+       char    *newstr, **newlist;
+       int     newmax;
+       
+       if (list->num+1 >= list->max) {
+               newmax = list->max + 10;
+               newlist = realloc(list->list, newmax * sizeof(char *));
+               if (newlist == 0)
+                       return ENOMEM;
+               list->max = newmax;
+               list->list = newlist;
+       }
+       newstr = malloc(strlen(str)+1);
+       if (newstr == 0)
+               return ENOMEM;
+       strcpy(newstr, str);
+
+       list->list[list->num++] = newstr;
+       list->list[list->num] = 0;
+       return 0;
+}
+
+/*
+ * Return TRUE if the string is already a member of the list.
+ */
+static int is_list_member(list, str)
+       struct profile_string_list *list;
+       const char      *str;
+{
+       char **cpp;
+
+       if (!list->list)
+               return 0;
+
+       for (cpp = list->list; *cpp; cpp++) {
+               if (!strcmp(*cpp, str))
+                       return 1;
+       }
+       return 0;
+}      
+       
+/*
+ * This function frees a null-terminated list as returned by
+ * profile_get_values.
+ */
+KRB5_DLLIMP void KRB5_CALLCONV profile_free_list(list)
+    char       **list;
+{
+    char       **cp;
+
+    if (list == 0)
+           return;
+    
+    for (cp = list; *cp; cp++)
+       free(*cp);
+    free(list);
+}
+
+/*
+ * This function searches the profile for a named section, looking in
+ * each file in the profile.  If ret_name is NULL, then this
+ * function looks at the entire names array; if ret_name is non-NULL,
+ * then the last entry in the names array is assumed to be the name of
+ * the relation desired by profile_get_values(), and is returned in
+ * ret_name.  The section looked up in that case will not include the
+ * last entry in the names array.
+ */
+static errcode_t lookup_section(profile, names, ret_name, ret_section)
+       profile_t       profile;
+       const char      **names;
+       const char      **ret_name;
+       struct profile_node **ret_section;
+{
+       prf_file_t      file;
+       errcode_t       retval;
+       int             done_idx = 0;
+       const char      **cpp;
+       void            *state;
+       struct profile_node *section;
+
+       if (profile == 0)
+               return PROF_NO_PROFILE;
+
+       if (names == 0 || names[0] == 0 || (ret_name && names[1] == 0))
+               return PROF_BAD_NAMESET;
+
+       if (ret_name)
+               done_idx = 1;
+
+       file = profile->first_file;
+       if ((retval = profile_update_file(file)))
+               return retval;
+
+       section = file->root;
+       cpp = names;
+
+       while (cpp[done_idx]) {
+               state = 0;
+               retval = profile_find_node_subsection(section, *cpp,
+                                                     &state, 0, &section);
+               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, &section);
+       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, &section);
+       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, &section);
+                       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, &section);
+       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;
+}
+
+
+
index f69fa0bb77d19c09f2c484ce9cb29264ba976504..cbf2bc2ad2de3019701ec5d1aa5a34159099a712 100644 (file)
@@ -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, &section);
-       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, &section);
-
-    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, &section);
-       if (retval)
-           goto cleanup;
-    }
-
-    state = 0;
-    retval = profile_find_node_relation(section, *cpp, &state, 0, &value);
-    if (retval)
-       goto cleanup;
-
-    *ret_value = value;
-    return 0;
-cleanup:
-    return retval;
-}
-
-errcode_t profile_get_string(profile, name, subname, subsubname,
-                            def_val, ret_string)
-    profile_t  profile;
-    const char *name, *subname, *subsubname;
-    const char *def_val;
-    char       **ret_string;
-{
-    const char *value;
-    errcode_t  retval;
-    const char *names[4];
-
-    if (profile) {
-       names[0] = name;
-       names[1] = subname;
-       names[2] = subsubname;
-       names[3] = 0;
-       retval = profile_get_value(profile, names, &value);
-       if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION)
-           value = def_val;
-       else if (retval)
-           return retval;
-    } else
-       value = def_val;
-    
-    if (value) {
-       *ret_string = malloc(strlen(value)+1);
-       if (*ret_string == 0)
-           return ENOMEM;
-       strcpy(*ret_string, value);
-    } else
-       *ret_string = 0;
-    return 0;
-}
-
-errcode_t profile_get_integer(profile, name, subname, subsubname,
-                             def_val, ret_int)
-    profile_t  profile;
-    const char *name, *subname, *subsubname;
-    int                def_val;
-    int                *ret_int;
-{
-   char        *value;
-   errcode_t   retval;
-    const char *names[4];
-
-   if (profile == 0) {
-       *ret_int = def_val;
-       return 0;
-   }
-
-   names[0] = name;
-   names[1] = subname;
-   names[2] = subsubname;
-   names[3] = 0;
-   retval = profile_get_value(profile, names, &value);
-   if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) {
-       *ret_int = def_val;
-       return 0;
-   } else if (retval)
-       return retval;
-   
-   *ret_int = atoi(value);
-   return 0;
-}
-
 errcode_t profile_ser_size(unused, profile, sizep)
     const char *unused;
     profile_t  profile;
@@ -407,14 +139,6 @@ errcode_t profile_ser_size(unused, profile, sizep)
     size_t     required;
     prf_file_t pfp;
 
-    /*
-     * ARGH - We want to avoid having to include k5-int.h.  We ASSuME that
-     * krb5_int32 is 4 bytes in length.
-     *
-     * krb5_int32 for header
-     * krb5_int32 for number of files.
-     * krb5_int32 for trailer
-     */
     required = 3*sizeof(prof_int32);
     for (pfp = profile->first_file; pfp; pfp = pfp->next) {
        required += sizeof(prof_int32);
@@ -502,63 +226,70 @@ static int unpack_int32(intp, bufpp, remainp)
 }
 
 errcode_t profile_ser_internalize(unused, profilep, bufpp, remainp)
-    const char         *unused;
-    profile_t          *profilep;
-    unsigned char      **bufpp;
-    size_t             *remainp;
+       const char              *unused;
+       profile_t               *profilep;
+       unsigned char   **bufpp;
+       size_t          *remainp;
 {
-    errcode_t          retval;
-    unsigned char      *bp;
-    size_t             remain;
-    int                        i;
-    prof_int32         fcount, tmp;
-    char               **flist;
-
-    bp = *bufpp;
-    remain = *remainp;
-    retval = EINVAL;
-
-    if (remain >= 12)
-       (void) unpack_int32(&tmp, &bp, &remain);
-    else
-       tmp = 0;
-    if (tmp == PROF_MAGIC_PROFILE) {
+       errcode_t               retval;
+       unsigned char   *bp;
+       size_t          remain;
+       int                     i;
+       prof_int32              fcount, tmp;
+       char            **flist = 0;
+
+       bp = *bufpp;
+       remain = *remainp;
+
+       if (remain >= 12)
+               (void) unpack_int32(&tmp, &bp, &remain);
+       else
+               tmp = 0;
+       
+       if (tmp != PROF_MAGIC_PROFILE) {
+               retval = EINVAL;
+               goto cleanup;
+       }
+       
        (void) unpack_int32(&fcount, &bp, &remain);
        retval = ENOMEM;
-       if (!fcount ||
-           (flist = (char **) malloc(sizeof(char *) * (fcount + 1)))) {
-           memset(flist, 0, sizeof(char *) * (fcount+1));
-           for (i=0; i<fcount; i++) {
+
+       flist = (char **) malloc(sizeof(char *) * (fcount + 1));
+       if (!flist)
+               goto cleanup;
+       
+       memset(flist, 0, sizeof(char *) * (fcount+1));
+       for (i=0; i<fcount; i++) {
                if (!unpack_int32(&tmp, &bp, &remain)) {
-                   if ((flist[i] = (char *) malloc((size_t) (tmp+1)))) {
+                       flist[i] = (char *) malloc((size_t) (tmp+1));
+                       if (!flist[i])
+                               goto cleanup;
                        memcpy(flist[i], bp, (size_t) tmp);
                        flist[i][tmp] = '\0';
                        bp += tmp;
                        remain -= (size_t) tmp;
-                   }
-                   else
-                       break;
                }
-               else
-                   break;
-           }
-           if ((i == fcount) &&
-               !unpack_int32(&tmp, &bp, &remain) &&
-               (tmp == PROF_MAGIC_PROFILE))
-               retval = profile_init((const char **)flist, profilep);
+       }
 
-           if (!retval) {
-               *bufpp = bp;
-               *remainp = remain;
-           }
+       if (unpack_int32(&tmp, &bp, &remain) ||
+           (tmp != PROF_MAGIC_PROFILE)) {
+               retval = EINVAL;
+               goto cleanup;
+       }
 
-           for (i=0; i<fcount; i++) {
-               if (flist[i])
-                   free(flist[i]);
-           }
-           free(flist);
+       if ((retval = profile_init((const char **)flist, profilep)))
+               goto cleanup;
+       
+       *bufpp = bp;
+       *remainp = remain;
+    
+cleanup:
+       if (flist) {
+               for (i=0; i<fcount; i++) {
+                       if (flist[i])
+                               free(flist[i]);
+               }
+               free(flist);
        }
-    }
-    return(retval);
+       return(retval);
 }
-
index 2096bd66d4440ebc97008e7d1e622de5388ff96c..8a45ec423eedd71b2ab339b8aa184a7ef98e525b 100644 (file)
@@ -60,27 +60,7 @@ struct _profile_t {
 
 typedef struct _profile_t *profile_t;
 
-/*
- * This structure defines the profile_section_t object, which is
- * returned to the user when a section is searched.
- */
-struct _profile_section_t {
-       prf_magic_t     magic;
-       int             top_lvl:1, top_lvl_search:1;
-       char            *name;
-       void            *state;
-       struct profile_node     *parent, *sect;
-       profile_t       profile;
-       prf_file_t      file_ptr;
-};
-
-typedef struct _profile_section_t *profile_section_t;
-
-errcode_t profile_get
-       PROTOTYPE((const char *filename, prf_file_t *ret_prof));
-
-errcode_t profile_update
-       PROTOTYPE((prf_file_t profile));
+/* profile_parse.c */
 
 errcode_t profile_parse_file
        PROTOTYPE((FILE *f, struct profile_node **root));
@@ -145,9 +125,15 @@ errcode_t profile_init_path
 void profile_release
        PROTOTYPE ((profile_t profile));
 
+/* prof_get.c */
+
+KRB5_DLLIMP void KRB5_CALLCONV profile_free_list
+       PROTOTYPE ((char **list));
 
 KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_get_values
-       PROTOTYPE ((profile_t profile, const char **names, char ***ret_values));
+       PROTOTYPE ((profile_t profile, const char **names,
+                   char ***ret_values));
+
 errcode_t profile_get_string
        PROTOTYPE((profile_t profile, const char *name, const char *subname, 
                        const char *subsubname, const char *def_val,
@@ -156,3 +142,10 @@ errcode_t profile_get_integer
        PROTOTYPE((profile_t profile, const char *name, const char *subname,
                        const char *subsubname, int def_val,
                        int *ret_default));
+
+errcode_t profile_get_relation_names
+       PROTOTYPE((profile_t profile, const char **names, char ***ret_names));
+
+errcode_t profile_get_subsection_names
+       PROTOTYPE((profile_t profile, const char **names, char ***ret_names));
+
index 5d92d9706a0c6e8bc33134410749d1b5dff9e187..cc7e36b8f3f9887ef1bf50d3f9f89ca0c47efc2e 100644 (file)
@@ -267,7 +267,7 @@ static void output_quoted_string(str, f)
                fputc('"', f);
                return;
        }
-       while (ch = *str++) {
+       while ((ch = *str++)) {
                switch (ch) {
                case '\\':
                        fputs("\\\\", f);
diff --git a/src/util/profile/prof_section.c b/src/util/profile/prof_section.c
deleted file mode 100644 (file)
index d147b79..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * prof_section.c --- routines that manipulate the profile_section_t
- *     object
- *
- * XXX this file is still under construction.
- */
-
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#include <errno.h>
-
-#include "prof_int.h"
-
-/*
- * This routine frees a profile_section
- */
-void profile_free_section(sect)
-       profile_section_t       sect;
-{
-       if (sect->name)
-               free(sect->name);
-       sect->magic = 0;
-       free(sect);
-}
-
-/*
- * This routine creates a profile_section from its parent.  If the
- * parent is NULL, then a top-level profile section is created.
- *
- * Top-level profile sections are different from normal
- * profile_sections in that top-level sections are agregated across
- * multiple files, where as subsections are not.
- */
-errcode_t profile_get_subsection(profile, parent, name, ret_name,
-                                ret_section)
-       profile_t               profile;
-       profile_section_t       parent;
-       const char *            name;
-       char **                 ret_name;
-       profile_section_t       *ret_section;
-{
-       profile_section_t       section;
-       prf_file_t              file;
-       errcode_t               retval;
-
-       section = malloc(sizeof(struct _profile_section_t));
-       if (section == 0)
-               return ENOMEM;
-       memset(section, 0, sizeof(struct _profile_section_t));
-       section->magic = PROF_MAGIC_SECTION;
-       section->name = malloc(strlen(name)+1);
-       if (section->name == 0) {
-               free(section);
-               return ENOMEM;
-       }
-       strcpy(section->name, name);
-       section->file_ptr = file = profile->first_file;
-       section->profile = profile;
-
-       if (parent == 0) {
-               /*
-                * If parent is NULL, then we are creating a
-                * top-level section which hangs off the root.
-                * 
-                * We make sure that the section exists in least one
-                * file.
-                */
-               section->top_lvl = 1;
-               if (name == 0)
-                       return PROF_TOPSECTION_ITER_NOSUPP;
-               while (file) {
-                       retval = profile_find_node_subsection(file->root,
-                               name, &section->state,
-                               ret_name, &section->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, &section->state, ret_name, &section->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, &section->state, ret_name, &section->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, &section->state, 0, &value);
-                       if (retval)
-                               continue;
-                       
-               }
-       } else {
-               if (section->sect == 0)
-                       return PROF_INVALID_SECTION;
-       }
-       return 0;
-}
-
-       
-       
index f4dc9751bb3ad2b7c5d7c7fc376b9a446e7e84dd..80d633dedd89a4b14f47c55369b2ae0d0bc60f7d 100644 (file)
@@ -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;
-}
index 6b9f163566e74c58bf77ae0ea8029b93f841d53b..42dc7fa2abd477dc39e53b59146c3b361dfb83ca 100644 (file)
@@ -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 */
index 171df93ecce28fa8aa75b72946a4cccb29b9ed03..19edbaf3f616916e40c931253b660ed339c489df 100644 (file)
@@ -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;
 }