10 #define SKIP_UNTIL(_str, _cond) \
11 while (*_str && (_cond)) \
14 static int parse_config_line(char *line, char **variable, char **value)
16 SKIP_UNTIL(line, isspace(*line));
22 /* The actual variable name begins here */
25 /* Find where the variable name ends */
26 SKIP_UNTIL(line, !isspace(*line) && *line != '=');
34 /* If we encounter line end already, the line can't be valid */
38 /* Terminate the variable name */
42 /* Find the equal sign */
43 SKIP_UNTIL(line, *line != '=');
49 SKIP_UNTIL(line, isspace(*line));
54 SKIP_UNTIL(line, *line != '\n' && *line != '#');
60 static void init_variable_value(struct variable_value *v)
65 static int store_str_variable_value_to_array(const char *variable,
67 struct plotter_config *cfg)
69 struct variable_value *v;
72 if (!cfg->variables) {
74 realloc(cfg->variables, sizeof(*cfg->variables));
76 init_variable_value(cfg->variables);
80 for (i = 0; v[i].name; i++) {
81 if (strcmp(variable, v[i].name))
90 * Failed to find an existing variable with same type, create
91 * a new one. Resize the variable array so that there is room
92 * for the new entry and one terminator entry (with all fields
95 cfg->variables = realloc(cfg->variables,
96 sizeof(*cfg->variables) * (i + 2));
98 init_variable_value(&cfg->variables[i + 1]);
101 v[i].name = strdup(variable);
102 v[i].type = TYPE_STRING;
103 v[i].ptr = strdup(value);
108 static int store_variable_value_to_plotter_config(const char *variable,
110 struct plotter_config *cfg)
112 #define TEST_STR_STORE_STR_RETURN(_cfg, _variable, _str, _value) \
113 if (!strcmp(_variable, #_str) && !cfg->_str) { \
114 cfg->_str = strdup(_value); \
118 #define TEST_STR_STORE_INT_RETURN(_cfg, _variable, _str, _value) \
119 if (!strcmp(_variable, #_str)) { \
120 cfg->_str = atoi(_value); \
124 TEST_STR_STORE_STR_RETURN(cfg, variable, charger_name, value);
125 TEST_STR_STORE_STR_RETURN(cfg, variable, plotter_scripts_dir, value);
126 TEST_STR_STORE_STR_RETURN(cfg, variable, images_output_dir, value);
127 TEST_STR_STORE_STR_RETURN(cfg, variable, device_path, value);
128 TEST_STR_STORE_STR_RETURN(cfg, variable, log_path, value);
129 TEST_STR_STORE_INT_RETURN(cfg, variable, baudrate, value);
131 return store_str_variable_value_to_array(variable, value, cfg);
134 static int read_config_file(FILE *file, struct plotter_config *cfg)
137 char *variable, *value;
139 while (fgets(line, sizeof(line), file)) {
140 if (parse_config_line(line, &variable, &value))
143 if (!store_variable_value_to_plotter_config(variable, value,
147 pr_debug("Discarding unsupported config variable %s\n",
154 int populate_config_data_from_file(const char *path,
155 struct plotter_config *cfg)
161 ret = glob(path, GLOB_TILDE, NULL, &globbuf);
165 if (globbuf.gl_pathc == 0) {
166 pr_debug("No config file foud from path %s\n", path);
170 if (globbuf.gl_pathc > 1) {
171 pr_warn("Found multiple config files from path %s, using the first one\n",
175 file = fopen(globbuf.gl_pathv[0], "r");
177 pr_err("Failed to open config file %s: %m\n",
178 globbuf.gl_pathv[0]);
182 return read_config_file(file, cfg);
185 static char *get_value_for_variable(char *variable,
186 const struct plotter_config *cfg)
188 static char result[256];
189 struct variable_value *values = cfg->variables;
195 for (i = 0; values[i].name; i++) {
196 if (strcmp(values[i].name, variable))
199 switch (values[i].type) {
202 snprintf(result, sizeof(result), "%d", *ip);
206 snprintf(result, sizeof(result), "%s", cp);
209 pr_err("BUG: Unknown variable type %d\n",
220 static int replace_variable_with_value(char *str, size_t len,
221 char *variable_start, char *variable_end,
224 int value_len = strlen(value);
228 if (variable_end - variable_start >= value_len) {
230 * The replacement string is shorter than the variable
231 * name, this is the easy case, no need to worry about
235 strcpy(variable_start, value);
237 from = variable_end + 1;
238 to = variable_start + value_len;
249 * The replacement string is longer than the space
250 * occupied by the variable name. We need to first
251 * make room for the value, without overflowing the
252 * buffer. Make an overlapping scring copy, start from
257 * The closing parenthesis was replaced with null byte
258 * earlier, put a non-zero char there to avoid
259 * confusing strlen().
263 from = str + strlen(str);
264 to = from + (value_len - (variable_end - variable_start)) - 1;
265 if (to >= str + len - 1) {
270 while (from >= variable_end) {
277 * use memcpy to avoid NULL terminating prematurely
280 memcpy(variable_start, value, value_len);
287 * Replace variable names from a string with the variable
288 * contents. Variable names are in format: $(name)
290 int replace_variables_with_values(char *str, size_t len,
291 const struct plotter_config *cfg)
296 while (*ptr && ptr < str + len) {
297 char *replace_start, *variable_start, *variable_end, *value;
299 SKIP_UNTIL(ptr, *ptr != '$');
307 /* Skip if not in correct format */
312 variable_start = ptr;
314 SKIP_UNTIL(ptr, *ptr != ')');
320 value = get_value_for_variable(variable_start, cfg);
322 pr_debug("Could not substitute unknown variable name %s\n",
326 * Put back the closing parenthesis so that
327 * the line remains as it was
332 overflow = replace_variable_with_value(str, len, replace_start,
333 variable_end, value);
337 pr_err("String buffer overflow\n");