+bool write_config_file(const struct splay_tree_t *config_tree, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "w+");
+
+ if(!fp) {
+ logger(NULL, MESHLINK_ERROR, "Cannot open config file %s: %s", fname, strerror(errno));
+ return false;
+ }
+
+ for splay_each(config_t, cnf, config_tree)
+ {
+ if(fwrite(cnf->variable, sizeof(char), strlen(cnf->variable), fp) < strlen(cnf->variable))
+ goto error;
+
+ if(fwrite(" = ", sizeof(char), 3, fp) < 3)
+ goto error;
+
+ if(fwrite(cnf->value, sizeof(char), strlen(cnf->value), fp) < strlen(cnf->value))
+ goto error;
+
+ if(fwrite("\n", sizeof(char), 1, fp) < 1)
+ goto error;
+ }
+
+ fclose(fp);
+ return true;
+
+error:
+ logger(NULL, MESHLINK_ERROR, "Cannot write to config file %s: %s", fname, strerror(errno));
+ fclose(fp);
+ return false;
+}
+
+bool read_server_config(meshlink_handle_t *mesh) {
+ char filename[PATH_MAX];
+ bool x;
+
+ snprintf(filename, PATH_MAX,"%s" SLASH "meshlink.conf", mesh->confbase);
+ errno = 0;
+ x = read_config_file(mesh->config, filename);
+
+ if(!x && errno)
+ logger(mesh, MESHLINK_ERROR, "Failed to read `%s': %s", filename, strerror(errno));
+
+ return x;
+}
+
+bool read_host_config(meshlink_handle_t *mesh, splay_tree_t *config_tree, const char *name) {
+ char filename[PATH_MAX];
+ bool x;
+
+ snprintf(filename,PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+ x = read_config_file(config_tree, filename);
+
+ return x;
+}
+
+bool write_host_config(struct meshlink_handle *mesh, const struct splay_tree_t *config_tree, const char *name)
+{
+ char filename[PATH_MAX];
+
+ snprintf(filename,PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+ return write_config_file(config_tree, filename);
+}
+
+bool change_config_file(meshlink_handle_t *mesh, const char *name, const char *key, const char *value) {
+ char filename[PATH_MAX];
+ char tmpname[PATH_MAX];
+ char buf[MAX_STRING_SIZE];
+ const int keylen = strlen(key);
+
+ snprintf(filename, PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+ snprintf(tmpname, PATH_MAX, "%s.tmp", filename);
+
+ FILE *in = fopen(filename, "r");
+ if(!in) {
+ // Hm, maybe the file does not exist? Try appending.
+ return append_config_file(mesh, name, key, value);
+ }
+
+ FILE *out = fopen(tmpname, "w");
+ if(!out) {
+ logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", tmpname, strerror(errno));
+ fclose(in);
+ return false;
+ }
+
+ bool ignore = false;
+
+ while(readline(in, buf, sizeof buf)) {
+ if(ignore) {
+ if(!strncmp(buf, "-----END", 8))
+ ignore = false;
+ } else {
+ if(!strncmp(buf, "-----BEGIN", 10))
+ ignore = true;