From 918fb606174dcf42553be65e3d2306996c52488f Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 21 Apr 2020 00:13:51 +0200 Subject: Implement recursive configuration file parsing (Fixes #59) --- README.md | 4 ++++ config.c | 25 +++++++++++++++++++++++-- midimonster.c | 2 +- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 12d87eb..a7ca212 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,10 @@ lines of the form `option = value`. Lines starting with a semicolon are treated as comments and ignored. Inline comments are not currently supported. +Configuration files may be included recursively in other configuration files using +the syntax `[include ]`. This will read the referenced configuration file as +if it were inserted at that point. + Example configuration files may be found in [configs/](configs/). ### Backend and instance configuration diff --git a/config.c b/config.c index aef4f87..b5e0747 100644 --- a/config.c +++ b/config.c @@ -2,6 +2,11 @@ #include #include #include +#ifndef _WIN32 +#include +#endif + +#define BACKEND_NAME "core/cfg" #include "midimonster.h" #include "config.h" #include "backend.h" @@ -349,6 +354,10 @@ static int config_line(char* line){ } } } + else if(!strncmp(line, "[include ", 9)){ + line[strlen(line) - 1] = 0; + return config_read(line + 9); + } else if(!strcmp(line, "[map]")){ //mapping configuration parser_state = map; @@ -493,7 +502,7 @@ int config_read(char* cfg_filepath){ char* line_raw = NULL; //create heap copy of file name because original might be in readonly memory - char* source_dir = strdup(cfg_filepath), *source_file = NULL; + char* source_dir = strdup(cfg_filepath), *source_file = NULL, original_dir[PATH_MAX * 2] = ""; #ifdef _WIN32 char path_separator = '\\'; #else @@ -510,6 +519,12 @@ int config_read(char* cfg_filepath){ if(source_file){ *source_file = 0; source_file++; + + if(!getcwd(original_dir, sizeof(original_dir))){ + fprintf(stderr, "Failed to read current working directory: %s\n", strerror(errno)); + goto bail; + } + if(chdir(source_dir)){ fprintf(stderr, "Failed to change to configuration file directory %s: %s\n", source_dir, strerror(errno)); goto bail; @@ -519,10 +534,11 @@ int config_read(char* cfg_filepath){ source_file = source_dir; } + fprintf(stderr, "Reading configuration file %s\n", cfg_filepath); source = fopen(source_file, "r"); if(!source){ - fprintf(stderr, "Failed to open configuration file for reading\n"); + fprintf(stderr, "Failed to open %s for reading\n", cfg_filepath); goto bail; } @@ -536,6 +552,11 @@ int config_read(char* cfg_filepath){ rv = 0; bail: + //change back to previous directory to allow recursive configuration file parsing + if(source_file && source_dir != source_file){ + chdir(original_dir); + } + free(source_dir); if(source){ fclose(source); diff --git a/midimonster.c b/midimonster.c index 8100607..1065e5c 100644 --- a/midimonster.c +++ b/midimonster.c @@ -482,7 +482,7 @@ int main(int argc, char** argv){ //read config if(config_read(cfg_file)){ - fprintf(stderr, "Failed to read configuration file %s\n", cfg_file); + fprintf(stderr, "Failed to parse master configuration file %s\n", cfg_file); backends_stop(); routing_cleanup(); fds_free(); -- cgit v1.2.3