Allow configuration file to include another recursively
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
diff --git a/README b/README
index c6a9763..59ab844 100644
--- a/README
+++ b/README
@@ -224,6 +224,10 @@ EXECUTIVE SUMMARY ON USAGE:
After saving configuration from the menu, you do not need to give cgminer any
arguments and it will load your configuration.
+Any configuration file may also contain a single
+ "include" : "filename"
+to recursively include another configuration file.
+
Single pool, regular desktop:
diff --git a/cgminer.c b/cgminer.c
index 8011a41..aacef35 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -197,6 +197,13 @@ char *opt_socks_proxy = NULL;
static const char def_conf[] = "cgminer.conf";
static bool config_loaded = false;
+static char *include_conf = NULL;
+static int include_count = 0;
+#define JSON_INCLUDE_CONF "include"
+#define JSON_LOAD_ERROR "JSON decode of file '%s' failed"
+#define JSON_LOAD_ERROR_LEN strlen(JSON_LOAD_ERROR)
+#define JSON_MAX_DEPTH 10
+#define JSON_MAX_DEPTH_ERR "Too many levels of JSON includes (limit 10) or a loop"
#if defined(unix)
static char *opt_stderr_cmd = NULL;
@@ -850,6 +857,8 @@ static struct opt_table opt_config_table[] = {
OPT_ENDTABLE
};
+static char *load_config(const char *arg, void __maybe_unused *unused);
+
static char *parse_config(json_t *config, bool fileconf)
{
static char err_buf[200];
@@ -905,6 +914,15 @@ static char *parse_config(json_t *config, bool fileconf)
}
free(name);
}
+
+ val = json_object_get(config, JSON_INCLUDE_CONF);
+ if (val && json_is_string(val)) {
+ if (include_conf == NULL)
+ include_conf = (char *)json_string_value(val);
+
+ return load_config(json_string_value(val), NULL);
+ }
+
return NULL;
}
@@ -912,14 +930,24 @@ static char *load_config(const char *arg, void __maybe_unused *unused)
{
json_error_t err;
json_t *config;
+ char *json_error;
+
+ if(++include_count > JSON_MAX_DEPTH)
+ return JSON_MAX_DEPTH_ERR;
#if JANSSON_MAJOR_VERSION > 1
config = json_load_file(arg, 0, &err);
#else
config = json_load_file(arg, &err);
#endif
- if (!json_is_object(config))
- return "JSON decode of file failed";
+ if (!json_is_object(config)) {
+ json_error = malloc(JSON_LOAD_ERROR_LEN + strlen(arg));
+ if (!json_error)
+ quit(1, "Malloc failure in json error");
+
+ sprintf(json_error, JSON_LOAD_ERROR, arg);
+ return json_error;
+ }
config_loaded = true;
/* Parse the config now, so we can override it. That can keep pointers
@@ -2449,10 +2477,12 @@ void write_config(FILE *fcfg)
for (i = 0; i < nDevs; i++)
if (gpus[i].deven != DEV_DISABLED)
fprintf(fcfg, ",\n\"device\" : \"%d\"", i);
- if (opt_api_allow != NULL)
+ if (opt_api_allow)
fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", opt_api_allow);
if (strcmp(opt_api_description, PACKAGE_STRING) != 0)
fprintf(fcfg, ",\n\"api-description\" : \"%s\"", opt_api_description);
+ if (include_conf)
+ fprintf(fcfg, ",\n\"%s\" : \"%s\"", JSON_INCLUDE_CONF, include_conf);
fputs("\n}", fcfg);
}