diff options
Diffstat (limited to 'src/conf_lexer.l')
-rw-r--r-- | src/conf_lexer.l | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/src/conf_lexer.l b/src/conf_lexer.l new file mode 100644 index 0000000..d089a57 --- /dev/null +++ b/src/conf_lexer.l @@ -0,0 +1,489 @@ +/* + * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd). + * conf_lexer.l: Scans the ircd configuration file for tokens. + * + * Copyright (C) 2002 by the past and present ircd coders, and others. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + * + * $Id$ + */ + +%option case-insensitive +%option noyywrap +%option nounput +%option never-interactive + +%{ +#include "stdinc.h" +#include "irc_string.h" +#include "conf.h" +#include "conf_parser.h" /* autogenerated header file */ +#include "memory.h" +#include "hostmask.h" +#include "log.h" + +#undef YY_INPUT +#define YY_FATAL_ERROR(msg) conf_yy_fatal_error(msg) +#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[IRCD_BUFSIZE]; +char conffilebuf[IRCD_BUFSIZE]; + +static int include_stack_ptr = 0; +static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; +static unsigned int lineno_stack[MAX_INCLUDE_DEPTH]; +static FILE *inc_fbfile_in[MAX_INCLUDE_DEPTH]; +static char conffile_stack[MAX_INCLUDE_DEPTH][IRCD_BUFSIZE]; +static void ccomment(void); +static void cinclude(void); +static int ieof(void); + +static int +conf_yy_input(char *lbuf, unsigned int max_size) +{ + return !fgets(lbuf, max_size, conf_parser_ctx.conf_file) ? 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}(\<.*\>|\".*\") + +%% +{include} { cinclude(); } +"/*" { ccomment(); } + +\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] != '"') + ilog(LOG_TYPE_IRCD, "Unterminated character string"); + else + { + int i,j; + + yylval.string[yyleng-2] = '\0'; /* remove close + * quote + */ + + for (j=i=0 ;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 + */ + { + ilog(LOG_TYPE_IRCD, + "Unterminated character string"); + break; + } + yylval.string[j] = yylval.string[i]; + } + } + yylval.string[j] = '\0'; + return QSTRING; + } + } + } + +accept_password { return ACCEPT_PASSWORD; } +admin { return ADMIN; } +administrator { return ADMIN; } +aftype { return AFTYPE; } +all { return T_ALL; } +auth { return IRCD_AUTH; } +autoconn { return AUTOCONN; } +can_flood { return CAN_FLOOD; } +caller_id_wait { return CALLER_ID_WAIT; } +opers_bypass_callerid { return OPERS_BYPASS_CALLERID; } +channel { return CHANNEL; } +cidr_bitlen_ipv4 { return CIDR_BITLEN_IPV4; } +cidr_bitlen_ipv6 { return CIDR_BITLEN_IPV6; } +class { return CLASS; } +cluster { return T_CLUSTER; } +connect { return CONNECT; } +connectfreq { return CONNECTFREQ; } +default_floodcount { return DEFAULT_FLOODCOUNT; } +default_split_server_count { return DEFAULT_SPLIT_SERVER_COUNT; } +default_split_user_count { return DEFAULT_SPLIT_USER_COUNT; } +deny { return DENY; } +description { return DESCRIPTION; } +die { return DIE; } +disable_auth { return DISABLE_AUTH; } +disable_fake_channels { return DISABLE_FAKE_CHANNELS; } +disable_remote_commands { return DISABLE_REMOTE_COMMANDS; } +dline { return T_DLINE; } +dots_in_ident { return DOTS_IN_IDENT; } +egdpool_path { return EGDPOOL_PATH; } +email { return EMAIL; } +encrypted { return ENCRYPTED; } +exceed_limit { return EXCEED_LIMIT; } +exempt { return EXEMPT; } +file { return T_FILE; } +flags { return IRCD_FLAGS; } +flatten_links { return FLATTEN_LINKS; } +gecos { return GECOS; } +general { return GENERAL; } +gline { return GLINE; } +gline_enable { return GLINE_ENABLE; } +gline_exempt { return GLINE_EXEMPT; } +gline_duration { return GLINE_DURATION; } +gline_request_duration { return GLINE_REQUEST_DURATION; } +gline_min_cidr { return GLINE_MIN_CIDR; } +gline_min_cidr6 { return GLINE_MIN_CIDR6; } +globops { return T_GLOBOPS; } +global_kill { return GLOBAL_KILL; } +have_ident { return NEED_IDENT; } +need_ident { return NEED_IDENT; } +havent_read_conf { return HAVENT_READ_CONF; } +hidden { return HIDDEN; } +hidden_name { return HIDDEN_NAME; } +hide_server_ips { return HIDE_SERVER_IPS; } +hide_servers { return HIDE_SERVERS; } +hide_spoof_ips { return HIDE_SPOOF_IPS; } +host { return HOST; } +hub { return HUB; } +hub_mask { return HUB_MASK; } +ignore_bogus_ts { return IGNORE_BOGUS_TS; } +invisible_on_connect { return INVISIBLE_ON_CONNECT; } +ip { return IP; } +ipv4 { return T_IPV4; } +ipv6 { return T_IPV6; } +join_flood_count { return JOIN_FLOOD_COUNT; } +join_flood_time { return JOIN_FLOOD_TIME; } +kill { return KILL; } +kill_chase_time_limit { return KILL_CHASE_TIME_LIMIT; } +kline { return KLINE; } +kline_exempt { return KLINE_EXEMPT; } +leaf_mask { return LEAF_MASK; } +listen { return LISTEN; } +log { return T_LOG; } +masked { return TMASKED; } +max_clients { return T_MAX_CLIENTS; } +max_ident { return MAX_IDENT; } +max_local { return MAX_LOCAL; } +max_global { return MAX_GLOBAL; } +max_number { return MAX_NUMBER; } +max_watch { return MAX_WATCH; } +message_locale { return MESSAGE_LOCALE; } +min_nonwildcard { return MIN_NONWILDCARD; } +min_nonwildcard_simple { return MIN_NONWILDCARD_SIMPLE; } +name { return NAME; } +need_password { return NEED_PASSWORD; } +network_desc { return NETWORK_DESC; } +network_name { return NETWORK_NAME; } +nick { return NICK; } +nick_changes { return NICK_CHANGES; } +no { yylval.number = 0; return TBOOL; } +no_create_on_split { return NO_CREATE_ON_SPLIT; } +no_join_on_split { return NO_JOIN_ON_SPLIT; } +no_oper_flood { return NO_OPER_FLOOD; } +no_tilde { return NO_TILDE; } +number_per_cidr { return NUMBER_PER_CIDR; } +number_per_ip { return NUMBER_PER_IP; } +oper { return OPERATOR; } +oper_pass_resv { return OPER_PASS_RESV; } +operator { return OPERATOR; } +passwd { return PASSWORD; } +password { return PASSWORD; } +ping_cookie { return PING_COOKIE; } +ping_time { return PING_TIME; } +ping_warning { return PING_WARNING; } +port { return PORT; } +quarantine { return RESV; } +quiet_on_ban { return QUIET_ON_BAN; } +reason { return REASON; } +recvq { return T_RECVQ; } +redirport { return REDIRPORT; } +redirserv { return REDIRSERV; } +regex { return REGEX_T; } +rehash { return REHASH; } +remote { return REMOTE; } +remoteban { return REMOTEBAN; } +restart { return T_RESTART; } +restrict_channels { return RESTRICT_CHANNELS; } +resv { return RESV; } +resv_exempt { return RESV_EXEMPT; } +rsa_private_key_file { return RSA_PRIVATE_KEY_FILE; } +rsa_public_key_file { return RSA_PUBLIC_KEY_FILE; } +ssl { return T_SSL; } +ssl_certificate_file { return SSL_CERTIFICATE_FILE; } +ssl_client_method { return T_SSL_CLIENT_METHOD; } +ssl_server_method { return T_SSL_SERVER_METHOD; } +ssl_dh_param_file { return SSL_DH_PARAM_FILE; } +ssl_cipher_list { return T_SSL_CIPHER_LIST; } +sslv3 { return T_SSLV3; } +tlsv1 { return T_TLSV1; } +send_password { return SEND_PASSWORD; } +sendq { return SENDQ; } +server { return T_SERVER; } +serverhide { return SERVERHIDE; } +serverinfo { return SERVERINFO; } +service { return T_SERVICE; } +services_name { return T_SERVICES_NAME; } +set { return T_SET; } +shared { return T_SHARED; } +short_motd { return SHORT_MOTD; } +sid { return IRCD_SID; } +size { return T_SIZE; } +spoof { return SPOOF; } +spoof_notice { return SPOOF_NOTICE; } +tkline_expire_notices { return TKLINE_EXPIRE_NOTICES; } +type { return TYPE; } +true_no_oper_flood { return TRUE_NO_OPER_FLOOD; } +umodes { return T_UMODES; } +unkline { return UNKLINE; } +undline { return T_UNDLINE; } +unlimited { return T_UNLIMITED; } +use_egd { return USE_EGD; } +use_logging { return USE_LOGGING; } +throttle_time { return THROTTLE_TIME; } +user { return USER; } +vhost { return VHOST; } +vhost6 { return VHOST6; } +xline { return XLINE; } +yes { yylval.number = 1; return TBOOL; } + +failed_oper_notice { return FAILED_OPER_NOTICE; } +max_accept { return MAX_ACCEPT; } +max_nick_changes { return MAX_NICK_CHANGES; } +max_chans_per_oper { return MAX_CHANS_PER_OPER; } +max_chans_per_user { return MAX_CHANS_PER_USER; } +max_nick_time { return MAX_NICK_TIME; } +anti_nick_flood { return ANTI_NICK_FLOOD; } +anti_spam_exit_message_time { return ANTI_SPAM_EXIT_MESSAGE_TIME; } +ts_max_delta { return TS_MAX_DELTA; } +ts_warn_delta { return TS_WARN_DELTA; } +links_delay { return LINKS_DELAY; } +warn_no_nline { return WARN_NO_NLINE; } + +stats_e_disabled { return STATS_E_DISABLED; } +stats_o_oper_only { return STATS_O_OPER_ONLY; } +stats_k_oper_only { return STATS_K_OPER_ONLY; } +stats_i_oper_only { return STATS_I_OPER_ONLY; } +stats_P_oper_only { return STATS_P_OPER_ONLY; } +pace_wait { return PACE_WAIT; } +pace_wait_simple { return PACE_WAIT_SIMPLE; } +knock_delay { return KNOCK_DELAY; } +knock_delay_channel { return KNOCK_DELAY_CHANNEL; } +max_bans { return MAX_BANS; } +modules { return MODULES; } +module { return MODULE; } +path { return PATH; } +max_targets { return MAX_TARGETS; } + +unxline { return T_UNXLINE; } +unresv { return T_UNRESV; } + +oper_only_umodes { return OPER_ONLY_UMODES; } +oper_umodes { return OPER_UMODES; } +bots { return T_BOTS; } +cconn { return T_CCONN; } +cconn_full { return T_CCONN_FULL; } +deaf { return T_DEAF; } +debug { return T_DEBUG; } +full { return T_FULL; } +skill { return T_SKILL; } +nchange { return T_NCHANGE; } +rej { return T_REJ; } +unauth { return T_UNAUTH; } +spy { return T_SPY; } +external { return T_EXTERNAL; } +operwall { return T_OPERWALL; } +servnotice { return T_SERVNOTICE; } +invisible { return T_INVISIBLE; } +wallop { return T_WALLOP; } +callerid { return T_CALLERID; } +softcallerid { return T_SOFTCALLERID; } +locops { return T_LOCOPS; } + +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; } +\.\. { return TWODOTS; } + +. { return yytext[0]; } +<<EOF>> { if (ieof()) yyterminate(); } + +%% + +/* C-comment ignoring routine -kre*/ +static void +ccomment(void) +{ + int c = 0; + + /* log(L_NOTICE, "got comment"); */ + while (1) + { + while ((c = input()) != '*' && c != EOF) + if (c == '\n') + ++lineno; + + if (c == '*') + { + while ((c = input()) == '*') + /* Nothing */ ; + if (c == '/') + break; + else if (c == '\n') + ++lineno; + } + + if (c == EOF) + { + YY_FATAL_ERROR("EOF in comment"); + /* XXX hack alert this disables + * the stupid unused function warning + * gcc generates + */ + if (1 == 0) + yy_fatal_error("EOF in comment"); + break; + } + } +} + +/* C-style .includes. This function will properly swap input conf buffers, + * and lineno -kre */ +static void +cinclude(void) +{ + char *p = NULL; + + if ((p = strchr(yytext, '<')) == NULL) + *strchr(p = strchr(yytext, '"') + 1, '"') = '\0'; + else + *strchr(++p, '>') = '\0'; + + /* log(L_NOTICE, "got include %s!", c); */ + + /* do stacking and co. */ + if (include_stack_ptr >= MAX_INCLUDE_DEPTH) + ilog(LOG_TYPE_IRCD, "Includes nested too deep in %s", p); + else + { + FILE *tmp_fbfile_in = NULL; + char filenamebuf[IRCD_BUFSIZE]; + + if (*p == '/') /* if it is an absolute path */ + snprintf(filenamebuf, sizeof(filenamebuf), "%s", p); + else + snprintf(filenamebuf, sizeof(filenamebuf), "%s/%s", ETCPATH, p); + + tmp_fbfile_in = fopen(filenamebuf, "r"); + + if (tmp_fbfile_in == NULL) + { + ilog(LOG_TYPE_IRCD, "Unable to read configuration file '%s': %s", + filenamebuf, strerror(errno)); + return; + } + + lineno_stack[include_stack_ptr] = lineno; + lineno = 1; + inc_fbfile_in[include_stack_ptr] = conf_parser_ctx.conf_file; + strlcpy(conffile_stack[include_stack_ptr], conffilebuf, IRCD_BUFSIZE); + include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; + conf_parser_ctx.conf_file = tmp_fbfile_in; + snprintf(conffilebuf, sizeof(conffilebuf), "%s", filenamebuf); + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + } +} + +/* This is function that will be called on EOF in conf file. It will + * apropriately close conf if it not main conf and swap input buffers -kre + * */ +static int +ieof(void) +{ + /* log(L_NOTICE, "return from include stack!"); */ + if (include_stack_ptr) + fclose(conf_parser_ctx.conf_file); + if (--include_stack_ptr < 0) + { + /* log(L_NOTICE, "terminating lexer"); */ + /* We will now exit the lexer - restore init values if we get /rehash + * later and reenter lexer -kre */ + include_stack_ptr = 0; + lineno = 1; + return 1; + } + + /* switch buffer */ + /* log(L_NOTICE, "deleting include_stack_ptr=%d", include_stack_ptr); */ + yy_delete_buffer(YY_CURRENT_BUFFER); + lineno = lineno_stack[include_stack_ptr]; + conf_parser_ctx.conf_file = inc_fbfile_in[include_stack_ptr]; + strlcpy(conffilebuf, conffile_stack[include_stack_ptr], sizeof(conffilebuf)); + yy_switch_to_buffer(include_stack[include_stack_ptr]); + + return 0; +} |