]> git.itanic.dy.fi Git - log-plotter/blob - config.c
Add primitive config file parsing support
[log-plotter] / config.c
1 #include <stdio.h>
2 #include <glob.h>
3 #include <ctype.h>
4 #include <string.h>
5 #include <stdlib.h>
6
7 #include "config.h"
8 #include "trace.h"
9
10 static int parse_config_line(char *line, char **variable, char **value)
11 {
12 #define SKIP_UNTIL(_str, _cond)         \
13         while (*_str && (_cond))        \
14                 _str++;
15
16         SKIP_UNTIL(line, isspace(*line));
17
18         /* Skip comments */
19         if (*line == '#')
20                 return -1;
21
22         /* The actual variable name begins here */
23         *variable = line;
24
25         /* Find where the variable name ends */
26         SKIP_UNTIL(line, !isspace(*line) && *line != '=');
27
28         if (*line == '=') {
29                 *line = '\0';
30                 line++;
31                 goto value_start;
32         }
33
34         /* If we encounter line end already, the line can't be valid */
35         if (!*line)
36                 return -1;
37
38         /* Terminate the variable name */
39         *line = '\0';
40         line++;
41          
42         /* Find the equal sign */
43         SKIP_UNTIL(line, *line != '=');
44
45         if (*line != '=')
46                 return -1;
47         line++;
48
49         SKIP_UNTIL(line, isspace(*line));
50
51 value_start:
52         *value = line;
53
54         SKIP_UNTIL(line, *line != '\n' && *line != '#');
55         *line = 0;
56
57         return 0;
58 }
59
60 static int store_variable_value_to_plotter_config(const char *variable,
61                                                 const char *value,
62                                                 struct plotter_config *cfg)
63 {
64 #define TEST_STR_STORE_STR_RETURN(_cfg, _variable, _str, _value)        \
65         if (!strcmp(_variable, #_str) && !cfg->_str) {                  \
66                 cfg->_str = strdup(_value);                             \
67                 return 0;                                               \
68         }
69
70 #define TEST_STR_STORE_INT_RETURN(_cfg, _variable, _str, _value)        \
71         if (!strcmp(_variable, #_str)) {                                \
72                 cfg->_str = atoi(_value);                               \
73                 return 0;                                               \
74         }
75
76         TEST_STR_STORE_STR_RETURN(cfg, variable, charger_name, value);
77         TEST_STR_STORE_STR_RETURN(cfg, variable, plotter_scripts_dir, value);
78         TEST_STR_STORE_STR_RETURN(cfg, variable, images_output_dir, value);
79         TEST_STR_STORE_STR_RETURN(cfg, variable, device_path, value);
80         TEST_STR_STORE_STR_RETURN(cfg, variable, log_path, value);
81         TEST_STR_STORE_INT_RETURN(cfg, variable, baudrate, value);
82
83         return -1;
84 }
85
86 static int read_config_file(FILE *file, struct plotter_config *cfg)
87 {
88         char line[1024];
89         char *variable, *value;
90
91         while (fgets(line, sizeof(line), file)) {
92                 if (parse_config_line(line, &variable, &value))
93                         continue;
94
95                 if (!store_variable_value_to_plotter_config(variable, value,
96                                                                 cfg))
97                         continue;
98
99                 pr_debug("Discarding unsupported config variable %s\n",
100                         variable);
101         }
102
103         return 0;
104 }
105
106 int populate_config_data_from_file(const char *path,
107                                 struct plotter_config *cfg)
108 {
109         glob_t globbuf;
110         FILE *file;
111         int ret;
112
113         ret = glob(path, GLOB_TILDE, NULL, &globbuf);
114         if (ret)
115                 return -1;
116
117         if (globbuf.gl_pathc == 0) {
118                 pr_debug("No config file foud from path %s\n", path);
119                 return -1;
120         }
121
122         if (globbuf.gl_pathc > 1) {
123                 pr_warn("Found multiple config files from path %s, using the first one\n",
124                         path);
125         }
126
127         file = fopen(globbuf.gl_pathv[0], "r");
128         if (!file) {
129                 pr_err("Failed to open config file %s: %m\n",
130                         globbuf.gl_pathv[0]);
131                 return -1;
132         }
133
134         return read_config_file(file, cfg);
135 }