summaryrefslogtreecommitdiffstats
path: root/src/cfg_file.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/cfg_file.y')
-rw-r--r--src/cfg_file.y545
1 files changed, 545 insertions, 0 deletions
diff --git a/src/cfg_file.y b/src/cfg_file.y
new file mode 100644
index 000000000..dbbdd4e63
--- /dev/null
+++ b/src/cfg_file.y
@@ -0,0 +1,545 @@
+/* $Id$ */
+
+%{
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <glib.h>
+
+#include "cfg_file.h"
+#include "main.h"
+
+#define YYDEBUG 1
+
+extern struct config_file *cfg;
+extern int yylineno;
+extern char *yytext;
+
+LIST_HEAD (moduleoptq, module_opt) *cur_module_opt = NULL;
+struct metric *cur_metric = NULL;
+
+%}
+
+%union
+{
+ char *string;
+ size_t limit;
+ char flag;
+ unsigned int seconds;
+ unsigned int number;
+ double fract;
+}
+
+%token ERROR STRING QUOTEDSTRING FLAG
+%token FILENAME REGEXP QUOTE SEMICOLON OBRACE EBRACE COMMA EQSIGN
+%token BINDSOCK SOCKCRED DOMAIN IPADDR IPNETWORK HOSTPORT NUMBER CHECK_TIMEOUT
+%token MAXSIZE SIZELIMIT SECONDS BEANSTALK MYSQL USER PASSWORD DATABASE
+%token TEMPDIR PIDFILE SERVERS ERROR_TIME DEAD_TIME MAXERRORS CONNECT_TIMEOUT PROTOCOL RECONNECT_TIMEOUT
+%token READ_SERVERS WRITE_SERVER DIRECTORY_SERVERS MAILBOX_QUERY USERS_QUERY LASTLOGIN_QUERY
+%token MEMCACHED WORKERS REQUIRE MODULE
+%token MODULE_OPT PARAM VARIABLE
+%token HEADER_FILTERS MIME_FILTERS MESSAGE_FILTERS URL_FILTERS FACTORS METRIC NAME
+%token REQUIRED_SCORE FUNCTION FRACT COMPOSITES CONTROL PASSWORD
+%token LOGGING LOG_TYPE LOG_TYPE_CONSOLE LOG_TYPE_SYSLOG LOG_TYPE_FILE
+%token LOG_LEVEL LOG_LEVEL_DEBUG LOG_LEVEL_INFO LOG_LEVEL_WARNING LOG_LEVEL_ERROR LOG_FACILITY LOG_FILENAME
+
+%type <string> STRING
+%type <string> VARIABLE
+%type <string> QUOTEDSTRING MODULE_OPT PARAM
+%type <string> FILENAME
+%type <string> SOCKCRED
+%type <string> IPADDR IPNETWORK
+%type <string> HOSTPORT
+%type <string> DOMAIN
+%type <limit> SIZELIMIT
+%type <flag> FLAG
+%type <seconds> SECONDS
+%type <number> NUMBER
+%type <string> memcached_hosts bind_cred
+%type <fract> FRACT
+%%
+
+file : /* empty */
+ | file command SEMICOLON { }
+ ;
+
+command :
+ bindsock
+ | control
+ | tempdir
+ | pidfile
+ | memcached
+ | workers
+ | require
+ | header_filters
+ | mime_filters
+ | message_filters
+ | url_filters
+ | module_opt
+ | variable
+ | factors
+ | metric
+ | composites
+ | logging
+ ;
+
+tempdir :
+ TEMPDIR EQSIGN QUOTEDSTRING {
+ struct stat st;
+
+ if (stat ($3, &st) == -1) {
+ yyerror ("yyparse: cannot stat directory \"%s\": %s", $3, strerror (errno));
+ YYERROR;
+ }
+ if (!S_ISDIR (st.st_mode)) {
+ yyerror ("yyparse: \"%s\" is not a directory", $3);
+ YYERROR;
+ }
+ cfg->temp_dir = memory_pool_strdup (cfg->cfg_pool, $3);
+ free ($3);
+ }
+ ;
+
+pidfile :
+ PIDFILE EQSIGN QUOTEDSTRING {
+ cfg->pid_file = $3;
+ }
+ ;
+
+control:
+ CONTROL OBRACE controlbody EBRACE
+ ;
+
+controlbody:
+ controlcmd SEMICOLON
+ | controlbody controlcmd SEMICOLON
+ ;
+
+controlcmd:
+ controlsock
+ | controlpassword
+ ;
+
+controlsock:
+ BINDSOCK EQSIGN bind_cred {
+ if (!parse_bind_line (cfg, $3, 1)) {
+ yyerror ("yyparse: parse_bind_line");
+ YYERROR;
+ }
+ cfg->controller_enabled = 1;
+ free ($3);
+ }
+ ;
+controlpassword:
+ PASSWORD EQSIGN QUOTEDSTRING {
+ cfg->control_password = memory_pool_strdup (cfg->cfg_pool, $3);
+ }
+ ;
+
+bindsock:
+ BINDSOCK EQSIGN bind_cred {
+ if (!parse_bind_line (cfg, $3, 0)) {
+ yyerror ("yyparse: parse_bind_line");
+ YYERROR;
+ }
+ free ($3);
+ }
+ ;
+
+bind_cred:
+ STRING {
+ $$ = $1;
+ }
+ | IPADDR{
+ $$ = $1;
+ }
+ | DOMAIN {
+ $$ = $1;
+ }
+ | HOSTPORT {
+ $$ = $1;
+ }
+ | QUOTEDSTRING {
+ $$ = $1;
+ }
+ ;
+
+header_filters:
+ HEADER_FILTERS EQSIGN QUOTEDSTRING {
+ cfg->header_filters_str = memory_pool_strdup (cfg->cfg_pool, $3);
+ free ($3);
+ }
+ ;
+
+mime_filters:
+ MIME_FILTERS EQSIGN QUOTEDSTRING {
+ cfg->mime_filters_str = memory_pool_strdup (cfg->cfg_pool, $3);
+ free ($3);
+ }
+ ;
+
+message_filters:
+ MESSAGE_FILTERS EQSIGN QUOTEDSTRING {
+ cfg->message_filters_str = memory_pool_strdup (cfg->cfg_pool, $3);
+ free ($3);
+ }
+ ;
+
+url_filters:
+ URL_FILTERS EQSIGN QUOTEDSTRING {
+ cfg->url_filters_str = memory_pool_strdup (cfg->cfg_pool, $3);
+ free ($3);
+ }
+ ;
+
+memcached:
+ MEMCACHED OBRACE memcachedbody EBRACE
+ ;
+
+memcachedbody:
+ memcachedcmd SEMICOLON
+ | memcachedbody memcachedcmd SEMICOLON
+ ;
+
+memcachedcmd:
+ memcached_servers
+ | memcached_connect_timeout
+ | memcached_error_time
+ | memcached_dead_time
+ | memcached_maxerrors
+ | memcached_protocol
+ ;
+
+memcached_servers:
+ SERVERS EQSIGN memcached_server
+ ;
+
+memcached_server:
+ memcached_params
+ | memcached_server COMMA memcached_params
+ ;
+
+memcached_params:
+ memcached_hosts {
+ if (!add_memcached_server (cfg, $1)) {
+ yyerror ("yyparse: add_memcached_server");
+ YYERROR;
+ }
+ free ($1);
+ }
+ ;
+memcached_hosts:
+ STRING
+ | IPADDR
+ | DOMAIN
+ | HOSTPORT
+ ;
+memcached_error_time:
+ ERROR_TIME EQSIGN NUMBER {
+ cfg->memcached_error_time = $3;
+ }
+ ;
+memcached_dead_time:
+ DEAD_TIME EQSIGN NUMBER {
+ cfg->memcached_dead_time = $3;
+ }
+ ;
+memcached_maxerrors:
+ MAXERRORS EQSIGN NUMBER {
+ cfg->memcached_maxerrors = $3;
+ }
+ ;
+memcached_connect_timeout:
+ CONNECT_TIMEOUT EQSIGN SECONDS {
+ cfg->memcached_connect_timeout = $3;
+ }
+ ;
+
+memcached_protocol:
+ PROTOCOL EQSIGN STRING {
+ if (strncasecmp ($3, "udp", sizeof ("udp") - 1) == 0) {
+ cfg->memcached_protocol = UDP_TEXT;
+ }
+ else if (strncasecmp ($3, "tcp", sizeof ("tcp") - 1) == 0) {
+ cfg->memcached_protocol = TCP_TEXT;
+ }
+ else {
+ yyerror ("yyparse: cannot recognize protocol: %s", $3);
+ YYERROR;
+ }
+ }
+ ;
+workers:
+ WORKERS EQSIGN NUMBER {
+ cfg->workers_number = $3;
+ }
+ ;
+
+metric:
+ METRIC OBRACE metricbody EBRACE {
+ if (cur_metric == NULL || cur_metric->name == NULL) {
+ yyerror ("yyparse: not enough arguments in metric definition");
+ YYERROR;
+ }
+ g_hash_table_insert (cfg->metrics, cur_metric->name, cur_metric);
+ cur_metric = NULL;
+ }
+ ;
+
+metricbody:
+ | metriccmd SEMICOLON
+ | metricbody metriccmd SEMICOLON
+ ;
+metriccmd:
+ | metricname
+ | metricfunction
+ | metricscore
+ ;
+
+metricname:
+ NAME EQSIGN QUOTEDSTRING {
+ if (cur_metric == NULL) {
+ cur_metric = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct metric));
+ }
+ cur_metric->name = memory_pool_strdup (cfg->cfg_pool, $3);
+ }
+ ;
+
+metricfunction:
+ FUNCTION EQSIGN QUOTEDSTRING {
+ if (cur_metric == NULL) {
+ cur_metric = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct metric));
+ }
+ cur_metric->func_name = memory_pool_strdup (cfg->cfg_pool, $3);
+ }
+ ;
+
+metricscore:
+ REQUIRED_SCORE EQSIGN NUMBER {
+ if (cur_metric == NULL) {
+ cur_metric = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct metric));
+ }
+ cur_metric->required_score = $3;
+ }
+ | REQUIRED_SCORE EQSIGN FRACT {
+ if (cur_metric == NULL) {
+ cur_metric = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct metric));
+ }
+ cur_metric->required_score = $3;
+ }
+ ;
+
+factors:
+ FACTORS OBRACE factorsbody EBRACE
+ ;
+
+factorsbody:
+ factorparam SEMICOLON
+ | factorsbody factorparam SEMICOLON
+ ;
+
+factorparam:
+ QUOTEDSTRING EQSIGN FRACT {
+ double *tmp = memory_pool_alloc (cfg->cfg_pool, sizeof (double));
+ *tmp = $3;
+ g_hash_table_insert (cfg->factors, $1, tmp);
+ }
+ | QUOTEDSTRING EQSIGN NUMBER {
+ double *tmp = memory_pool_alloc (cfg->cfg_pool, sizeof (double));
+ *tmp = $3;
+ g_hash_table_insert (cfg->factors, $1, tmp);
+ };
+
+require:
+ REQUIRE OBRACE requirebody EBRACE
+ ;
+
+requirebody:
+ requirecmd SEMICOLON
+ | requirebody requirecmd SEMICOLON
+ ;
+
+requirecmd:
+ MODULE EQSIGN QUOTEDSTRING {
+ struct stat st;
+ struct perl_module *cur;
+ if (stat ($3, &st) == -1) {
+ yyerror ("yyparse: cannot stat file %s, %m", $3);
+ YYERROR;
+ }
+ cur = memory_pool_alloc (cfg->cfg_pool, sizeof (struct perl_module));
+ if (cur == NULL) {
+ yyerror ("yyparse: g_malloc: %s", strerror(errno));
+ YYERROR;
+ }
+ cur->path = $3;
+ LIST_INSERT_HEAD (&cfg->perl_modules, cur, next);
+ }
+ ;
+
+composites:
+ COMPOSITES OBRACE compositesbody EBRACE
+ ;
+
+compositesbody:
+ compositescmd SEMICOLON
+ | compositesbody compositescmd SEMICOLON
+ ;
+
+compositescmd:
+ QUOTEDSTRING EQSIGN QUOTEDSTRING {
+ struct expression *expr;
+ if ((expr = parse_expression (cfg->cfg_pool, $3)) == NULL) {
+ yyerror ("yyparse: cannot parse composite expression: %s", $3);
+ YYERROR;
+ }
+ g_hash_table_insert (cfg->composite_symbols, $1, expr);
+ }
+ ;
+module_opt:
+ MODULE_OPT OBRACE moduleoptbody EBRACE {
+ g_hash_table_insert (cfg->modules_opts, $1, cur_module_opt);
+ cur_module_opt = NULL;
+ }
+ ;
+
+moduleoptbody:
+ optcmd SEMICOLON
+ | moduleoptbody optcmd SEMICOLON
+ ;
+
+optcmd:
+ PARAM EQSIGN QUOTEDSTRING {
+ struct module_opt *mopt;
+ if (cur_module_opt == NULL) {
+ cur_module_opt = g_malloc (sizeof (cur_module_opt));
+ LIST_INIT (cur_module_opt);
+ }
+ mopt = memory_pool_alloc (cfg->cfg_pool, sizeof (struct module_opt));
+ mopt->param = $1;
+ mopt->value = $3;
+ LIST_INSERT_HEAD (cur_module_opt, mopt, next);
+ }
+ ;
+
+variable:
+ VARIABLE EQSIGN QUOTEDSTRING {
+ g_hash_table_insert (cfg->variables, $1, $3);
+ }
+ ;
+
+logging:
+ LOGGING OBRACE loggingbody EBRACE
+ ;
+
+loggingbody:
+ loggingcmd SEMICOLON
+ | loggingbody loggingcmd SEMICOLON
+ ;
+
+loggingcmd:
+ loggingtype
+ | logginglevel
+ | loggingfacility
+ | loggingfile
+ ;
+
+loggingtype:
+ LOG_TYPE EQSIGN LOG_TYPE_CONSOLE {
+ cfg->log_type = RSPAMD_LOG_CONSOLE;
+ }
+ LOG_TYPE EQSIGN LOG_TYPE_SYSLOG {
+ cfg->log_type = RSPAMD_LOG_SYSLOG;
+ }
+ LOG_TYPE EQSIGN LOG_TYPE_FILE {
+ cfg->log_type = RSPAMD_LOG_FILE;
+ }
+ ;
+
+logginglevel:
+ LOG_LEVEL EQSIGN LOG_LEVEL_DEBUG {
+ cfg->log_level = G_LOG_LEVEL_DEBUG;
+ }
+ LOG_LEVEL EQSIGN LOG_LEVEL_INFO {
+ cfg->log_level = G_LOG_LEVEL_INFO | G_LOG_LEVEL_MESSAGE;
+ }
+ LOG_LEVEL EQSIGN LOG_LEVEL_WARNING {
+ cfg->log_level = G_LOG_LEVEL_WARNING;
+ }
+ LOG_LEVEL EQSIGN LOG_LEVEL_ERROR {
+ cfg->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
+ }
+ ;
+
+loggingfacility:
+ LOG_FACILITY EQSIGN QUOTEDSTRING {
+ if (strncasecmp ($3, "LOG_AUTH", sizeof ("LOG_AUTH") - 1) == 0) {
+ cfg->log_facility = LOG_AUTH;
+ }
+ else if (strncasecmp ($3, "LOG_CRON", sizeof ("LOG_CRON") - 1) == 0) {
+ cfg->log_facility = LOG_CRON;
+ }
+ else if (strncasecmp ($3, "LOG_DAEMON", sizeof ("LOG_DAEMON") - 1) == 0) {
+ cfg->log_facility = LOG_DAEMON;
+ }
+ else if (strncasecmp ($3, "LOG_MAIL", sizeof ("LOG_MAIL") - 1) == 0) {
+ cfg->log_facility = LOG_MAIL;
+ }
+ else if (strncasecmp ($3, "LOG_USER", sizeof ("LOG_USER") - 1) == 0) {
+ cfg->log_facility = LOG_USER;
+ }
+ else if (strncasecmp ($3, "LOG_LOCAL0", sizeof ("LOG_LOCAL0") - 1) == 0) {
+ cfg->log_facility = LOG_LOCAL0;
+ }
+ else if (strncasecmp ($3, "LOG_LOCAL1", sizeof ("LOG_LOCAL1") - 1) == 0) {
+ cfg->log_facility = LOG_LOCAL1;
+ }
+ else if (strncasecmp ($3, "LOG_LOCAL2", sizeof ("LOG_LOCAL2") - 1) == 0) {
+ cfg->log_facility = LOG_LOCAL2;
+ }
+ else if (strncasecmp ($3, "LOG_LOCAL3", sizeof ("LOG_LOCAL3") - 1) == 0) {
+ cfg->log_facility = LOG_LOCAL3;
+ }
+ else if (strncasecmp ($3, "LOG_LOCAL4", sizeof ("LOG_LOCAL4") - 1) == 0) {
+ cfg->log_facility = LOG_LOCAL4;
+ }
+ else if (strncasecmp ($3, "LOG_LOCAL5", sizeof ("LOG_LOCAL5") - 1) == 0) {
+ cfg->log_facility = LOG_LOCAL5;
+ }
+ else if (strncasecmp ($3, "LOG_LOCAL6", sizeof ("LOG_LOCAL6") - 1) == 0) {
+ cfg->log_facility = LOG_LOCAL6;
+ }
+ else if (strncasecmp ($3, "LOG_LOCAL7", sizeof ("LOG_LOCAL7") - 1) == 0) {
+ cfg->log_facility = LOG_LOCAL7;
+ }
+ else {
+ yyerror ("yyparse: invalid logging facility: %s", $3);
+ YYERROR;
+ }
+
+ free ($3);
+ }
+ ;
+
+loggingfile:
+ LOG_FILENAME EQSIGN QUOTEDSTRING {
+ cfg->log_file = memory_pool_strdup (cfg->cfg_pool, $3);
+
+ free ($3);
+ }
+ ;
+
+%%
+/*
+ * vi:ts=4
+ */