summaryrefslogtreecommitdiffstats
path: root/agents/virt/config/simpleconfig.c
diff options
context:
space:
mode:
Diffstat (limited to 'agents/virt/config/simpleconfig.c')
-rw-r--r--agents/virt/config/simpleconfig.c494
1 files changed, 494 insertions, 0 deletions
diff --git a/agents/virt/config/simpleconfig.c b/agents/virt/config/simpleconfig.c
new file mode 100644
index 0000000..3315b32
--- /dev/null
+++ b/agents/virt/config/simpleconfig.c
@@ -0,0 +1,494 @@
+#include "config.h"
+
+#include <stdio.h>
+#include <pthread.h>
+#include <string.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "simpleconfig.h"
+#include "config-stack.h"
+#include "static_map.h"
+
+
+static pthread_mutex_t parser_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int
+print_value(struct value *v, int depth, FILE *fp)
+{
+ int x;
+
+ if (v->val == NULL)
+ return 0;
+
+ for (x = 0; x < depth; x++)
+ fprintf(fp, "\t");
+ fprintf(fp, "%s = \"%s\";\n", v->id, v->val);
+
+ return 0;
+}
+
+
+static void
+_sc_dump_d(struct node *node, int depth, FILE *fp)
+{
+ struct node *n;
+ struct value *v;
+ int x;
+
+ if (!node) {
+ //printf("Empty node\n");
+ return;
+ }
+
+ for (x = 0; x < depth; x++)
+ fprintf(fp, "\t");
+
+ if (node->val) {
+ fprintf(fp, "%s = \"%s\" {\n", node->id, node->val);
+ } else {
+ fprintf(fp, "%s {\n", node->id);
+ }
+
+ for (n = node->nodes; n; n = n->next) {
+ _sc_dump_d(n, depth+1, fp);
+ }
+
+ for (v = node->values; v; v = v->next) {
+ print_value(v, depth+1, fp);
+ }
+
+ for (x = 0; x < depth; x++)
+ fprintf(fp, "\t");
+ fprintf(fp, "}\n\n");
+}
+
+
+static void
+_sc_dump(void *config, FILE *fp)
+{
+ struct node *n, *node;
+ struct value *v, *values;
+
+ if (!config)
+ return;
+
+ values = ((struct parser_context *)config)->val_list;
+ node = ((struct parser_context *)config)->node_list;
+
+ for (n = node; n; n = n->next) {
+ _sc_dump_d(n, 0, fp);
+ }
+
+ for (v = values; v; v = v->next) {
+ print_value(v, 0, fp);
+ }
+}
+
+
+static int
+free_value(struct value *v)
+{
+ if (v) {
+ free(v->id);
+ free(v->val);
+ free(v);
+ }
+
+ return 0;
+}
+
+
+static void
+_sc_free_node(struct node *node)
+{
+ struct node *n;
+ struct value *v;
+
+ if (!node)
+ return;
+
+ while (node->nodes) {
+ n = node->nodes;
+ if (n) {
+ node->nodes = node->nodes->next;
+ _sc_free_node(n);
+ }
+ }
+
+ while (node->values) {
+ v = node->values;
+ node->values = node->values->next;
+ free_value(v);
+ }
+
+ free(node->id);
+ free(node);
+}
+
+
+static int
+_sc_free(void *config)
+{
+ struct node *n, *nlist;
+ struct value *v, *vlist;
+
+ if (!config)
+ return -1;
+
+ vlist = ((struct parser_context *)config)->val_list;
+ nlist = ((struct parser_context *)config)->node_list;
+
+ while (nlist) {
+ n = nlist;
+ nlist = nlist->next;
+ _sc_free_node(n);
+ }
+
+ ((struct parser_context *)config)->node_list = NULL;
+
+ while (vlist) {
+ v = vlist;
+ vlist = vlist->next;
+ free_value(v);
+ }
+
+ ((struct parser_context *)config)->val_list = NULL;
+
+ free(config);
+
+ return 0;
+}
+
+
+static int
+_sc_get(void *config, const char *key, char *value, size_t valuesz)
+{
+ char buf[1024];
+ struct node *n, *node;
+ struct value *v, *values;
+ char *ptr;
+ char *slash;
+ char *bracket;
+ char *id;
+ int req_index = 0;
+ int curr_index = 0;
+ int found;
+
+ if (!config)
+ return -1;
+
+ node = ((struct parser_context *)config)->node_list;
+ values = ((struct parser_context *)config)->val_list;
+
+ assert(strlen(key) < sizeof(buf));
+
+ ptr = (char *)key;
+
+ while ((slash = strchr(ptr, '/'))) {
+ memset(buf, 0, sizeof(buf));
+ strncpy(buf, ptr, (slash - ptr));
+ ptr = ++slash;
+
+ id = NULL;
+ bracket = strchr(buf, '[');
+ if (bracket) {
+ *bracket = 0;
+ ++bracket;
+
+ id = bracket;
+
+ bracket = strchr(bracket, ']');
+ if (!bracket)
+ return 1;
+ *bracket = 0;
+
+ if (id[0] == '@') {
+ ++id;
+ if (!strlen(id)) {
+ return 1;
+ }
+ } else {
+ req_index = atoi(id);
+ if (req_index <= 0)
+ return 1;
+ id = NULL;
+ }
+ }
+
+ found = 0;
+ curr_index = 0;
+
+ for (n = node; n; n = n->next) {
+
+ if (strcasecmp(n->id, buf))
+ continue;
+
+ ++curr_index;
+
+ if (req_index && (curr_index != req_index)) {
+ continue;
+ } else if (id && strcasecmp(n->val, id)) {
+ continue;
+ }
+
+ node = n->nodes;
+ values = n->values;
+ found = 1;
+ break;
+ }
+
+ if (!found)
+ return 1;
+ }
+
+ if (ptr[0] != '@') {
+
+ strncpy(buf, ptr, sizeof(buf) - 1);
+ id = NULL;
+ bracket = strchr(buf, '[');
+ if (bracket) {
+ *bracket = 0;
+ ++bracket;
+
+ id = bracket;
+
+ bracket = strchr(bracket, ']');
+ if (!bracket)
+ return 1;
+ *bracket = 0;
+
+ if (id[0] == '@') {
+ ++id;
+ if (!strlen(id)) {
+ return 1;
+ }
+ } else {
+ req_index = atoi(id);
+ if (req_index <= 0)
+ return 1;
+ id = NULL;
+ }
+ }
+
+ found = 0;
+ curr_index = 0;
+
+ for (n = node; n; n = n->next) {
+
+ if (strcasecmp(n->id, buf))
+ continue;
+
+ ++curr_index;
+
+ if (req_index && (curr_index != req_index)) {
+ continue;
+ } else if (id && strcasecmp(n->val, id)) {
+ continue;
+ }
+ if (node->val) {
+ strncpy(value, node->val, valuesz);
+ return 0;
+ }
+ return 1;
+ }
+ }
+
+ ++ptr;
+ found = 0;
+ id = NULL;
+
+ strncpy(buf, ptr, sizeof(buf) - 1);
+ bracket = strchr(buf, '[');
+
+ req_index = 0;
+ curr_index = 0;
+
+ if (bracket) {
+ *bracket = 0;
+ ++bracket;
+
+ id = bracket;
+
+ bracket = strchr(bracket, ']');
+ if (!bracket)
+ return 1;
+ *bracket = 0;
+
+ req_index = atoi(id);
+ if (req_index <= 0)
+ return 1;
+ id = NULL;
+ }
+
+ for (v = values; v; v = v->next) {
+
+ if (strcasecmp(v->id, buf))
+ continue;
+
+ ++curr_index;
+ if (req_index && (curr_index != req_index))
+ continue;
+ snprintf(value, valuesz, "%s", v->val);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+static int
+_sc_set(void *config, const char *key, const char *value)
+{
+ char buf[1024];
+ struct node *n, **nodes = &((struct parser_context *)config)->node_list;
+ struct value *v, **values = &((struct parser_context *)config)->val_list;
+ char *ptr;
+ char *slash;
+ char *id_dup, *val_dup;
+ int found = 0;
+
+ ptr = (char *)key;
+ while ((slash = strchr(ptr, '/'))) {
+ memset(buf, 0, sizeof(buf));
+ strncpy(buf, ptr, (slash - ptr));
+ ptr = ++slash;
+ found = 0;
+
+ for (n = *nodes; n; n = n->next) {
+ if (strcasecmp(n->id, buf))
+ continue;
+
+ nodes = &n->nodes;
+ values = &n->values;
+ found = 1;
+ break;
+ }
+
+ if (!found) {
+ id_dup = strdup(buf);
+ if (!id_dup)
+ return -1;
+ _sc_node_add(id_dup, NULL, NULL, NULL, nodes);
+ n = *nodes;
+ nodes = &n->nodes;
+ values = &n->values;
+ }
+ }
+
+ if (ptr[0] != '@')
+ return 1;
+ ++ptr;
+
+ for (v = *values; v; v = v->next) {
+ if (strcasecmp(v->id, ptr))
+ continue;
+
+ ptr = v->val;
+ if (value) {
+ v->val = strdup(value);
+ if (!v->val) {
+ v->val = ptr;
+ return -1;
+ }
+ } else {
+ v->val = NULL;
+ }
+ free(ptr);
+
+ return 0;
+ }
+
+ if (!value)
+ return 0;
+
+ id_dup = strdup(ptr);
+ if (!id_dup)
+ return -1;
+
+ val_dup = strdup(value);
+ if (!val_dup) {
+ free(id_dup);
+ return -1;
+ }
+ _sc_value_add(id_dup, val_dup, values);
+
+ return 0;
+}
+
+
+static int
+_sc_parse(const char *filename, void **config)
+{
+ struct parser_context *c;
+ FILE *fp = NULL;
+ int ret = 0;
+
+ if (!config)
+ return -1;
+
+ pthread_mutex_lock(&parser_mutex);
+ if (filename) {
+ fp = fopen(filename, "r");
+ yyin = fp;
+ if (fp)
+ ret = yyparse();
+ else
+ ret = 1;
+ } else {
+ ret = 1;
+ }
+
+ c = malloc(sizeof(*c));
+ if (!c) {
+ ret = -1;
+ goto out_unlock;
+ }
+ c->node_list = node_list;
+ c->val_list = val_list;
+ c->next = NULL;
+ val_list = NULL;
+ node_list = NULL;
+ *config = (void *)c;
+
+ if (fp)
+ fclose(fp);
+
+out_unlock:
+ pthread_mutex_unlock(&parser_mutex);
+ return ret;
+}
+
+
+static const config_object_t sc_object = {
+ .get = _sc_get,
+ .set = _sc_set,
+ .parse = _sc_parse,
+ .free = _sc_free,
+ .dump = _sc_dump,
+ .info = NULL
+};
+
+
+config_object_t *
+sc_init(void)
+{
+ config_object_t *o;
+
+ o = malloc(sizeof(*o));
+ if (!o)
+ return NULL;
+ memset(o, 0, sizeof(*o));
+ memcpy(o, &sc_object, sizeof(*o));
+
+ return o;
+}
+
+
+void
+sc_release(config_object_t *c)
+{
+ sc_free(c);
+ free(c);
+}