/* This file is part of Eclat.
Copyright (C) 2012 Sergey Poznyakoff.
Eclat is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Eclat is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Eclat. If not, see . */
#include "eclat.h"
struct config_finish_hook_entry
{
struct config_finish_hook_entry *next;
config_finish_hook_t fun;
void *data;
};
static struct config_finish_hook_entry *cfh_head, *cfh_tail;
void
add_config_finish_hook(config_finish_hook_t fun, void *data)
{
struct config_finish_hook_entry *ent = grecs_malloc(sizeof(*ent));
ent->next = NULL;
ent->fun = fun;
ent->data = data;
if (cfh_tail)
cfh_tail->next = ent;
else
cfh_head = ent;
cfh_tail = ent;
}
int
run_config_finish_hooks()
{
struct config_finish_hook_entry *p;
int rc = 0;
for (p = cfh_head; p; p = p->next)
rc |= p->fun(p->data);
return rc;
}
/* Translation table: region -> endpoint. Its elements are of
struct ec2_param type. */
struct grecs_symtab *ec2_regtab;
char *
region_to_endpoint(const char *region)
{
struct ec2_param *p, key;
key.name = (char*) region;
p = grecs_symtab_lookup_or_install(ec2_regtab, &key, NULL);
return p ? p->value : NULL;
}
static int
cb_region(enum grecs_callback_command cmd,
grecs_locus_t *locus,
void *varptr,
grecs_value_t *value,
void *cb_data)
{
struct ec2_param *p, key;
int install = 1;
if (cmd != grecs_callback_set_value) {
grecs_error(locus, 0, "Unexpected block statement");
return 1;
}
if (!value || value->type != GRECS_TYPE_ARRAY || value->v.arg.c != 2) {
grecs_error(locus, 0, "expected two strings");
return 1;
}
if (value->v.arg.v[0]->type != GRECS_TYPE_STRING ||
value->v.arg.v[1]->type != GRECS_TYPE_STRING) {
grecs_error(locus, 0, "expected two strings");
return 1;
}
key.name = value->v.arg.v[0]->v.string;
p = grecs_symtab_lookup_or_install(ec2_regtab, &key, &install);
if (!install)
free(p->value); /* FIXME: Redefinition warning */
p->value = grecs_strdup(value->v.arg.v[1]->v.string);
return 0;
}
static struct grecs_keyword eclat_kw[] = {
{ "default-endpoint", "hostname",
"Set default EC2 endpoint",
grecs_type_string, GRECS_DFLT, &endpoint },
{ "region", " ",
"Define a region",
grecs_type_string, GRECS_MULT, NULL, 0, cb_region },
{ "access-file", "file",
"Specify a file containing `accessID:accessKey' pairs",
grecs_type_string, GRECS_DFLT, &access_file_name },
{ "default-region", "name",
"Define default AWS region",
grecs_type_string, GRECS_DFLT, ®ion_name },
{ NULL }
};
void
config_help()
{
static char docstring[] =
N_("Configuration file structure for eclat.\n"
"For more information, use `info eclat configuration'.");
grecs_print_docstring(docstring, 0, stdout);
grecs_print_statement_array(eclat_kw, 1, 0, stdout);
}
static void
grecs_print_diag(grecs_locus_t const *locus, int err, int errcode,
const char *msg)
{
diag(locus, err ? NULL : "warning", "%s", msg);
}
void
config_init()
{
grecs_include_path_setup(DEFAULT_VERSION_INCLUDE_DIR,
DEFAULT_INCLUDE_DIR, NULL);
grecs_preprocessor = DEFAULT_PREPROCESSOR;
grecs_log_to_stderr = 1;
grecs_adjust_string_locations = 1;
grecs_print_diag_fun = grecs_print_diag;
ec2_regtab = grecs_symtab_create_default(sizeof(struct ec2_param));
}
void
config_finish(struct grecs_node *tree)
{
struct grecs_node *node;
grecs_tree_reduce(tree, eclat_kw, GRECS_AGGR);
if (debug_level[ECLAT_DEBCAT_CONF]) {
grecs_print_node(tree, GRECS_NODE_FLAG_DEFAULT, stderr);
fputc('\n', stdout);
}
if (grecs_tree_process(tree, eclat_kw))
exit(EX_CONFIG);
if (grecs_error_count || run_config_finish_hooks())
exit(EX_CONFIG);
}