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 struct variable_value *prepare_slot_for_insertion(
66 struct plotter_config *cfg, const char *variable)
68 struct variable_value *v;
71 if (!cfg->variables) {
73 realloc(cfg->variables, sizeof(*cfg->variables));
75 init_variable_value(cfg->variables);
79 for (i = 0; v[i].name; i++) {
80 if (strcmp(variable, v[i].name))
92 * Failed to find an existing variable with same name, create
93 * a new one. Resize the variable array so that there is room
94 * for the new entry and one terminator entry (with all fields
97 cfg->variables = realloc(cfg->variables,
98 sizeof(*cfg->variables) * (i + 2));
100 init_variable_value(&cfg->variables[i + 1]);
105 static int store_str_variable_value_to_array(const char *variable,
107 struct plotter_config *cfg)
109 struct variable_value *v;
111 v = prepare_slot_for_insertion(cfg, variable);
113 v->name = strdup(variable);
114 v->type = TYPE_STRING;
115 v->ptr = strdup(value);
120 int store_int_variable_value_to_array(const char *variable, int value,
121 struct plotter_config *cfg)
123 struct variable_value *v;
126 v = prepare_slot_for_insertion(cfg, variable);
128 v->name = strdup(variable);
130 p = v->ptr = malloc(sizeof(value));
136 static int store_variable_value_to_plotter_config(const char *variable,
138 struct plotter_config *cfg)
140 #define TEST_STR_STORE_STR_RETURN(_cfg, _variable, _str, _value) \
141 if (!strcmp(_variable, #_str) && !cfg->_str) { \
142 cfg->_str = strdup(_value); \
146 #define TEST_STR_STORE_INT_RETURN(_cfg, _variable, _str, _value) \
147 if (!strcmp(_variable, #_str)) { \
148 cfg->_str = atoi(_value); \
152 TEST_STR_STORE_STR_RETURN(cfg, variable, charger_name, value);
153 TEST_STR_STORE_STR_RETURN(cfg, variable, plotter_scripts_dir, value);
154 TEST_STR_STORE_STR_RETURN(cfg, variable, images_output_dir, value);
155 TEST_STR_STORE_STR_RETURN(cfg, variable, device_path, value);
156 TEST_STR_STORE_STR_RETURN(cfg, variable, log_path, value);
157 TEST_STR_STORE_INT_RETURN(cfg, variable, baudrate, value);
159 return store_str_variable_value_to_array(variable, value, cfg);
162 static int read_config_file(FILE *file, struct plotter_config *cfg)
165 char *variable, *value;
167 while (fgets(line, sizeof(line), file)) {
168 if (parse_config_line(line, &variable, &value))
171 if (!store_variable_value_to_plotter_config(variable, value,
175 pr_debug("Discarding unsupported config variable %s\n",
182 int populate_config_data_from_file(const char *path,
183 struct plotter_config *cfg)
189 ret = glob(path, GLOB_TILDE, NULL, &globbuf);
193 if (globbuf.gl_pathc == 0) {
194 pr_debug("No config file foud from path %s\n", path);
198 if (globbuf.gl_pathc > 1) {
199 pr_warn("Found multiple config files from path %s, using the first one\n",
203 file = fopen(globbuf.gl_pathv[0], "r");
205 pr_err("Failed to open config file %s: %m\n",
206 globbuf.gl_pathv[0]);
210 return read_config_file(file, cfg);
213 static char *get_value_for_variable(char *variable,
214 const struct plotter_config *cfg)
216 static char result[256];
217 struct variable_value *values = cfg->variables;
223 for (i = 0; values[i].name; i++) {
224 if (strcmp(values[i].name, variable))
227 switch (values[i].type) {
230 snprintf(result, sizeof(result), "%d", *ip);
234 snprintf(result, sizeof(result), "%s", cp);
237 pr_err("BUG: Unknown variable type %d\n",
248 static int replace_variable_with_value(char *str, size_t len,
249 char *variable_start, char *variable_end,
252 int value_len = strlen(value);
256 if (variable_end - variable_start >= value_len) {
258 * The replacement string is shorter than the variable
259 * name, this is the easy case, no need to worry about
263 strcpy(variable_start, value);
265 from = variable_end + 1;
266 to = variable_start + value_len;
277 * The replacement string is longer than the space
278 * occupied by the variable name. We need to first
279 * make room for the value, without overflowing the
280 * buffer. Make an overlapping scring copy, start from
285 * The closing parenthesis was replaced with null byte
286 * earlier, put a non-zero char there to avoid
287 * confusing strlen().
291 from = str + strlen(str);
292 to = from + (value_len - (variable_end - variable_start)) - 1;
293 if (to >= str + len - 1) {
298 while (from >= variable_end) {
305 * use memcpy to avoid NULL terminating prematurely
308 memcpy(variable_start, value, value_len);
315 * Replace variable names from a string with the variable
316 * contents. Variable names are in format: $(name)
318 int replace_variables_with_values(char *str, size_t len,
319 const struct plotter_config *cfg)
324 while (*ptr && ptr < str + len) {
325 char *replace_start, *variable_start, *variable_end, *value;
327 SKIP_UNTIL(ptr, *ptr != '$');
335 /* Skip if not in correct format */
340 variable_start = ptr;
342 SKIP_UNTIL(ptr, *ptr != ')');
348 value = get_value_for_variable(variable_start, cfg);
350 pr_debug("Could not substitute unknown variable name %s\n",
354 * Put back the closing parenthesis so that
355 * the line remains as it was
360 overflow = replace_variable_with_value(str, len, replace_start,
361 variable_end, value);
365 pr_err("String buffer overflow\n");