diff --git a/src/scconf/parse.c b/src/scconf/parse.c index 8913b152..afb0d17f 100644 --- a/src/scconf/parse.c +++ b/src/scconf/parse.c @@ -127,8 +127,12 @@ scconf_item *scconf_item_add(scconf_context * config, scconf_block * block, scco scconf_parser parser; scconf_block *dst = NULL; - memset(&parser, 0, sizeof(scconf_parser)); + if (!config && !block) + return NULL; + if (!data) + return NULL; + memset(&parser, 0, sizeof(scconf_parser)); parser.config = config ? config : NULL; parser.key = key ? strdup(key) : NULL; parser.block = block ? block : config->root; @@ -141,20 +145,18 @@ scconf_item *scconf_item_add(scconf_context * config, scconf_block * block, scco scconf_list_copy(dst->name, &parser.name); } scconf_item_add_internal(&parser, type); - if (data) { - switch (parser.current_item->type) { - case SCCONF_ITEM_TYPE_COMMENT: - parser.current_item->value.comment = strdup((char *) data); - break; - case SCCONF_ITEM_TYPE_BLOCK: - dst->parent = parser.block; - parser.current_item->value.block = dst; - scconf_list_destroy(parser.name); - break; - case SCCONF_ITEM_TYPE_VALUE: - scconf_list_copy((const scconf_list *) data, &parser.current_item->value.list); - break; - } + switch (parser.current_item->type) { + case SCCONF_ITEM_TYPE_COMMENT: + parser.current_item->value.comment = strdup((char *) data); + break; + case SCCONF_ITEM_TYPE_BLOCK: + dst->parent = parser.block; + parser.current_item->value.block = dst; + scconf_list_destroy(parser.name); + break; + case SCCONF_ITEM_TYPE_VALUE: + scconf_list_copy((const scconf_list *) data, &parser.current_item->value.list); + break; } return parser.current_item; } @@ -189,7 +191,6 @@ scconf_block *scconf_block_add(scconf_context * config, scconf_block * block, co scconf_parser parser; memset(&parser, 0, sizeof(scconf_parser)); - parser.config = config ? config : NULL; parser.key = key ? strdup(key) : NULL; parser.block = block ? block : config->root; diff --git a/src/scconf/scconf.c b/src/scconf/scconf.c index 577008cc..cdc89b63 100644 --- a/src/scconf/scconf.c +++ b/src/scconf/scconf.c @@ -81,7 +81,7 @@ const scconf_block *scconf_find_block(const scconf_context * config, const sccon return item->value.block; } } - return block; + return NULL; } scconf_block **scconf_find_blocks(const scconf_context * config, const scconf_block * block, const char *item_name, const char *key) @@ -160,6 +160,40 @@ int scconf_get_bool(const scconf_block * block, const char *option, int def) return toupper((int) *list->data) == 'T' || toupper((int) *list->data) == 'Y'; } +const char *scconf_put_str(scconf_block * block, const char *option, const char *value) +{ + scconf_list *list = NULL; + scconf_item *item; + + scconf_list_add(&list, value); + item = scconf_item_add(NULL, block, NULL, SCCONF_ITEM_TYPE_VALUE, option, list); + scconf_list_destroy(list); + return value; +} + +int scconf_put_int(scconf_block * block, const char *option, int value) +{ + const char *ret; + char *str; + + str = (char *) malloc(64); + if (!str) { + return value; + } + snprintf(str, 64, "%i", value); + ret = scconf_put_str(block, option, str); + free(str); + return value; +} + +int scconf_put_bool(scconf_block * block, const char *option, int value) +{ + const char *ret; + + ret = scconf_put_str(block, option, !value ? "false" : "true"); + return value; +} + scconf_item *scconf_item_copy(const scconf_item * src, scconf_item ** dst) { scconf_item *ptr, *_dst = NULL, *next = NULL; @@ -361,14 +395,42 @@ char *scconf_list_strdup(const scconf_list * list, const char *filler) return buf; } -static int parse_entries(scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth); +static scconf_block **getblocks(const scconf_context * config, const scconf_block * block, scconf_entry * entry) +{ + scconf_block **blocks = NULL; -static int parse_type(scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) + blocks = scconf_find_blocks(config, block, entry->name, NULL); + if (blocks) { + if (blocks[0] != NULL) { + if (config->debug) { + fprintf(stderr, "block found (%s)\n", entry->name); + } + return blocks; + } + free(blocks); + blocks = NULL; + } + if (scconf_find_list(block, entry->name) != NULL) { + if (config->debug) { + fprintf(stderr, "list found (%s)\n", entry->name); + } + blocks = (scconf_block **) realloc(blocks, sizeof(scconf_block *) * 2); + if (!blocks) + return NULL; + blocks[0] = (scconf_block *) block; + blocks[1] = NULL; + } + return blocks; +} + +static int parse_entries(const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth); + +static int parse_type(const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) { void *parm = entry->parm; - int (*callback_func) (scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) = - (int (*)(scconf_context *, const scconf_block *, scconf_entry *, int)) parm; size_t *len = (size_t *) entry->arg; + int (*callback_func) (const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) = + (int (*)(const scconf_context *, const scconf_block *, scconf_entry *, int)) parm; int r = 0; if (config->debug) { @@ -429,7 +491,7 @@ static int parse_type(scconf_context * config, const scconf_block * block, sccon break; case SCCONF_INTEGER: { - int val = scconf_get_int(block, entry->name, 42); + int val = scconf_get_int(block, entry->name, 0); if (parm) { *((int *) parm) = val; @@ -480,35 +542,7 @@ static int parse_type(scconf_context * config, const scconf_block * block, sccon return 0; } -static scconf_block **getblocks(scconf_context * config, const scconf_block * block, scconf_entry * entry) -{ - scconf_block **blocks = NULL; - - blocks = scconf_find_blocks(config, block, entry->name, NULL); - if (blocks) { - if (blocks[0] != NULL) { - if (config->debug) { - fprintf(stderr, "block found (%s)\n", entry->name); - } - return blocks; - } - free(blocks); - blocks = NULL; - } - if (scconf_find_list(block, entry->name) != NULL) { - if (config->debug) { - fprintf(stderr, "list found (%s)\n", entry->name); - } - blocks = (scconf_block **) realloc(blocks, sizeof(scconf_block *) * 2); - if (!blocks) - return NULL; - blocks[0] = (scconf_block *) block; - blocks[1] = NULL; - } - return blocks; -} - -static int parse_entries(scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) +static int parse_entries(const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) { int r, i, idx; scconf_entry *e; @@ -545,7 +579,7 @@ static int parse_entries(scconf_context * config, const scconf_block * block, sc return 0; } -int scconf_parse_entries(scconf_context * config, const scconf_block * block, scconf_entry * entry) +int scconf_parse_entries(const scconf_context * config, const scconf_block * block, scconf_entry * entry) { if (!entry) return 1; @@ -553,3 +587,112 @@ int scconf_parse_entries(scconf_context * config, const scconf_block * block, sc block = config->root; return parse_entries(config, block, entry, 0); } + +static int write_entries(scconf_context * config, scconf_block * block, scconf_entry * entry, int depth); + +static int write_type(scconf_context * config, scconf_block * block, scconf_entry * entry, int depth) +{ + void *parm = entry->parm; + void *arg = entry->arg; + int (*callback_func) (scconf_context * config, scconf_block * block, scconf_entry * entry, int depth) = + (int (*)(scconf_context *, scconf_block *, scconf_entry *, int)) parm; + int r = 0; + + if (config->debug) { + fprintf(stderr, "encoding '%s'\n", entry->name); + } + switch (entry->type) { + case SCCONF_CALLBACK: + if (parm) { + r = callback_func(config, block, entry, depth); + } + break; + case SCCONF_BLOCK: + if (parm) { + scconf_block *subblock; + const scconf_list *name = (const scconf_list *) arg; + + subblock = scconf_block_add(config, block, entry->name, name); + r = write_entries(config, subblock, (scconf_entry *) parm, depth + 1); + } + break; + case SCCONF_LIST: + if (parm) { + const scconf_list *val = (const scconf_list *) parm; + + scconf_item_add(config, block, NULL, SCCONF_ITEM_TYPE_VALUE, entry->name, val); + if (entry->flags & SCCONF_VERBOSE) { + char *buf = scconf_list_strdup(val, ", "); + printf("%s = %s\n", entry->name, buf); + free(buf); + } + } + break; + case SCCONF_BOOLEAN: + if (parm) { + const int val = parm ? (int) parm : 0; + + scconf_put_bool(block, entry->name, val); + if (entry->flags & SCCONF_VERBOSE) { + printf("%s = %s\n", entry->name, val == 0 ? "false" : "true"); + } + } + break; + case SCCONF_INTEGER: + if (parm) { + const int val = parm ? (int) parm : 0; + + scconf_put_int(block, entry->name, val); + if (entry->flags & SCCONF_VERBOSE) { + printf("%s = %i\n", entry->name, val); + } + } + break; + case SCCONF_STRING: + if (parm) { + const char *val = parm ? (const char *) parm : ""; + + scconf_put_str(block, entry->name, val); + if (entry->flags & SCCONF_VERBOSE) { + printf("%s = %s\n", entry->name, val); + } + } + break; + default: + fprintf(stderr, "invalid configuration type: %d\n", entry->type); + } + if (r) { + fprintf(stderr, "encoding of configuration entry '%s' failed.\n", entry->name); + return r; + } + entry->flags |= SCCONF_PRESENT; + return 0; +} + +static int write_entries(scconf_context * config, scconf_block * block, scconf_entry * entry, int depth) +{ + int r, idx; + scconf_entry *e; + + if (config->debug) { + fprintf(stderr, "write_entries called, depth %d\n", depth); + } + for (idx = 0; entry[idx].name; idx++) { + e = &entry[idx]; + r = 0; + r = write_type(config, block, e, depth); + if (r) { + return r; + } + } + return 0; +} + +int scconf_write_entries(scconf_context * config, scconf_block * block, scconf_entry * entry) +{ + if (!entry) + return 1; + if (!block) + block = config->root; + return write_entries(config, block, entry, 0); +} diff --git a/src/scconf/scconf.h b/src/scconf/scconf.h index dd9b7be0..e7f878ef 100644 --- a/src/scconf/scconf.h +++ b/src/scconf/scconf.h @@ -102,7 +102,7 @@ extern int scconf_parse(scconf_context * config); /* Parse entries */ -int scconf_parse_entries(scconf_context * config, const scconf_block * block, scconf_entry * entry); +extern int scconf_parse_entries(const scconf_context * config, const scconf_block * block, scconf_entry * entry); /* Write config to a file * If the filename is NULL, use the config->filename @@ -110,6 +110,10 @@ int scconf_parse_entries(scconf_context * config, const scconf_block * block, sc */ extern int scconf_write(scconf_context * config, const char *filename); +/* Write configuration entries to block + */ +extern int scconf_write_entries(scconf_context * config, scconf_block * block, scconf_entry * entry); + /* Find a block by the item_name * If the block is NULL, the root block is used */ @@ -140,6 +144,18 @@ extern int scconf_get_int(const scconf_block * block, const char *option, int de */ extern int scconf_get_bool(const scconf_block * block, const char *option, int def); +/* Write value to a block as a string + */ +extern const char *scconf_put_str(scconf_block * block, const char *option, const char *value); + +/* Write value to a block as an integer + */ +extern int scconf_put_int(scconf_block * block, const char *option, int value); + +/* Write value to a block as a boolean + */ +extern int scconf_put_bool(scconf_block * block, const char *option, int value); + /* Add block structure * If the block is NULL, the root block is used */ diff --git a/src/scconf/test-conf.c b/src/scconf/test-conf.c index 62fa9b82..dfd1625e 100644 --- a/src/scconf/test-conf.c +++ b/src/scconf/test-conf.c @@ -30,7 +30,7 @@ #define ADD_TEST -static int ldap_cb(scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) +static int ldap_cb(const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) { scconf_entry ldap_entry[] = { @@ -58,7 +58,7 @@ static int ldap_cb(scconf_context * config, const scconf_block * block, scconf_e return 0; /* 0 for ok, 1 for error */ } -static int card_cb(scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) +static int card_cb(const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) { char *str = scconf_list_strdup(block->name, " "); scconf_entry card_entry[] = @@ -79,12 +79,39 @@ static int card_cb(scconf_context * config, const scconf_block * block, scconf_e return 0; /* 0 for ok, 1 for error */ } +static int write_cb(scconf_context * config, scconf_block * block, scconf_entry * entry, int depth) +{ + scconf_put_str(block, entry->name, "inside write_cb();"); + scconf_item_add(config, block, NULL, SCCONF_ITEM_TYPE_COMMENT, NULL, "# commentN"); + return 0; /* 0 for ok, 1 for error */ +} + +int write_entries(scconf_context *conf, scconf_list *list) +{ + scconf_entry subblock[] = + { + {"stringIT", SCCONF_STRING, SCCONF_VERBOSE, (void *) "sexy"}, + {"callback_str", SCCONF_CALLBACK, SCCONF_VERBOSE, (void *) write_cb}, + {NULL} + }; + scconf_entry wentry[] = + { + {"string", SCCONF_STRING, SCCONF_VERBOSE, (void *) "value1"}, + {"integer", SCCONF_INTEGER, SCCONF_VERBOSE, (void *) 42}, + {"sucks", SCCONF_BOOLEAN, SCCONF_VERBOSE, (void *) 1}, + {"listN", SCCONF_LIST, SCCONF_VERBOSE, (void *) list}, + {"blockN", SCCONF_BLOCK, SCCONF_VERBOSE, (void *) subblock, (void *) list}, + {NULL} + }; + return scconf_write_entries(conf, NULL, wentry); +} + int main(int argc, char **argv) { #ifdef ADD_TEST scconf_block *foo_block = NULL; - scconf_list *foo_list = NULL; scconf_item *foo_item = NULL; + scconf_list *foo_list = NULL; #endif scconf_context *conf = NULL; scconf_entry entry[] = @@ -130,12 +157,18 @@ int main(int argc, char **argv) scconf_list_add(&foo_list, "value3"); - foo_item = scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_COMMENT, "key", "# comment1"); + foo_item = scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_COMMENT, NULL, "# comment1"); foo_item = scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_VALUE, "list1", foo_list); foo_block = NULL; foo_item = scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_BLOCK, "block3", (void *) scconf_find_block(conf, NULL, "foo")); foo_item = scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_VALUE, "list2", foo_list); - foo_item = scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_COMMENT, "key", "# comment2"); + foo_item = scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_COMMENT, NULL, "# comment2"); + + if (write_entries(conf, foo_list) != 0) { + printf("scconf_write_entries failed\n"); + scconf_free(conf); + return 1; + } scconf_list_destroy(foo_list); #endif