+int read_config_file(avl_tree_t *config_tree, const char *fname)
+{
+ int err = -2; /* Parse error */
+ FILE *fp;
+ char *buffer, *line;
+ char *variable, *value, *eol;
+ int lineno = 0;
+ int len;
+ bool ignore = false;
+ config_t *cfg;
+ size_t bufsize;
+
+ cp();
+
+ fp = fopen(fname, "r");
+
+ if(!fp) {
+ logger(LOG_ERR, _("Cannot open config file %s: %s"), fname,
+ strerror(errno));
+ return -3;
+ }
+
+ bufsize = 100;
+ buffer = xmalloc(bufsize);
+
+ for(;;) {
+ line = readline(fp, &buffer, &bufsize);
+
+ if(!line) {
+ err = -1;
+ break;
+ }
+
+ if(feof(fp)) {
+ err = 0;
+ break;
+ }
+
+ lineno++;
+
+ if(!*line || *line == '#')
+ continue;
+
+ if(ignore) {
+ if(!strncmp(line, "-----END", 8))
+ ignore = false;
+ continue;
+ }
+
+ if(!strncmp(line, "-----BEGIN", 10)) {
+ ignore = true;
+ continue;
+ }
+
+ variable = value = line;
+
+ eol = line + strlen(line);
+ while(strchr("\t ", *--eol))
+ *eol = '\0';
+
+ len = strcspn(value, "\t =");
+ value += len;
+ value += strspn(value, "\t ");
+ if(*value == '=') {
+ value++;
+ value += strspn(value, "\t ");
+ }
+ variable[len] = '\0';
+
+
+ if(!*value) {
+ logger(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"),
+ variable, lineno, fname);
+ break;
+ }
+
+ cfg = new_config();
+ cfg->variable = xstrdup(variable);
+ cfg->value = xstrdup(value);
+ cfg->file = xstrdup(fname);
+ cfg->line = lineno;
+
+ config_add(config_tree, cfg);
+ }
+
+ free(buffer);
+ fclose(fp);
+
+ return err;
+}
+
+bool read_server_config()
+{
+ char *fname;
+ int x;
+
+ cp();
+
+ asprintf(&fname, "%s/tinc.conf", confbase);
+ x = read_config_file(config_tree, fname);
+
+ if(x == -1) { /* System error: complain */
+ logger(LOG_ERR, _("Failed to read `%s': %s"), fname, strerror(errno));
+ }
+
+ free(fname);
+
+ return x == 0;
+}
+
+FILE *ask_and_open(const char *filename, const char *what, const char *mode)
+{
+ FILE *r;
+ char *directory;
+ char *fn;
+
+ /* Check stdin and stdout */
+ if(!isatty(0) || !isatty(1)) {
+ /* Argh, they are running us from a script or something. Write
+ the files to the current directory and let them burn in hell
+ for ever. */
+ fn = xstrdup(filename);
+ } else {
+ /* Ask for a file and/or directory name. */
+ fprintf(stdout, _("Please enter a file to save %s to [%s]: "),
+ what, filename);
+ fflush(stdout);
+
+ fn = readline(stdin, NULL, NULL);
+
+ if(!fn) {
+ fprintf(stderr, _("Error while reading stdin: %s\n"),
+ strerror(errno));
+ return NULL;
+ }
+
+ if(!strlen(fn))
+ /* User just pressed enter. */
+ fn = xstrdup(filename);
+ }
+
+#ifdef HAVE_MINGW
+ if(fn[0] != '\\' && fn[0] != '/' && !strchr(fn, ':')) {
+#else
+ if(fn[0] != '/') {
+#endif
+ /* The directory is a relative path or a filename. */
+ char *p;
+
+ directory = get_current_dir_name();
+ asprintf(&p, "%s/%s", directory, fn);
+ free(fn);
+ free(directory);
+ fn = p;
+ }
+
+ umask(0077); /* Disallow everything for group and other */
+
+ /* Open it first to keep the inode busy */
+
+ r = fopen(fn, mode);
+
+ if(!r) {
+ fprintf(stderr, _("Error opening file `%s': %s\n"),
+ fn, strerror(errno));
+ free(fn);
+ return NULL;
+ }
+
+ free(fn);
+
+ return r;