/* ** Perform a reduce action and the shift that must immediately ** follow the reduce. */ static void yy_reduce( yyParser *yypParser, /* The parser */ int yyruleno /* Number of the rule by which to reduce */ ){ int yygoto; /* The next state */ int yyact; /* The next action */ YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ yyStackEntry *yymsp; /* The top of the parser's stack */ int yysize; /* Amount to pop the stack */ configparserARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG if( yyTraceFILE && yyruleno>=0 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, yyRuleName[yyruleno]); } #endif /* NDEBUG */ switch( yyruleno ){ /* Beginning here are the reduction cases. A typical example ** follows: ** case 0: ** #line <lineno> <grammarfile> ** { ... } // User supplied code ** #line <lineno> <thisfile> ** break; */ case 0: /* No destructor defined for metalines */ break; case 1: /* No destructor defined for metalines */ /* No destructor defined for metaline */ break; case 2: break; case 3: /* No destructor defined for varline */ break; case 4: /* No destructor defined for global */ break; case 5: #line 115 "./configparser.y" { yymsp[-1].minor.yy78 = NULL; } #line 822 "configparser.c" yy_destructor(1,&yymsp[0].minor); break; case 6: /* No destructor defined for include */ break; case 7: /* No destructor defined for include_shell */ break; case 8: yy_destructor(1,&yymsp[0].minor); break; case 9: #line 144 "./configparser.y" { if (ctx->ok) { buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43); if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) { fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n", ctx->current->context_ndx, ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr); ctx->ok = 0; } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) { array_insert_unique(ctx->current->value, yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } else { fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n", ctx->current->context_ndx, ctx->current->key->ptr, yymsp[0].minor.yy41->key->ptr); ctx->ok = 0; yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } } buffer_free(yymsp[-2].minor.yy43); yymsp[-2].minor.yy43 = NULL; } #line 859 "configparser.c" yy_destructor(2,&yymsp[-1].minor); break; case 10: #line 168 "./configparser.y" { array *vars = ctx->current->value; data_unset *du; if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) { fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n", ctx->current->context_ndx, ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr); ctx->ok = 0; } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) { /* exists in current block */ du = configparser_merge_data(du, yymsp[0].minor.yy41); if (NULL == du) { ctx->ok = 0; } else { buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43); array_replace(vars, du); } yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) { du = configparser_merge_data(du, yymsp[0].minor.yy41); if (NULL == du) { ctx->ok = 0; du->free(du); } else { buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43); array_insert_unique(ctx->current->value, du); } yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); } else { buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43); array_insert_unique(ctx->current->value, yymsp[0].minor.yy41); } buffer_free(yymsp[-2].minor.yy43); yymsp[-2].minor.yy43 = NULL; yymsp[0].minor.yy41 = NULL; } #line 903 "configparser.c" yy_destructor(3,&yymsp[-1].minor); break; case 11: #line 208 "./configparser.y" { if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) { yygotominor.yy43 = buffer_init_string("var."); buffer_append_string_buffer(yygotominor.yy43, yymsp[0].minor.yy0); buffer_free(yymsp[0].minor.yy0); yymsp[0].minor.yy0 = NULL; } else { yygotominor.yy43 = yymsp[0].minor.yy0; yymsp[0].minor.yy0 = NULL; } } #line 919 "configparser.c" break; case 12: #line 220 "./configparser.y" { yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41); if (NULL == yygotominor.yy41) { ctx->ok = 0; } yymsp[-2].minor.yy41 = NULL; yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } #line 932 "configparser.c" yy_destructor(5,&yymsp[-1].minor); break; case 13: #line 230 "./configparser.y" { yygotominor.yy41 = yymsp[0].minor.yy41; yymsp[0].minor.yy41 = NULL; } #line 941 "configparser.c" break; case 14: #line 235 "./configparser.y" { yygotominor.yy41 = NULL; if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) { char *env; if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) { data_string *ds; ds = data_string_init(); buffer_append_string(ds->value, env); yygotominor.yy41 = (data_unset *)ds; } else { fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4); ctx->ok = 0; } } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) { fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr); ctx->ok = 0; } if (!yygotominor.yy41) { /* make a dummy so it won't crash */ yygotominor.yy41 = (data_unset *)data_string_init(); } buffer_free(yymsp[0].minor.yy43); yymsp[0].minor.yy43 = NULL; } #line 971 "configparser.c" break; case 15: #line 262 "./configparser.y" { yygotominor.yy41 = (data_unset *)data_string_init(); buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0); buffer_free(yymsp[0].minor.yy0); yymsp[0].minor.yy0 = NULL; } #line 981 "configparser.c" break; case 16: #line 269 "./configparser.y" { yygotominor.yy41 = (data_unset *)data_integer_init(); ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10); buffer_free(yymsp[0].minor.yy0); yymsp[0].minor.yy0 = NULL; } #line 991 "configparser.c" break; case 17: #line 275 "./configparser.y" { yygotominor.yy41 = (data_unset *)data_array_init(); array_free(((data_array *)(yygotominor.yy41))->value); ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40; yymsp[0].minor.yy40 = NULL; } #line 1001 "configparser.c" break; case 18: #line 281 "./configparser.y" { yygotominor.yy40 = array_init(); } #line 1008 "configparser.c" yy_destructor(8,&yymsp[-1].minor); yy_destructor(9,&yymsp[0].minor); break; case 19: #line 284 "./configparser.y" { yygotominor.yy40 = yymsp[-1].minor.yy40; yymsp[-1].minor.yy40 = NULL; } #line 1018 "configparser.c" yy_destructor(8,&yymsp[-2].minor); yy_destructor(9,&yymsp[0].minor); break; case 20: #line 289 "./configparser.y" { if (buffer_is_empty(yymsp[0].minor.yy41->key) || NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) { array_insert_unique(yymsp[-2].minor.yy40, yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } else { fprintf(stderr, "Duplicate array-key: %s\n", yymsp[0].minor.yy41->key->ptr); ctx->ok = 0; yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } yygotominor.yy40 = yymsp[-2].minor.yy40; yymsp[-2].minor.yy40 = NULL; } #line 1040 "configparser.c" yy_destructor(10,&yymsp[-1].minor); break; case 21: #line 306 "./configparser.y" { yygotominor.yy40 = yymsp[-1].minor.yy40; yymsp[-1].minor.yy40 = NULL; } #line 1049 "configparser.c" yy_destructor(10,&yymsp[0].minor); break; case 22: #line 311 "./configparser.y" { yygotominor.yy40 = array_init(); array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } #line 1059 "configparser.c" break; case 23: #line 317 "./configparser.y" { yygotominor.yy41 = yymsp[0].minor.yy41; yymsp[0].minor.yy41 = NULL; } #line 1067 "configparser.c" break; case 24: #line 321 "./configparser.y" { buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43); buffer_free(yymsp[-2].minor.yy43); yymsp[-2].minor.yy43 = NULL; yygotominor.yy41 = yymsp[0].minor.yy41; yymsp[0].minor.yy41 = NULL; } #line 1079 "configparser.c" yy_destructor(11,&yymsp[-1].minor); break; case 25: yy_destructor(1,&yymsp[0].minor); break; case 26: break; case 27: #line 333 "./configparser.y" { data_config *dc; dc = (data_config *)array_get_element(ctx->srv->config_context, "global"); assert(dc); configparser_push(ctx, dc, 0); } #line 1095 "configparser.c" yy_destructor(12,&yymsp[0].minor); break; case 28: #line 340 "./configparser.y" { data_config *cur; cur = ctx->current; configparser_pop(ctx); assert(cur && ctx->current); yygotominor.yy78 = cur; } #line 1110 "configparser.c" /* No destructor defined for globalstart */ yy_destructor(13,&yymsp[-2].minor); /* No destructor defined for metalines */ yy_destructor(14,&yymsp[0].minor); break; case 29: #line 351 "./configparser.y" { assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx); yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78; yymsp[-3].minor.yy78->next = yymsp[0].minor.yy78; yygotominor.yy78 = yymsp[0].minor.yy78; yymsp[-3].minor.yy78 = NULL; yymsp[0].minor.yy78 = NULL; } #line 1126 "configparser.c" /* No destructor defined for eols */ yy_destructor(15,&yymsp[-1].minor); break; case 30: #line 360 "./configparser.y" { yygotominor.yy78 = yymsp[0].minor.yy78; yymsp[0].minor.yy78 = NULL; } #line 1136 "configparser.c" break; case 31: #line 365 "./configparser.y" { data_config *cur; cur = ctx->current; configparser_pop(ctx); assert(cur && ctx->current); yygotominor.yy78 = cur; } #line 1150 "configparser.c" /* No destructor defined for context */ yy_destructor(13,&yymsp[-2].minor); /* No destructor defined for metalines */ yy_destructor(14,&yymsp[0].minor); break; case 32: #line 376 "./configparser.y" { data_config *dc; buffer *b, *rvalue, *op; if (ctx->ok && yymsp[0].minor.yy41->type != TYPE_STRING) { fprintf(stderr, "rvalue must be string"); ctx->ok = 0; } switch(yymsp[-1].minor.yy27) { case CONFIG_COND_NE: op = buffer_init_string("!="); break; case CONFIG_COND_EQ: op = buffer_init_string("=="); break; case CONFIG_COND_NOMATCH: op = buffer_init_string("!~"); break; case CONFIG_COND_MATCH: op = buffer_init_string("=~"); break; default: assert(0); return; } b = buffer_init(); buffer_copy_string_buffer(b, ctx->current->key); buffer_append_string(b, "/"); buffer_append_string_buffer(b, yymsp[-5].minor.yy0); buffer_append_string_buffer(b, yymsp[-3].minor.yy43); buffer_append_string_buffer(b, op); rvalue = ((data_string*)yymsp[0].minor.yy41)->value; buffer_append_string_buffer(b, rvalue); if (NULL != (dc = (data_config *)array_get_element(ctx->all_configs, b->ptr))) { configparser_push(ctx, dc, 0); } else { struct { comp_key_t comp; char *comp_key; size_t len; } comps[] = { { COMP_SERVER_SOCKET, CONST_STR_LEN("SERVER[\"socket\"]" ) }, { COMP_HTTP_URL, CONST_STR_LEN("HTTP[\"url\"]" ) }, { COMP_HTTP_HOST, CONST_STR_LEN("HTTP[\"host\"]" ) }, { COMP_HTTP_REFERER, CONST_STR_LEN("HTTP[\"referer\"]" ) }, { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"useragent\"]" ) }, { COMP_HTTP_USER_AGENT, CONST_STR_LEN("HTTP[\"user-agent\"]" ) }, { COMP_HTTP_COOKIE, CONST_STR_LEN("HTTP[\"cookie\"]" ) }, { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remoteip\"]" ) }, { COMP_HTTP_REMOTE_IP, CONST_STR_LEN("HTTP[\"remote-ip\"]" ) }, { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"querystring\"]") }, { COMP_HTTP_QUERY_STRING, CONST_STR_LEN("HTTP[\"query-string\"]") }, { COMP_HTTP_REQUEST_METHOD, CONST_STR_LEN("HTTP[\"request-method\"]") }, { COMP_HTTP_SCHEME, CONST_STR_LEN("HTTP[\"scheme\"]" ) }, { COMP_UNSET, NULL, 0 }, }; size_t i; dc = data_config_init(); buffer_copy_string_buffer(dc->key, b); buffer_copy_string_buffer(dc->op, op); buffer_copy_string_buffer(dc->comp_key, yymsp[-5].minor.yy0); buffer_append_string_len(dc->comp_key, CONST_STR_LEN("[\"")); buffer_append_string_buffer(dc->comp_key, yymsp[-3].minor.yy43); buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]")); dc->cond = yymsp[-1].minor.yy27; for (i = 0; comps[i].comp_key; i ++) { if (buffer_is_equal_string( dc->comp_key, comps[i].comp_key, comps[i].len)) { dc->comp = comps[i].comp; break; } } if (COMP_UNSET == dc->comp) { fprintf(stderr, "error comp_key %s", dc->comp_key->ptr); ctx->ok = 0; } switch(yymsp[-1].minor.yy27) { case CONFIG_COND_NE: case CONFIG_COND_EQ: dc->string = buffer_init_buffer(rvalue); break; case CONFIG_COND_NOMATCH: case CONFIG_COND_MATCH: { #ifdef HAVE_PCRE_H const char *errptr; int erroff; if (NULL == (dc->regex = pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) { dc->string = buffer_init_string(errptr); dc->cond = CONFIG_COND_UNSET; fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n", rvalue->ptr, errptr, erroff); ctx->ok = 0; } else if (NULL == (dc->regex_study = pcre_study(dc->regex, 0, &errptr)) && errptr != NULL) { fprintf(stderr, "studying regex failed: %s -> %s\n", rvalue->ptr, errptr); ctx->ok = 0; } else { dc->string = buffer_init_buffer(rvalue); } #else fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n" "(perhaps just a missing pcre-devel package ?) \n", yymsp[-5].minor.yy0->ptr, yymsp[-3].minor.yy43->ptr); ctx->ok = 0; #endif break; } default: fprintf(stderr, "unknown condition for $%s[%s]\n", yymsp[-5].minor.yy0->ptr, yymsp[-3].minor.yy43->ptr); ctx->ok = 0; break; } configparser_push(ctx, dc, 1); } buffer_free(b); buffer_free(op); buffer_free(yymsp[-5].minor.yy0); yymsp[-5].minor.yy0 = NULL; buffer_free(yymsp[-3].minor.yy43); yymsp[-3].minor.yy43 = NULL; yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } #line 1298 "configparser.c" yy_destructor(16,&yymsp[-6].minor); yy_destructor(18,&yymsp[-4].minor); yy_destructor(19,&yymsp[-2].minor); break; case 33: #line 516 "./configparser.y" { yygotominor.yy27 = CONFIG_COND_EQ; } #line 1308 "configparser.c" yy_destructor(20,&yymsp[0].minor); break; case 34: #line 519 "./configparser.y" { yygotominor.yy27 = CONFIG_COND_MATCH; } #line 1316 "configparser.c" yy_destructor(21,&yymsp[0].minor); break; case 35: #line 522 "./configparser.y" { yygotominor.yy27 = CONFIG_COND_NE; } #line 1324 "configparser.c" yy_destructor(22,&yymsp[0].minor); break; case 36: #line 525 "./configparser.y" { yygotominor.yy27 = CONFIG_COND_NOMATCH; } #line 1332 "configparser.c" yy_destructor(23,&yymsp[0].minor); break; case 37: #line 529 "./configparser.y" { yygotominor.yy43 = NULL; if (ctx->ok) { if (yymsp[0].minor.yy41->type == TYPE_STRING) { yygotominor.yy43 = buffer_init_buffer(((data_string*)yymsp[0].minor.yy41)->value); } else if (yymsp[0].minor.yy41->type == TYPE_INTEGER) { yygotominor.yy43 = buffer_init(); buffer_copy_long(yygotominor.yy43, ((data_integer *)yymsp[0].minor.yy41)->value); } else { fprintf(stderr, "operand must be string"); ctx->ok = 0; } } yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } #line 1353 "configparser.c" break; case 38: #line 546 "./configparser.y" { if (ctx->ok) { if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) { ctx->ok = 0; } buffer_free(yymsp[0].minor.yy43); yymsp[0].minor.yy43 = NULL; } } #line 1366 "configparser.c" yy_destructor(24,&yymsp[-1].minor); break; case 39: #line 556 "./configparser.y" { if (ctx->ok) { if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) { ctx->ok = 0; } buffer_free(yymsp[0].minor.yy43); yymsp[0].minor.yy43 = NULL; } } #line 1380 "configparser.c" yy_destructor(25,&yymsp[-1].minor); break; }; yygoto = yyRuleInfo[yyruleno].lhs; yysize = yyRuleInfo[yyruleno].nrhs; yypParser->yyidx -= yysize; yyact = yy_find_reduce_action(yypParser,yygoto); if( yyact < YYNSTATE ){ yy_shift(yypParser,yyact,yygoto,&yygotominor); }else if( yyact == YYNSTATE + YYNRULE + 1 ){ yy_accept(yypParser); } }
int config_read(server *srv, const char *fn) { config_t context; data_config *dc; data_integer *dpid; data_string *dcwd; int ret; char *pos; data_array *modules; context_init(srv, &context); context.all_configs = srv->config_context; #ifdef __WIN32 pos = strrchr(fn, '\\'); #else pos = strrchr(fn, '/'); #endif if (pos) { buffer_copy_string_len(context.basedir, fn, pos - fn + 1); fn = pos + 1; } dc = data_config_init(); buffer_copy_string_len(dc->key, CONST_STR_LEN("global")); assert(context.all_configs->used == 0); dc->context_ndx = context.all_configs->used; array_insert_unique(context.all_configs, (data_unset *)dc); context.current = dc; /* default context */ srv->config = dc->value; dpid = data_integer_init(); dpid->value = getpid(); buffer_copy_string_len(dpid->key, CONST_STR_LEN("var.PID")); array_insert_unique(srv->config, (data_unset *)dpid); dcwd = data_string_init(); buffer_prepare_copy(dcwd->value, 1024); if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) { dcwd->value->used = strlen(dcwd->value->ptr) + 1; buffer_copy_string_len(dcwd->key, CONST_STR_LEN("var.CWD")); array_insert_unique(srv->config, (data_unset *)dcwd); } ret = config_parse_file(srv, &context, fn); /* remains nothing if parser is ok */ assert(!(0 == ret && context.ok && 0 != context.configs_stack->used)); context_free(&context); if (0 != ret) { return ret; } if (NULL != (dc = (data_config *)array_get_element(srv->config_context, "global"))) { srv->config = dc->value; } else { return -1; } if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) { data_string *ds; data_array *prepends; if (modules->type != TYPE_ARRAY) { fprintf(stderr, "server.modules must be an array"); return -1; } prepends = data_array_init(); /* prepend default modules */ if (NULL == array_get_element(modules->value, "mod_indexfile")) { ds = data_string_init(); buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile")); array_insert_unique(prepends->value, (data_unset *)ds); } prepends = (data_array *)configparser_merge_data((data_unset *)prepends, (data_unset *)modules); buffer_copy_string_buffer(prepends->key, modules->key); array_replace(srv->config, (data_unset *)prepends); modules->free((data_unset *)modules); modules = prepends; /* append default modules */ if (NULL == array_get_element(modules->value, "mod_dirlisting")) { ds = data_string_init(); buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting")); array_insert_unique(modules->value, (data_unset *)ds); } if (NULL == array_get_element(modules->value, "mod_staticfile")) { ds = data_string_init(); buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile")); array_insert_unique(modules->value, (data_unset *)ds); } } else { data_string *ds; modules = data_array_init(); /* server.modules is not set */ ds = data_string_init(); buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_indexfile")); array_insert_unique(modules->value, (data_unset *)ds); ds = data_string_init(); buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_dirlisting")); array_insert_unique(modules->value, (data_unset *)ds); ds = data_string_init(); buffer_copy_string_len(ds->value, CONST_STR_LEN("mod_staticfile")); array_insert_unique(modules->value, (data_unset *)ds); buffer_copy_string_len(modules->key, CONST_STR_LEN("server.modules")); array_insert_unique(srv->config, (data_unset *)modules); } if (0 != config_insert(srv)) { return -1; } return 0; }