From 9d9b7bccfcad45f9efc9f64eef802c35a49e97ca Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Mon, 31 Aug 2015 11:33:10 +0300 Subject: [PATCH] Changed to PCRE for processing configuration file parameters. --- .../Getting-Started/Configuration-Guide.md | 13 +++- server/core/config.c | 70 +++++++++++++++++-- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/Documentation/Getting-Started/Configuration-Guide.md b/Documentation/Getting-Started/Configuration-Guide.md index 8077791ff..8e88eb9ef 100644 --- a/Documentation/Getting-Started/Configuration-Guide.md +++ b/Documentation/Getting-Started/Configuration-Guide.md @@ -33,7 +33,18 @@ The MaxScale configuration is read from a file which can be located in a number An explicit path to a configuration file can be passed by using the `-f` option to MaxScale. -The configuration file itself is based on the ".ini" file format and consists of various sections that are used to build the configuration, these sections define services, servers, listeners, monitors and global settings. +The configuration file itself is based on the ".ini" file format and consists of various sections that are used to build the configuration, these sections define services, servers, listeners, monitors and global settings. Parameters which expect a comma-separated list of values can be defined on multiple lines. The following is an example of a multi-line definition. + +``` +[MyService] +type=service +router=readconnroute +servers=server1, + server2, + server3 +``` + +The values of the parameter that are not on the first line need to have at least one whitespace character before them in order for them to be recognized as a part of the multi-line parameter. Please see the section about [Protocol Modules](#protocol-modules) for more details about MaxScale and the default directories where modules will be searched for. diff --git a/server/core/config.c b/server/core/config.c index 28e0ac03c..9ea23da25 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -73,7 +73,10 @@ #include #include #include +#include +/** According to the PCRE manual, this should be a multiple of 3 */ +#define MAXSCALE_PCRE_BUFSZ 24 /** Defined in log_manager.cc */ extern int lm_enabled_logfiles_bitmask; @@ -125,6 +128,57 @@ char *ptr; return str; } +/** + * Remove extra commas and whitespace from a string. This string is interpreted + * as a list of string values separated by commas. + * @param strptr String to clean + * @return pointer to a new string or NULL if an error occurred + */ +char* config_clean_string_list(char* str) +{ + char *tmp; + + if((tmp = malloc(sizeof(char)*(strlen(str) + 1))) != NULL) + { + char *ptr; + int match[MAXSCALE_PCRE_BUFSZ]; + pcre* re; + const char *re_err; + int err_offset,rval; + + + tmp[0] = '\0'; + + if((re = pcre_compile("\\s*+([^,]*[^,\\s])",0,&re_err,&err_offset,NULL)) == NULL) + { + skygw_log_write(LE,"[%s] Error: Regular expression compilation failed at %d: %s", + __FUNCTION__,err_offset,re_err); + free(tmp); + return NULL; + } + + ptr = str; + + while((rval = pcre_exec(re,NULL,ptr,strlen(ptr),0,0,(int*)&match,MAXSCALE_PCRE_BUFSZ)) > 1) + { + const char* substr; + + pcre_get_substring(ptr,(int*)&match,rval,1,&substr); + if(strlen(tmp) > 0) + strcat(tmp,","); + strcat(tmp,substr); + pcre_free_substring(substr); + ptr = &ptr[match[1]]; + } + pcre_free(re); + } + else + { + skygw_log_write(LE,"[%s] Error: Memory allocation failed.",__FUNCTION__); + } + + return tmp; +} /** * Config item handler for the ini file reader * @@ -174,7 +228,7 @@ CONFIG_PARAMETER *param, *p1; { if (!strcmp(p1->name, name)) { - char* tmp; + char *tmp; int paramlen = strlen(p1->value) + strlen(value) + 2; if((tmp = realloc(p1->value,sizeof(char) * (paramlen))) == NULL) @@ -182,13 +236,15 @@ CONFIG_PARAMETER *param, *p1; skygw_log_write(LE,"[%s] Error: Memory allocation failed.",__FUNCTION__); return 0; } - /** This is a parameter with no comma or separate definition of - * an already existing parameter. Add a comma to it and concatenate - * the values. */ - if(p1->value[strlen(p1->value)-1] != ',') - strcat(tmp,","); + strcat(tmp,value); - p1->value = tmp; + if((p1->value = config_clean_string_list(tmp)) == NULL) + { + p1->value = tmp; + skygw_log_write(LE,"[%s] Error: Cleaning configuration parameter failed.",__FUNCTION__); + return 0; + } + free(tmp); return 1; } p1 = p1->next;