Do not use C macros for configuration files.

This commit is contained in:
Jan Vidar Krey 2010-04-15 19:49:23 +02:00
parent 51c5b6169c
commit 201acad409
5 changed files with 1325 additions and 445 deletions

View File

@ -29,101 +29,52 @@
#define INT_MIN (-0x7fffffff - 1) #define INT_MIN (-0x7fffffff - 1)
#endif #endif
#define CFG_APPLY_BOOLEAN(KEY, TARGET) \ static int apply_boolean(const char* key, const char* data, int* target)
if (strcmp(KEY, key) == 0) \ {
{ \ if (strlen(data) == 1 && (data[0] == '1')) *target = 1;
if (strlen(data) == 1 && (data[0] == '1')) TARGET = 1; \ else if (strlen(data) == 1 && (data[0] == '0')) *target = 0;
else if (strlen(data) == 1 && (data[0] == '0')) TARGET = 0; \ else if (strncasecmp(data, "true", 4) == 0) *target = 1;
else if (strncasecmp(data, "true", 4) == 0) TARGET = 1; \ else if (strncasecmp(data, "false", 5) == 0) *target = 0;
else if (strncasecmp(data, "false", 5) == 0) TARGET = 0; \ else if (strncasecmp(data, "yes", 3) == 0) *target = 1;
else if (strncasecmp(data, "yes", 3) == 0) TARGET = 1; \ else if (strncasecmp(data, "no", 2) == 0) *target = 0;
else if (strncasecmp(data, "no", 2) == 0) TARGET = 0; \ else if (strncasecmp(data, "on", 2) == 0) *target = 1;
else if (strncasecmp(data, "on", 2) == 0) TARGET = 1; \ else if (strncasecmp(data, "off", 3) == 0) *target = 0;
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \ else
else\ return 0;
{ \ return 1;
LOG_FATAL("Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
return -1; \
} \
return 0; \
}
#define CFG_APPLY_STRING(KEY, TARGET) \
if (strcmp(KEY, key) == 0) \
{ \
TARGET = hub_strdup(data); \
return 0; \
}
#define CFG_APPLY_INTEGER(KEY, TARGET) \
if (strcmp(KEY, key) == 0) \
{ \
char* endptr; \
int val; \
errno = 0; \
val = strtol(data, &endptr, 10); \
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
LOG_FATAL("Configuration error on line %d: '%s' must be a number", line_count, key); \
return -1; \
} \
TARGET = val; \
return 0; \
}
#define DEFAULT_STRING(KEY, VALUE) \
{ \
if (config->KEY == 0) \
config->KEY = hub_strdup(VALUE); \
} }
#define DEFAULT_INTEGER(KEY, VALUE) \ static int apply_string(const char* key, const char* data, char** target, char* regexp)
{ \ {
if (config->KEY == 0) \ (void) regexp;
config->KEY = VALUE; \ // FIXME: Add regexp checks for correct data
if (*target)
hub_free(*target);
*target = hub_strdup(data);
return 1;
} }
#define DEFAULT_BOOLEAN(KEY, VALUE) \ static int apply_integer(const char* key, const char* data, int* target, int* min, int* max)
config->KEY = config->KEY & 0x000000ff; {
char* endptr;
int val;
errno = 0;
val = strtol(data, &endptr, 10);
#define GET_STR(NAME) CFG_APPLY_STRING ( #NAME , config->NAME ) if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data)
#define GET_INT(NAME) CFG_APPLY_INTEGER( #NAME , config->NAME ) return 0;
#define GET_BOOL(NAME) CFG_APPLY_BOOLEAN( #NAME , config->NAME )
#define IGNORED(NAME) \
if (strcmp(#NAME, key) == 0) \
{ \
LOG_WARN("Configuration option %s deprecated and ingnored.", key); \
return 0; \
}
#define DUMP_STR(NAME, DEFAULT) \ if (min && val < *min)
if (ignore_defaults) \ return 0;
{ \
if (strcmp(config->NAME, DEFAULT) != 0) \
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
} \
else \
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
#define DUMP_INT(NAME, DEFAULT) \
if (ignore_defaults) \
{ \
if (config->NAME != DEFAULT) \
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
} \
else \
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
#define DUMP_BOOL(NAME, DEFAULT) \ if (max && val > *max)
if (ignore_defaults) \ return 0;
{ \
if (config->NAME != DEFAULT) \
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no")); \
} \
else \
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no"));
*target = val;
return 1;
}
#include "gen_config.c" #include "gen_config.c"

View File

@ -20,8 +20,7 @@ open GENHEAD, ">gen_config.h" || die "Unable to write header file";
print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\nstruct hub_config\n{\n"; print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\nstruct hub_config\n{\n";
foreach my $p ($tree->root->children("option")) foreach my $p ($tree->root->children("option"))
{ {
my @data = ($p->att("type"), $p->att("name"), $p->att("default"), $p->att("advanced"), $p->children_text("short"), $p->children_text("description"), $p->children_text("since"), $p->children_text("example")); write_c_header(get_data($p));
write_c_header(@data);
} }
print GENHEAD "};\n\n"; print GENHEAD "};\n\n";
@ -38,7 +37,8 @@ foreach my $p ($tree->root->children("option"))
print GENIMPL "}\n\n"; print GENIMPL "}\n\n";
# apply function # apply function
print GENIMPL "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n"; print GENIMPL "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n";
foreach my $p ($tree->root->children("option")) foreach my $p ($tree->root->children("option"))
{ {
write_c_impl_apply(get_data($p)); write_c_impl_apply(get_data($p));
@ -105,29 +105,92 @@ sub write_c_impl_defaults(@)
{ {
my @output = @_; my @output = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output; my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
my $prefix = "";
my $suffix = "";
print GENIMPL "\t"; print GENIMPL "\tconfig->$name = ";
print GENIMPL "DEFAULT_INTEGER" if ($type eq "int");
print GENIMPL "DEFAULT_BOOLEAN" if ($type eq "boolean");
if ($type =~ /(string|file|message)/) if ($type =~ /(string|file|message)/)
{ {
print GENIMPL "DEFAULT_STRING "; $prefix = "hub_strdup(\"";
$default = "\"" . $default . "\""; $suffix = "\")"
} }
print GENIMPL "(" . $name . ", " . $default . ");\n"; print GENIMPL $prefix . $default . $suffix . ";\n";
} }
sub write_c_impl_apply(@) sub write_c_impl_apply(@)
{ {
my @output = @_; my @output = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output; my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $p) = @output;
print GENIMPL "\t"; my $min;
print GENIMPL "GET_INT " if ($type eq "int"); my $max;
print GENIMPL "GET_BOOL" if ($type eq "boolean"); my $regexp;
print GENIMPL "GET_STR " if ($type =~ /(string|file|message)/);
print GENIMPL "(" . $name . ");\n"; if (defined $p)
{
$min = $p->att("min");
$max = $p->att("max");
$regexp = $p->att("regexp");
print "'check' is defined for option $name";
print ", min=$min" if (defined $min);
print ", max=$max" if (defined $max);
print ", regexp=\"$regexp\"" if (defined $regexp);
print "\n";
}
print GENIMPL "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n";
if ($type eq "int")
{
if (defined $min)
{
print GENIMPL "\t\tmin = $min;\n"
}
if (defined $max)
{
print GENIMPL "\t\tmax = $max;\n"
}
print GENIMPL "\t\tif (!apply_integer(key, data, &config->$name, ";
if (defined $min)
{
print GENIMPL "&min";
}
else
{
print GENIMPL "0";
}
print GENIMPL ", ";
if (defined $max)
{
print GENIMPL "&max";
}
else
{
print GENIMPL "0";
}
print GENIMPL "))\n";
}
elsif ($type eq "boolean")
{
print GENIMPL "\t\tif (!apply_boolean(key, data, &config->$name))\n";
}
elsif ($type =~ /(string|file|message)/)
{
print GENIMPL "\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n";
}
print GENIMPL "\t\t{\n" .
"\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" .
"\t\t\treturn -1;\n" .
"\t\t}\n" .
"\t\treturn 0;\n" .
"\t}\n\n";
} }
sub write_c_impl_free(@) sub write_c_impl_free(@)
@ -135,30 +198,44 @@ sub write_c_impl_free(@)
my @output = @_; my @output = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output; my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
print GENIMPL "\thub_free(config->" . $name . ");\n" if ($type =~ /(string|file|message)/) if ($type =~ /(string|file|message)/)
{
print GENIMPL "\thub_free(config->" . $name . ");\n\n"
}
} }
sub write_c_impl_dump(@) sub write_c_impl_dump(@)
{ {
my @output = @_; my @output = @_;
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output; my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
my $out;
my $val = "config->$name";
my $test = "config->$name != $default";
print GENIMPL "\t"; if ($type eq "int")
print GENIMPL "DUMP_INT " if ($type eq "int");
print GENIMPL "DUMP_BOOL" if ($type eq "boolean");
if ($type =~ /(string|file|message)/)
{ {
print GENIMPL "DUMP_STR"; $out = "%d";
$default = "\"" . $default . "\"";
} }
print GENIMPL "(" . $name . ", " . $default . ");\n" elsif ($type eq "boolean")
{
$out = "%s";
$val = "config->$name ? \"yes\" : \"no\"";
}
elsif ($type =~ /(string|file|message)/)
{
$out = "\\\"%s\\\"";
$test = "strcmp(config->$name, \"$default\") != 0";
}
print GENIMPL "\tif (!ignore_defaults || $test)\n";
print GENIMPL "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n\n";
} }
sub get_data($) sub get_data($)
{ {
my $p = shift; my $p = shift;
my @data = ($p->att("type"), $p->att("name"), $p->att("default"), $p->att("advanced"), $p->children_text("short"), $p->children_text("description"), $p->children_text("since"), $p->children_text("example")); my $check = $p->first_child_matches("check");
my @data = ($p->att("type"), $p->att("name"), $p->att("default"), $p->att("advanced"), $p->children_text("short"), $p->children_text("description"), $p->children_text("since"), $p->children_text("example"), $check);
return @data; return @data;
} }

View File

@ -1,5 +1,14 @@
<?xml version='1.0' standalone="yes" ?> <?xml version='1.0' standalone="yes" ?>
<config> <config>
<option name="hub_enabled" type="boolean" default="1">
<short>Is server enabled</short>
<description>
Use this to disable the hub for a while.
</description>
<since>0.1.3</since>
</option>
<option name="server_port" type="int" default="1511"> <option name="server_port" type="int" default="1511">
<check min="1" max="65535" /> <check min="1" max="65535" />
<since>0.1.0</since> <since>0.1.0</since>
@ -60,14 +69,6 @@
<since>0.3.0</since> <since>0.3.0</since>
</option> </option>
<option name="hub_enabled" type="boolean" default="1">
<short>Is server enabled</short>
<description>
Use this to disable the hub for a while.
</description>
<since>0.1.3</since>
</option>
<option name="show_banner" type="boolean" default="1"> <option name="show_banner" type="boolean" default="1">
<short>Show banner on connect</short> <short>Show banner on connect</short>
<description> <description>
@ -86,7 +87,7 @@
</option> </option>
<option name="max_users" type="int" default="500"> <option name="max_users" type="int" default="500">
<check min="1" /> <check min="1" max="1048576" />
<short>Maximum number of users allowed on the hub</short> <short>Maximum number of users allowed on the hub</short>
<description> <description>
The maximum amount of users allowed on the hub. The maximum amount of users allowed on the hub.
@ -327,7 +328,7 @@
</option> </option>
<option name="flood_ctl_interval" type="int" default="0"> <option name="flood_ctl_interval" type="int" default="0">
<check min="0" max="60" /> <check min="1" max="60" />
<short>Time interval in seconds for flood control check.</short> <short>Time interval in seconds for flood control check.</short>
<description> <description>
This is the time interval that will be used for all flood control calculations. This is the time interval that will be used for all flood control calculations.

File diff suppressed because it is too large Load Diff

View File

@ -2,85 +2,3 @@
struct hub_config struct hub_config
{ {
int server_port; /*<<< Server port to bind to (default: 1511) */
char* server_bind_addr; /*<<< Server bind address (default: any) */
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: ) */
int hub_enabled; /*<<< Is server enabled (default: 1) */
int show_banner; /*<<< Show banner on connect (default: 1) */
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
int registered_users_only; /*<<< Allow registered users only (default: 0) */
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
int chat_only; /*<<< Allow chat only operation on hub (default: 0) */
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
char* hub_name; /*<<< Name of hub (default: uhub) */
char* hub_description; /*<<< Short hub description, topic or subject. (default: no description) */
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */
int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */
int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
int low_bandwidth_mode; /*<<< Enable bandwidth saving measures (default: 0) */
int max_chat_history; /*<<< Number of chat messages kept in history (default: 20) */
int max_logout_log; /*<<< Number of log entries for people leaving the hub (default: 20) */
int limit_max_hubs_user; /*<<< Max concurrent hubs as a guest user (default: 10) */
int limit_max_hubs_reg; /*<<< Max concurrent hubs as a registered user (default: 10) */
int limit_max_hubs_op; /*<<< Max concurrent hubs as a operator (or admin) (default: 10) */
int limit_max_hubs; /*<<< Max total hub connections allowed, user/reg/op combined. (default: 25) */
int limit_min_hubs_user; /*<<< Minimum concurrent hubs as a guest user (default: 0) */
int limit_min_hubs_reg; /*<<< Minimum concurrent hubs as a registered user (default: 0) */
int limit_min_hubs_op; /*<<< Minimum concurrent hubs as a operator (or admin) (default: 0) */
int limit_min_share; /*<<< Limit minimum share size in megabytes (default: 0) */
int limit_max_share; /*<<< Limit maximum share size in megabytes (default: 0) */
int limit_min_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
int limit_max_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
int flood_ctl_interval; /*<<< Time interval in seconds for flood control check. (default: 0) */
int flood_ctl_chat; /*<<< Max chat messages allowed in time interval (default: 0) */
int flood_ctl_connect; /*<<< Max connections requests allowed in time interval (default: 0) */
int flood_ctl_search; /*<<< Max search requests allowed in time interval (default: 0) */
int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) (default: 0) */
char* tls_certificate; /*<<< Certificate file (default: ) */
char* tls_private_key; /*<<< Private key file (default: ) */
char* file_motd; /*<<< File containing the 'message of the day (default: ) */
char* file_acl; /*<<< File containing access control lists (default: ) */
char* file_rules; /*<<< File containing hub rules (default: ) */
char* msg_hub_full; /*<<< "Hub is full" */
char* msg_hub_disabled; /*<<< "Hub is disabled" */
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */
char* msg_inf_error_nick_missing; /*<<< "No nickname given" */
char* msg_inf_error_nick_multiple; /*<<< "Multiple nicknames given" */
char* msg_inf_error_nick_invalid; /*<<< "Nickname is invalid" */
char* msg_inf_error_nick_long; /*<<< "Nickname too long" */
char* msg_inf_error_nick_short; /*<<< "Nickname too short" */
char* msg_inf_error_nick_spaces; /*<<< "Nickname cannot start with spaces" */
char* msg_inf_error_nick_bad_chars; /*<<< "Nickname contains invalid characters" */
char* msg_inf_error_nick_not_utf8; /*<<< "Nickname is not valid UTF-8" */
char* msg_inf_error_nick_taken; /*<<< "Nickname is already in use" */
char* msg_inf_error_nick_restricted; /*<<< "Nickname cannot be used on this hub" */
char* msg_inf_error_cid_invalid; /*<<< "CID is not valid" */
char* msg_inf_error_cid_missing; /*<<< "CID is not specified" */
char* msg_inf_error_cid_taken; /*<<< "CID is taken" */
char* msg_inf_error_pid_missing; /*<<< "PID is not specified" */
char* msg_inf_error_pid_invalid; /*<<< "PID is invalid" */
char* msg_ban_permanently; /*<<< "Banned permanently" */
char* msg_ban_temporarily; /*<<< "Banned temporarily" */
char* msg_auth_invalid_password; /*<<< "Password is wrong" */
char* msg_auth_user_not_found; /*<<< "User not found in password database" */
char* msg_error_no_memory; /*<<< "No memory" */
char* msg_user_share_size_low; /*<<< "User is not sharing enough" */
char* msg_user_share_size_high; /*<<< "User is sharing too much" */
char* msg_user_slots_low; /*<<< "User have too few upload slots." */
char* msg_user_slots_high; /*<<< "User have too many upload slots." */
char* msg_user_hub_limit_low; /*<<< "User is on too few hubs." */
char* msg_user_hub_limit_high; /*<<< "User is on too many hubs." */
char* msg_user_flood_chat; /*<<< "Chat flood detected, messages are dropped." */
char* msg_user_flood_connect; /*<<< "Connect flood detected, connection refused." */
char* msg_user_flood_search; /*<<< "Search flood detected, search is stopped." */
char* msg_user_flood_update; /*<<< "Update flood detected." */
char* msg_user_flood_extras; /*<<< "Flood detected." */
char* msg_proto_no_common_hash; /*<<< "No common hash algorithm." */
char* msg_proto_obsolete_adc0; /*<<< "Client is using an obsolete ADC protocol version." */
};