--- /dev/null
+#include <stdio.h>
+#include <glob.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "trace.h"
+
+static int parse_config_line(char *line, char **variable, char **value)
+{
+#define SKIP_UNTIL(_str, _cond) \
+ while (*_str && (_cond)) \
+ _str++;
+
+ SKIP_UNTIL(line, isspace(*line));
+
+ /* Skip comments */
+ if (*line == '#')
+ return -1;
+
+ /* The actual variable name begins here */
+ *variable = line;
+
+ /* Find where the variable name ends */
+ SKIP_UNTIL(line, !isspace(*line) && *line != '=');
+
+ if (*line == '=') {
+ *line = '\0';
+ line++;
+ goto value_start;
+ }
+
+ /* If we encounter line end already, the line can't be valid */
+ if (!*line)
+ return -1;
+
+ /* Terminate the variable name */
+ *line = '\0';
+ line++;
+
+ /* Find the equal sign */
+ SKIP_UNTIL(line, *line != '=');
+
+ if (*line != '=')
+ return -1;
+ line++;
+
+ SKIP_UNTIL(line, isspace(*line));
+
+value_start:
+ *value = line;
+
+ SKIP_UNTIL(line, *line != '\n' && *line != '#');
+ *line = 0;
+
+ return 0;
+}
+
+static int store_variable_value_to_plotter_config(const char *variable,
+ const char *value,
+ struct plotter_config *cfg)
+{
+#define TEST_STR_STORE_STR_RETURN(_cfg, _variable, _str, _value) \
+ if (!strcmp(_variable, #_str) && !cfg->_str) { \
+ cfg->_str = strdup(_value); \
+ return 0; \
+ }
+
+#define TEST_STR_STORE_INT_RETURN(_cfg, _variable, _str, _value) \
+ if (!strcmp(_variable, #_str)) { \
+ cfg->_str = atoi(_value); \
+ return 0; \
+ }
+
+ TEST_STR_STORE_STR_RETURN(cfg, variable, charger_name, value);
+ TEST_STR_STORE_STR_RETURN(cfg, variable, plotter_scripts_dir, value);
+ TEST_STR_STORE_STR_RETURN(cfg, variable, images_output_dir, value);
+ TEST_STR_STORE_STR_RETURN(cfg, variable, device_path, value);
+ TEST_STR_STORE_STR_RETURN(cfg, variable, log_path, value);
+ TEST_STR_STORE_INT_RETURN(cfg, variable, baudrate, value);
+
+ return -1;
+}
+
+static int read_config_file(FILE *file, struct plotter_config *cfg)
+{
+ char line[1024];
+ char *variable, *value;
+
+ while (fgets(line, sizeof(line), file)) {
+ if (parse_config_line(line, &variable, &value))
+ continue;
+
+ if (!store_variable_value_to_plotter_config(variable, value,
+ cfg))
+ continue;
+
+ pr_debug("Discarding unsupported config variable %s\n",
+ variable);
+ }
+
+ return 0;
+}
+
+int populate_config_data_from_file(const char *path,
+ struct plotter_config *cfg)
+{
+ glob_t globbuf;
+ FILE *file;
+ int ret;
+
+ ret = glob(path, GLOB_TILDE, NULL, &globbuf);
+ if (ret)
+ return -1;
+
+ if (globbuf.gl_pathc == 0) {
+ pr_debug("No config file foud from path %s\n", path);
+ return -1;
+ }
+
+ if (globbuf.gl_pathc > 1) {
+ pr_warn("Found multiple config files from path %s, using the first one\n",
+ path);
+ }
+
+ file = fopen(globbuf.gl_pathv[0], "r");
+ if (!file) {
+ pr_err("Failed to open config file %s: %m\n",
+ globbuf.gl_pathv[0]);
+ return -1;
+ }
+
+ return read_config_file(file, cfg);
+}
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
+#include <string.h>
#include "options.h"
+#include "config.h"
#include "baud.h"
#include "trace.h"
#include "data.h"
int main(int argc, char *argv[])
{
struct plotter_options options;
+ struct plotter_config cfg;
int fd, baud, ret = 0, out_fd = 0;
+ bzero(&cfg, sizeof(cfg));
+
if (read_args(argc, argv, &options))
return 1;
+ if (options.config_file_path)
+ populate_config_data_from_file(options.config_file_path, &cfg);
+
baud = options.baud_rate;
fd = open_at_baud(options.device_path, &baud);
if (fd < 0)
pr_info(" -o, --output logfile path, stdout only if omited\n");
pr_info(" -v, --verbose increase verbosity\n");
pr_info(" -q, --quiet decrease verbosity\n");
+ pr_info(" -c, --config=PATH config file path\n");
pr_info(" -h, --help show this help\n");
exit(0);
{ .val = 'b', .name = "baud", .has_arg = 1 },
{ .val = 'v', .name = "verbose", .has_arg = 2 },
{ .val = 'q', .name = "quiet", },
+ { .val = 'c', .name = "config", .has_arg = 1 },
{ .val = 'h', .name = "help", },
};
- char short_options[] = "d:o:b:vqh";
+ char short_options[] = "d:o:b:vqc:h";
set_default_options(opts);
trace_level--;
pr_debug("Degreased trace level to %d\n", trace_level);
break;
+ case 'c':
+ opts->config_file_path = optarg;
+ break;
case 'h':
print_help_and_die(argv[0]);
break;