aboutsummaryrefslogtreecommitdiff
path: root/src/util/profile
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/profile')
-rw-r--r--src/util/profile/ChangeLog18
-rw-r--r--src/util/profile/prof_parse.c113
-rw-r--r--src/util/profile/prof_tree.c20
3 files changed, 136 insertions, 15 deletions
diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog
index 9bfcde8..3e61d02 100644
--- a/src/util/profile/ChangeLog
+++ b/src/util/profile/ChangeLog
@@ -1,3 +1,21 @@
+1998-08-06 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * prof_tree.c (profile_delete_node_relation): Fix bug where
+ deleting a node would corrupt the linked list.
+ (profile_add_node): Fix another linked list corruption
+ problem where an insertion into the middle of the linked
+ list didn't update a previous link. [krb5-libs/615]
+
+Fri Jan 23 20:55:06 1998 Theodore Ts'o <tytso@rsts-11.mit.edu>
+
+ * prof_parse.c (parse_std_line, parse_quoted_string,
+ need_double_quotes, output_quoted_string, dump_profile,
+ dump_profile_to_file): Vastly improved the profile
+ parsing; whitespace at the end of lines are now ignored.
+ Added quoted string parsing, complete with backquote
+ processing. Strings which need to be quoted are properly
+ quoted on output.
+
Mon Nov 4 17:04:51 1996 Theodore Y. Ts'o <tytso@mit.edu>
* prof_parse.c (parse_std_line): Accept either ';' or '#' on the
diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c
index 941cc33..e7e72b8 100644
--- a/src/util/profile/prof_parse.c
+++ b/src/util/profile/prof_parse.c
@@ -43,6 +43,36 @@ static void strip_line(line)
}
}
+static void parse_quoted_string(char *str)
+{
+ char *to, *from;
+
+ to = from = str;
+
+ for (to = from = str; *from && *from != '"'; to++, from++) {
+ if (*from == '\\') {
+ from++;
+ switch (*from) {
+ case 'n':
+ *to = '\n';
+ break;
+ case 't':
+ *to = '\t';
+ break;
+ case 'b':
+ *to = '\b';
+ break;
+ default:
+ *to = *from;
+ }
+ continue;
+ }
+ *to = *from;
+ }
+ *to = '\0';
+}
+
+
static errcode_t parse_init_state(state)
struct parse_state *state;
{
@@ -126,12 +156,19 @@ static errcode_t parse_std_line(line, state)
}
cp = skip_over_blanks(cp+1);
value = cp;
- if (value[0] == 0) {
+ if (value[0] == '"') {
+ value++;
+ parse_quoted_string(value);
+ } else if (value[0] == 0) {
do_subsection++;
state->state = STATE_GET_OBRACE;
- }
- if (value[0] == '{' && value[1] == 0)
+ } else if (value[0] == '{' && value[1] == 0)
do_subsection++;
+ else {
+ cp = value + strlen(value) - 1;
+ while ((cp > value) && isspace(*cp))
+ *cp-- = 0;
+ }
if (do_subsection) {
retval = profile_add_node(state->current_section,
tag, 0, &state->current_section);
@@ -200,6 +237,60 @@ errcode_t profile_parse_file(f, root)
return 0;
}
+/*
+ * Return TRUE if the string begins or ends with whitespace
+ */
+static int need_double_quotes(str)
+ char *str;
+{
+ if (!str || !*str)
+ return 0;
+ if (isspace(*str) ||isspace(*(str + strlen(str) - 1)))
+ return 1;
+ if (strchr(str, '\n') || strchr(str, '\t') || strchr(str, '\b'))
+ return 1;
+ return 0;
+}
+
+/*
+ * Output a string with double quotes, doing appropriate backquoting
+ * of characters as necessary.
+ */
+static void output_quoted_string(str, f)
+ char *str;
+ FILE *f;
+{
+ char ch;
+
+ fputc('"', f);
+ if (!str) {
+ fputc('"', f);
+ return;
+ }
+ while (ch = *str++) {
+ switch (ch) {
+ case '\\':
+ fputs("\\\\", f);
+ break;
+ case '\n':
+ fputs("\\n", f);
+ break;
+ case '\t':
+ fputs("\\t", f);
+ break;
+ case '\b':
+ fputs("\\b", f);
+ break;
+ default:
+ fputc(ch, f);
+ break;
+ }
+ }
+ fputc('"', f);
+}
+
+
+
#if defined(_MSDOS) || defined(_WIN32)
#define EOL "\r\n"
#endif
@@ -232,7 +323,13 @@ void dump_profile(root, level)
break;
for (i=0; i < level; i++)
printf(" ");
- printf("%s = '%s'%s", name, value, EOL);
+ 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;
@@ -269,7 +366,13 @@ void dump_profile_to_file(root, level, dstfile)
break;
for (i=0; i < level; i++)
fprintf(dstfile, "\t");
- fprintf(dstfile, "%s = %s%s", name, value, EOL);
+ if (need_double_quotes(value)) {
+ fputs(name, dstfile);
+ fputs(" = ", dstfile);
+ output_quoted_string(value, dstfile);
+ fputs(EOL, dstfile);
+ } else
+ fprintf(dstfile, "%s = %s%s", name, value, EOL);
} while (iter != 0);
iter = 0;
diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c
index a192e1d..24b447e 100644
--- a/src/util/profile/prof_tree.c
+++ b/src/util/profile/prof_tree.c
@@ -145,9 +145,14 @@ errcode_t profile_add_node(section, name, value, ret_node)
if (section->value)
return PROF_ADD_NOT_SECTION;
+ /*
+ * Find the place to insert the new node. We look for the
+ * place *after* the last match of the node name, since
+ * order matters.
+ */
for (p=section->first_child, last = 0; p; last = p, p = p->next) {
cmp = strcmp(p->name, name);
- if (cmp >= 0)
+ if (cmp > 0)
break;
}
retval = profile_create_node(name, value, &new);
@@ -155,19 +160,14 @@ errcode_t profile_add_node(section, name, value, ret_node)
return retval;
new->group_level = section->group_level+1;
new->parent = section;
- if (cmp == 0) {
- do {
- last = p;
- p = p->next;
- } while (p && strcmp(p->name, name) == 0);
- }
new->prev = last;
+ new->next = p;
+ if (p)
+ p->prev = new;
if (last)
last->next = new;
else
section->first_child = new;
- if (p)
- new->next = p;
if (ret_node)
*ret_node = new;
return 0;
@@ -317,7 +317,7 @@ errcode_t profile_delete_node_relation(section, name)
section->first_child = p->next;
next = p->next;
if (p->next)
- p->next->prev = p;
+ p->next->prev = p->prev;
profile_free_node(p);
p = next;
}