static int scconf_replace_str_list(scconf_block * block, const char *option, const char *value) { scconf_list *list = NULL; scconf_item *item; char *lstitem = NULL; char *next; while (value != NULL) { if ((next=strchr(value, ',')) != NULL) { lstitem = strndup(value, next-value); next++; } else { lstitem = strdup(value); } if (lstitem == NULL) return 1; scconf_list_add(&list, lstitem); value = next; free(lstitem); } item = scconf_item_add(NULL, block, NULL, SCCONF_ITEM_TYPE_VALUE, option, list); /* now clear out the item list */ scconf_list_destroy(item->value.list); item->value.list = list; /* adopt */ return 0; }
const char *scconf_put_str(scconf_block * block, const char *option, const char *value) { scconf_list *list = NULL; scconf_list_add(&list, value); scconf_item_add(NULL, block, NULL, SCCONF_ITEM_TYPE_VALUE, option, list); scconf_list_destroy(list); return value; }
scconf_list *scconf_list_copy(const scconf_list * src, scconf_list ** dst) { scconf_list *next; while (src) { next = src->next; scconf_list_add(dst, src->data); src = next; } return *dst; }
static const char *scconf_replace_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); /* now clear out the item list */ scconf_list_destroy(item->value.list); item->value.list = list; /* adopt */ return value; }
static void scconf_block_add_internal(scconf_parser * parser) { scconf_block *block; scconf_item *item; item = scconf_item_add_internal(parser, SCCONF_ITEM_TYPE_BLOCK); block = (scconf_block *) malloc(sizeof(scconf_block)); if (!block) { return; } memset(block, 0, sizeof(scconf_block)); block->parent = parser->block; item->value.block = block; if (!parser->name) { scconf_list_add(&parser->name, ""); } block->name = parser->name; parser->name = NULL; parser->block = block; parser->last_item = NULL; }
void scconf_parse_token(scconf_parser * parser, int token_type, const char *token) { scconf_item *item; int len; if (parser->error) { /* fatal error */ return; } switch (token_type) { case TOKEN_TYPE_NEWLINE: parser->line++; if (parser->last_token_type != TOKEN_TYPE_NEWLINE) { break; } /* fall through - treat empty lines as comments */ case TOKEN_TYPE_COMMENT: item = scconf_item_add_internal(parser, SCCONF_ITEM_TYPE_COMMENT); item->value.comment = token ? strdup(token) : NULL; break; case TOKEN_TYPE_STRING: { char *stoken = NULL; if ((parser->state & (STATE_VALUE | STATE_SET)) == (STATE_VALUE | STATE_SET)) { scconf_parse_warning_expect(parser, ";"); scconf_parse_reset_state(parser); } if (*token == '"') { /* quoted string, remove them */ token++; len = strlen(token); if (len < 1 || token[len - 1] != '"') { scconf_parse_warning_expect(parser, "\""); } else { /* stoken */ stoken = token ? strdup(token) : NULL; if (stoken) { stoken[len - 1] = '\0'; } } } if (!stoken) { stoken = token ? strdup(token) : NULL; } if (parser->state == 0) { /* key */ parser->key = stoken ? strdup(stoken) : NULL; parser->state = STATE_NAME; } else if (parser->state == STATE_NAME) { /* name */ parser->state |= STATE_SET; scconf_list_add(&parser->name, stoken); } else if (parser->state == STATE_VALUE) { /* value */ parser->state |= STATE_SET; scconf_list_add(&parser->current_item->value.list, stoken); } else { /* error */ scconf_parse_error_not_expect(parser, stoken); } if (stoken) { free(stoken); } stoken = NULL; } break; case TOKEN_TYPE_PUNCT: switch (*token) { case '{': if ((parser->state & STATE_NAME) == 0) { scconf_parse_error_not_expect(parser, "{"); break; } scconf_block_add_internal(parser); scconf_parse_reset_state(parser); break; case '}': if (parser->state != 0) { if ((parser->state & STATE_VALUE) == 0 || (parser->state & STATE_SET) == 0) { scconf_parse_error_not_expect(parser, "}"); break; } /* foo = bar } */ scconf_parse_warning_expect(parser, ";"); scconf_parse_reset_state(parser); } if (!parser->block->parent) { /* too many '}' */ scconf_parse_error(parser, "missing matching '{'"); break; } scconf_parse_parent(parser); break; case ',': if ((parser->state & (STATE_NAME | STATE_VALUE)) == 0) { scconf_parse_error_not_expect(parser, ","); } parser->state &= ~STATE_SET; break; case '=': if ((parser->state & STATE_NAME) == 0) { scconf_parse_error_not_expect(parser, "="); break; } scconf_item_add_internal(parser, SCCONF_ITEM_TYPE_VALUE); parser->state = STATE_VALUE; break; case ';': #if 0 if ((parser->state & STATE_VALUE) == 0 || (parser->state & STATE_SET) == 0) { scconf_parse_error_not_expect(parser, ";"); break; } #endif scconf_parse_reset_state(parser); break; default: snprintf(parser->emesg, sizeof(parser->emesg), "Line %d: bad token ignoring\n", parser->line); } break; } parser->last_token_type = token_type; }
static int parse_type(const scconf_context * config, const scconf_block * block, scconf_entry * entry, int depth) { void *parm = entry->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) { fprintf(stderr, "decoding '%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) { r = parse_entries(config, block, (scconf_entry *) parm, depth + 1); } break; case SCCONF_LIST: { const scconf_list *val = scconf_find_list(block, entry->name); if (!val) { r = 1; break; } if (parm) { if (entry->flags & SCCONF_ALLOC) { scconf_list *dest = NULL; for (; val != NULL; val = val->next) { if (!scconf_list_add(&dest, val->data)) { r = 1; break; } } *((scconf_list **) parm) = dest; } else { *((const scconf_list **) parm) = 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: { int val = scconf_get_bool(block, entry->name, 0); if (parm) { *((int *) parm) = val; } if (entry->flags & SCCONF_VERBOSE) { printf("%s = %s\n", entry->name, val == 0 ? "false" : "true"); } } break; case SCCONF_INTEGER: { int val = scconf_get_int(block, entry->name, 0); if (parm) { *((int *) parm) = val; } if (entry->flags & SCCONF_VERBOSE) { printf("%s = %i\n", entry->name, val); } } break; case SCCONF_STRING: { const char *val = scconf_get_str(block, entry->name, NULL); int vallen = val ? strlen(val) : 0; if (!vallen) { r = 1; break; } if (parm) { if (entry->flags & SCCONF_ALLOC) { char **buf = (char **) parm; *buf = malloc(vallen + 1); if (*buf == NULL) { r = 1; break; } memset(*buf, 0, vallen + 1); if (len) { *len = vallen; } parm = *buf; } memcpy((char *) parm, val, vallen); } 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, "decoding of configuration entry '%s' failed.\n", entry->name); return r; } entry->flags |= SCCONF_PRESENT; return 0; }
int main(int argc, char **argv) { #ifdef ADD_TEST scconf_block *foo_block = NULL; scconf_item *foo_item = NULL; scconf_list *foo_list = NULL; #endif scconf_context *conf = NULL; scconf_entry entry[] = { {"ldap", SCCONF_CALLBACK, SCCONF_VERBOSE | SCCONF_ALL_BLOCKS, (void *) ldap_cb, NULL}, {"card", SCCONF_CALLBACK, SCCONF_VERBOSE | SCCONF_ALL_BLOCKS, (void *) card_cb, NULL}, {NULL, 0, 0, NULL, NULL} }; char *in = NULL, *out = NULL; int r; if (argc != 3) { printf("Usage: test-conf <in.conf> <out.conf>\n"); return 1; } in = argv[argc - 2]; out = argv[argc - 1]; conf = scconf_new(in); if (!conf) { printf("scconf_new failed\n"); return 1; } if (scconf_parse(conf) < 1) { printf("scconf_parse failed: %s\n", conf->errmsg); scconf_free(conf); return 1; } conf->debug = 1; if (scconf_parse_entries(conf, NULL, entry) != 0) { printf("scconf_parse_entries failed\n"); scconf_free(conf); return 1; } #ifdef ADD_TEST scconf_list_add(&foo_list, "value1"); scconf_list_add(&foo_list, "value2"); foo_block = (scconf_block *) scconf_find_block(conf, NULL, "foo"); foo_block = scconf_block_add(conf, foo_block, "block1", foo_list); foo_block = scconf_block_add(conf, foo_block, "block2", foo_list); scconf_list_add(&foo_list, "value3"); /* this will not segfault as type SCCONF_ITEM_TYPE_COMMENT is used */ scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_COMMENT, NULL, "# comment1"); scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_VALUE, "list1", foo_list); foo_block = NULL; scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_BLOCK, "block3", (void *) scconf_find_block(conf, NULL, "foo")); scconf_item_add(conf, foo_block, foo_item, SCCONF_ITEM_TYPE_VALUE, "list2", foo_list); 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 if ((r = scconf_write(conf, out)) != 0) { printf("scconf_write: %s\n", strerror(r)); } else { printf("Successfully rewrote file \"%s\" as \"%s\"\n", in, out); } scconf_free(conf); return 0; }
int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm) { sc_context_t *ctx; struct _sc_ctx_options opts; int r; char *driver; if (ctx_out == NULL || parm == NULL) return SC_ERROR_INVALID_ARGUMENTS; ctx = calloc(1, sizeof(sc_context_t)); if (ctx == NULL) return SC_ERROR_OUT_OF_MEMORY; memset(&opts, 0, sizeof(opts)); /* set the application name if set in the parameter options */ if (parm->app_name != NULL) ctx->app_name = strdup(parm->app_name); else ctx->app_name = strdup("default"); if (ctx->app_name == NULL) { sc_release_context(ctx); return SC_ERROR_OUT_OF_MEMORY; } ctx->flags = parm->flags; set_defaults(ctx, &opts); if (0 != list_init(&ctx->readers)) { sc_release_context(ctx); return SC_ERROR_OUT_OF_MEMORY; } list_attributes_seeker(&ctx->readers, reader_list_seeker); /* set thread context and create mutex object (if specified) */ if (parm->thread_ctx != NULL) ctx->thread_ctx = parm->thread_ctx; r = sc_mutex_create(ctx, &ctx->mutex); if (r != SC_SUCCESS) { sc_release_context(ctx); return r; } #if defined(ENABLE_OPENSSL) && defined(OPENSSL_SECURE_MALLOC_SIZE) if (!CRYPTO_secure_malloc_initialized()) { CRYPTO_secure_malloc_init(OPENSSL_SECURE_MALLOC_SIZE, OPENSSL_SECURE_MALLOC_SIZE/8); } #endif process_config_file(ctx, &opts); sc_log(ctx, "==================================="); /* first thing in the log */ sc_log(ctx, "opensc version: %s", sc_get_version()); #ifdef ENABLE_PCSC ctx->reader_driver = sc_get_pcsc_driver(); #elif defined(ENABLE_CRYPTOTOKENKIT) ctx->reader_driver = sc_get_cryptotokenkit_driver(); #elif defined(ENABLE_CTAPI) ctx->reader_driver = sc_get_ctapi_driver(); #elif defined(ENABLE_OPENCT) ctx->reader_driver = sc_get_openct_driver(); #endif r = ctx->reader_driver->ops->init(ctx); if (r != SC_SUCCESS) { sc_release_context(ctx); return r; } driver = getenv("OPENSC_DRIVER"); if (driver) { scconf_list *list = NULL; scconf_list_add(&list, driver); set_drivers(&opts, list); scconf_list_destroy(list); } load_card_drivers(ctx, &opts); load_card_atrs(ctx); del_drvs(&opts); sc_ctx_detect_readers(ctx); *ctx_out = ctx; return SC_SUCCESS; }