summaryrefslogtreecommitdiff
path: root/src/configfile.c
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2016-05-11 22:34:53 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2016-05-13 20:49:31 -0400
commitbd66026fc25da317a42abf9105fb317814ec3dfb (patch)
treefd534b4409fbaaf0023f1b4f8c266dda633968fa /src/configfile.c
parent1cd31ae2ccf9e839325ccafdb72108e6b2d39745 (diff)
downloadlighttpd-git-bd66026fc25da317a42abf9105fb317814ec3dfb.tar.gz
[config] support include file glob (fixes #1221)
x-ref: "support *(wild card character) within include directive" https://redmine.lighttpd.net/issues/1221
Diffstat (limited to 'src/configfile.c')
-rw-r--r--src/configfile.c67
1 files changed, 53 insertions, 14 deletions
diff --git a/src/configfile.c b/src/configfile.c
index 6c9260f7..7198b964 100644
--- a/src/configfile.c
+++ b/src/configfile.c
@@ -20,6 +20,7 @@
#include <ctype.h>
#include <limits.h>
#include <assert.h>
+#include <glob.h>
static int config_insert(server *srv) {
@@ -1073,31 +1074,67 @@ static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *inpu
return 0;
}
-int config_parse_file(server *srv, config_t *context, const char *fn) {
+static int config_parse_file_stream(server *srv, config_t *context, const buffer *filename) {
tokenizer_t t;
stream s;
int ret;
- buffer *filename;
-
- if (buffer_string_is_empty(context->basedir) ||
- (fn[0] == '/' || fn[0] == '\\') ||
- (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
- filename = buffer_init_string(fn);
- } else {
- filename = buffer_init_buffer(context->basedir);
- buffer_append_string(filename, fn);
- }
if (0 != stream_open(&s, filename)) {
log_error_write(srv, __FILE__, __LINE__, "sbss",
"opening configfile ", filename, "failed:", strerror(errno));
- ret = -1;
+ return -1;
} else {
tokenizer_init(&t, filename, s.start, s.size);
ret = config_parse(srv, context, &t);
}
stream_close(&s);
+ return ret;
+}
+
+int config_parse_file(server *srv, config_t *context, const char *fn) {
+ buffer *filename;
+ size_t i;
+ int ret = -1;
+ #ifdef GLOB_BRACE
+ int flags = GLOB_BRACE;
+ #else
+ int flags = 0;
+ #endif
+ glob_t gl;
+
+ if ((fn[0] == '/' || fn[0] == '\\') ||
+ (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\')) ||
+ (fn[0] == '.' && fn[1] == '.' && (fn[2] == '/' || fn[2] == '\\'))) {
+ filename = buffer_init_string(fn);
+ } else {
+ filename = buffer_init_buffer(context->basedir);
+ buffer_append_string(filename, fn);
+ }
+
+ switch (glob(filename->ptr, flags, NULL, &gl)) {
+ case 0:
+ for (i = 0; i < gl.gl_pathc; ++i) {
+ buffer_copy_string(filename, gl.gl_pathv[i]);
+ ret = config_parse_file_stream(srv, context, filename);
+ if (0 != ret) break;
+ }
+ globfree(&gl);
+ break;
+ case GLOB_NOMATCH:
+ if (filename->ptr[strcspn(filename->ptr, "*?[]{}")] != '\0') { /*(contains glob metachars)*/
+ ret = 0; /* not an error if no files match glob pattern */
+ }
+ else {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "include file not found: ", filename);
+ }
+ break;
+ case GLOB_ABORTED:
+ case GLOB_NOSPACE:
+ log_error_write(srv, __FILE__, __LINE__, "sbss", "glob()", filename, "failed:", strerror(errno));
+ break;
+ }
+
buffer_free(filename);
return ret;
}
@@ -1194,6 +1231,7 @@ int config_read(server *srv, const char *fn) {
data_string *dcwd;
int ret;
char *pos;
+ buffer *filename;
context_init(srv, &context);
context.all_configs = srv->config_context;
@@ -1205,7 +1243,6 @@ int config_read(server *srv, const char *fn) {
#endif
if (pos) {
buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
- fn = pos + 1;
}
dc = data_config_init();
@@ -1232,7 +1269,9 @@ int config_read(server *srv, const char *fn) {
dcwd->free((data_unset*) dcwd);
}
- ret = config_parse_file(srv, &context, fn);
+ filename = buffer_init_string(fn);
+ ret = config_parse_file_stream(srv, &context, filename);
+ buffer_free(filename);
/* remains nothing if parser is ok */
force_assert(!(0 == ret && context.ok && 0 != context.configs_stack.used));