| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 | 
							- #include "common.h"
 
- #include "config.h"
 
- #include <esp_spiffs.h>
 
- #include <ctype.h>
 
- #define CONFIG_FILE	"/spiffs/config.txt"
 
- struct env_var {
 
-     const char *var, *val;
 
- };
 
- static const struct env_var default_config[] = {
 
-     {"LANG","sv"},
 
-     {"TZ", "CET-1CEST,M3.5.0,M10.5.0/3"}, /* Sweden */
 
-     {"tzname", "Europe/Stockholm"},
 
-     {"hostname", "max80"},
 
-     {"sntp.enabled", "1"},
 
-     {"sntp.server","time.max80.abc80.org"},
 
-     {"abc.hosttype","auto"}
 
- };
 
- static int save_config(void);
 
- static bool config_changed;
 
- int setenv_config(const char *name, const char *value)
 
- {
 
-     config_changed = true;
 
-     if (name[0] == '-') {
 
- 	name++;
 
- 	value = NULL;
 
-     }
 
-     return setenv_cond(name, value);
 
- }
 
- int setenv_cond(const char *name, const char *value)
 
- {
 
-     if (value)
 
- 	return setenv(name, value, 1);
 
-     else
 
- 	return unsetenv(name);
 
- }
 
- static int reset_config(void)
 
- {
 
-     while (1) {
 
- 	char **envp;
 
- 	for (envp = environ; *envp; envp++) {
 
- 	    if (!strncmp("status.", *envp, 7))
 
- 		continue;
 
- 	    else
 
- 		break;
 
- 	}
 
- 	if (!*envp)
 
- 	    break;
 
- 	const char *eq = strchr(*envp, '=');
 
- 	char ename[eq - *envp + 1];
 
- 	memcpy(ename, *envp, eq - *envp);
 
- 	ename[eq - *envp] = '\0';
 
- 	unsetenv(ename);
 
-     }
 
-     size_t i;
 
-     for (i = 0; i < ARRAY_SIZE(default_config); i++)
 
- 	setenv(default_config[i].var, default_config[i].val, 1);
 
-     config_changed = true;
 
- }
 
- 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';
 
- 	setenv_config(var, p);
 
- 	p = q;
 
-     } while (c == separator);
 
-     return 0;
 
- }
 
- static void finish_config_update(bool save)
 
- {
 
-     if (config_changed) {
 
- 	if (save)
 
- 	    save_config();
 
- 	tzset();
 
- 	config_changed = false;
 
-     }
 
- }
 
- /*
 
-  * 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_env(FILE *f, bool status)
 
- {
 
-     size_t skip = status ? 7 : 0;
 
-     for (char **var = environ; *var; var++) {
 
- 	if (!strncmp(*var, "status.", 7) == status) {
 
- 		fputs(*var + skip, 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_env(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);
 
-     }
 
-     reset_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);
 
- }
 
- const char *getenv_def(const char *var, const char *def)
 
- {
 
-     const char *val = getenv(var);
 
-     return val ? val : def;
 
- }
 
- long getenv_l(const char *var, long def)
 
- {
 
-     const char *ep;
 
-     var = getenv(var);
 
-     if (!var || !*var)
 
- 	return def;
 
-     long val = strtol(var, (char **)&ep, 0);
 
-     return *ep ? def : val;
 
- }
 
- void setenv_l(const char *var, long val)
 
- {
 
-     char vbuf[2+3*sizeof val];
 
-     snprintf(vbuf, sizeof vbuf, "%ld", val);
 
-     setenv(var, vbuf, 1);
 
- }
 
- unsigned long getenv_ul(const char *var, unsigned long def)
 
- {
 
-     const char *ep;
 
-     var = getenv(var);
 
-     if (!var || !*var)
 
- 	return def;
 
-     unsigned long val = strtol(var, (char **)&ep, 0);
 
-     return *ep ? def : val;
 
- }
 
- void setenv_ul(const char *var, unsigned long val)
 
- {
 
-     char vbuf[2+3*sizeof val];
 
-     snprintf(vbuf, sizeof vbuf, "%lu", val);
 
-     setenv(var, vbuf, 1);
 
- }
 
- bool getenv_bool(const char *var)
 
- {
 
-     var = getenv(var);
 
-     if (!var)
 
- 	return false;
 
-     unsigned char c = *var;
 
-     unsigned char cl = c | 0x20;
 
-     return !(!c || c == '0' || cl == 'f' || cl == 'n' || cl == 'd' ||
 
- 	     (cl == 'o' && (var[1] | 0x20) == 'f'));
 
- }
 
- void setenv_bool(const char *var, bool val)
 
- {
 
-     return setenv_ul(var, val);
 
- }
 
 
  |