#include "common.h" #include "config.h" #include #include #define MAX_CONFIG_LINE 256 #define CONFIG_FILE "/spiffs/config.txt" struct configvar { const char *name; const char *val; }; static const struct configvar default_config[] = { { "TZ", "CET-1CEST,M3.5.0,M10.5.0/3" }, /* Sweden */ { "hostname", "max80" } }; #ifndef HAVE_CLEARENV static void clearenv(void) { char **new_environ = calloc(ARRAY_SIZE(default_config)+1, sizeof(char *)); char **old_environ = environ; environ = new_environ; for (char **envp = old_environ; *envp; envp++) free(*envp); free(old_environ); } #endif /* HAVE_CLEARENV */ static void reset_config(void) { clearenv(); for (size_t i = 0; i < ARRAY_SIZE(default_config); i++) setenv(default_config[i].name, default_config[i].val, 1); } static bool is_end_of_string(int c) { return c <= 0 || c == '\n' || c == '\r'; } static void skip_rest_of_line(FILE *f) { int c; do { c = getc(f); } while (!is_end_of_string(c)); } int read_config(FILE *f) { char *linebuf = NULL; int err = -1; linebuf = malloc(MAX_CONFIG_LINE); if (!linebuf) goto exit; while (fgets(linebuf, MAX_CONFIG_LINE, f)) { char *p, *q; unsigned char c; p = linebuf; do { c = *p++; } while (isalnum(c) || c == '.' || c == '-'); if (c != '=') continue; /* Invalid config line (blank, comment...) */ p[-1] = '\0'; q = p; do { c = *q++; } while (!is_end_of_string(c)); if (q >= linebuf + MAX_CONFIG_LINE) { /* Overlong line, discard rest and drop */ skip_rest_of_line(f); } else { q[-1] = '\0'; if (linebuf[0] == '-') unsetenv(linebuf+1); else setenv(linebuf, p, 1); } } err = 0; exit: if (linebuf) free(linebuf); tzset(); return err; }; int write_config(FILE *f) { for (char **var = environ; *var; var++) { fputs(*var, f); putc('\n', f); } return ferror(f) ? -1 : 0; } int save_config(void) { FILE *f = fopen(CONFIG_FILE, "w"); if (!f) return -1; int err = write_config(f); fclose(f); 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) { reset_config(); if (!esp_spiffs_mounted(spiffs_conf.partition_label)) esp_vfs_spiffs_register(&spiffs_conf); FILE *f = fopen(CONFIG_FILE, "r"); if (!f) return; /* No config file */ read_config(f); fclose(f); } 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; if (!c || c == '0' || cl == 'f' || cl == 'n' || cl == 'o' && (var[1] | 0x20) == 'f') return false; else return true; } void setenv_bool(const char *var, bool val) { return setenv_ul(var, val); }