/* * Copyright (c) 2002-2013 BalaBit IT Ltd, Budapest, Hungary * Copyright (c) 1998-2012 Balázs Scheidler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * As an additional exemption you are allowed to compile & link against the * OpenSSL libraries as published by the OpenSSL project. See the file * COPYING for details. * */ #include "cfg-parser.h" #include "cfg-lexer.h" #include "cfg-grammar.h" #include extern int main_debug; /* defined in the parser */ int main_parse(CfgLexer *lexer, gpointer *dummy, gpointer arg); static CfgLexerKeyword main_keywords[] = { /* statements */ { "source", KW_SOURCE }, { "filter", KW_FILTER }, { "parser", KW_PARSER, 0x0300, }, { "rewrite", KW_REWRITE, 0x0300, }, { "destination", KW_DESTINATION }, { "log", KW_LOG }, { "junction", KW_JUNCTION, 0x0304 }, { "channel", KW_CHANNEL, 0x0304 }, { "options", KW_OPTIONS }, { "include", KW_INCLUDE, 0x0300, }, { "block", KW_BLOCK, 0x0302 }, /* source or destination items */ { "internal", KW_INTERNAL }, { "columns", KW_COLUMNS, 0x0300 }, { "delimiters", KW_DELIMITERS, 0x0300 }, { "quotes", KW_QUOTES, 0x0300 }, { "quote_pairs", KW_QUOTE_PAIRS, 0x0300}, { "null", KW_NULL, 0x0300 }, /* value pairs */ { "value_pairs", KW_VALUE_PAIRS, 0x0303 }, { "select", KW_SELECT, 0x0303 }, { "exclude", KW_EXCLUDE, 0x0303 }, { "pair", KW_PAIR, 0x0303 }, { "key", KW_KEY, 0x0303 }, { "scope", KW_SCOPE, 0x0303 }, { "rekey", KW_REKEY, 0x0303 }, { "shift", KW_SHIFT, 0x0303 }, { "add_prefix", KW_ADD_PREFIX, 0x0303 }, { "replace", KW_REPLACE_PREFIX, 0x0303, KWS_OBSOLETE, "replace_prefix" }, { "replace_prefix", KW_REPLACE_PREFIX, 0x0304 }, /* option items */ { "flags", KW_FLAGS }, { "pad_size", KW_PAD_SIZE }, { "mark_freq", KW_MARK_FREQ }, { "mark", KW_MARK_FREQ, 0, KWS_OBSOLETE, "mark_freq" }, { "mark_mode", KW_MARK_MODE, 0x0304 }, { "stats_freq", KW_STATS_FREQ }, { "stats_level", KW_STATS_LEVEL }, { "stats", KW_STATS_FREQ, 0, KWS_OBSOLETE, "stats_freq" }, { "flush_lines", KW_FLUSH_LINES }, { "flush_timeout", KW_FLUSH_TIMEOUT }, { "suppress", KW_SUPPRESS }, { "sync_freq", KW_FLUSH_LINES, 0, KWS_OBSOLETE, "flush_lines" }, { "sync", KW_FLUSH_LINES, 0, KWS_OBSOLETE, "flush_lines" }, { "long_hostnames", KW_CHAIN_HOSTNAMES, 0, KWS_OBSOLETE, "chain_hostnames" }, { "chain_hostnames", KW_CHAIN_HOSTNAMES }, { "normalize_hostnames",KW_NORMALIZE_HOSTNAMES }, { "keep_hostname", KW_KEEP_HOSTNAME }, { "check_hostname", KW_CHECK_HOSTNAME }, { "bad_hostname", KW_BAD_HOSTNAME }, { "keep_timestamp", KW_KEEP_TIMESTAMP }, { "encoding", KW_ENCODING, 0x0300 }, { "ts_format", KW_TS_FORMAT }, { "frac_digits", KW_FRAC_DIGITS }, { "time_zone", KW_TIME_ZONE }, { "recv_time_zone", KW_RECV_TIME_ZONE }, { "send_time_zone", KW_SEND_TIME_ZONE }, { "local_time_zone", KW_LOCAL_TIME_ZONE, 0x0300 }, { "format", KW_FORMAT, 0x0302 }, { "use_time_recvd", KW_USE_TIME_RECVD, 0, KWS_OBSOLETE, "Use R_ or S_ prefixed macros in templates or keep_timestamp(no)" }, { "use_fqdn", KW_USE_FQDN }, { "use_dns", KW_USE_DNS }, { "time_reopen", KW_TIME_REOPEN }, { "time_reap", KW_TIME_REAP }, { "time_sleep", KW_TIME_SLEEP, 0, KWS_OBSOLETE, "time_sleep() has been deprecated since " VERSION_3_3 }, { "file_template", KW_FILE_TEMPLATE }, { "proto_template", KW_PROTO_TEMPLATE }, { "default_level", KW_DEFAULT_LEVEL, 0x0300 }, { "default_priority", KW_DEFAULT_LEVEL, 0x0300 }, { "default_facility", KW_DEFAULT_FACILITY, 0x0300 }, { "threaded", KW_THREADED, 0x0303 }, { "value", KW_VALUE, 0x0300 }, { "log_fifo_size", KW_LOG_FIFO_SIZE }, { "log_fetch_limit", KW_LOG_FETCH_LIMIT }, { "log_iw_size", KW_LOG_IW_SIZE }, { "log_msg_size", KW_LOG_MSG_SIZE }, { "log_prefix", KW_LOG_PREFIX, 0, KWS_OBSOLETE, "program_override" }, { "program_override", KW_PROGRAM_OVERRIDE, 0x0300 }, { "host_override", KW_HOST_OVERRIDE, 0x0300 }, { "throttle", KW_THROTTLE }, { "create_dirs", KW_CREATE_DIRS }, { "optional", KW_OPTIONAL }, { "owner", KW_OWNER }, { "group", KW_GROUP }, { "perm", KW_PERM }, { "dir_owner", KW_DIR_OWNER }, { "dir_group", KW_DIR_GROUP }, { "dir_perm", KW_DIR_PERM }, { "template", KW_TEMPLATE }, { "template_escape", KW_TEMPLATE_ESCAPE }, { "on_error", KW_ON_ERROR }, { "persist_only", KW_PERSIST_ONLY }, { "dns_cache_hosts", KW_DNS_CACHE_HOSTS }, { "dns_cache", KW_DNS_CACHE }, { "dns_cache_size", KW_DNS_CACHE_SIZE }, { "dns_cache_expire", KW_DNS_CACHE_EXPIRE }, { "dns_cache_expire_failed", KW_DNS_CACHE_EXPIRE_FAILED }, /* filter items */ { "type", KW_TYPE, 0x0300 }, { "tags", KW_TAGS, 0x0300 }, /* on/off switches */ { "yes", KW_YES }, { "on", KW_YES }, { "no", KW_NO }, { "off", KW_NO }, { NULL, 0 } }; CfgParser main_parser = { #if ENABLE_DEBUG .debug_flag = &main_debug, #endif .name = "config", .context = LL_CONTEXT_ROOT, .keywords = main_keywords, .parse = main_parse, }; CFG_PARSER_IMPLEMENT_LEXER_BINDING(main_, gpointer *) void report_syntax_error(CfgLexer *lexer, YYLTYPE *yylloc, const char *what, const char *msg) { CfgIncludeLevel *level = yylloc->level, *from; gint lineno = 1; gint i; gint file_pos; gchar buf[1024]; fprintf(stderr, "Error parsing %s, %s in %n%s at line %d, column %d:\n", what, msg, &file_pos, yylloc->level->name, yylloc->first_line, yylloc->first_column); from = level - 1; while (from >= lexer->include_stack) { fprintf(stderr, "%*sincluded from %s line %d, column %d\n", MAX(file_pos - 14, 0), "", from->name, from->lloc.first_line, from->lloc.first_column); from--; } buf[0] = 0; if (level->include_type == CFGI_FILE) { FILE *f; f = fopen(level->name, "r"); if (f) { while (fgets(buf, sizeof(buf), f) && lineno < yylloc->first_line) lineno++; if (lineno != yylloc->first_line) buf[0] = 0; fclose(f); } } else if (level->include_type == CFGI_BUFFER) { gchar *sol, *eol; sol = level->buffer.content; eol = strchr(sol, '\n'); while (eol && lineno < yylloc->first_line) { lineno++; sol = eol + 1; eol = strchr(sol, '\n'); } if (lineno == yylloc->first_line) { gsize cs = MIN(eol ? eol - sol - 1 : strlen(sol), sizeof(buf) - 2); memcpy(buf, sol, cs); buf[cs] = 0; } } if (buf[0]) { fprintf(stderr, "\n%s", buf); if (buf[strlen(buf) - 1] != '\n') fprintf(stderr, "\n"); for (i = 0; buf[i] && i < yylloc->first_column - 1; i++) { fprintf(stderr, "%c", buf[i] == '\t' ? '\t' : ' '); } for (i = yylloc->first_column; i < yylloc->last_column; i++) fprintf(stderr, "^"); fprintf(stderr, "\n"); } fprintf(stderr, "\nsyslog-ng documentation: http://www.balabit.com/support/documentation/?product=syslog-ng\n" "mailing list: https://lists.balabit.hu/mailman/listinfo/syslog-ng\n"); } /* * This function can be used to parse flags in a flags(...) option. It * makes it quite easy to write a flags parser by specifying the * operations to be performed in a getopt-like array. */ gboolean cfg_process_flag(CfgFlagHandler *handlers, gpointer base, const gchar *flag_) { gint h; gchar flag[32]; for (h = 0; flag_[h] && h < sizeof(flag); h++) { if (flag_[h] == '_') flag[h] = '-'; else flag[h] = flag_[h]; } flag[h] = 0; for (h = 0; handlers[h].name; h++) { CfgFlagHandler *handler = &handlers[h]; if (strcmp(handlers[h].name, flag) == 0) { guint32 *field = ((guint32 *) (((gchar *) base) + handler->ofs)); switch (handler->op) { case CFH_SET: /* this works if handler->mask is unset and handler->param is a single bit only */ if (handler->mask) *field = ((*field) & ~handler->mask) | handler->param; else *field = (*field) | handler->param; return TRUE; case CFH_CLEAR: /* set the bitfield to zero */ if (handler->mask) *field = (*field) & ~handler->mask; else *field = (*field) & ~handler->param; return TRUE; } } } return FALSE; }