test_profile.c: Added ability to test profile set functions, and in a
authorTheodore Tso <tytso@mit.edu>
Wed, 3 Mar 1999 04:56:15 +0000 (04:56 +0000)
committerTheodore Tso <tytso@mit.edu>
Wed, 3 Mar 1999 04:56:15 +0000 (04:56 +0000)
batch mode.

prof_init.c (profile_flush): Add new public function for flushing
changes made to the profile.

prof_parse.c (profile_write_tree_file): Add official internal function
for flushing out a profile tree to a FILE *.

configure.in, prof_file.c (rw_access): Add new function which checks
to see whether we have read/write access, and emulate this for losing
non-POSIX OS's.

prof_file.c (profile_flush_file): Add support for writing modified
profile file's.  Call profile_flush_file from profile_close_file().

Also fixed minor bugs in prof_tree.c which affected renaming sections and
modifying existing relations.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11237 dc483132-0cff-0310-8789-dd5450dbe970

14 files changed:
src/util/profile/ChangeLog
src/util/profile/Makefile.in
src/util/profile/argv_parse.c [new file with mode: 0644]
src/util/profile/argv_parse.h [new file with mode: 0644]
src/util/profile/configure.in
src/util/profile/krb5.conf
src/util/profile/prof_file.c
src/util/profile/prof_init.c
src/util/profile/prof_int.h
src/util/profile/prof_parse.c
src/util/profile/prof_tree.c
src/util/profile/profile.hin
src/util/profile/test_parse.c
src/util/profile/test_profile.c

index 983ccb3c64aed5d66156378527d9b8fc7119b3d7..b54fe058eabfe7ffcb1519ff08f5e783d38089c4 100644 (file)
@@ -1,5 +1,22 @@
 Tue Mar  2 18:55:50 1999  Theodore Y. Ts'o  <tytso@mit.edu>
 
+       * test_profile.c: Added ability to test profile set functions, and
+               in a batch mode.
+       
+       * prof_init.c (profile_flush): Add new public function for
+               flushing changes made to the profile.
+
+       * prof_parse.c (profile_write_tree_file): Add official internal
+               function for flushing out a profile tree to a FILE *.
+       
+       * configure.in, prof_file.c (rw_access): Add new function which
+               checks to see whether we have read/write access, and
+               emulate this for losing non-POSIX OS's.
+
+       * prof_file.c (profile_flush_file): Add support for writing
+               modified profile file's.  Call profile_flush_file from
+               profile_close_file().
+
        * prof_tree.c: Add new functions profile_get_node_name,
                profile_get_node_value, profile_find_node,
                profile_remove_node, profile_set_relation_value,
index 86cd74eb59ef8be283185c87753539d85d7f5f94..34b9b2e3e215dea152227871433bc7928e7c63a6 100644 (file)
@@ -78,8 +78,9 @@ awk-windows:
 test_parse: test_parse.$(OBJEXT) $(OBJS) $(DEPLIBS)
        $(CC_LINK) -o test_parse test_parse.$(OBJEXT) $(OBJS) $(MLIBS)
 
-test_profile: test_profile.$(OBJEXT) $(OBJS) $(DEPLIBS)
-       $(CC_LINK) -o test_profile test_profile.$(OBJEXT) $(OBJS) $(MLIBS)
+test_profile: test_profile.$(OBJEXT) argv_parse.$(OBJEXT) $(OBJS) $(DEPLIBS)
+       $(CC_LINK) -o test_profile test_profile.$(OBJEXT) \
+               argv_parse.$(OBJEXT) $(OBJS) $(MLIBS)
 
 test_parse.exe: 
        $(CC) $(CFLAGS2) -o test_parse.exe test_parse.c \
diff --git a/src/util/profile/argv_parse.c b/src/util/profile/argv_parse.c
new file mode 100644 (file)
index 0000000..d5f1073
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * argv_parse.c --- utility function for parsing a string into a
+ *     argc, argv array.
+ * 
+ * This file defines a function argv_parse() which parsing a
+ * passed-in string, handling double quotes and backslashes, and
+ * creates an allocated argv vector which can be freed using the
+ * argv_free() function.
+ *
+ * See argv_parse.h for the formal definition of the functions.
+ *
+ * Copyright 1999 by Theodore Ts'o.
+ * 
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose with or without fee is hereby granted, provided that
+ * the above copyright notice and this permission notice appear in all
+ * copies.  THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE
+ * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  (Isn't
+ * it sick that the U.S. culture of lawsuit-happy lawyers requires
+ * this kind of disclaimer?)
+ *
+ * Version 1.1, modified 2/27/1999
+ */
+
+#include <stdlib.h>
+#include <ctype.h>
+#include "argv_parse.h"
+
+#define STATE_WHITESPACE       1
+#define STATE_TOKEN            2
+#define STATE_QUOTED           3
+
+/*
+ * Returns 0 on success, -1 on failure.
+ */
+int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)
+{
+       int     argc = 0, max_argc = 0;
+       char    **argv, **new_argv, *buf, ch;
+       char    *cp = 0, *outcp = 0;
+       int     state = STATE_WHITESPACE;
+
+       buf = malloc(strlen(in_buf)+1);
+       if (!buf)
+               return -1;
+
+       max_argc = 0; argc = 0; argv = 0;
+       outcp = buf;
+       for (cp = in_buf; (ch = *cp); cp++) {
+               if (state == STATE_WHITESPACE) {
+                       if (isspace(ch))
+                               continue;
+                       /* Not whitespace, so start a new token */
+                       state = STATE_TOKEN;
+                       if (argc >= max_argc) {
+                               max_argc += 3;
+                               new_argv = realloc(argv,
+                                                 (max_argc+1)*sizeof(char *));
+                               if (!new_argv) {
+                                       if (argv) free(argv);
+                                       free(buf);
+                                       return -1;
+                               }
+                               argv = new_argv;
+                       }
+                       argv[argc++] = outcp;
+               }
+               if (state == STATE_QUOTED) {
+                       if (ch == '"')
+                               state = STATE_TOKEN;
+                       else
+                               *outcp++ = ch;
+                       continue;
+               }
+               /* Must be processing characters in a word */
+               if (isspace(ch)) {
+                       /*
+                        * Terminate the current word and start
+                        * looking for the beginning of the next word.
+                        */
+                       *outcp++ = 0;
+                       state = STATE_WHITESPACE;
+                       continue;
+               }
+               if (ch == '"') {
+                       state = STATE_QUOTED;
+                       continue;
+               }
+               if (ch == '\\') {
+                       ch = *++cp;
+                       switch (ch) {
+                       case '\0':
+                               ch = '\\'; cp--; break;
+                       case 'n':
+                               ch = '\n'; break;
+                       case 't':
+                               ch = '\t'; break;
+                       case 'b':
+                               ch = '\b'; break;
+                       }
+               }
+               *outcp++ = ch;
+       }
+       if (state != STATE_WHITESPACE)
+               *outcp++ = '\0';
+       if (argv == 0) {
+               argv = malloc(sizeof(char *));
+               free(buf);
+       }
+       argv[argc] = 0;
+       if (ret_argc)
+               *ret_argc = argc;
+       if (ret_argv)
+               *ret_argv = argv;
+       return 0;
+}
+
+void argv_free(char **argv)
+{
+       if (*argv)
+               free(*argv);
+       free(argv);
+}
+
+#ifdef DEBUG
+/*
+ * For debugging
+ */
+
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+       int     ac, ret;
+       char    **av, **cpp;
+       char    buf[256];
+
+       while (!feof(stdin)) {
+               if (fgets(buf, sizeof(buf), stdin) == NULL)
+                       break;
+               ret = argv_parse(buf, &ac, &av);
+               if (ret != 0) {
+                       printf("Argv_parse returned %d!\n", ret);
+                       continue;
+               }
+               printf("Argv_parse returned %d arguments...\n", ac);
+               for (cpp = av; *cpp; cpp++) {
+                       if (cpp != av)
+                               printf(", ");
+                       printf("'%s'", *cpp);
+               }
+               printf("\n");
+               argv_free(av);
+       }
+       exit(0);
+}
+#endif /* DEBUG */
diff --git a/src/util/profile/argv_parse.h b/src/util/profile/argv_parse.h
new file mode 100644 (file)
index 0000000..84568e7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * argv_parse.h --- header file for the argv parser.
+ *
+ * This file defines the interface for the functions argv_parse() and
+ * argv_free().
+ * 
+ ***********************************************************************
+ * int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv)
+ *
+ * This function takes as its first argument a string which it will
+ * parse into an argv argument vector, with each white-space separated
+ * word placed into its own slot in the argv.  This function handles
+ * double quotes and backslashes so that the parsed words can contain
+ * special characters.   The count of the number words found in the
+ * parsed string, as well as the argument vector, are returned into
+ * ret_argc and ret_argv, respectively.
+ ***********************************************************************
+ * extern void argv_free(char **argv);
+ * 
+ * This function frees the argument vector created by argv_parse().
+ ***********************************************************************
+ *
+ * Copyright 1999 by Theodore Ts'o.
+ * 
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose with or without fee is hereby granted, provided that
+ * the above copyright notice and this permission notice appear in all
+ * copies.  THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE
+ * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  (Isn't
+ * it sick that the U.S. culture of lawsuit-happy lawyers requires
+ * this kind of disclaimer?)
+ *
+ * Version 1.1, modified 2/27/1999
+ */
+
+extern int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv);
+extern void argv_free(char **argv);
index 850f3befbb732cfa4324ed909cf54614044535ce..aa6b49df82b4d4ee89341dd02e2690b0959b1214 100644 (file)
@@ -5,7 +5,7 @@ AC_CHECK_SIZEOF(short)
 AC_CHECK_SIZEOF(int)
 AC_CHECK_SIZEOF(long)
 AC_CHECK_HEADERS(unistd.h stdlib.h)
-AC_HAVE_FUNCS(stat)
+AC_HAVE_FUNCS(stat access)
 AC_PROG_AWK
 KRB5_BUILD_LIBOBJS
 KRB5_BUILD_PROGRAM
index c4f62d2ba30fa6d864a4010ba1052d7ce1941dae..01eb66ce8aceb4c3673ab3c8835086132d99930e 100644 (file)
@@ -1,12 +1,57 @@
+[libdefaults]
+       default_realm = ATHENA.MIT.EDU
+       default_tgs_enctypes = des-cbc-crc
+       default_tkt_enctypes = des-cbc-crc
+       krb4_config = /etc/athena/krb.conf
+       krb4_realms = /etc/athena/krb.realms
+       default_keytab_name = FILE:/etc/krb5.keytab
+       kdc_timesync = 1
+       ccache_type = 4
+
 [realms]
        ATHENA.MIT.EDU = {
-               kdc = KERBEROS.MIT.EDU:88
-               kdc = KERBEROS-1.MIT.EDU:88
-               admin_server = KERBEROS.MIT.EDU
+#              kdc = kerberos-2000.mit.edu
+               kdc = kerberos.mit.edu:88
+               kdc = kerberos-1.mit.edu:88
+               kdc = kerberos-2.mit.edu:88
+               kdc = kerberos-3.mit.edu:88
+               admin_server = kerberos.mit.edu
+               default_domain = mit.edu
+       }
+       MEDIA-LAB.MIT.EDU = {
+               kdc = kerberos.media.mit.edu
+               admin_server = kerberos.media.mit.edu
+       }
+       ZONE.MIT.EDU = {
+               kdc = casio.mit.edu
+               kdc = seiko.mit.edu
+               admin_server = casio.mit.edu
+       }
+       MOOF.MIT.EDU = {
+               kdc = three-headed-dogcow.mit.edu:88
+               kdc = three-headed-dogcow-1.mit.edu:88
+               admin_server = three-headed-dogcow.mit.edu
+       }
+       CYGNUS.COM = {
+               kdc = KERBEROS-1.CYGNUS.COM
+               kdc = KERBEROS.CYGNUS.COM
+               admin_server = KERBEROS.CYGNUS.COM
+       }
+       GREY17.ORG = {
+               kdc = kerberos.grey17.org
+               admin_server = kerberos.grey17.org
+       }
+       IHTFP.ORG = {
+               kdc = kerberos.ihtfp.org
+               admin_server = kerberos.ihtfp.org
        }
 
-[kdc]
-       port = 88
+[domain_realm]
+       .mit.edu = ATHENA.MIT.EDU
+       mit.edu = ATHENA.MIT.EDU
+       .media.mit.edu = MEDIA-LAB.MIT.EDU
+       media.mit.edu = MEDIA-LAB.MIT.EDU
 
-[libdefaults]
-       ticket_lifetime = 10 hours
+[login]
+       krb4_convert = true
+       krb4_get_tickets = true
index fde68748266af05d1dd3449f0151f7ce92085ed7..3bdb5d6f305ccdc9501c4aa27ea8e285f14ada02 100644 (file)
@@ -6,6 +6,9 @@
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <string.h>
 
 #include "prof_int.h"
 
 
 #if defined(_MSDOS) || defined(_WIN32)
+#include <io.h>
+#define HAVE_STAT      
 #define stat _stat
 #endif
 
+static int rw_access(filename)
+       const char *filename;
+{
+#ifdef HAVE_ACCESS
+       if (access(filename, W_OK) == 0)
+               return 1;
+       else
+               return 0;
+#else
+       /*
+        * We're on a substandard OS that doesn't support access.  So
+        * we kludge a test using stdio routines, and hope fopen
+        * checks the r/w permissions.
+        */
+       FILE    *f;
+
+       f = fopen(filename, "r+");
+       if (f) {
+               fclose(f);
+               return 1;
+       }
+       return 0;
+#endif
+}
+
 errcode_t profile_open_file(filename, ret_prof)
        const char *filename;
        prf_file_t *ret_prof;
@@ -99,6 +129,9 @@ errcode_t profile_update_file(prf)
        if (f == NULL)
                return errno;
        prf->upd_serial++;
+       prf->flags = 0;
+       if (rw_access(prf->filename))
+               prf->flags |= PROFILE_FILE_RW;
        retval = profile_parse_file(f, &prf->root);
        fclose(f);
        if (retval)
@@ -109,9 +142,75 @@ errcode_t profile_update_file(prf)
        return 0;
 }
 
+errcode_t profile_flush_file(prf)
+       prf_file_t prf;
+{
+       FILE            *f;
+       char            *new_name = 0, *old_name = 0;
+       errcode_t       retval = 0;
+       
+       if (!prf || prf->magic != PROF_MAGIC_FILE)
+               return PROF_MAGIC_FILE;
+       
+       if ((prf->flags & PROFILE_FILE_DIRTY) == 0)
+               return 0;
+
+       retval = ENOMEM;
+       new_name = malloc(strlen(prf->filename) + 5);
+       if (!new_name)
+               goto errout;
+       old_name = malloc(strlen(prf->filename) + 5);
+       if (!old_name)
+               goto errout;
+
+       sprintf(new_name, "%s.$$$", prf->filename);
+       sprintf(old_name, "%s.bak", prf->filename);
+
+       f = fopen(new_name, "w");
+       if (!f) {
+               retval = errno;
+               goto errout;
+       }
+
+       profile_write_tree_file(prf->root, f);
+       if (fclose(f) != 0) {
+               retval = errno;
+               goto errout;
+       }
+
+       unlink(old_name);
+       if (rename(prf->filename, old_name)) {
+               retval = errno;
+               goto errout;
+       }
+       if (rename(new_name, prf->filename)) {
+               retval = errno;
+               rename(old_name, prf->filename); /* back out... */
+               goto errout;
+       }
+
+       prf->flags = 0;
+       if (rw_access(prf->filename))
+               prf->flags |= PROFILE_FILE_RW;
+       retval = 0;
+       
+errout:
+       if (new_name)
+               free(new_name);
+       if (old_name)
+               free(old_name);
+       return retval;
+}
+
+
 errcode_t profile_close_file(prf)
        prf_file_t prf;
 {
+       errcode_t       retval;
+       
+       retval = profile_flush_file(prf);
+       if (retval)
+               return retval;
        if (prf->filename)
                free(prf->filename);
        if (prf->root)
index d88d5f3ac349925d7683fa1d7a1d940e437e4cc8..6a076612fbd49b03cca8ced87c01472eee352dde 100644 (file)
@@ -119,6 +119,19 @@ profile_init_path(filepath, ret_profile)
        return retval;
 }
 
+KRB5_DLLIMP errcode_t KRB5_CALLCONV
+profile_flush(profile)
+       profile_t       profile;
+{
+       if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+               return PROF_MAGIC_PROFILE;
+
+       if (profile->first_file)
+               return profile_flush_file(profile->first_file);
+
+       return 0;
+}
+
 
 KRB5_DLLIMP void KRB5_CALLCONV
 profile_release(profile)
index 143bd53e82cab30ff37db0d828b5230a982e479e..312b78e2b18761cf9a039d66d64bd7d399321d13 100644 (file)
@@ -81,6 +81,10 @@ typedef struct _profile_t *profile_t;
 errcode_t profile_parse_file
        PROTOTYPE((FILE *f, struct profile_node **root));
 
+errcode_t profile_write_tree_file
+       PROTOTYPE((struct profile_node *root, FILE *dstfile));
+
+
 /* prof_tree.c */
 
 void profile_free_node
@@ -165,6 +169,9 @@ errcode_t profile_open_file
 errcode_t profile_update_file
        PROTOTYPE ((prf_file_t profile));
 
+errcode_t profile_flush_file
+       PROTOTYPE ((prf_file_t profile));
+
 errcode_t profile_close_file
        PROTOTYPE ((prf_file_t profile));
 
index 833f80d358e54b4c2fc543b528ef314e94b90688..0e3cffe7466a318bcaa5f4cee724fee72561f6ea 100644 (file)
@@ -319,51 +319,7 @@ static void output_quoted_string(str, f)
 #define EOL "\n"
 #endif
 
-#if !defined(_MSDOS) && !defined(_WIN32)
-
-void dump_profile(root, level)
-       struct profile_node *root;
-       int level;
-{
-       int i;
-       struct profile_node *p;
-       void *iter;
-       long retval;
-       char *name, *value;
-       
-       iter = 0;
-       do {
-               retval = profile_find_node_relation(root, 0, &iter,
-                                                   &name, &value);
-               if (retval)
-                       break;
-               for (i=0; i < level; i++)
-                       printf("   ");
-               if (need_double_quotes(value)) {
-                       fputs(name, stdout);
-                       fputs(" = ", stdout);
-                       output_quoted_string(value, stdout);
-                       fputs(EOL, stdout);
-               } else
-                       printf("%s = '%s'%s", name, value, EOL);
-       } while (iter != 0);
-
-       iter = 0;
-       do {
-               retval = profile_find_node_subsection(root, 0, &iter,
-                                                     &name, &p);
-               if (retval)
-                       break;
-               for (i=0; i < level; i++)
-                       printf("   ");
-               printf("[%s]%s", name, EOL);
-               dump_profile(p, level+1);
-       } while (iter != 0);
-}
-#endif /* !_MSDOS && !_WIN32 */
-
-
-void dump_profile_to_file(root, level, dstfile)
+static void dump_profile_to_file(root, level, dstfile)
        struct profile_node *root;
        int level;
        FILE *dstfile;
@@ -416,3 +372,11 @@ void dump_profile_to_file(root, level, dstfile)
                }
        } while (iter != 0);
 }
+
+errcode_t profile_write_tree_file(root, dstfile)
+       struct profile_node *root;
+       FILE            *dstfile;
+{
+       dump_profile_to_file(root, 0, dstfile);
+       return 0;
+}
index 5fde5e9300f27e02aacea7b36b708e341e40de05..47160906acfdefbe63e016e461d92d0baa5a857a 100644 (file)
@@ -594,7 +594,7 @@ errcode_t profile_set_relation_value(node, new_value)
        
        CHECK_MAGIC(node);
 
-       if (node->value)
+       if (!node->value)
                return PROF_SET_SECTION_VALUE;
 
        cp = malloc(strlen(new_value)+1);
@@ -644,25 +644,31 @@ errcode_t profile_rename_node(node, new_name)
        }
 
        /*
-        * OK, let's detach the node
+        * If we need to move the node, do it now.
         */
-       if (node->prev)
-               node->prev->next = node->next;
-       else
-               node->parent->first_child = node->next;
-
-       if (node->next)
-               node->next->prev = node->prev;
+       if ((p != node) && (last != node)) {
+               /*
+                * 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;
+               /*
+                * 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;
+               node->next = p;
+               node->prev = last;
+       }
 
        free(node->name);
        node->name = new_string;
index 581de74ed888f78aef1cff536df060b430a5c731..bbc2d0b16dcb903d60b43c65bd56c9107e019ba4 100644 (file)
@@ -41,6 +41,9 @@ KRB5_DLLIMP long KRB5_CALLCONV profile_init
 KRB5_DLLIMP long KRB5_CALLCONV profile_init_path
        PROTOTYPE ((const char *filepath, profile_t *ret_profile));
 
+KRB5_DLLIMP errcode_t KRB5_CALLCONV profile_flush
+       PROTOTYPE ((profile_t profile));
+
 KRB5_DLLIMP void KRB5_CALLCONV profile_release
        PROTOTYPE ((profile_t profile));
 
index 2f00d9e81158d22def6477de810d45bafbb83621..29e2b59405b9e064210deaf93418018d3e69b24a 100644 (file)
@@ -38,12 +38,8 @@ int main(argc, argv)
        fclose(f);
        
        printf("\n\nDebugging dump.\n");
-#if 0
-       dump_profile(root, 0);
-#else
-       dump_profile_to_file(root, 0, stdout);
-#endif
-
+       profile_write_tree_file(root, stdout);
+       
        retval = profile_verify_node(root);
        if (retval) {
                printf("profile_verify_node reported an error: %s\n",
index 4b2df6d36de282cb4ccfb9e886d865ca2dda6712..a36b778bc3fcc764d632596a0d471775d5261d6b 100644 (file)
@@ -8,6 +8,7 @@
 #endif
 
 #include "prof_int.h"
+#include "argv_parse.h"
 #ifndef _MSDOS
 #include "com_err.h"
 #else
@@ -22,6 +23,96 @@ void com_err (char *fmt, long err, char *msg) {
 
 const char *program_name = "test_profile";
 
+#define PRINT_VALUE    1
+#define PRINT_VALUES   2
+
+static void do_batchmode(profile)
+       profile_t       profile;
+{
+       errcode_t       retval;
+       int             argc, ret;
+       char            **argv, **values, **cpp;
+       char            buf[256];
+       const char      **names, *value;
+       char            *cmd;
+       int             print_status;
+
+       while (!feof(stdin)) {
+               if (fgets(buf, sizeof(buf), stdin) == NULL)
+                       break;
+               printf(">%s", buf);
+               ret = argv_parse(buf, &argc, &argv);
+               if (ret != 0) {
+                       printf("Argv_parse returned %d!\n", ret);
+                       continue;
+               }
+               cmd = *(argv);
+               names = (const char **) argv + 1;
+               print_status = 0;
+               retval = 0;
+               if (cmd == 0) {
+                       argv_free(argv);
+                       continue;
+               }
+               if (!strcmp(cmd, "query")) {
+                       retval = profile_get_values(profile, names, &values);
+                       print_status = PRINT_VALUES;
+               } else if (!strcmp(cmd, "query1")) {
+                       retval = profile_get_value(profile, names, &value);
+                       print_status = PRINT_VALUE;
+               } else if (!strcmp(cmd, "list_sections")) {
+                       retval = profile_get_subsection_names(profile, names, 
+                                                             &values);
+                       print_status = PRINT_VALUES;
+               } else if (!strcmp(cmd, "list_relations")) {
+                       retval = profile_get_relation_names(profile, names, 
+                                                           &values);
+                       print_status = PRINT_VALUES;
+               } else if (!strcmp(cmd, "dump")) {
+                       retval = profile_write_tree_file
+                               (profile->first_file->root, stdout);
+               } else if (!strcmp(cmd, "clear")) {
+                       retval = profile_clear_relation(profile, names);
+               } else if (!strcmp(cmd, "update")) {
+                       retval = profile_update_relation(profile, names+2,
+                                                        *names, *(names+1));
+               } else if (!strcmp(cmd, "verify")) {
+                       retval = profile_verify_node
+                               (profile->first_file->root);
+               } else if (!strcmp(cmd, "rename_section")) {
+                       retval = profile_rename_section(profile, names+1,
+                                                       *names);
+               } else if (!strcmp(cmd, "add")) {
+                       retval = profile_add_relation(profile, names+1,
+                                                     *names);
+               } else if (!strcmp(cmd, "flush")) {
+                       retval = profile_flush(profile);
+               } else {
+                       printf("Invalid command.\n");
+               }
+               if (retval) {
+                       com_err(cmd, retval, "");
+                       print_status = 0;
+               }
+               switch (print_status) {
+               case PRINT_VALUE:
+                       printf("%s\n", value);
+                       break;
+               case PRINT_VALUES:
+                       for (cpp = values; *cpp; cpp++)
+                               printf("%s\n", *cpp);
+                       profile_free_list(values);
+                       break;
+               }
+               printf("\n");
+               argv_free(argv);
+       }
+       profile_release(profile);
+       exit(0);
+       
+}
+
+
 int main(argc, argv)
     int                argc;
     char       **argv;
@@ -34,8 +125,8 @@ int main(argc, argv)
     char       *cmd;
     int                print_value = 0;
     
-    if (argc < 3) {
-           fprintf(stderr, "Usage: %s filename cmd argset\n", program_name);
+    if (argc < 2) {
+           fprintf(stderr, "Usage: %s filename [cmd argset]\n", program_name);
            exit(1);
     }
 
@@ -48,6 +139,8 @@ int main(argc, argv)
     }
     cmd = *(argv+2);
     names = (const char **) argv+3;
+    if (!cmd || !strcmp(cmd, "batch"))
+           do_batchmode(profile);
     if (!strcmp(cmd, "query")) {
            retval = profile_get_values(profile, names, &values);
     } else if (!strcmp(cmd, "query1")) {