/* * conf.C: Configuration processing. * * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team * Rights to this code are as documented in COPYING. * * * Portions of this file were derived from sources bearing the following license: * Rights to this code are documented in doc/pod/license.pod. * Copyright © 2005-2007 Atheme Project (http://www.atheme.org) */ static char const rcsid[] = "$Id: conf.C,v 1.10 2007/09/22 14:27:30 pippijn Exp $"; #include "atheme.h" #include "confparse.h" #include #include #include #include #include #include #include "uplink.h" #include "pmodule.h" #include "privs.h" ConfTable::callbacks ConfTable::callback; static void deinit_conf (void); enum config_error { no_param, wrong_param }; template int param_error (config_entry_t *ce, char const * const msg = NULL); template<> int param_error (config_entry_t *ce, char const * const msg) { slog (LG_INFO, "%s:%i: %s: %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, msg ? msg : "no parameter for option", ce->ce_varname); return 1; } template<> int param_error (config_entry_t *ce, char const * const msg) { slog (LG_INFO, "%s:%i: %s: %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, msg ? msg : "wrong parameter for option", ce->ce_varname); return 1; } static int c_serverinfo (config_entry_t *); static int c_general (config_entry_t *); static int c_database (config_entry_t *); static int c_uplink (config_entry_t *); static int c_chanserv (config_entry_t *); static int c_globserv (config_entry_t *); static int c_operserv (config_entry_t *); static int c_memoserv (config_entry_t *); static int c_gameserv (config_entry_t *); static int c_nickserv (config_entry_t *); static int c_saslserv (config_entry_t *); static int c_loadmodule (config_entry_t *); static int c_backend (config_entry_t *); static int c_crypto (config_entry_t *); static int c_protocol (config_entry_t *); static int c_operclass (config_entry_t *); static int c_operator (config_entry_t *); static int c_logfile (config_entry_t *); static int c_si_name (config_entry_t *); static int c_si_desc (config_entry_t *); static int c_si_numeric (config_entry_t *); static int c_si_vhost (config_entry_t *); static int c_si_recontime (config_entry_t *); static int c_si_restarttime (config_entry_t *); static int c_si_netname (config_entry_t *); static int c_si_hidehostsuffix (config_entry_t *); static int c_si_adminname (config_entry_t *); static int c_si_adminemail (config_entry_t *); static int c_si_mta (config_entry_t *); static int c_si_loglevel (config_entry_t *); static int c_si_maxlogins (config_entry_t *); static int c_si_maxusers (config_entry_t *); static int c_si_maxnicks (config_entry_t *); static int c_si_maxchans (config_entry_t *); static int c_si_emaillimit (config_entry_t *); static int c_si_emailtime (config_entry_t *); static int c_si_auth (config_entry_t *); static int c_si_mdlimit (config_entry_t *); static int c_si_casemapping (config_entry_t *); /* ChanServ client information. */ static int c_ci_nick (config_entry_t *); static int c_ci_user (config_entry_t *); static int c_ci_host (config_entry_t *); static int c_ci_real (config_entry_t *); static int c_ci_fantasy (config_entry_t *); static int c_ci_vop (config_entry_t *); static int c_ci_hop (config_entry_t *); static int c_ci_aop (config_entry_t *); static int c_ci_sop (config_entry_t *); static int c_ci_changets (config_entry_t *); static int c_ci_trigger (config_entry_t *); static int c_ci_expire (config_entry_t *); static int c_ci_maxchanacs (config_entry_t *); static int c_ci_maxfounders (config_entry_t *); /* GlobServ client information. */ static int c_gl_nick (config_entry_t *); static int c_gl_user (config_entry_t *); static int c_gl_host (config_entry_t *); static int c_gl_real (config_entry_t *); /* OperServ client information. */ static int c_oi_nick (config_entry_t *); static int c_oi_user (config_entry_t *); static int c_oi_host (config_entry_t *); static int c_oi_real (config_entry_t *); /* NickServ client information. */ static int c_ni_nick (config_entry_t *); static int c_ni_user (config_entry_t *); static int c_ni_host (config_entry_t *); static int c_ni_real (config_entry_t *); static int c_ni_spam (config_entry_t *); static int c_ni_no_nick_ownership (config_entry_t *); static int c_ni_expire (config_entry_t *); /* SaslServ client information. */ static int c_ss_nick (config_entry_t *); static int c_ss_user (config_entry_t *); static int c_ss_host (config_entry_t *); static int c_ss_real (config_entry_t *); /* MemoServ client information. */ static int c_ms_nick (config_entry_t *); static int c_ms_user (config_entry_t *); static int c_ms_host (config_entry_t *); static int c_ms_real (config_entry_t *); /* GameServ client information. */ static int c_gs_nick (config_entry_t *); static int c_gs_user (config_entry_t *); static int c_gs_host (config_entry_t *); static int c_gs_real (config_entry_t *); /* Database information. */ static int c_db_user (config_entry_t *); static int c_db_host (config_entry_t *); static int c_db_password (config_entry_t *); static int c_db_database (config_entry_t *); static int c_db_port (config_entry_t *); static int c_gi_chan (config_entry_t *); static int c_gi_silent (config_entry_t *); static int c_gi_verbose_wallops (config_entry_t *); static int c_gi_use_privmsg (config_entry_t *); static int c_gi_join_chans (config_entry_t *); static int c_gi_leave_chans (config_entry_t *); static int c_gi_uflags (config_entry_t *); static int c_gi_cflags (config_entry_t *); static int c_gi_raw (config_entry_t *); static int c_gi_flood_msgs (config_entry_t *); static int c_gi_flood_time (config_entry_t *); static int c_gi_kline_time (config_entry_t *); static int c_gi_commit_interval (config_entry_t *); static int c_gi_expire (config_entry_t *); static int c_gi_secure (config_entry_t *); static int c_gi_default_clone_limit (config_entry_t *); /* *INDENT-OFF* */ static Token uflags[] = { { "HOLD", MU_HOLD }, { "NEVEROP", MU_NEVEROP }, { "NOOP", MU_NOOP }, { "HIDEMAIL", MU_HIDEMAIL }, { "NONE", 0 }, { NULL, 0 } }; static Token cflags[] = { { "HOLD", MC_HOLD }, { "SECURE", MC_SECURE }, { "VERBOSE", MC_VERBOSE }, { "KEEPTOPIC", MC_KEEPTOPIC }, { "VERBOSE_OPS", MC_VERBOSE_OPS }, { "TOPICLOCK", MC_TOPICLOCK }, { "GUARD", MC_GUARD }, { "NONE", 0 }, { NULL, 0 } }; static Token logflags[] = { { "DEBUG", LG_ALL }, { "TRACE", LG_INFO | LG_ERROR | LG_CMD_ALL | LG_NETWORK | LG_WALLOPS | LG_REGISTER }, { "MISC", LG_INFO | LG_ERROR | LG_CMD_ADMIN | LG_CMD_REGISTER | LG_CMD_SET | LG_NETWORK | LG_WALLOPS | LG_REGISTER }, { "NOTICE", LG_INFO | LG_ERROR | LG_CMD_ADMIN | LG_CMD_REGISTER | LG_NETWORK | LG_REGISTER }, { "ALL", LG_ALL }, { "INFO", LG_INFO }, { "ERROR", LG_ERROR }, { "COMMANDS", LG_CMD_ALL }, { "ADMIN", LG_CMD_ADMIN }, { "REGISTER", LG_CMD_REGISTER | LG_REGISTER }, { "SET", LG_CMD_SET }, { "NETWORK", LG_NETWORK }, { "WALLOPS", LG_WALLOPS }, { "RAWDATA", LG_RAWDATA }, { NULL, 0 } }; static ConfTable::list_type confblocks; static ConfTable::list_type conf_si_table; static ConfTable::list_type conf_ci_table; static ConfTable::list_type conf_gl_table; static ConfTable::list_type conf_oi_table; static ConfTable::list_type conf_ni_table; static ConfTable::list_type conf_db_table; static ConfTable::list_type conf_gi_table; static ConfTable::list_type conf_ms_table; static ConfTable::list_type conf_la_table; static ConfTable::list_type conf_ss_table; static ConfTable::list_type conf_gs_table; /* *INDENT-ON* */ static void conf_report_error (config_entry_t *ce, char const * const fmt, ...) { va_list va; char buf[BUFSIZE]; return_if_fail (ce != NULL); return_if_fail (fmt != NULL); va_start (va, fmt); vsnprintf (buf, BUFSIZE, fmt, va); va_end (va); slog (LG_INFO, "%s:%d: configuration error - %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, buf); } static void conf_process (config_file_t *cfp) { config_file_t *cfptr; config_entry_t *ce; ConfTable *ct = NULL; for (cfptr = cfp; cfptr; cfptr = cfptr->cf_next) { for (ce = cfptr->cf_entries; ce; ce = ce->ce_next) { foreach (ConfTable *ct2, confblocks) { ct = ct2; if (!strcasecmp (ct->name, ce->ce_varname)) { ct->handler (ce); break; } } if (ct == NULL) conf_report_error (ce, "invalid configuration option: %s", ce->ce_varname); } } } bool conf_parse (char *file) { config_file_t *cfp; cfp = config_load (file); if (cfp == NULL) { slog (LG_ERROR, "conf_parse(): unable to load configuration file: %s", strerror (errno)); return false; } conf_process (cfp); config_free (cfp); if (!protocol::handler::loaded) { slog (LG_ERROR, "No protocol module loaded, aborting"); exit (EXIT_FAILURE); } ConfTable::callback.ready (); return true; } void conf_cleanup () { me.cleanup (); if (config_options.chan) sfree (config_options.chan); if (config_options.global) sfree (config_options.global); if (chansvs.trigger != NULL) sfree (chansvs.trigger); deinit_conf (); } void conf_init (void) { me.init (); if (chansvs.nick) sfree (chansvs.nick); if (config_options.chan) sfree (config_options.chan); if (config_options.global) sfree (config_options.global); chansvs.nick = config_options.chan = config_options.global = config_options.languagefile = NULL; config_options.flood_msgs = config_options.flood_time = config_options.kline_time = config_options.commit_interval = 0; nicksvs.expiry = chansvs.expiry = 0; config_options.defuflags = config_options.defcflags = 0x00000000; config_options.silent = config_options.join_chans = config_options.leave_chans = config_options.raw = false; me.auth = AUTH_NONE; me.mdlimit = 30; chansvs.fantasy = false; chansvs.ca_vop = CA_VOP_DEF & ca_all; chansvs.ca_hop = CA_HOP_DEF & ca_all; chansvs.ca_aop = CA_AOP_DEF & ca_all; chansvs.ca_sop = CA_SOP_DEF & ca_all; chansvs.changets = false; if (chansvs.trigger != NULL) sfree (chansvs.trigger); chansvs.trigger = sstrdup ("!"); chansvs.maxchanacs = 0; chansvs.maxfounders = 4; if (!(runflags & RF_REHASHING)) { if (me.name) sfree (me.name); if (me.desc) sfree (me.desc); if (me.vhost) sfree (me.vhost); if (chansvs.user) sfree (chansvs.user); if (chansvs.host) sfree (chansvs.host); if (chansvs.real) sfree (chansvs.real); me.name = me.desc = me.vhost = chansvs.user = chansvs.host = chansvs.real = NULL; set_match_mapping (MATCH_RFC1459); /* default to RFC compliancy */ } } int subblock_handler (config_entry_t *ce, ConfTable::list_type &entries) { ConfTable *ct = NULL; for (ce = ce->ce_entries; ce; ce = ce->ce_next) { foreach (ConfTable *ct2, entries) { ct = ct2; if (!strcasecmp (ct->name, ce->ce_varname)) { ct->handler (ce); break; } } if (ct == NULL) conf_report_error (ce, "invalid configuration option: %s", ce->ce_varname); } return 0; } ConfTable * find_top_conf (char const * const name) { foreach (ConfTable *ct, confblocks) if (!strcasecmp (ct->name, name)) return ct; return NULL; } ConfTable * find_conf_item (char const * const name, ConfTable::list_type &conflist) { foreach (ConfTable *ct, conflist) if (!strcasecmp (ct->name, name)) return ct; return NULL; } void add_top_conf (char const * const name, int (*handler) (config_entry_t *ce)) { ConfTable *ct; if ((ct = find_top_conf (name))) { slog (LG_DEBUG, "add_top_conf(): duplicate config block '%s'.", name); return; } ct = new ConfTable (name, 1, handler); confblocks.insert (ct); } void add_conf_item (char const * const name, ConfTable::list_type &conflist, int (*handler) (config_entry_t *ce)) { ConfTable *ct; if ((ct = find_conf_item (name, conflist))) { slog (LG_DEBUG, "add_conf_item(): duplicate item %s", name); return; } ct = new ConfTable (name, 1, handler); conflist.insert (ct); } void del_top_conf (char const * const name) { ConfTable *ct; if (!(ct = find_top_conf (name))) { slog (LG_DEBUG, "del_top_conf(): cannot delete nonexistant block %s", name); return; } confblocks.erase (ct); delete ct; } void del_conf_item (char const * const name, ConfTable::list_type &conflist) { ConfTable *ct; if (!(ct = find_conf_item (name, conflist))) { slog (LG_DEBUG, "del_conf_item(): cannot delete nonexistant item %s", name); return; } conflist.erase (ct); delete ct; } /* stolen from Sentinel */ #define TOKEN_UNMATCHED -1 #define TOKEN_ERROR -2 static int token_to_value (Token token_table[], char *token) { int i; if ((token_table != NULL) && (token != NULL)) { for (i = 0; token_table[i].text != NULL; i++) if (strcasecmp (token_table[i].text, token) == 0) return token_table[i].value; /* If no match... */ return TOKEN_UNMATCHED; } /* Otherwise... */ return TOKEN_ERROR; } void init_newconf (void) { #if 0 conftable_heap = BlockHeapCreate (sizeof (ConfTable), 32); #endif /* First we set up the blocks. */ add_top_conf ("SERVERINFO", c_serverinfo); add_top_conf ("CHANSERV", c_chanserv); add_top_conf ("GLOBAL", c_globserv); add_top_conf ("OPERSERV", c_operserv); add_top_conf ("NICKSERV", c_nickserv); add_top_conf ("SASLSERV", c_saslserv); add_top_conf ("MEMOSERV", c_memoserv); add_top_conf ("GAMESERV", c_gameserv); add_top_conf ("UPLINK", c_uplink); add_top_conf ("GENERAL", c_general); add_top_conf ("DATABASE", c_database); add_top_conf ("LOADMODULE", c_loadmodule); add_top_conf ("BACKEND", c_backend); add_top_conf ("CRYPTO", c_crypto); add_top_conf ("PROTOCOL", c_protocol); add_top_conf ("OPERCLASS", c_operclass); add_top_conf ("OPERATOR", c_operator); add_top_conf ("LOGFILE", c_logfile); /* Now we fill in the information */ add_conf_item ("NAME", conf_si_table, c_si_name); add_conf_item ("DESC", conf_si_table, c_si_desc); add_conf_item ("NUMERIC", conf_si_table, c_si_numeric); add_conf_item ("VHOST", conf_si_table, c_si_vhost); add_conf_item ("RECONTIME", conf_si_table, c_si_recontime); add_conf_item ("RESTARTTIME", conf_si_table, c_si_restarttime); add_conf_item ("EXPIRE", conf_si_table, c_gi_expire); add_conf_item ("NETNAME", conf_si_table, c_si_netname); add_conf_item ("HIDEHOSTSUFFIX", conf_si_table, c_si_hidehostsuffix); add_conf_item ("ADMINNAME", conf_si_table, c_si_adminname); add_conf_item ("ADMINEMAIL", conf_si_table, c_si_adminemail); add_conf_item ("MTA", conf_si_table, c_si_mta); add_conf_item ("LOGLEVEL", conf_si_table, c_si_loglevel); add_conf_item ("MAXLOGINS", conf_si_table, c_si_maxlogins); add_conf_item ("MAXUSERS", conf_si_table, c_si_maxusers); add_conf_item ("MAXNICKS", conf_si_table, c_si_maxnicks); add_conf_item ("MAXCHANS", conf_si_table, c_si_maxchans); add_conf_item ("EMAILLIMIT", conf_si_table, c_si_emaillimit); add_conf_item ("EMAILTIME", conf_si_table, c_si_emailtime); add_conf_item ("AUTH", conf_si_table, c_si_auth); add_conf_item ("MDLIMIT", conf_si_table, c_si_mdlimit); add_conf_item ("CASEMAPPING", conf_si_table, c_si_casemapping); /* general{} block. */ add_conf_item ("CHAN", conf_gi_table, c_gi_chan); add_conf_item ("VERBOSE_WALLOPS", conf_gi_table, c_gi_verbose_wallops); add_conf_item ("USE_PRIVMSG", conf_gi_table, c_gi_use_privmsg); add_conf_item ("SILENT", conf_gi_table, c_gi_silent); add_conf_item ("JOIN_CHANS", conf_gi_table, c_gi_join_chans); add_conf_item ("LEAVE_CHANS", conf_gi_table, c_gi_leave_chans); add_conf_item ("UFLAGS", conf_gi_table, c_gi_uflags); add_conf_item ("CFLAGS", conf_gi_table, c_gi_cflags); add_conf_item ("RAW", conf_gi_table, c_gi_raw); add_conf_item ("SECURE", conf_gi_table, c_gi_secure); add_conf_item ("FLOOD_MSGS", conf_gi_table, c_gi_flood_msgs); add_conf_item ("FLOOD_TIME", conf_gi_table, c_gi_flood_time); add_conf_item ("KLINE_TIME", conf_gi_table, c_gi_kline_time); add_conf_item ("COMMIT_INTERVAL", conf_gi_table, c_gi_commit_interval); add_conf_item ("EXPIRE", conf_gi_table, c_gi_expire); add_conf_item ("DEFAULT_CLONE_LIMIT", conf_gi_table, c_gi_default_clone_limit); /* chanserv{} block */ add_conf_item ("NICK", conf_ci_table, c_ci_nick); add_conf_item ("USER", conf_ci_table, c_ci_user); add_conf_item ("HOST", conf_ci_table, c_ci_host); add_conf_item ("REAL", conf_ci_table, c_ci_real); add_conf_item ("FANTASY", conf_ci_table, c_ci_fantasy); add_conf_item ("VOP", conf_ci_table, c_ci_vop); add_conf_item ("HOP", conf_ci_table, c_ci_hop); add_conf_item ("AOP", conf_ci_table, c_ci_aop); add_conf_item ("SOP", conf_ci_table, c_ci_sop); add_conf_item ("CHANGETS", conf_ci_table, c_ci_changets); add_conf_item ("TRIGGER", conf_ci_table, c_ci_trigger); add_conf_item ("EXPIRE", conf_ci_table, c_ci_expire); add_conf_item ("MAXCHANACS", conf_ci_table, c_ci_maxchanacs); add_conf_item ("MAXFOUNDERS", conf_ci_table, c_ci_maxfounders); /* global{} block */ add_conf_item ("NICK", conf_gl_table, c_gl_nick); add_conf_item ("USER", conf_gl_table, c_gl_user); add_conf_item ("HOST", conf_gl_table, c_gl_host); add_conf_item ("REAL", conf_gl_table, c_gl_real); /* operserv{} block */ add_conf_item ("NICK", conf_oi_table, c_oi_nick); add_conf_item ("USER", conf_oi_table, c_oi_user); add_conf_item ("HOST", conf_oi_table, c_oi_host); add_conf_item ("REAL", conf_oi_table, c_oi_real); /* nickserv{} block */ add_conf_item ("NICK", conf_ni_table, c_ni_nick); add_conf_item ("USER", conf_ni_table, c_ni_user); add_conf_item ("HOST", conf_ni_table, c_ni_host); add_conf_item ("REAL", conf_ni_table, c_ni_real); add_conf_item ("SPAM", conf_ni_table, c_ni_spam); add_conf_item ("NO_NICK_OWNERSHIP", conf_ni_table, c_ni_no_nick_ownership); add_conf_item ("EXPIRE", conf_ni_table, c_ni_expire); /* saslserv{} block */ add_conf_item ("NICK", conf_ss_table, c_ss_nick); add_conf_item ("USER", conf_ss_table, c_ss_user); add_conf_item ("HOST", conf_ss_table, c_ss_host); add_conf_item ("REAL", conf_ss_table, c_ss_real); /* memoserv{} block */ add_conf_item ("NICK", conf_ms_table, c_ms_nick); add_conf_item ("USER", conf_ms_table, c_ms_user); add_conf_item ("HOST", conf_ms_table, c_ms_host); add_conf_item ("REAL", conf_ms_table, c_ms_real); /* memoserv{} block */ add_conf_item ("NICK", conf_gs_table, c_gs_nick); add_conf_item ("USER", conf_gs_table, c_gs_user); add_conf_item ("HOST", conf_gs_table, c_gs_host); add_conf_item ("REAL", conf_gs_table, c_gs_real); /* database{} block */ add_conf_item ("USER", conf_db_table, c_db_user); add_conf_item ("HOST", conf_db_table, c_db_host); add_conf_item ("PASSWORD", conf_db_table, c_db_password); add_conf_item ("DATABASE", conf_db_table, c_db_database); add_conf_item ("PORT", conf_db_table, c_db_port); } static void deinit_conf (void) { #if 0 conftable_heap = BlockHeapCreate (sizeof (ConfTable), 32); #endif /* Now we fill in the information */ del_conf_item ("NAME", conf_si_table); del_conf_item ("DESC", conf_si_table); del_conf_item ("NUMERIC", conf_si_table); del_conf_item ("VHOST", conf_si_table); del_conf_item ("RECONTIME", conf_si_table); del_conf_item ("RESTARTTIME", conf_si_table); del_conf_item ("EXPIRE", conf_si_table); del_conf_item ("NETNAME", conf_si_table); del_conf_item ("HIDEHOSTSUFFIX", conf_si_table); del_conf_item ("ADMINNAME", conf_si_table); del_conf_item ("ADMINEMAIL", conf_si_table); del_conf_item ("MTA", conf_si_table); del_conf_item ("LOGLEVEL", conf_si_table); del_conf_item ("MAXLOGINS", conf_si_table); del_conf_item ("MAXUSERS", conf_si_table); del_conf_item ("MAXNICKS", conf_si_table); del_conf_item ("MAXCHANS", conf_si_table); del_conf_item ("EMAILLIMIT", conf_si_table); del_conf_item ("EMAILTIME", conf_si_table); del_conf_item ("AUTH", conf_si_table); del_conf_item ("MDLIMIT", conf_si_table); del_conf_item ("CASEMAPPING", conf_si_table); /* general{} block. */ del_conf_item ("CHAN", conf_gi_table); del_conf_item ("VERBOSE_WALLOPS", conf_gi_table); del_conf_item ("USE_PRIVMSG", conf_gi_table); del_conf_item ("SILENT", conf_gi_table); del_conf_item ("JOIN_CHANS", conf_gi_table); del_conf_item ("LEAVE_CHANS", conf_gi_table); del_conf_item ("UFLAGS", conf_gi_table); del_conf_item ("CFLAGS", conf_gi_table); del_conf_item ("RAW", conf_gi_table); del_conf_item ("SECURE", conf_gi_table); del_conf_item ("FLOOD_MSGS", conf_gi_table); del_conf_item ("FLOOD_TIME", conf_gi_table); del_conf_item ("KLINE_TIME", conf_gi_table); del_conf_item ("COMMIT_INTERVAL", conf_gi_table); del_conf_item ("EXPIRE", conf_gi_table); del_conf_item ("DEFAULT_CLONE_LIMIT", conf_gi_table); /* chanserv{} block */ del_conf_item ("NICK", conf_ci_table); del_conf_item ("USER", conf_ci_table); del_conf_item ("HOST", conf_ci_table); del_conf_item ("REAL", conf_ci_table); del_conf_item ("FANTASY", conf_ci_table); del_conf_item ("VOP", conf_ci_table); del_conf_item ("HOP", conf_ci_table); del_conf_item ("AOP", conf_ci_table); del_conf_item ("SOP", conf_ci_table); del_conf_item ("CHANGETS", conf_ci_table); del_conf_item ("TRIGGER", conf_ci_table); del_conf_item ("EXPIRE", conf_ci_table); del_conf_item ("MAXCHANACS", conf_ci_table); del_conf_item ("MAXFOUNDERS", conf_ci_table); /* global{} block */ del_conf_item ("NICK", conf_gl_table); del_conf_item ("USER", conf_gl_table); del_conf_item ("HOST", conf_gl_table); del_conf_item ("REAL", conf_gl_table); /* operserv{} block */ del_conf_item ("NICK", conf_oi_table); del_conf_item ("USER", conf_oi_table); del_conf_item ("HOST", conf_oi_table); del_conf_item ("REAL", conf_oi_table); /* nickserv{} block */ del_conf_item ("NICK", conf_ni_table); del_conf_item ("USER", conf_ni_table); del_conf_item ("HOST", conf_ni_table); del_conf_item ("REAL", conf_ni_table); del_conf_item ("SPAM", conf_ni_table); del_conf_item ("NO_NICK_OWNERSHIP", conf_ni_table); del_conf_item ("EXPIRE", conf_ni_table); /* saslserv{} block */ del_conf_item ("NICK", conf_ss_table); del_conf_item ("USER", conf_ss_table); del_conf_item ("HOST", conf_ss_table); del_conf_item ("REAL", conf_ss_table); /* memoserv{} block */ del_conf_item ("NICK", conf_ms_table); del_conf_item ("USER", conf_ms_table); del_conf_item ("HOST", conf_ms_table); del_conf_item ("REAL", conf_ms_table); /* memoserv{} block */ del_conf_item ("NICK", conf_gs_table); del_conf_item ("USER", conf_gs_table); del_conf_item ("HOST", conf_gs_table); del_conf_item ("REAL", conf_gs_table); /* database{} block */ del_conf_item ("USER", conf_db_table); del_conf_item ("HOST", conf_db_table); del_conf_item ("PASSWORD", conf_db_table); del_conf_item ("DATABASE", conf_db_table); del_conf_item ("PORT", conf_db_table); /* First we set up the blocks. */ del_top_conf ("SERVERINFO"); del_top_conf ("CHANSERV"); del_top_conf ("GLOBAL"); del_top_conf ("OPERSERV"); del_top_conf ("NICKSERV"); del_top_conf ("SASLSERV"); del_top_conf ("MEMOSERV"); del_top_conf ("GAMESERV"); del_top_conf ("UPLINK"); del_top_conf ("GENERAL"); del_top_conf ("DATABASE"); del_top_conf ("LOADMODULE"); del_top_conf ("BACKEND"); del_top_conf ("CRYPTO"); del_top_conf ("PROTOCOL"); del_top_conf ("OPERCLASS"); del_top_conf ("OPERATOR"); del_top_conf ("LOGFILE"); } static int c_serverinfo (config_entry_t *ce) { return subblock_handler (ce, conf_si_table); } static int c_chanserv (config_entry_t *ce) { return subblock_handler (ce, conf_ci_table); } static int c_globserv (config_entry_t *ce) { return subblock_handler (ce, conf_gl_table); } static int c_operserv (config_entry_t *ce) { return subblock_handler (ce, conf_oi_table); } static int c_nickserv (config_entry_t *ce) { return subblock_handler (ce, conf_ni_table); } static int c_saslserv (config_entry_t *ce) { return subblock_handler (ce, conf_ss_table); } static int c_memoserv (config_entry_t *ce) { return subblock_handler (ce, conf_ms_table); } static int c_gameserv (config_entry_t *ce) { return subblock_handler (ce, conf_gs_table); } static int c_database (config_entry_t *ce) { return subblock_handler (ce, conf_db_table); } static int c_protocol (config_entry_t *ce) { char *name; if (cold_start == false) return 0; if (ce->vardata () == NULL) return param_error (ce); name = ce->vardata (); typedef factory::factory_mgr protocol_factory; protocol_factory &f = protocol_factory::instance (); if (!f.provides (name)) return param_error (ce, "no such protocol handler"); phandler = f.create (name); return 0; } static int c_loadmodule (config_entry_t *ce) { char *name; if (cold_start == false) return 0; if (ce->vardata () == NULL) return param_error (ce); name = ce->vardata (); if (!modules::provides (name)) return param_error (ce, "no such module"); modules::enable (name); return 0; } static int c_crypto (config_entry_t *ce) { char *name; if (cold_start == false) return 0; if (ce->vardata () == NULL) return param_error (ce); name = ce->vardata (); typedef factory::factory_mgr crypto_factory; crypto_factory &f = crypto_factory::instance (); if (!f.provides (name)) return param_error (ce, "no such crypto handler"); crypter = f.create (name); return 0; } static int c_backend (config_entry_t *ce) { char *name; if (cold_start == false) return 0; if (ce->vardata () == NULL) return param_error (ce); name = ce->vardata (); typedef factory::factory_mgr backend_factory; backend_factory &f = backend_factory::instance (); if (!f.provides (name)) return param_error (ce, "no such database backend"); backend = f.create (name); return 0; } static int c_uplink (config_entry_t *ce) { char *name; char *host = NULL, *vhost = NULL, *password = NULL; unsigned int port = 0; if (ce->vardata () == NULL) return param_error (ce); if (me.name != NULL && !irccasecmp (ce->vardata (), me.name)) slog (LG_ERROR, "%s:%d: uplink's server name %s should not be the same as our server name, continuing anyway", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->vardata ()); else if (!strchr (ce->vardata (), '.')) slog (LG_ERROR, "%s:%d: uplink's server name %s is invalid, continuing anyway", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->vardata ()); else if (isdigit (ce->vardata ()[0])) slog (LG_ERROR, "%s:%d: uplink's server name %s starts with a digit, probably invalid (continuing anyway)", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->vardata ()); name = ce->vardata (); for (ce = ce->ce_entries; ce; ce = ce->ce_next) { if (!strcasecmp ("HOST", ce->ce_varname)) { if (ce->vardata () == NULL) return param_error (ce); host = ce->vardata (); } else if (!strcasecmp ("VHOST", ce->ce_varname)) { if (ce->vardata () == NULL) return param_error (ce); vhost = ce->vardata (); } else if (!strcasecmp ("PASSWORD", ce->ce_varname)) { if (ce->vardata () == NULL) return param_error (ce); password = ce->vardata (); } else if (!strcasecmp ("PORT", ce->ce_varname)) { if (ce->vardata () == NULL) return param_error (ce); port = ce->vardata (); } else { slog (LG_ERROR, "%s:%d: Invalid configuration option uplink::%s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_varname); continue; } } uplink_add (name, host, password, vhost, port); return 0; } static int c_operclass (config_entry_t *ce) { operclass_t *operclass; char *name; char *privs = NULL, *newprivs; int flags = 0; if (ce->vardata () == NULL) return param_error (ce); name = ce->vardata (); for (ce = ce->ce_entries; ce; ce = ce->ce_next) { if (!strcasecmp ("PRIVS", ce->ce_varname)) { if (ce->vardata () == NULL && ce->ce_entries == NULL) return param_error (ce); if (ce->ce_entries == NULL) { if (privs == NULL) privs = sstrdup (ce->vardata ()); else { newprivs = salloc (strlen (privs) + 1 + strlen (ce->vardata ()) + 1); strcpy (newprivs, privs); strcat (newprivs, " "); strcat (newprivs, ce->vardata ()); sfree (privs); privs = newprivs; } } else { config_entry_t *conf_p; /* * New definition format for operclasses. * * operclass "sra" { * privs = { * special:ircop; * }; * }; * * - nenolod */ for (conf_p = ce->ce_entries; conf_p; conf_p = conf_p->ce_next) { if (privs == NULL) privs = sstrdup (conf_p->ce_varname); else { newprivs = salloc (strlen (privs) + 1 + strlen (conf_p->ce_varname) + 1); strcpy (newprivs, privs); strcat (newprivs, " "); strcat (newprivs, conf_p->ce_varname); sfree (privs); privs = newprivs; } } } } else if (!strcasecmp ("NEEDOPER", ce->ce_varname)) flags |= OPERCLASS_NEEDOPER; else { slog (LG_ERROR, "%s:%d: Invalid configuration option operclass::%s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_varname); continue; } } operclass = operclass_add (name, privs ? privs : ""); if (operclass != NULL) operclass->flags |= flags; sfree (privs); return 0; } static int c_operator (config_entry_t *ce) { char *name; operclass_t *operclass = NULL; config_entry_t *topce; if (ce->vardata () == NULL) return param_error (ce); topce = ce; name = ce->vardata (); for (ce = ce->ce_entries; ce; ce = ce->ce_next) { if (!strcasecmp ("OPERCLASS", ce->ce_varname)) { if (ce->vardata () == NULL) return param_error (ce); operclass = operclass_find (ce->vardata ()); if (operclass == NULL) slog (LG_ERROR, "%s:%d: invalid operclass %s for operator %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->vardata (), name); } else { slog (LG_ERROR, "%s:%d: Invalid configuration option operator::%s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_varname); continue; } } if (operclass != NULL) soper_add (name, operclass->name, SOPER_CONF); else slog (LG_ERROR, "%s:%d: skipping operator %s because of bad/missing parameters", topce->ce_fileptr->cf_filename, topce->ce_varlinenum, name); return 0; } static int c_general (config_entry_t *ce) { return subblock_handler (ce, conf_gi_table); } static int c_si_name (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (!(runflags & RF_REHASHING)) me.name = sstrdup (ce->vardata ()); return 0; } static int c_si_desc (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (me.desc != NULL) sfree (me.desc); me.desc = sstrdup (ce->vardata ()); return 0; } static int c_si_numeric (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (!(runflags & RF_REHASHING)) me.numeric = sstrdup (ce->vardata ()); return 0; } static int c_si_mdlimit (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.mdlimit = ce->vardata (); return 0; } static int c_si_vhost (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.vhost = sstrdup (ce->vardata ()); return 0; } static int c_si_recontime (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.recontime = ce->vardata (); return 0; } static int c_si_restarttime (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.restarttime = ce->vardata (); return 0; } static int c_si_netname (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.netname = sstrdup (ce->vardata ()); return 0; } static int c_si_hidehostsuffix (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.hidehostsuffix = sstrdup (ce->vardata ()); return 0; } static int c_si_adminname (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.adminname = sstrdup (ce->vardata ()); return 0; } static int c_si_adminemail (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.adminemail = sstrdup (ce->vardata ()); return 0; } static int c_si_mta (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.mta = sstrdup (ce->vardata ()); return 0; } static int c_si_loglevel (config_entry_t *ce) { config_entry_t *flce; int val; int mask = 0; if (ce->vardata () != NULL) { val = token_to_value (logflags, ce->vardata ()); if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR)) mask |= val; else slog (LG_INFO, "%s:%d: unknown flag: %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->vardata ()); } for (flce = ce->ce_entries; flce; flce = flce->ce_next) { val = token_to_value (logflags, flce->ce_varname); if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR)) mask |= val; else slog (LG_INFO, "%s:%d: unknown flag: %s", flce->ce_fileptr->cf_filename, flce->ce_varlinenum, flce->ce_varname); } log_master_set_mask (mask); return 0; } static int c_si_maxlogins (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.maxlogins = ce->vardata (); return 0; } static int c_si_maxusers (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.maxusers = ce->vardata (); return 0; } static int c_si_maxnicks (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.maxnicks = ce->vardata (); return 0; } static int c_si_maxchans (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.maxchans = ce->vardata (); return 0; } static int c_si_emaillimit (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.emaillimit = ce->vardata (); return 0; } static int c_si_emailtime (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); me.emailtime = ce->vardata (); return 0; } static int c_si_auth (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (!strcasecmp ("EMAIL", ce->vardata ())) me.auth = AUTH_EMAIL; else me.auth = AUTH_NONE; return 0; } static int c_si_casemapping (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (!strcasecmp ("ASCII", ce->vardata ())) set_match_mapping (MATCH_ASCII); else set_match_mapping (MATCH_RFC1459); return 0; } static int c_ci_nick (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (chansvs.nick != NULL) sfree (chansvs.nick); chansvs.nick = sstrdup (ce->vardata ()); return 0; } static int c_ci_user (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (chansvs.user != NULL) sfree (chansvs.user); chansvs.user = sstrdup (ce->vardata ()); return 0; } static int c_ci_host (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (chansvs.host != NULL) sfree (chansvs.host); chansvs.host = sstrdup (ce->vardata ()); return 0; } static int c_ci_real (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (chansvs.real != NULL) sfree (chansvs.real); chansvs.real = sstrdup (ce->vardata ()); return 0; } static int c_ci_fantasy (config_entry_t *ce) { chansvs.fantasy = true; return 0; } static int c_ci_vop (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); chansvs.ca_vop = flags_to_bitmask (ce->vardata (), chanacs_flags, 0); return 0; } static int c_ci_hop (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); chansvs.ca_hop = flags_to_bitmask (ce->vardata (), chanacs_flags, 0); return 0; } static int c_ci_aop (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); chansvs.ca_aop = flags_to_bitmask (ce->vardata (), chanacs_flags, 0); return 0; } static int c_ci_sop (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); chansvs.ca_sop = flags_to_bitmask (ce->vardata (), chanacs_flags, 0); return 0; } static int c_ci_changets (config_entry_t *ce) { chansvs.changets = true; return 0; } static int c_ci_trigger (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (chansvs.trigger != NULL) sfree (chansvs.trigger); chansvs.trigger = sstrdup (ce->vardata ()); return 0; } static int c_ci_expire (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); chansvs.expiry = (ce->vardata () * 60 * 60 * 24); return 0; } static int c_ci_maxchanacs (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); chansvs.maxchanacs = ce->vardata (); return 0; } static int c_ci_maxfounders (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); chansvs.maxfounders = ce->vardata (); return 0; } static int c_gi_chan (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); config_options.chan = sstrdup (ce->vardata ()); return 0; } static int c_gi_silent (config_entry_t *ce) { config_options.silent = true; return 0; } static int c_gi_verbose_wallops (config_entry_t *ce) { config_options.verbose_wallops = true; return 0; } static int c_gi_use_privmsg (config_entry_t *ce) { config_options.use_privmsg = true; return 0; } static int c_gi_secure (config_entry_t *ce) { config_options.secure = true; return 0; } static int c_gi_join_chans (config_entry_t *ce) { config_options.join_chans = true; return 0; } static int c_gi_leave_chans (config_entry_t *ce) { config_options.leave_chans = true; return 0; } static int c_gi_uflags (config_entry_t *ce) { config_entry_t *flce; for (flce = ce->ce_entries; flce; flce = flce->ce_next) { int val; val = token_to_value (uflags, flce->ce_varname); if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR)) config_options.defuflags |= val; else { slog (LG_INFO, "%s:%d: unknown flag: %s", flce->ce_fileptr->cf_filename, flce->ce_varlinenum, flce->ce_varname); } } return 0; } static int c_gi_cflags (config_entry_t *ce) { config_entry_t *flce; for (flce = ce->ce_entries; flce; flce = flce->ce_next) { int val; val = token_to_value (cflags, flce->ce_varname); if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR)) config_options.defcflags |= val; else { slog (LG_INFO, "%s:%d: unknown flag: %s", flce->ce_fileptr->cf_filename, flce->ce_varlinenum, flce->ce_varname); } } if (config_options.defcflags & MC_TOPICLOCK) config_options.defcflags |= MC_KEEPTOPIC; return 0; } static int c_gi_raw (config_entry_t *ce) { config_options.raw = true; return 0; } static int c_gi_flood_msgs (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); config_options.flood_msgs = ce->vardata (); return 0; } static int c_gi_flood_time (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); config_options.flood_time = ce->vardata (); return 0; } static int c_gi_kline_time (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); config_options.kline_time = (ce->vardata () * 60 * 60 * 24); return 0; } static int c_gi_commit_interval (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); config_options.commit_interval = (ce->vardata () * 60); return 0; } static int c_gi_expire (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); slog (LG_INFO, "warning: general::expire has been deprecated. please use nickserv::expire and chanserv::expire respectively."); nicksvs.expiry = (ce->vardata () * 60 * 60 * 24); chansvs.expiry = (ce->vardata () * 60 * 60 * 24); return 0; } static int c_gi_default_clone_limit (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); config_options.default_clone_limit = ce->vardata (); return 0; } static int c_oi_nick (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (opersvs.nick != NULL) sfree (opersvs.nick); opersvs.nick = sstrdup (ce->vardata ()); return 0; } static int c_oi_user (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (opersvs.user != NULL) sfree (opersvs.user); opersvs.user = sstrdup (ce->vardata ()); return 0; } static int c_oi_host (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (opersvs.host != NULL) sfree (opersvs.host); opersvs.host = sstrdup (ce->vardata ()); return 0; } static int c_oi_real (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (opersvs.real != NULL) sfree (opersvs.real); opersvs.real = sstrdup (ce->vardata ()); return 0; } static int c_ni_nick (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (nicksvs.nick != NULL) sfree (nicksvs.nick); nicksvs.nick = sstrdup (ce->vardata ()); return 0; } static int c_ni_user (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (nicksvs.user != NULL) sfree (nicksvs.user); nicksvs.user = sstrdup (ce->vardata ()); return 0; } static int c_ni_host (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (nicksvs.host != NULL) sfree (nicksvs.host); nicksvs.host = sstrdup (ce->vardata ()); return 0; } static int c_ni_real (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (nicksvs.real != NULL) sfree (nicksvs.real); nicksvs.real = sstrdup (ce->vardata ()); return 0; } static int c_ni_spam (config_entry_t *ce) { nicksvs.spam = true; return 0; } static int c_ni_no_nick_ownership (config_entry_t *ce) { nicksvs.no_nick_ownership = true; return 0; } static int c_ni_expire (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); nicksvs.expiry = (ce->vardata () * 60 * 60 * 24); return 0; } static int c_ss_nick (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (saslsvs.nick != NULL) sfree (saslsvs.nick); saslsvs.nick = sstrdup (ce->vardata ()); return 0; } static int c_ss_user (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (saslsvs.user != NULL) sfree (saslsvs.user); saslsvs.user = sstrdup (ce->vardata ()); return 0; } static int c_ss_host (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (saslsvs.host != NULL) sfree (saslsvs.host); saslsvs.host = sstrdup (ce->vardata ()); return 0; } static int c_ss_real (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (saslsvs.real != NULL) sfree (saslsvs.real); saslsvs.real = sstrdup (ce->vardata ()); return 0; } static int c_ms_nick (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (memosvs.nick != NULL) sfree (memosvs.nick); memosvs.nick = sstrdup (ce->vardata ()); return 0; } static int c_ms_user (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (memosvs.user != NULL) sfree (memosvs.user); memosvs.user = sstrdup (ce->vardata ()); return 0; } static int c_ms_host (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (memosvs.host != NULL) sfree (memosvs.host); memosvs.host = sstrdup (ce->vardata ()); return 0; } static int c_ms_real (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (memosvs.real != NULL) sfree (memosvs.real); memosvs.real = sstrdup (ce->vardata ()); return 0; } static int c_gs_nick (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (gamesvs.nick != NULL) sfree (gamesvs.nick); gamesvs.nick = sstrdup (ce->vardata ()); return 0; } static int c_gs_user (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (gamesvs.user != NULL) sfree (gamesvs.user); gamesvs.user = sstrdup (ce->vardata ()); return 0; } static int c_gs_host (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (gamesvs.host != NULL) sfree (gamesvs.host); gamesvs.host = sstrdup (ce->vardata ()); return 0; } static int c_gs_real (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (gamesvs.real != NULL) sfree (gamesvs.real); gamesvs.real = sstrdup (ce->vardata ()); return 0; } static int c_gl_nick (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (globsvs.nick != NULL) sfree (globsvs.nick); globsvs.nick = sstrdup (ce->vardata ()); return 0; } static int c_gl_user (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (globsvs.user != NULL) sfree (globsvs.user); globsvs.user = sstrdup (ce->vardata ()); return 0; } static int c_gl_host (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (globsvs.host != NULL) sfree (globsvs.host); globsvs.host = sstrdup (ce->vardata ()); return 0; } static int c_gl_real (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (globsvs.real != NULL) sfree (globsvs.real); globsvs.real = sstrdup (ce->vardata ()); return 0; } static int c_db_user (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (database_options.user != NULL) sfree (database_options.user); database_options.user = sstrdup (ce->vardata ()); return 0; } static int c_db_host (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (database_options.host != NULL) sfree (database_options.host); database_options.host = sstrdup (ce->vardata ()); return 0; } static int c_db_password (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (database_options.pass != NULL) sfree (database_options.pass); database_options.pass = sstrdup (ce->vardata ()); return 0; } static int c_db_database (config_entry_t *ce) { if (ce->vardata () == NULL) return param_error (ce); if (database_options.database != NULL) sfree (database_options.database); database_options.database = sstrdup (ce->vardata ()); return 0; } static int c_db_port (config_entry_t *ce) { if (ce->vardata () == 0) return param_error (ce); database_options.port = ce->vardata (); return 0; } static int c_logfile (config_entry_t *ce) { config_entry_t *flce; unsigned int logval = 0; if (ce->vardata () == NULL) return param_error (ce); for (flce = ce->ce_entries; flce; flce = flce->ce_next) { int val; val = token_to_value (logflags, flce->ce_varname); if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR)) logval |= val; else { slog (LG_INFO, "%s:%d: unknown flag: %s", flce->ce_fileptr->cf_filename, flce->ce_varlinenum, flce->ce_varname); } } logfile_t::create (ce->vardata (), logval); return 0; } bool conf_rehash (void) { me_t hold_me; char *oldsnoop; config_file_t *cfp; /* we're rehashing */ slog (LG_INFO, "conf_rehash(): rehashing"); runflags |= RF_REHASHING; errno = 0; cfp = config_load (config_file); if (cfp == NULL) { slog (LG_ERROR, "conf_rehash(): unable to load configuration file: %s, aborting rehash", strerror (errno)); runflags &= ~RF_REHASHING; return false; } hold_me = me; oldsnoop = config_options.chan != NULL ? sstrdup (config_options.chan) : NULL; /* reset everything */ conf_init (); mark_all_illegal (); log_shutdown (); /* now reload */ log_open (); conf_process (cfp); config_free (cfp); ConfTable::callback.ready (); /* now recheck */ if (!conf_check ()) { slog (LG_ERROR, "conf_rehash(): conf file was malformed, aborting rehash"); /* freeing the new conf strings */ sfree (chansvs.nick); me.cleanup (); /* return everything to the way it was before */ me = hold_me; /* not fully ok, oh well */ unmark_all_illegal (); sfree (oldsnoop); runflags &= ~RF_REHASHING; return false; } if (oldsnoop != NULL || config_options.chan != NULL) { if (config_options.chan == NULL) partall (oldsnoop); else if (oldsnoop == NULL) joinall (config_options.chan); else if (strcmp (oldsnoop, config_options.chan)) { partall (oldsnoop); joinall (config_options.chan); } } remove_illegals (); sfree (oldsnoop); runflags &= ~RF_REHASHING; return true; } bool conf_check (void) { if (!me.name) { slog (LG_ERROR, "conf_check(): no `name' set in %s", config_file); return false; } /* The following checks could perhaps be stricter */ if (!strchr (me.name, '.') || strchr ("!\"#$%&+,-./:@", me.name[0]) || strchr (me.name, ' ')) { slog (LG_ERROR, "conf_check(): bogus `name' in %s (did you specify a valid server name?)", config_file); return false; } if (isdigit (me.name[0])) slog (LG_ERROR, "conf_check(): `name' in %s starts with a digit, probably invalid (continuing anyway)", config_file); if (!me.desc) me.desc = sstrdup ("Ermyth IRC Services"); if ((!me.recontime) || (me.recontime < 10)) { slog (LG_INFO, "conf_check(): invalid `recontime' set in %s; " "defaulting to 10", config_file); me.recontime = 10; } if (!me.netname) { slog (LG_INFO, "conf_check(): no `netname' set in %s", config_file); return false; } if (!me.adminname) { slog (LG_INFO, "conf_check(): no `adminname' set in %s", config_file); return false; } if (!me.adminemail) { slog (LG_INFO, "conf_check(): no `adminemail' set in %s", config_file); return false; } if (!me.mta && me.auth == AUTH_EMAIL) { slog (LG_INFO, "conf_check(): no `mta' set in %s (but `auth' is email)", config_file); return false; } if (!me.maxlogins) { slog (LG_INFO, "conf_check(): no `maxlogins' set in %s; " "defaulting to 5", config_file); me.maxlogins = 5; } if (!me.maxusers) { slog (LG_INFO, "conf_check(): no `maxusers' set in %s; " "defaulting to 5", config_file); me.maxusers = 5; } if (!me.maxnicks) { if (!nicksvs.no_nick_ownership) slog (LG_INFO, "conf_check(): no `maxnicks' set in %s; " "defaulting to 5", config_file); me.maxnicks = 5; } if (!me.maxchans) { slog (LG_INFO, "conf_check(): no `maxchans' set in %s; " "defaulting to 5", config_file); me.maxchans = 5; } if (!me.emaillimit) { slog (LG_INFO, "conf_check(): no `emaillimit' set in %s; " "defaulting to 10", config_file); me.emaillimit = 10; } if (!me.emailtime) { slog (LG_INFO, "conf_check(): no `emailtime' set in %s; " "defaulting to 300", config_file); me.emailtime = 300; } if (me.auth != 0 && me.auth != 1) { slog (LG_INFO, "conf_check(): no `auth' set in %s; " "defaulting to NONE", config_file); me.auth = AUTH_NONE; } if (!chansvs.nick || !chansvs.user || !chansvs.host || !chansvs.real) { slog (LG_ERROR, "conf_check(): invalid chanserv{} block in %s", config_file); return false; } if ((strchr (chansvs.user, ' ')) || (strlen (chansvs.user) > 10)) { slog (LG_ERROR, "conf_check(): invalid `chanserv::user' in %s", config_file); return false; } /* we know ca_all now */ chansvs.ca_vop &= ca_all; chansvs.ca_hop &= ca_all; chansvs.ca_aop &= ca_all; chansvs.ca_sop &= ca_all; /* chansvs.ca_hop may be equal to chansvs.ca_vop to disable HOP */ if (!chansvs.ca_vop || !chansvs.ca_hop || !chansvs.ca_aop || !chansvs.ca_sop || chansvs.ca_vop == chansvs.ca_aop || chansvs.ca_vop == chansvs.ca_sop || chansvs.ca_hop == chansvs.ca_aop || chansvs.ca_hop == chansvs.ca_sop || chansvs.ca_aop == chansvs.ca_sop) { slog (LG_INFO, "conf_check(): invalid xop levels in %s, using defaults", config_file); chansvs.ca_vop = CA_VOP_DEF & ca_all; chansvs.ca_hop = CA_HOP_DEF & ca_all; chansvs.ca_aop = CA_AOP_DEF & ca_all; chansvs.ca_sop = CA_SOP_DEF & ca_all; } if (config_options.flood_msgs && !config_options.flood_time) config_options.flood_time = 10; if (!config_options.default_clone_limit) config_options.default_clone_limit = 6; /* recall that commit_interval is in seconds */ if ((!config_options.commit_interval) || (config_options.commit_interval < 60) || (config_options.commit_interval > 3600)) { slog (LG_INFO, "conf_check(): invalid `commit_interval' set in %s; " "defaulting to 5 minutes", config_file); config_options.commit_interval = 300; } return true; }