Commit b427927f authored by Adrian Reber's avatar Adrian Reber Committed by Andrei Vagin

config: use dynamic variables for configuration files

The code to read and parse configuration files was writing the result of
the global configuration file to one variable and the result from the
configuration file in the user's home to another variable:

  char **global_conf = NULL;
  char **user_conf = NULL;

With this change the code now uses dynamic memory allocation to handle
the different configuration files.

It used to be:

  * parse global config
  * parse user config
  * evaluate global config
  * evaluate user config
  * evaluate CLI

And now it is:

  * parse global config
  * evaluate global config
  * parse user config
  * evaluate user config
  * evaluate CLI

This change is in preparation for the upcoming setting of a
configuration file via environment variable and RPC configuration file
usage.
Signed-off-by: 's avatarAdrian Reber <areber@redhat.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 4bd4b5fc
...@@ -31,9 +31,6 @@ ...@@ -31,9 +31,6 @@
struct cr_options opts; struct cr_options opts;
char **global_conf = NULL;
char **user_conf = NULL;
static int count_elements(char **to_count) static int count_elements(char **to_count)
{ {
int count = 0; int count = 0;
...@@ -152,37 +149,60 @@ static char ** parse_config(char *filepath) ...@@ -152,37 +149,60 @@ static char ** parse_config(char *filepath)
return configuration; return configuration;
} }
static void init_configuration(int argc, char *argv[], bool no_default_config, #define PARSING_GLOBAL_CONF 1
char *cfg_file) #define PARSING_USER_CONF 2
#define PARSING_ENV_CONF 3
#define PARSING_CMDLINE_CONF 4
#define PARSING_ARGV 5
static int next_config(char **argv, char ***_argv, bool no_default_config,
int state, char *cfg_file)
{ {
char local_filepath[PATH_MAX + 1]; char local_filepath[PATH_MAX + 1];
char *home_dir = getenv("HOME"); char *home_dir = NULL;
if ((cfg_file == NULL) && (!no_default_config)) { if (state > PARSING_ARGV)
global_conf = parse_config(GLOBAL_CONFIG_DIR DEFAULT_CONFIG_FILENAME); return 0;
if (!home_dir) {
pr_info("Unable to get $HOME directory, local configuration file will not be used."); switch(state) {
} else { case PARSING_GLOBAL_CONF:
snprintf(local_filepath, PATH_MAX, "%s/%s%s", if (no_default_config)
home_dir, USER_CONFIG_DIR, DEFAULT_CONFIG_FILENAME); break;
user_conf = parse_config(local_filepath); *_argv = parse_config(GLOBAL_CONFIG_DIR DEFAULT_CONFIG_FILENAME);
} break;
} else if (cfg_file != NULL) { case PARSING_USER_CONF:
global_conf = parse_config(cfg_file); if (no_default_config)
if (global_conf == NULL) { break;
pr_err("Can't access configuration file %s.\n", cfg_file); home_dir = getenv("HOME");
exit(1); if (!home_dir) {
} pr_info("Unable to get $HOME directory, local configuration file will not be used.");
} else {
snprintf(local_filepath, PATH_MAX, "%s/%s%s",
home_dir, USER_CONFIG_DIR, DEFAULT_CONFIG_FILENAME);
*_argv = parse_config(local_filepath);
}
break;
case PARSING_ENV_CONF:
break;
case PARSING_CMDLINE_CONF:
if (!cfg_file)
break;
*_argv = parse_config(cfg_file);
break;
case PARSING_ARGV:
*_argv = argv;
break;
default:
break;
} }
return ++state;
} }
static int init_config(int argc, char **argv, int *global_cfg_argc, int *user_cfg_argc, static int pre_parse(int argc, char **argv, bool *usage_error, bool *no_default_config,
bool *usage_error) char **cfg_file)
{ {
bool no_default_config = false;
char *cfg_file = NULL;
int i; int i;
/* /*
* We are runnning before getopt(), so we need to pre-parse * We are runnning before getopt(), so we need to pre-parse
* the command line. * the command line.
...@@ -200,24 +220,20 @@ static int init_config(int argc, char **argv, int *global_cfg_argc, int *user_cf ...@@ -200,24 +220,20 @@ static int init_config(int argc, char **argv, int *global_cfg_argc, int *user_cf
*usage_error = false; *usage_error = false;
return 1; return 1;
} else if (!strcmp(argv[i], "--no-default-config")) { } else if (!strcmp(argv[i], "--no-default-config")) {
no_default_config = true; *no_default_config = true;
} else if (!strcmp(argv[i], "--config")) { } else if (!strcmp(argv[i], "--config")) {
/* /*
* getopt takes next string as required * getopt takes next string as required
* argument automatically, we do the same * argument automatically, we do the same
*/ */
cfg_file = argv[i + 1]; *cfg_file = argv[i + 1];
*no_default_config = true;
} else if (strstr(argv[i], "--config=") != NULL) { } else if (strstr(argv[i], "--config=") != NULL) {
cfg_file = argv[i] + strlen("--config="); *cfg_file = argv[i] + strlen("--config=");
*no_default_config = true;
} }
} }
init_configuration(argc, argv, no_default_config, cfg_file);
if (global_conf != NULL)
*global_cfg_argc = count_elements(global_conf);
if (user_conf != NULL)
*user_cfg_argc = count_elements(user_conf);
return 0; return 0;
} }
...@@ -374,10 +390,6 @@ static int parse_join_ns(const char *ptr) ...@@ -374,10 +390,6 @@ static int parse_join_ns(const char *ptr)
return 0; return 0;
} }
#define PARSING_GLOBAL_CONF 1
#define PARSING_USER_CONF 2
#define PARSING_ARGV 3
/* /*
* parse_options() is the point where the getopt parsing happens. The CLI * parse_options() is the point where the getopt parsing happens. The CLI
* parsing as well as the configuration file parsing happens here. * parsing as well as the configuration file parsing happens here.
...@@ -389,10 +401,13 @@ static int parse_join_ns(const char *ptr) ...@@ -389,10 +401,13 @@ static int parse_join_ns(const char *ptr)
int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd) int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd)
{ {
int state = PARSING_GLOBAL_CONF; int state = PARSING_GLOBAL_CONF;
int global_cfg_argc = 0, user_cfg_argc = 0;
int ret; int ret;
int opt; int opt = -1;
int idx; int idx;
bool no_default_config = false;
char *cfg_file = NULL;
char **_argv = NULL;
int _argc = 0;
#define BOOL_OPT(OPT_NAME, SAVE_TO) \ #define BOOL_OPT(OPT_NAME, SAVE_TO) \
...@@ -479,54 +494,55 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd) ...@@ -479,54 +494,55 @@ int parse_options(int argc, char **argv, bool *usage_error, bool *has_exec_cmd)
#undef BOOL_OPT #undef BOOL_OPT
ret = pre_parse(argc, argv, usage_error, &no_default_config,
&cfg_file);
ret = init_config(argc, argv, &global_cfg_argc, &user_cfg_argc,
usage_error);
if (ret) if (ret)
return 2; return 2;
while (1) { while (1) {
char **_argv = NULL;
int _argc = 0;
idx = -1; idx = -1;
/* Only if opt is -1 we are going to the next configuration input */
switch (state) {
case PARSING_GLOBAL_CONF:
_argc = global_cfg_argc;
_argv = global_conf;
break;
case PARSING_USER_CONF:
_argc = user_cfg_argc;
_argv = user_conf;
break;
case PARSING_ARGV:
_argc = argc;
_argv = argv;
break;
default:
BUG();
}
opt = getopt_long(_argc, _argv, short_opts, long_opts, &idx);
if (opt == -1) { if (opt == -1) {
switch (state) { /* Do not free any memory if it points to argv */
case PARSING_GLOBAL_CONF: if (state != PARSING_ARGV + 1) {
case PARSING_USER_CONF: int i;
if (optind < _argc) { for (i=1; i < _argc; i++) {
pr_err("Unknown config parameter: %s\n", _argv[optind]); free(_argv[i]);
return -1;
} }
break; free(_argv);
;
} }
if (state < PARSING_ARGV) { /* This needs to be reset for a new getopt() run */
state++; _argc = 0;
optind = 0; _argv = NULL;
continue;
} else { state = next_config(argv, &_argv, no_default_config, state, cfg_file);
/* if next_config() returns 0 it means no more configs found */
if (state == 0)
break; break;
}
if (!_argv)
continue;
_argc = count_elements(_argv);
optind = 0;
} }
opt = getopt_long(_argc, _argv, short_opts, long_opts, &idx);
/*
* The end of the current _argv has been reached,
* let's go to the next _argv
*/
if (opt == -1)
continue;
/*
* If opt == 0 then getopt will directly fill out the corresponding
* field in CRIU's opts structure.
*/
if (!opt) if (!opt)
continue; continue;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment