|
|
|
@ -765,7 +765,7 @@ void config_patch_connection(server *srv, connection *con) {
|
|
|
|
|
#undef PATCH |
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
|
const buffer *source; |
|
|
|
|
const char *source; |
|
|
|
|
const char *input; |
|
|
|
|
size_t offset; |
|
|
|
|
size_t size; |
|
|
|
@ -779,43 +779,6 @@ typedef struct {
|
|
|
|
|
int simulate_eol; |
|
|
|
|
} tokenizer_t; |
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const char *fn) { |
|
|
|
|
if (buffer_string_is_empty(basedir) || |
|
|
|
|
(fn[0] == '/' || fn[0] == '\\') || |
|
|
|
|
(fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) { |
|
|
|
|
t->file = buffer_init_string(fn); |
|
|
|
|
} else { |
|
|
|
|
t->file = buffer_init_buffer(basedir); |
|
|
|
|
buffer_append_string(t->file, fn); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (0 != stream_open(&(t->s), t->file)) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbss", |
|
|
|
|
"opening configfile ", t->file, "failed:", strerror(errno)); |
|
|
|
|
buffer_free(t->file); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
t->input = t->s.start; |
|
|
|
|
t->offset = 0; |
|
|
|
|
t->size = t->s.size; |
|
|
|
|
t->line = 1; |
|
|
|
|
t->line_pos = 1; |
|
|
|
|
|
|
|
|
|
t->in_key = 1; |
|
|
|
|
t->in_brace = 0; |
|
|
|
|
t->in_cond = 0; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int tokenizer_close(server *srv, tokenizer_t *t) { |
|
|
|
|
UNUSED(srv); |
|
|
|
|
|
|
|
|
|
buffer_free(t->file); |
|
|
|
|
return stream_close(&(t->s)); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
static int config_skip_newline(tokenizer_t *t) { |
|
|
|
|
int skipped = 1; |
|
|
|
|
force_assert(t->input[t->offset] == '\r' || t->input[t->offset] == '\n'); |
|
|
|
@ -837,6 +800,13 @@ static int config_skip_comment(tokenizer_t *t) {
|
|
|
|
|
return i; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
__attribute_cold__ |
|
|
|
|
static int config_tokenizer_err(server *srv, const char *file, unsigned int line, tokenizer_t *t, const char *msg) { |
|
|
|
|
log_error(srv->errh, file, line, "source: %s line: %d pos: %d %s", |
|
|
|
|
t->source, t->line, t->line_pos, msg); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) { |
|
|
|
|
int tid = 0; |
|
|
|
|
size_t i; |
|
|
|
@ -862,11 +832,8 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
|
|
|
|
|
tid = TK_ARRAY_ASSIGN; |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"use => for assignments in arrays"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} else if (t->in_cond) { |
|
|
|
|
if (t->input[t->offset + 1] == '=') { |
|
|
|
@ -882,11 +849,8 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
|
|
|
|
|
tid = TK_MATCH; |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"only =~ and == are allowed in the condition"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
t->in_key = 1; |
|
|
|
|
t->in_cond = 0; |
|
|
|
@ -898,11 +862,8 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
t->offset++; |
|
|
|
|
t->line_pos++; |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"unexpected equal-sign: ="); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -921,20 +882,14 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
|
|
|
|
|
tid = TK_NOMATCH; |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"only !~ and != are allowed in the condition"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
t->in_key = 1; |
|
|
|
|
t->in_cond = 0; |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"unexpected exclamation-marks: !"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -1018,14 +973,8 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (t->input[t->offset + i] == '\0') { |
|
|
|
|
/* ERROR */ |
|
|
|
|
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"missing closing quote"); |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
t->offset += i + 1; |
|
|
|
@ -1077,12 +1026,8 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
tid = TK_FORCE_ASSIGN; |
|
|
|
|
buffer_copy_string_len(token, CONST_STR_LEN(":=")); |
|
|
|
|
} else { |
|
|
|
|
/* ERROR */ |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"unexpected character ':'"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
@ -1153,12 +1098,8 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
t->offset += i; |
|
|
|
|
t->line_pos += i; |
|
|
|
|
} else { |
|
|
|
|
/* ERROR */ |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"invalid character in condition"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} else if (isdigit((unsigned char)c)) { |
|
|
|
|
/* take all digits */ |
|
|
|
@ -1200,12 +1141,8 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
t->offset += i; |
|
|
|
|
t->line_pos += i; |
|
|
|
|
} else { |
|
|
|
|
/* ERROR */ |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsds", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
return config_tokenizer_err(srv, __FILE__, __LINE__, t, |
|
|
|
|
"invalid character in variable name"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
@ -1214,13 +1151,6 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
|
|
|
|
|
if (tid) { |
|
|
|
|
*token_id = tid; |
|
|
|
|
#if 0 |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
token, token->used - 1, tid); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} else if (t->offset < t->size) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "Dsb", tid, ",", token); |
|
|
|
@ -1228,17 +1158,30 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int config_parse(server *srv, config_t *context, tokenizer_t *t) { |
|
|
|
|
static int config_parse(server *srv, config_t *context, const char *source, const char *input, size_t isize) { |
|
|
|
|
void *pParser; |
|
|
|
|
int token_id; |
|
|
|
|
buffer *token, *lasttoken; |
|
|
|
|
int token_id = 0; |
|
|
|
|
int ret; |
|
|
|
|
tokenizer_t t; |
|
|
|
|
|
|
|
|
|
t.source = source; |
|
|
|
|
t.input = input; |
|
|
|
|
t.size = isize; |
|
|
|
|
t.offset = 0; |
|
|
|
|
t.line = 1; |
|
|
|
|
t.line_pos = 1; |
|
|
|
|
|
|
|
|
|
t.in_key = 1; |
|
|
|
|
t.in_brace = 0; |
|
|
|
|
t.in_cond = 0; |
|
|
|
|
t.simulate_eol = 0; |
|
|
|
|
|
|
|
|
|
pParser = configparserAlloc( malloc ); |
|
|
|
|
force_assert(pParser); |
|
|
|
|
lasttoken = buffer_init(); |
|
|
|
|
token = buffer_init(); |
|
|
|
|
while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) { |
|
|
|
|
while((1 == (ret = config_tokenizer(srv, &t, &token_id, token))) && context->ok) { |
|
|
|
|
buffer_copy_buffer(lasttoken, token); |
|
|
|
|
configparser(pParser, token_id, token, context); |
|
|
|
|
|
|
|
|
@ -1256,13 +1199,12 @@ static int config_parse(server *srv, config_t *context, tokenizer_t *t) {
|
|
|
|
|
configparserFree(pParser, free); |
|
|
|
|
|
|
|
|
|
if (ret == -1) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sb", |
|
|
|
|
"configfile parser failed at:", lasttoken); |
|
|
|
|
log_error(srv->errh, __FILE__, __LINE__, |
|
|
|
|
"configfile parser failed at: %s", lasttoken->ptr); |
|
|
|
|
} else if (context->ok == 0) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb", |
|
|
|
|
"source:", t->source, |
|
|
|
|
"line:", t->line, "pos:", t->line_pos, |
|
|
|
|
"parser failed somehow near here:", lasttoken); |
|
|
|
|
log_error(srv->errh, __FILE__, __LINE__, "source: %s line: %d pos: %d " |
|
|
|
|
"parser failed somehow near here: %s", |
|
|
|
|
t.source, t.line, t.line_pos, lasttoken->ptr); |
|
|
|
|
ret = -1; |
|
|
|
|
} |
|
|
|
|
buffer_free(lasttoken); |
|
|
|
@ -1270,43 +1212,22 @@ static int config_parse(server *srv, config_t *context, tokenizer_t *t) {
|
|
|
|
|
return ret == -1 ? -1 : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *input, size_t size) { |
|
|
|
|
|
|
|
|
|
t->source = source; |
|
|
|
|
t->input = input; |
|
|
|
|
t->size = size; |
|
|
|
|
t->offset = 0; |
|
|
|
|
t->line = 1; |
|
|
|
|
t->line_pos = 1; |
|
|
|
|
|
|
|
|
|
t->in_key = 1; |
|
|
|
|
t->in_brace = 0; |
|
|
|
|
t->in_cond = 0; |
|
|
|
|
t->simulate_eol = 0; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int config_parse_file_stream(server *srv, config_t *context, const buffer *filename) { |
|
|
|
|
tokenizer_t t; |
|
|
|
|
static int config_parse_file_stream(server *srv, config_t *context, const char *fn) { |
|
|
|
|
stream s; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
if (0 != stream_open(&s, filename)) { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sbss", |
|
|
|
|
"opening configfile ", filename, "failed:", strerror(errno)); |
|
|
|
|
if (0 != stream_open(&s, fn)) { |
|
|
|
|
log_error(srv->errh, __FILE__, __LINE__, |
|
|
|
|
"opening configfile %s failed: %s", fn, strerror(errno)); |
|
|
|
|
return -1; |
|
|
|
|
} else { |
|
|
|
|
tokenizer_init(&t, filename, s.start, s.size); |
|
|
|
|
ret = config_parse(srv, context, &t); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int ret = config_parse(srv, context, fn, s.start, (size_t)s.size); |
|
|
|
|
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; |
|
|
|
@ -1326,9 +1247,8 @@ int config_parse_file(server *srv, config_t *context, const char *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); |
|
|
|
|
for (size_t i = 0; i < gl.gl_pathc; ++i) { |
|
|
|
|
ret = config_parse_file_stream(srv, context, gl.gl_pathv[i]); |
|
|
|
|
if (0 != ret) break; |
|
|
|
|
} |
|
|
|
|
globfree(&gl); |
|
|
|
@ -1438,11 +1358,7 @@ int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (-1 != ret) { |
|
|
|
|
buffer *source = buffer_init_string(cmd); |
|
|
|
|
tokenizer_t t; |
|
|
|
|
tokenizer_init(&t, source, CONST_BUF_LEN(out)); |
|
|
|
|
ret = config_parse(srv, context, &t); |
|
|
|
|
buffer_free(source); |
|
|
|
|
ret = config_parse(srv, context, cmd, CONST_BUF_LEN(out)); |
|
|
|
|
} |
|
|
|
|
buffer_free(out); |
|
|
|
|
} |
|
|
|
@ -1476,7 +1392,6 @@ int config_read(server *srv, const char *fn) {
|
|
|
|
|
buffer *dcwd; |
|
|
|
|
int ret; |
|
|
|
|
char *pos; |
|
|
|
|
buffer *filename; |
|
|
|
|
|
|
|
|
|
context_init(srv, &context); |
|
|
|
|
context.all_configs = srv->config_context; |
|
|
|
@ -1508,9 +1423,7 @@ int config_read(server *srv, const char *fn) {
|
|
|
|
|
array_set_key_value(dc->value, CONST_STR_LEN("var.CWD"), CONST_BUF_LEN(dcwd)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
filename = buffer_init_string(fn); |
|
|
|
|
ret = config_parse_file_stream(srv, &context, filename); |
|
|
|
|
buffer_free(filename); |
|
|
|
|
ret = config_parse_file_stream(srv, &context, fn); |
|
|
|
|
|
|
|
|
|
/* remains nothing if parser is ok */ |
|
|
|
|
force_assert(!(0 == ret && context.ok && 0 != context.configs_stack.used)); |
|
|
|
|