| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | #include "common.h"#include "config.h"#include <esp_spiffs.h>#include <ctype.h>#define CONFIG_FILE	"/spiffs/config.txt"static int save_config(void);static bool is_end_of_string(int c){    return c <= 0 || c == '\n' || c == '\r';}/* * Note: the string must be mutable; use strdup() if necessary. * The "separator" allows the string to be separated into multiple * arguments; no other decoding is done. */static int set_config_string(char *str, unsigned int separator){    char *p, *q;    unsigned char c;    p = str;    do {	const char *var = p;	do {	    c = *p++;	} while (isalnum(c) || c == '.' || c == '-');	if (c != '=')	    return -EINVAL; /* Invalid config line (blank, comment...) */	p[-1] = '\0';	q = p;	do {	    c = *q++;	} while (!is_end_of_string(c) && c != separator);	/* Overlong line */	if (q >= str + MAX_CONFIG_LINE)	    return -EOVERFLOW;	q[-1] = '\0';	size_t nvar = sysvar_find(sysvar_ns_config, var);	if (nvar) {	    setvar_fromstr(nvar, p);	}	p = q;    } while (c == separator);    return 0;}static void finish_config_update(bool save){    if (sysvar_changed < sysvar_ns[sysvar_ns_status].first) {	if (save)	    save_config();	/* Can do other things here... */    }    sysvar_changed = sysvar_count;}/* * At the moment "url" just allows values to be separated by semicolons; * no other decoding is done, and '&' is not supported. */int set_config_url_string(const char *str){    char *wstr = strdup(str);    if (!wstr)	return -ENOMEM;    int err = set_config_string(wstr, ';');    free(wstr);    finish_config_update(true);    return err;}static void skip_rest_of_line(FILE *f){    int c;    do {	c = getc(f);    } while (!is_end_of_string(c));}/* Calling with with f == NULL just finalizes the update */int read_config(FILE *f, bool save){    char *linebuf = NULL;    int err = -1;    if (f) {	linebuf = malloc(MAX_CONFIG_LINE);	if (!linebuf) {	    err = -ENOMEM;	    goto exit;	}	while (fgets(linebuf, MAX_CONFIG_LINE, f)) {	    if (set_config_string(linebuf, -1) == -EOVERFLOW)		skip_rest_of_line(f);	}    }    err = 0;    if (linebuf)	free(linebuf);exit:    finish_config_update(save);    return err;};int write_sysvars(FILE *f, bool status){    size_t ns = status ? sysvar_ns_status : sysvar_ns_config;    const sysvar_ns_t * const nsi = &sysvar_ns[ns];    for (enum sysvar_enum var = nsi->first; var < nsi[1].first; var++) {	fputs(sysvar_name[var], f);	putc('=', f);	fputs(notempty(getvar_tostr(var)), f);	putc('\n', f);    }    return ferror(f) ? -1 : 0;}static int save_config(void){    int err = -ENOENT;    FILE *f = fopen(CONFIG_FILE, "w");    if (f) {	err = write_sysvars(f, false);	fclose(f);    }    if (err)	printf("[CONF] Failed to save configuration (error %d)\n", err);    return err;}static const esp_vfs_spiffs_conf_t spiffs_conf = {    .base_path              = "/spiffs",    .partition_label        = NULL,    .max_files              = 4,    .format_if_mount_failed = true};void init_config(void){    if (!esp_spiffs_mounted(spiffs_conf.partition_label)) {	esp_err_t err;	err = esp_vfs_spiffs_register(&spiffs_conf);	if (err)	    printf("[CONF] Failed to mount %s (error 0x%x)\n",		   spiffs_conf.base_path, err);    }    sysvar_reset(sysvar_ns_config);    FILE *f = fopen(CONFIG_FILE, "r");    if (!f)	printf("[CONF] No configuration file found, using defaults\n");    read_config(f, false);    if (f)	fclose(f);}void log_config_status(void){    const sysvar_ns_t *nsi = &sysvar_ns[0];    for (enum sysvar_enum var = 1; var < sysvar_count; var++) {	if (var >= nsi[1].first)	    nsi++;	logmsg(nsi->name, "%s = %s\n", sysvar_name[var],	       notempty(getvar_tostr(var)));    }}
 |