+ while(readline(in, buf, sizeof buf)) {
+ if(ignore) {
+ if(!strncmp(buf, "-----END", 8))
+ ignore = false;
+ } else {
+ if(!strncmp(buf, "-----BEGIN", 10))
+ ignore = true;
+ }
+
+ if(!ignore && !strncmp(buf, key, keylen)) {
+ if(strchr("\t =", buf[keylen])) {
+ continue;
+ }
+ }
+
+ fputs(buf, out);
+ fputc('\n', out);
+ }
+
+ if(ferror(in)) {
+ logger(mesh, MESHLINK_ERROR, "Failed to read `%s': %s", filename, strerror(errno));
+ fclose(in);
+ fclose(out);
+ return false;
+ }
+
+ fclose(in);
+
+ fprintf(out, "%s = %s\n", key, value);
+
+ if(ferror(out)) {
+ logger(mesh, MESHLINK_ERROR, "Failed to write `%s': %s", tmpname, strerror(errno));
+ fclose(out);
+ return false;
+ }
+
+ fclose(out);
+
+#ifdef HAVE_MINGW
+ // We cannot atomically replace files on Windows.
+ char bakname[PATH_MAX];
+ snprintf(bakname, PATH_MAX, "%s.bak", filename);
+ if(rename(tmpname, bakfile) || rename(bakfile, filename)) {
+ rename(bakfile, filename);
+#else
+ if(rename(tmpname, filename)) {
+#endif
+ logger(mesh, MESHLINK_ERROR, "Failed to update `%s': %s", filename, strerror(errno));
+ return false;
+ }
+
+ return true;
+}
+
+bool append_config_file(meshlink_handle_t *mesh, const char *name, const char *key, const char *value) {
+ char filename[PATH_MAX];
+ snprintf(filename,PATH_MAX, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, name);
+
+ FILE *fp = fopen(filename, "a");