diff options
Diffstat (limited to 'src/config-lexer.l')
| -rw-r--r-- | src/config-lexer.l | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/src/config-lexer.l b/src/config-lexer.l new file mode 100644 index 0000000..bea9365 --- /dev/null +++ b/src/config-lexer.l @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2002 Erik Fears + * Copyright (c) 2014-2018 ircd-hybrid development team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +%option case-insensitive +%option noyywrap +%option noinput +%option nounput +%option never-interactive + +%x IN_COMMENT + +%{ +#include <stdio.h> +#include <string.h> + +#include "compat.h" +#include "config.h" +#include "config-parser.h" /* autogenerated header file */ +#include "log.h" + +/* libopm includes */ +#include "libopm/src/opm_types.h" + +#undef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) conf_yy_fatal_error(msg) + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if (!(result = conf_yy_input(buf, max_size))) \ + YY_FATAL_ERROR("input in flex scanner failed"); +#define MAX_INCLUDE_DEPTH 10 + + +unsigned int lineno = 1; +char linebuf[512]; +char conffilebuf[512]; + +static struct included_file +{ + YY_BUFFER_STATE state; + unsigned int lineno; + FILE *file; + char conffile[512]; +} include_stack[MAX_INCLUDE_DEPTH]; + +static unsigned int include_stack_ptr; + + +static void conf_include(void); +static int conf_eof(void); + +static int +conf_yy_input(char *lbuf, unsigned int max_size) +{ + return fgets(lbuf, max_size, conf_file) == NULL ? 0 : strlen(lbuf); +} + +static int +conf_yy_fatal_error(const char *msg) +{ + return 0; +} +%} + +WS [[:blank:]]* +DIGIT [[:digit:]]+ +COMMENT ("//"|"#").* +qstring \"[^\"\n]*[\"\n] +include \.include{WS}(\<.*\>|\".*\") + +%% + +"/*" { BEGIN IN_COMMENT; } +<IN_COMMENT>"*/" { BEGIN INITIAL; } +<IN_COMMENT>. ; /* Eat everything but a newline */ +<IN_COMMENT>\n { ++lineno; } +<IN_COMMENT><<EOF>> { BEGIN INITIAL; if (conf_eof()) yyterminate(); } + +{include} { conf_include(); } +\n.* { strlcpy(linebuf, yytext + 1, sizeof(linebuf)); ++lineno; yyless(1); } +{WS} ; +{COMMENT} ; +{DIGIT} { yylval.number = atoi(yytext); return NUMBER; } +{qstring} { if (yytext[yyleng - 2] == '\\') + { + yyless(yyleng - 1); /* Return last quote */ + yymore(); /* Append next string */ + } + else + { + yylval.string = yytext + 1; + + if (yylval.string[yyleng - 2] != '"') + log_printf("CONFIG ->Unterminated character string"); + else + { + unsigned int i = 0, j = 0; + + yylval.string[yyleng - 2] = '\0'; /* Remove close quote */ + + for (; yylval.string[i] != '\0'; ++i, ++j) + { + if (yylval.string[i] != '\\') + yylval.string[j] = yylval.string[i]; + else + { + ++i; + + if (yylval.string[i] == '\0') /* XXX: should not happen */ + { + log_printf("CONFIG -> Unterminated character string"); + break; + } + + yylval.string[j] = yylval.string[i]; + } + } + + yylval.string[j] = '\0'; + return STRING; + } + } + } + +ADDRESS_FAMILY { return ADDRESS_FAMILY; } +AWAY { return AWAY; } +BAN_UNKNOWN { return BAN_UNKNOWN; } +BLACKLIST { return BLACKLIST; } +CHANNEL { return CHANNEL; } +COMMAND_INTERVAL { return COMMAND_INTERVAL; } +COMMAND_QUEUE_SIZE { return COMMAND_QUEUE_SIZE; } +COMMAND_TIMEOUT { return COMMAND_TIMEOUT; } +CONNREGEX { return CONNREGEX; } +DNS_FDLIMIT { return DNS_FDLIMIT; } +DNS_TIMEOUT { return DNS_TIMEOUT; } +DNSBL_FROM { return DNSBL_FROM; } +DNSBL_TO { return DNSBL_TO; } +EXEMPT { return EXEMPT; } +FD { return FD; } +INVITE { return INVITE; } +IPV4 { return IPV4; } +IPV6 { return IPV6; } +IRC { return IRC; } +KLINE { return KLINE; } +KEY { return KEY; } +MASK { return MASK; } +MAX_READ { return MAX_READ; } +MODE { return MODE; } +NAME { return NAME; } +NEGCACHE { return NEGCACHE; } +NEGCACHE_REBUILD { return NEGCACHE_REBUILD; } +NICK { return NICK; } +NICKSERV { return NICKSERV; } +NOTICE { return NOTICE; } +OPER { return OPER; } +OPM { return OPM; } +OPTIONS { return OPTIONS; } +PASSWORD { return PASSWORD; } +PERFORM { return PERFORM; } +PIDFILE { return PIDFILE; } +PORT { return PORT; } +PROTOCOL { return PROTOCOL; } +READTIMEOUT { return READTIMEOUT; } +REALNAME { return REALNAME; } +RECONNECTINTERVAL { return RECONNECTINTERVAL; } +REPLY { return REPLY; } +SCANLOG { return SCANLOG; } +SCANNER { return SCANNER; } +SENDMAIL { return SENDMAIL; } +SERVER { return SERVER; } +TARGET_IP { return TARGET_IP; } +TARGET_PORT { return TARGET_PORT; } +TARGET_STRING { return TARGET_STRING;} +TIMEOUT { return TIMEOUT; } +TYPE { return TYPE; } +USER { return USER; } +USERNAME { return USERNAME; } +VHOST { return VHOST; } + +years { return YEARS; } +year { return YEARS; } +months { return MONTHS; } +month { return MONTHS; } +weeks { return WEEKS; } +week { return WEEKS; } +days { return DAYS; } +day { return DAYS; } +hours { return HOURS; } +hour { return HOURS; } +minutes { return MINUTES; } +minute { return MINUTES; } +seconds { return SECONDS; } +second { return SECONDS; } + +bytes { return BYTES; } +byte { return BYTES; } +kilobytes { return KBYTES; } +kilobyte { return KBYTES; } +kbytes { return KBYTES; } +kbyte { return KBYTES; } +kb { return KBYTES; } +megabytes { return MBYTES; } +megabyte { return MBYTES; } +mbytes { return MBYTES; } +mbyte { return MBYTES; } +mb { return MBYTES; } + +HTTP { + yylval.number = OPM_TYPE_HTTP; + return PROTOCOLTYPE; + } + +HTTPPOST { + yylval.number = OPM_TYPE_HTTPPOST; + return PROTOCOLTYPE; + } + +HTTPS { + yylval.number = OPM_TYPE_HTTPS; + return PROTOCOLTYPE; + } + +HTTPSPOST { + yylval.number = OPM_TYPE_HTTPSPOST; + return PROTOCOLTYPE; + } + +SOCKS4 { + yylval.number = OPM_TYPE_SOCKS4; + return PROTOCOLTYPE; + } + +SOCKS5 { + yylval.number = OPM_TYPE_SOCKS5; + return PROTOCOLTYPE; + } + +WINGATE { + yylval.number = OPM_TYPE_WINGATE; + return PROTOCOLTYPE; + } + +ROUTER { + yylval.number = OPM_TYPE_ROUTER; + return PROTOCOLTYPE; + } + +DREAMBOX { + yylval.number = OPM_TYPE_DREAMBOX; + return PROTOCOLTYPE; + } + + +SSH { + yylval.number = OPM_TYPE_SSH; + return PROTOCOLTYPE; + } + +TRUE { + yylval.number=1; + return NUMBER; + } +YES { + yylval.number=1; + return NUMBER; + } +ON { + yylval.number=1; + return NUMBER; + } + + + +FALSE { + yylval.number=0; + return NUMBER; + } + +NO { + yylval.number=0; + return NUMBER; + } + +OFF { + yylval.number=0; + return NUMBER; + } + +. { return yytext[0]; } +<<EOF>> { if (conf_eof()) yyterminate(); } + +%% + +static void +conf_include(void) +{ + char *p = NULL; + char filenamebuf[512]; + + if ((p = strchr(yytext, '<')) == NULL) + *strchr(p = strchr(yytext, '"') + 1, '"') = '\0'; + else + *strchr(++p, '>') = '\0'; + + /* do stacking and co. */ + if (include_stack_ptr >= MAX_INCLUDE_DEPTH) + { + log_printf("CONFIG -> Includes nested too deep in %s", p); + return; + } + + if (*p == '/') /* if it is an absolute path */ + snprintf(filenamebuf, sizeof(filenamebuf), "%s", p); + else + snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", HOPM_ETCDIR, p); + + FILE *tmp_fbfile_in = fopen(filenamebuf, "r"); + if (!tmp_fbfile_in) + { + log_printf("CONFIG -> Unable to read configuration file '%s': %s", + filenamebuf, strerror(errno)); + return; + } + + struct included_file *file = &include_stack[include_stack_ptr++]; + file->lineno = lineno; + file->file = conf_file; + file->state = YY_CURRENT_BUFFER; + strlcpy(file->conffile, conffilebuf, sizeof(file->conffile)); + + lineno = 1; + conf_file = tmp_fbfile_in; + strlcpy(conffilebuf, filenamebuf, sizeof(conffilebuf)); + + yy_switch_to_buffer(yy_create_buffer(NULL, YY_BUF_SIZE)); +} + +static int +conf_eof(void) +{ + if (include_stack_ptr == 0) + return 1; + + /* switch buffer */ + struct included_file *file = &include_stack[--include_stack_ptr]; + + /* close current file */ + fclose(conf_file); + + /* switch buffers */ + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(file->state); + + /* switch lineno */ + lineno = file->lineno; + + /* switch file */ + conf_file = file->file; + + strlcpy(conffilebuf, file->conffile, sizeof(conffilebuf)); + return 0; +} |
