|
|
|
@ -258,184 +258,6 @@ int config_plugin_values_init(server * const srv, void *p_d, const config_plugin |
|
|
|
|
return rc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* handle global options */ |
|
|
|
|
|
|
|
|
|
/* parse config array */ |
|
|
|
|
int config_insert_values_internal(server *srv, const array *ca, const config_values_t cv[], config_scope_type_t scope) { |
|
|
|
|
size_t i; |
|
|
|
|
const data_unset *du; |
|
|
|
|
|
|
|
|
|
for (i = 0; cv[i].key; i++) { |
|
|
|
|
|
|
|
|
|
if (NULL == (du = array_get_element_klen(ca, cv[i].key, strlen(cv[i].key)))) { |
|
|
|
|
/* no found */ |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((T_CONFIG_SCOPE_SERVER == cv[i].scope) |
|
|
|
|
&& (T_CONFIG_SCOPE_SERVER != scope)) { |
|
|
|
|
/* server scope options should only be set in server scope, not in conditionals */ |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ss", |
|
|
|
|
"DEPRECATED: don't set server options in conditionals, variable:", |
|
|
|
|
cv[i].key); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch (cv[i].type) { |
|
|
|
|
case T_CONFIG_ARRAY: |
|
|
|
|
if (du->type == TYPE_ARRAY) { |
|
|
|
|
size_t j; |
|
|
|
|
const data_array *da = (const data_array *)du; |
|
|
|
|
|
|
|
|
|
for (j = 0; j < da->value.used; j++) { |
|
|
|
|
data_unset *ds = da->value.data[j]; |
|
|
|
|
if (ds->type == TYPE_STRING || ds->type == TYPE_INTEGER || ds->type == TYPE_ARRAY) { |
|
|
|
|
array_insert_unique(cv[i].destination, ds->fn->copy(ds)); |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sssbsd", |
|
|
|
|
"the value of an array can only be a string, variable:", |
|
|
|
|
cv[i].key, "[", &ds->key, "], type:", ds->type); |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ss", cv[i].key, "should have been a array of strings like ... = ( \"...\" )"); |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case T_CONFIG_STRING: |
|
|
|
|
if (du->type == TYPE_STRING) { |
|
|
|
|
const data_string *ds = (const data_string *)du; |
|
|
|
|
|
|
|
|
|
buffer_copy_buffer(cv[i].destination, &ds->value); |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ss", cv[i].key, "should have been a string like ... = \"...\""); |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case T_CONFIG_SHORT: |
|
|
|
|
switch(du->type) { |
|
|
|
|
case TYPE_INTEGER: { |
|
|
|
|
const data_integer *di = (const data_integer *)du; |
|
|
|
|
|
|
|
|
|
*((unsigned short *)(cv[i].destination)) = di->value; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case TYPE_STRING: { |
|
|
|
|
const data_string *ds = (const data_string *)du; |
|
|
|
|
|
|
|
|
|
/* If the value came from an environment variable, then it is a
|
|
|
|
|
* data_string, although it may contain a number in ASCII |
|
|
|
|
* decimal format. We try to interpret the string as a decimal |
|
|
|
|
* short before giving up, in order to support setting numeric |
|
|
|
|
* values with environment variables (eg, port number). |
|
|
|
|
*/ |
|
|
|
|
if (ds->value.ptr && *ds->value.ptr) { |
|
|
|
|
char *e; |
|
|
|
|
long l = strtol(ds->value.ptr, &e, 10); |
|
|
|
|
if (e != ds->value.ptr && !*e && l >=0 && l <= 65535) { |
|
|
|
|
*((unsigned short *)(cv[i].destination)) = l; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected a short:", cv[i].key, &ds->value); |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
default: |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a short integer, range 0 ... 65535"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case T_CONFIG_INT: |
|
|
|
|
switch(du->type) { |
|
|
|
|
case TYPE_INTEGER: { |
|
|
|
|
const data_integer *di = (const data_integer *)du; |
|
|
|
|
|
|
|
|
|
*((unsigned int *)(cv[i].destination)) = di->value; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case TYPE_STRING: { |
|
|
|
|
const data_string *ds = (const data_string *)du; |
|
|
|
|
|
|
|
|
|
if (ds->value.ptr && *ds->value.ptr) { |
|
|
|
|
char *e; |
|
|
|
|
long l = strtol(ds->value.ptr, &e, 10); |
|
|
|
|
if (e != ds->value.ptr && !*e && l >= 0) { |
|
|
|
|
*((unsigned int *)(cv[i].destination)) = l; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected an integer:", cv[i].key, &ds->value); |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
default: |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected an integer, range 0 ... 4294967295"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case T_CONFIG_BOOLEAN: |
|
|
|
|
if (du->type == TYPE_STRING) { |
|
|
|
|
const data_string *ds = (const data_string *)du; |
|
|
|
|
|
|
|
|
|
if (buffer_is_equal_string(&ds->value, CONST_STR_LEN("enable"))) { |
|
|
|
|
*((unsigned short *)(cv[i].destination)) = 1; |
|
|
|
|
} else if (buffer_is_equal_string(&ds->value, CONST_STR_LEN("disable"))) { |
|
|
|
|
*((unsigned short *)(cv[i].destination)) = 0; |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, &ds->value, "(enable|disable)"); |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\""); |
|
|
|
|
|
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case T_CONFIG_LOCAL: |
|
|
|
|
case T_CONFIG_UNSET: |
|
|
|
|
break; |
|
|
|
|
case T_CONFIG_UNSUPPORTED: |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found unsupported key:", cv[i].key, "-", (char *)(cv[i].destination)); |
|
|
|
|
|
|
|
|
|
srv->srvconf.config_unsupported = 1; |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
case T_CONFIG_DEPRECATED: |
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination)); |
|
|
|
|
|
|
|
|
|
srv->srvconf.config_deprecated = 1; |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int config_insert_values_global(server *srv, const array *ca, const config_values_t cv[], config_scope_type_t scope) { |
|
|
|
|
size_t i; |
|
|
|
|
const data_unset *du; |
|
|
|
|
|
|
|
|
|
for (i = 0; cv[i].key; i++) { |
|
|
|
|
if (NULL == (du = array_get_element_klen(ca, cv[i].key, strlen(cv[i].key)))) { |
|
|
|
|
/* no found */ |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
array_set_key_value(srv->srvconf.config_touched, CONST_BUF_LEN(&du->key), CONST_STR_LEN("")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return config_insert_values_internal(srv, ca, cv, scope); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
__attribute_cold__ |
|
|
|
|
__attribute_noinline__ |
|
|
|
|
static void config_cond_result_trace(connection *con, const data_config *dc, int cached) { |
|
|
|
|