From c2ddecc2b1dbc9d055166bdf296da2e4536f74f6 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 27 Aug 2010 20:56:28 -0400 Subject: Added a new logging system --- src/bots.cpp | 15 +- src/channels.cpp | 72 ++++----- src/chanserv.cpp | 16 +- src/commands.cpp | 8 +- src/config.cpp | 127 +++++++++++++--- src/encrypt.cpp | 4 +- src/init.cpp | 157 ++++++++------------ src/language.cpp | 19 ++- src/log.cpp | 264 --------------------------------- src/logger.cpp | 399 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/mail.cpp | 4 +- src/main.cpp | 268 +++++++++++++++++---------------- src/memoserv.cpp | 2 +- src/messages.cpp | 10 +- src/misc.cpp | 4 +- src/modes.cpp | 40 +++-- src/modulemanager.cpp | 26 ++-- src/modules.cpp | 22 +-- src/nickalias.cpp | 2 +- src/nickcore.cpp | 2 +- src/nickserv.cpp | 8 +- src/process.cpp | 24 +-- src/regchannel.cpp | 10 +- src/send.cpp | 8 +- src/servers.cpp | 30 ++-- src/sessions.cpp | 12 +- src/sockets.cpp | 2 +- src/users.cpp | 110 +++++--------- 28 files changed, 903 insertions(+), 762 deletions(-) delete mode 100644 src/log.cpp create mode 100644 src/logger.cpp (limited to 'src') diff --git a/src/bots.cpp b/src/bots.cpp index d63f6787f..e6124e135 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -20,16 +20,15 @@ BotInfo *MemoServ = NULL; BotInfo *NickServ = NULL; BotInfo *OperServ = NULL; -BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal) : User(nnick, ts6_uid_retrieve()) +BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal) : User(nnick, nuser, nhost, ts6_uid_retrieve()) { - this->ident = nuser; - this->host = nhost; this->realname = nreal; this->server = Me; this->chancount = 0; this->lastmsg = this->created = time(NULL); + this->SetFlag(BI_CORE); if (!Config->s_ChanServ.empty() && nnick.equals_ci(Config->s_ChanServ)) ChanServ = this; else if (!Config->s_BotServ.empty() && nnick.equals_ci(Config->s_BotServ)) @@ -44,6 +43,8 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A NickServ = this; else if (!Config->s_GlobalNoticer.empty() && nnick.equals_ci(Config->s_GlobalNoticer)) Global = this; + else + this->UnsetFlag(BI_CORE); BotListByNick[this->nick] = this; if (!this->uid.empty()) @@ -168,16 +169,16 @@ void BotInfo::Join(Channel *c, bool update_ts) c->JoinUser(this); ChannelContainer *cc = this->FindChannel(c); - for (std::list::iterator it = BotModes.begin(), it_end = BotModes.end(); it != it_end; ++it) + for (int i = 0; i < Config->BotModeList.size(); ++i) { if (!update_ts) { - c->SetMode(this, *it, this->nick, false); + c->SetMode(this, Config->BotModeList[i], this->nick, false); } else { - cc->Status->SetFlag((*it)->Name); - c->SetModeInternal(*it, this->nick, false); + cc->Status->SetFlag(Config->BotModeList[i]->Name); + c->SetModeInternal(Config->BotModeList[i], this->nick, false); } } if (!update_ts) diff --git a/src/channels.cpp b/src/channels.cpp index aa2e0affc..506dbfc7d 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -37,6 +37,8 @@ Channel::Channel(const Anope::string &name, time_t ts) this->ci = cs_findchan(this->name); if (this->ci) this->ci->c = this; + + Log(NULL, this, "create"); FOREACH_MOD(I_OnChannelCreate, OnChannelCreate(this)); } @@ -49,7 +51,7 @@ Channel::~Channel() FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(this)); - Alog(LOG_DEBUG) << "Deleting channel " << this->name; + Log(NULL, this, "destroy"); for (bd = this->bd; bd; bd = next) { @@ -114,7 +116,7 @@ void Channel::Sync() void Channel::JoinUser(User *user) { - Alog(LOG_DEBUG) << user->nick << " joins " << this->name; + Log(user, this, "join"); ChannelStatus *Status = new ChannelStatus(); ChannelContainer *cc = new ChannelContainer(this); @@ -128,7 +130,7 @@ void Channel::JoinUser(User *user) bool update_ts = false; if (this->ci && this->ci->HasFlag(CI_PERSIST) && this->creation_time > this->ci->time_registered) { - Alog(LOG_DEBUG) << "Changing TS of " << this->name << " from " << this->creation_time << " to " << this->ci->time_registered; + Log(LOG_DEBUG) << "Changing TS of " << this->name << " from " << this->creation_time << " to " << this->ci->time_registered; this->creation_time = this->ci->time_registered; update_ts = true; } @@ -188,13 +190,13 @@ void Channel::DeleteUser(User *user) if (this->ci) update_cs_lastseen(user, this->ci); - Alog(LOG_DEBUG) << user->nick << " leaves " << this->name; + Log(user, this, "leaves"); CUserList::iterator cit, cit_end = this->users.end(); for (cit = this->users.begin(); (*cit)->user != user && cit != cit_end; ++cit); if (cit == cit_end) { - Alog(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant user " << user->nick << " from channel " << this->name; + Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant user " << user->nick << " from channel " << this->name; return; } @@ -206,7 +208,7 @@ void Channel::DeleteUser(User *user) for (uit = user->chans.begin(); (*uit)->chan != this && uit != uit_end; ++uit); if (uit == uit_end) { - Alog(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant channel " << this->name << " from " << user->nick << "'s channel list"; + Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant channel " << this->name << " from " << user->nick << "'s channel list"; return; } @@ -310,7 +312,7 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool { if (param.empty()) { - Alog() << "Channel::SetModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; + Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; return; } @@ -321,11 +323,11 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool if (!u) { - Alog(LOG_DEBUG) << "MODE " << this->name << " +" << cm->ModeChar << " for nonexistant user " << param; + Log() << "MODE " << this->name << " +" << cm->ModeChar << " for nonexistant user " << param; return; } - Alog(LOG_DEBUG) << "Setting +" << cm->ModeChar << " on " << this->name << " for " << u->nick; + Log(LOG_DEBUG) << "Setting +" << cm->ModeChar << " on " << this->name << " for " << u->nick; /* Set the status on the user */ ChannelContainer *cc = u->FindChannel(this); @@ -342,7 +344,7 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool { if (param.empty()) { - Alog() << "Channel::SetModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; + Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; return; } @@ -357,7 +359,7 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool { if (cm->Type != MODE_PARAM) { - Alog() << "Channel::SetModeInternal() mode " << cm->ModeChar << " for " << this->name << " with a paramater, but its not a param mode"; + Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " for " << this->name << " with a paramater, but its not a param mode"; return; } @@ -437,7 +439,7 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo { if (param.empty()) { - Alog() << "Channel::RemoveModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; + Log() << "Channel::RemoveModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; return; } @@ -449,17 +451,17 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo /* Reset modes on bots if we're supposed to */ if (bi) { - if (std::find(BotModes.begin(), BotModes.end(), cm) != BotModes.end()) + if (std::find(Config->BotModeList.begin(), Config->BotModeList.end(), cm) != Config->BotModeList.end()) this->SetMode(bi, cm, bi->nick); } if (!u) { - Alog() << "Channel::RemoveModeInternal() MODE " << this->name << "-" << cm->ModeChar << " for nonexistant user " << param; + Log() << "Channel::RemoveModeInternal() MODE " << this->name << "-" << cm->ModeChar << " for nonexistant user " << param; return; } - Alog(LOG_DEBUG) << "Setting -" << cm->ModeChar << " on " << this->name << " for " << u->nick; + Log(LOG_DEBUG) << "Setting -" << cm->ModeChar << " on " << this->name << " for " << u->nick; /* Remove the status on the user */ ChannelContainer *cc = u->FindChannel(this); @@ -473,7 +475,7 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo { if (param.empty()) { - Alog() << "Channel::RemoveModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; + Log() << "Channel::RemoveModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; return; } @@ -904,11 +906,11 @@ void ChanSetInternalModes(Channel *c, int ac, const char **av) c->RemoveModeInternal(cm, av[j]); } else - Alog() << "warning: ChanSetInternalModes() recieved more modes requiring params than params, modes: " << merge_args(ac, av) << ", ac: " << ac << ", j: " << j; + Log() << "warning: ChanSetInternalModes() recieved more modes requiring params than params, modes: " << merge_args(ac, av) << ", ac: " << ac << ", j: " << j; } if (j + k + 1 < ac) - Alog() << "warning: ChanSetInternalModes() recieved more params than modes requiring them, modes: " << merge_args(ac, av) << ", ac: " << ac << ", j: " << j << " k: " << k; + Log() << "warning: ChanSetInternalModes() recieved more params than modes requiring them, modes: " << merge_args(ac, av) << ", ac: " << ac << ", j: " << j << " k: " << k; } /** Kick a user from a channel internally @@ -924,11 +926,11 @@ void Channel::KickInternal(const Anope::string &source, const Anope::string &nic User *user = bi ? bi : finduser(nick); if (!user) { - Alog(LOG_DEBUG) << "Channel::KickInternal got a nonexistent user " << nick << " on " << this->name << ": " << reason; + Log() << "Channel::KickInternal got a nonexistent user " << nick << " on " << this->name << ": " << reason; return; } - Alog(LOG_DEBUG) << "Channel::KickInternal kicking " << user->nick << " from " << this->name; + Log(user, this, "kick") << "by " << source << " (" << reason << ")"; Anope::string chname = this->name; @@ -938,7 +940,7 @@ void Channel::KickInternal(const Anope::string &source, const Anope::string &nic this->DeleteUser(user); } else - Alog(LOG_DEBUG) << "Channel::KickInternal got kick for user " << user->nick << " who isn't on channel " << this->name << " ?"; + Log() << "Channel::KickInternal got kick for user " << user->nick << " who isn't on channel " << this->name << " ?"; /* Bots get rejoined */ if (bi) @@ -1113,7 +1115,7 @@ void do_join(const Anope::string &source, int ac, const char **av) user = finduser(source); if (!user) { - Alog(LOG_DEBUG) << "JOIN from nonexistent user " << source << ": " << merge_args(ac, av); + Log() << "JOIN from nonexistent user " << source << ": " << merge_args(ac, av); return; } @@ -1150,7 +1152,7 @@ void do_join(const Anope::string &source, int ac, const char **av) /* Their time is older, we lose */ if (chan->creation_time > ts) { - Alog(LOG_DEBUG) << "Recieved an older TS " << chan->name << " in JOIN, changing from " << chan->creation_time << " to " << ts; + Log(LOG_DEBUG) << "Recieved an older TS " << chan->name << " in JOIN, changing from " << chan->creation_time << " to " << ts; chan->creation_time = ts; chan->Reset(); @@ -1188,7 +1190,7 @@ void do_kick(const Anope::string &source, int ac, const char **av) Channel *c = findchan(av[0]); if (!c) { - Alog(LOG_DEBUG) << "Recieved kick for nonexistant channel " << av[0]; + Log() << "Recieved kick for nonexistant channel " << av[0]; return; } @@ -1210,7 +1212,7 @@ void do_part(const Anope::string &source, int ac, const char **av) User *user = finduser(source); if (!user) { - Alog(LOG_DEBUG) << "PART from nonexistent user " << source << ": " << merge_args(ac, av); + Log() << "PART from nonexistent user " << source << ": " << merge_args(ac, av); return; } @@ -1221,17 +1223,17 @@ void do_part(const Anope::string &source, int ac, const char **av) Channel *c = findchan(buf); if (!c) - Alog(LOG_DEBUG) << "Recieved PART from " << user->nick << " for nonexistant channel " << buf; - - if (user->FindChannel(c)) + Log() << "Recieved PART from " << user->nick << " for nonexistant channel " << buf; + else if (user->FindChannel(c)) { + Log(user, c, "part") << "Reason: " << (av[1] ? av[1] : "No reason"); FOREACH_MOD(I_OnPrePartChannel, OnPrePartChannel(user, c)); Anope::string ChannelName = c->name; c->DeleteUser(user); FOREACH_MOD(I_OnPartChannel, OnPartChannel(user, findchan(ChannelName), ChannelName, av[1] ? av[1] : "")); } else - Alog(LOG_DEBUG) << "Recieved PART from " << user->nick << " for " << c->name << ", but " << user->nick << " isn't in " << c->name << "?"; + Log() << "Recieved PART from " << user->nick << " for " << c->name << ", but " << user->nick << " isn't in " << c->name << "?"; } } @@ -1264,7 +1266,7 @@ void do_cmode(const Anope::string &source, int ac, const char **av) ++av; } else - Alog() << "TSMODE enabled but MODE has no valid TS"; + Log() << "TSMODE enabled but MODE has no valid TS"; } /* :42XAAAAAO TMODE 1106409026 #ircops +b *!*@*.aol.com */ @@ -1281,7 +1283,7 @@ void do_cmode(const Anope::string &source, int ac, const char **av) { ci = cs_findchan(av[0]); if (!ci || ci->HasFlag(CI_FORBIDDEN)) - Alog(LOG_DEBUG) << "MODE " << merge_args(ac - 1, av + 1) << " for nonexistant channel " << av[0]; + Log(LOG_DEBUG) << "MODE " << merge_args(ac - 1, av + 1) << " for nonexistant channel " << av[0]; } return; } @@ -1298,6 +1300,10 @@ void do_cmode(const Anope::string &source, int ac, const char **av) --ac; ++av; + + User *u = finduser(source); + if (u) + Log(u, c, "mode") << merge_args(ac, av); ChanSetInternalModes(c, ac, av); } @@ -1313,7 +1319,7 @@ void do_topic(const Anope::string &source, int ac, const char **av) if (!c) { - Alog(LOG_DEBUG) << "TOPIC " << merge_args(ac - 1, av + 1) << " for nonexistent channel " << av[0]; + Log() << "TOPIC " << merge_args(ac - 1, av + 1) << " for nonexistent channel " << av[0]; return; } @@ -1380,7 +1386,7 @@ void chan_set_correct_modes(User *user, Channel *c, int give_modes) if (ci->HasFlag(CI_FORBIDDEN) || c->name[0] == '+') return; - Alog(LOG_DEBUG) << "Setting correct user modes for " << user->nick << " on " << c->name << " (" << (give_modes ? "" : "not ") << "giving modes)"; + Log(LOG_DEBUG) << "Setting correct user modes for " << user->nick << " on " << c->name << " (" << (give_modes ? "" : "not ") << "giving modes)"; if (give_modes && !get_ignore(user->nick) && (!user->Account() || user->Account()->HasFlag(NI_AUTOOP))) { diff --git a/src/chanserv.cpp b/src/chanserv.cpp index c80de4c75..b6df9d8cd 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -252,7 +252,7 @@ void check_modes(Channel *c) if (!c) { - Alog(LOG_DEBUG) << "check_modes called with NULL values"; + Log() << "check_modes called with NULL values"; return; } @@ -263,7 +263,7 @@ void check_modes(Channel *c) if (c->server_modecount >= 3 && c->chanserv_modecount >= 3) { ircdproto->SendGlobops(NULL, "Warning: unable to set modes on channel %s. Are your servers' U:lines configured correctly?", c->name.c_str()); - Alog() << Config->s_ChanServ << ": Bouncy modes on channel " << c->name; + Log() << "Bouncy modes on channel " << c->name; c->bouncy_modes = 1; return; } @@ -497,7 +497,7 @@ int check_topiclock(Channel *c, time_t topic_time) if (!c) { - Alog(LOG_DEBUG) << "check_topiclock called with NULL values"; + Log() << "check_topiclock called with NULL values"; return 0; } @@ -572,7 +572,7 @@ void expire_chans() continue; Anope::string chname = ci->name; - Alog() << "Expiring channel " << ci->name << " (founder: " << (ci->founder ? ci->founder->display : "(none)") << " )"; + Log(LOG_NORMAL, "chanserv/expire") << "Expiring channel " << ci->name << " (founder: " << (ci->founder ? ci->founder->display : "(none)") << " )"; delete ci; FOREACH_MOD(I_OnChanExpire, OnChanExpire(chname)); } @@ -599,13 +599,13 @@ void cs_remove_nick(const NickCore *nc) NickCore *nc2 = ci->successor; if (!nc2->IsServicesOper() && Config->CSMaxReg && nc2->channelcount >= Config->CSMaxReg) { - Alog() << Config->s_ChanServ << ": Successor (" << nc2->display << " ) of " << ci->name << " owns too many channels, deleting channel", + Log(LOG_NORMAL, "chanserv/expire") << "Successor (" << nc2->display << " ) of " << ci->name << " owns too many channels, deleting channel", delete ci; continue; } else { - Alog() << Config->s_ChanServ << ": Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to successor " << nc2->display; + Log(LOG_NORMAL, "chanserv/expire") << "Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to successor " << nc2->display; ci->founder = nc2; ci->successor = NULL; ++nc2->channelcount; @@ -613,7 +613,7 @@ void cs_remove_nick(const NickCore *nc) } else { - Alog() << Config->s_ChanServ << ": Deleting channel " << ci->name << "owned by deleted nick " << nc->display; + Log(LOG_NORMAL, "chanserv/expire") << "Deleting channel " << ci->name << "owned by deleted nick " << nc->display; if (ModeManager::FindChannelModeByName(CMODE_REGISTERED)) { @@ -712,7 +712,7 @@ void reset_levels(ChannelInfo *ci) if (!ci) { - Alog(LOG_DEBUG) << "reset_levels() called with NULL values"; + Log() << "reset_levels() called with NULL values"; return; } diff --git a/src/commands.cpp b/src/commands.cpp index 26ca76e65..bbf2a5233 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -58,7 +58,7 @@ void mod_run_cmd(BotInfo *bi, User *u, Command *c, const Anope::string &command, if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified()) { notice_lang(bi->nick, u, NICK_IDENTIFY_REQUIRED, Config->s_NickServ.c_str()); - Alog() << "Access denied for unregistered user " << u->nick << " with service " << bi->nick << " and command " << command; + Log(LOG_COMMAND, "denied", bi) << "Access denied for unregistered user " << u->GetMask() << " with command " << command; return; } @@ -103,13 +103,13 @@ void mod_run_cmd(BotInfo *bi, User *u, Command *c, const Anope::string &command, if (ci->HasFlag(CI_FORBIDDEN) && !c->HasFlag(CFLAG_ALLOW_FORBIDDEN)) { notice_lang(bi->nick, u, CHAN_X_FORBIDDEN, ci->name.c_str()); - Alog() << "Access denied for user " << u->nick << " with service " << bi->nick << " and command " << command << " because of FORBIDDEN channel " << ci->name; + Log(LOG_COMMAND, "denied", bi) << "Access denied for user " << u->GetMask() << " with command " << command << " because of FORBIDDEN channel " << ci->name; return; } else if (ci->HasFlag(CI_SUSPENDED) && !c->HasFlag(CFLAG_ALLOW_SUSPENDED)) { notice_lang(bi->nick, u, CHAN_X_FORBIDDEN, ci->name.c_str()); - Alog() << "Access denied for user " << u->nick << " with service " << bi->nick <<" and command " << command << " because of SUSPENDED channel " << ci->name; + Log(LOG_COMMAND, "denied", bi) << "Access denied for user " << u->GetMask() << " with command " << command << " because of SUSPENDED channel " << ci->name; return; } } @@ -131,7 +131,7 @@ void mod_run_cmd(BotInfo *bi, User *u, Command *c, const Anope::string &command, if (!c->permission.empty() && !u->Account()->HasCommand(c->permission)) { notice_lang(bi->nick, u, ACCESS_DENIED); - Alog() << "Access denied for user " << u->nick << " with service " << bi->nick << " and command " << command; + Log(LOG_COMMAND, "denied", bi) << "Access denied for user " << u->GetMask() << " with command " << command; return; } diff --git a/src/config.cpp b/src/config.cpp index 0dfc9702e..48563b0c5 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -82,7 +82,7 @@ ServerConfig::ServerConfig() : errstr(""), config_data() else if (option.equals_ci("msg")) { if (!this->UsePrivmsg) - Alog() << "msg in can only be used when UsePrivmsg is set"; + Log() << "msg in can only be used when UsePrivmsg is set"; else this->NSDefFlags.SetFlag(NI_MSG); } @@ -262,7 +262,7 @@ ServerConfig::ServerConfig() : errstr(""), config_data() /* Check the user keys */ if (this->UserKey1 == this->UserKey2 || this->UserKey1 == this->UserKey3 || this->UserKey3 == this->UserKey2) - Alog() << "Every UserKey must be different. It's for YOUR safety! Remember that!"; + Log() << "Every UserKey must be different. It's for YOUR safety! Remember that!"; /** * Check all DEFCON dependiencies... @@ -349,10 +349,6 @@ ServerConfig::ServerConfig() : errstr(""), config_data() } SetDefaultMLock(this); - - /* Disable the log channel if its defined in the conf, but not enabled */ - if (this->LogChannel.empty() && LogChan) - LogChan = false; } bool ServerConfig::CheckOnce(const Anope::string &tag) @@ -614,13 +610,13 @@ bool ValidateNickLen(ServerConfig *, const Anope::string &, const Anope::string int nicklen = data.GetInteger(); if (!nicklen) { - Alog() << "You have not defined the directive. It is strongly"; - Alog() << "adviced that you do configure this correctly in your services.conf"; + Log() << "You have not defined the directive. It is strongly"; + Log() << "adviced that you do configure this correctly in your services.conf"; data.Set(31); } else if (nicklen < 1) { - Alog() << " has an invalid value; setting to 31"; + Log() << " has an invalid value; setting to 31"; data.Set(31); } return true; @@ -645,7 +641,7 @@ bool ValidateGlobalOnCycle(ServerConfig *config, const Anope::string &tag, const { if (data.GetValue().empty()) { - Alog() << "<" << tag << ":" << value << "> was undefined, disabling "; + Log() << "<" << tag << ":" << value << "> was undefined, disabling "; config->GlobalOnCycle = false; } } @@ -733,7 +729,7 @@ static bool DoOperType(ServerConfig *config, const Anope::string &, const Anope: { if ((*it)->GetName().equals_ci(tok)) { - Alog() << "Inheriting commands and privs from " << (*it)->GetName() << " to " << ot->GetName(); + Log() << "Inheriting commands and privs from " << (*it)->GetName() << " to " << ot->GetName(); ot->Inherits(*it); break; } @@ -797,7 +793,7 @@ static bool DoneOpers(ServerConfig *config, const Anope::string &) OperType *ot = *tit; if (ot->GetName().equals_ci(type)) { - Alog() << "Tied oper " << na->nc->display << " to type " << type; + Log() << "Tied oper " << na->nc->display << " to type " << type; na->nc->ot = ot; } } @@ -833,6 +829,91 @@ bool DoneModules(ServerConfig *, const Anope::string &) return true; } +bool InitLogs(ServerConfig *config, const Anope::string &) +{ + for (unsigned i = 0; i < config->LogInfos.size(); ++i) + { + LogInfo *l = config->LogInfos[i]; + + for (std::list::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) + { + const Anope::string &target = *sit; + + if (target[0] == '#') + { + Channel *c = findchan(target); + if (c && c->HasFlag(CH_LOGCHAN)) + { + for (CUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit) + { + UserContainer *uc = *cit; + BotInfo *bi = findbot(uc->user->nick); + + if (bi && bi->HasFlag(BI_CORE)) + { + bi->Part(c, "Reloading"); + } + } + + c->UnsetFlag(CH_PERSIST); + c->UnsetFlag(CH_LOGCHAN); + if (c->users.empty()) + delete c; + } + } + } + + delete config->LogInfos[i]; + } + config->LogInfos.clear(); + + return true; +} + +bool DoLogs(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) +{ + //{"target", "source", "logage", "admin", "override", "commands", "servers", "channels", "users", "normal", "rawio", "debug"}, + Anope::string targets = values[0].GetValue(); + ValueItem vi(targets); + if (!ValidateNotEmpty(config, "log", "target", vi)) + throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); + + Anope::string source = values[1].GetValue(); + int logage = values[2].GetInteger(); + Anope::string admin = values[3].GetValue(); + Anope::string override = values[4].GetValue(); + Anope::string commands = values[5].GetValue(); + Anope::string servers = values[6].GetValue(); + Anope::string channels = values[7].GetValue(); + Anope::string users = values[8].GetValue(); + bool normal = values[9].GetBool(); + bool rawio = values[10].GetBool(); + bool ldebug = values[11].GetBool(); + + LogInfo *l = new LogInfo(logage, normal, rawio, ldebug); + l->Targets = BuildStringList(targets); + l->Sources = BuildStringList(source); + l->Admin = BuildStringList(admin); + l->Override = BuildStringList(override); + l->Commands = BuildStringList(commands); + l->Servers = BuildStringList(servers); + l->Channels = BuildStringList(channels); + l->Users = BuildStringList(users); + + config->LogInfos.push_back(l); + + return true; +} + +bool DoneLogs(ServerConfig *config, const Anope::string &) +{ + InitLogChannels(config); + + Log() << "Loaded " << config->LogInfos.size() << " log blocks"; + + return true; +} + void ServerConfig::Read() { errstr.clear(); @@ -902,8 +983,6 @@ void ServerConfig::Read() {"serverinfo", "hostname", "", new ValueContainerString(&this->ServiceHost), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"serverinfo", "pid", "services.pid", new ValueContainerString(&this->PIDFilename), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"serverinfo", "motd", "services.motd", new ValueContainerString(&this->MOTDFilename), DT_STRING, ValidateNotEmpty}, - {"networkinfo", "logchannel", "", new ValueContainerString(&this->LogChannel), DT_STRING, NoValidation}, - {"networkinfo", "logbot", "no", new ValueContainerBool(&this->LogBot), DT_BOOLEAN, NoValidation}, {"networkinfo", "networkname", "", new ValueContainerString(&this->NetworkName), DT_STRING, ValidateNotEmpty}, {"networkinfo", "nicklen", "0", new ValueContainerUInt(&this->NickLen), DT_UINTEGER | DT_NORELOAD, ValidateNickLen}, {"networkinfo", "userlen", "10", new ValueContainerUInt(&this->UserLen), DT_UINTEGER | DT_NORELOAD, NoValidation}, @@ -930,7 +1009,6 @@ void ServerConfig::Read() {"options", "useprivmsg", "no", new ValueContainerBool(&this->UsePrivmsg), DT_BOOLEAN, NoValidation}, {"options", "usestrictprivmsg", "no", new ValueContainerBool(&this->UseStrictPrivMsg), DT_BOOLEAN, NoValidation}, {"options", "dumpcore", "yes", new ValueContainerBool(&this->DumpCore), DT_BOOLEAN | DT_NORELOAD, NoValidation}, - {"options", "logusers", "no", new ValueContainerBool(&this->LogUsers), DT_BOOLEAN, NoValidation}, {"options", "hidestatso", "no", new ValueContainerBool(&this->HideStatsO), DT_BOOLEAN, NoValidation}, {"options", "globaloncycle", "no", new ValueContainerBool(&this->GlobalOnCycle), DT_BOOLEAN, NoValidation}, {"options", "globaloncycledown", "", new ValueContainerString(&this->GlobalOnCycleMessage), DT_STRING, ValidateGlobalOnCycle}, @@ -940,7 +1018,6 @@ void ServerConfig::Read() {"options", "restrictopernicks", "no", new ValueContainerBool(&this->RestrictOperNicks), DT_BOOLEAN, NoValidation}, {"options", "newscount", "3", new ValueContainerUInt(&this->NewsCount), DT_UINTEGER, NoValidation}, {"options", "ulineservers", "", new ValueContainerString(&UlineServers), DT_STRING, NoValidation}, - {"options", "enablelogchannel", "no", new ValueContainerBool(&LogChan), DT_BOOLEAN, NoValidation}, {"options", "mlock", "+nrt", new ValueContainerString(&this->MLock), DT_STRING, NoValidation}, {"options", "botmodes", "", new ValueContainerString(&this->BotModes), DT_STRING, NoValidation}, {"options", "maxretries", "10", new ValueContainerUInt(&this->MaxRetries), DT_UINTEGER, NoValidation}, @@ -1017,7 +1094,6 @@ void ServerConfig::Read() {"operserv", "globaldescription", "Global Noticer", new ValueContainerString(&this->desc_GlobalNoticer), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"operserv", "modules", "", new ValueContainerString(&OperCoreModules), DT_STRING, NoValidation}, {"operserv", "superadmin", "no", new ValueContainerBool(&this->SuperAdmin), DT_BOOLEAN, NoValidation}, - {"operserv", "logmaxusers", "no", new ValueContainerBool(&this->LogMaxUsers), DT_BOOLEAN, NoValidation}, {"operserv", "autokillexpiry", "0", new ValueContainerTime(&this->AutokillExpiry), DT_TIME, ValidateNotZero}, {"operserv", "chankillexpiry", "0", new ValueContainerTime(&this->ChankillExpiry), DT_TIME, ValidateNotZero}, {"operserv", "snlineexpiry", "0", new ValueContainerTime(&this->SNLineExpiry), DT_TIME, ValidateNotZero}, @@ -1067,6 +1143,11 @@ void ServerConfig::Read() {"", ""}, {DT_CHARPTR}, InitModules, DoModule, DoneModules}, + {"log", + {"target", "source", "logage", "admin", "override", "commands", "servers", "channels", "users", "normal", "rawio", "debug", ""}, + {"", "", "7", "", "", "", "", "", "", "", "no", "no", ""}, + {DT_STRING, DT_STRING, DT_INTEGER, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_BOOLEAN, DT_BOOLEAN, DT_BOOLEAN}, + InitLogs, DoLogs, DoneLogs}, {"opertype", {"name", "inherits", "commands", "privs", ""}, {"", "", "", "", ""}, @@ -1339,10 +1420,10 @@ void ServerConfig::Read() } throw ConfigException(ce); } - Alog(LOG_DEBUG) << "End config"; + Log(LOG_DEBUG) << "End config"; for (int Index = 0; !Once[Index].empty(); ++Index) CheckOnce(Once[Index]); - Alog() << "Done reading configuration file."; + Log() << "Done reading configuration file."; } bool ServerConfig::LoadConf(ConfigDataHash &target, const Anope::string &filename) @@ -1358,7 +1439,7 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const Anope::string &filenam errstr << "File " << filename << " could not be opened." << std::endl; return false; } - Alog(LOG_DEBUG) << "Start to read conf " << filename; + Log(LOG_DEBUG) << "Start to read conf " << filename; // Start reading characters... while (getline(conf, line.str())) { @@ -1462,7 +1543,7 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const Anope::string &filenam return false; } // this is the same as the below section for testing if itemname is non-empty after the loop, but done inside it to allow the above construct - Alog(LOG_DEBUG) << "ln "<< linenumber << " EOL: s='" << section << "' '" << itemname << "' set to '" << wordbuffer << "'"; + Log(LOG_DEBUG) << "ln "<< linenumber << " EOL: s='" << section << "' '" << itemname << "' set to '" << wordbuffer << "'"; sectiondata.push_back(KeyVal(itemname, wordbuffer)); wordbuffer.clear(); itemname.clear(); @@ -1504,7 +1585,7 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const Anope::string &filenam errstr << "Item without value: " << filename << ":" << linenumber << std::endl; return false; } - Alog(LOG_DEBUG) << "ln " << linenumber << " EOL: s='" << section << "' '" << itemname << "' set to '" << wordbuffer << "'"; + Log(LOG_DEBUG) << "ln " << linenumber << " EOL: s='" << section << "' '" << itemname << "' set to '" << wordbuffer << "'"; sectiondata.push_back(KeyVal(itemname, wordbuffer)); wordbuffer.clear(); itemname.clear(); @@ -1555,7 +1636,7 @@ bool ServerConfig::ConfValue(ConfigDataHash &target, const Anope::string &tag, c { if (!allow_linefeeds && j->second.find('\n') != Anope::string::npos) { - Alog(LOG_DEBUG) << "Value of <" << tag << ":" << var << "> contains a linefeed, and linefeeds in this value are not permitted -- stripped to spaces."; + Log(LOG_DEBUG) << "Value of <" << tag << ":" << var << "> contains a linefeed, and linefeeds in this value are not permitted -- stripped to spaces."; j->second.replace_all_cs("\n", " "); } else diff --git a/src/encrypt.cpp b/src/encrypt.cpp index 0121c0c4a..57c120301 100644 --- a/src/encrypt.cpp +++ b/src/encrypt.cpp @@ -38,7 +38,7 @@ int enc_decrypt(const Anope::string &src, Anope::string &dest) size_t pos = src.find(':'); if (pos == Anope::string::npos) { - Alog() << "Error: enc_decrypt() called with invalid password string (" << src << ")"; + Log() << "Error: enc_decrypt() called with invalid password string (" << src << ")"; return -1; } Anope::string hashm(src.begin(), src.begin() + pos); @@ -62,7 +62,7 @@ int enc_check_password(Anope::string &plaintext, Anope::string &password) size_t pos = password.find(':'); if (pos == Anope::string::npos) { - Alog() << "Error: enc_check_password() called with invalid password string (" << password << ")"; + Log() << "Error: enc_check_password() called with invalid password string (" << password << ")"; return 0; } Anope::string hashm(password.begin(), password.begin() + pos); diff --git a/src/init.cpp b/src/init.cpp index d3476a490..5b6d22445 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -25,7 +25,7 @@ void introduce_user(const Anope::string &user) time_t now = time(NULL); static time_t lasttime = now - 4; if (lasttime >= now - 3) - fatal("introduce_user loop detected"); + throw FatalException("introduce_user loop detected"); lasttime = now; if (user.empty()) @@ -54,6 +54,8 @@ void introduce_user(const Anope::string &user) /* Load MLock from the database now that we know what modes exist */ for (registered_channel_map::iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it) it->second->LoadMLock(); + /* Setup log chanels */ + InitLogChannels(Config); } } @@ -81,7 +83,7 @@ static int set_group() } else { - Alog() << "Unknown run group '" << RUNGROUP << "'"; + Log() << "Unknown run group '" << RUNGROUP << "'"; return -1; } #endif @@ -182,7 +184,7 @@ static void write_pidfile() atexit(remove_pidfile); } else - log_perror("Warning: cannot write to PID file %s", Config->PIDFilename.c_str()); + throw FatalException("Can not write to PID file " + Config->PIDFilename); } /*************************************************************************/ @@ -191,7 +193,7 @@ static void write_pidfile() int openlog_failed = 0, openlog_errno = 0; -int init_primary(int ac, char **av) +void Init(int ac, char **av) { int started_from_term = isatty(0) && isatty(1) && isatty(2); @@ -200,38 +202,38 @@ int init_primary(int ac, char **av) umask(DEFUMASK); #endif if (set_group() < 0) - return -1; + throw FatalException("set_group() fail"); /* Parse command line arguments */ ParseCommandLineArguments(ac, av); if (GetCommandLineArgument("version", 'v')) { - Alog(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::Build(); - return -1; + Log(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::Build(); + throw FatalException(); } if (GetCommandLineArgument("help", 'h')) { - Alog(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::Build(); - Alog(LOG_TERMINAL) << "Anope IRC Services (http://www.anope.org)"; - Alog(LOG_TERMINAL) << "Usage ./" << SERVICES_BIN << " [options] ..."; - Alog(LOG_TERMINAL) << "-c, --config=filename.conf"; - Alog(LOG_TERMINAL) << "-d, --debug[=level]"; - Alog(LOG_TERMINAL) << " --dir=services_directory"; - Alog(LOG_TERMINAL) << "-h, --help"; - Alog(LOG_TERMINAL) << " --log=log_filename"; - Alog(LOG_TERMINAL) << "-e, --noexpire"; - Alog(LOG_TERMINAL) << "-n, --nofork"; - Alog(LOG_TERMINAL) << " --nothird"; - Alog(LOG_TERMINAL) << " --protocoldebug"; - Alog(LOG_TERMINAL) << "-r, --readonly"; - Alog(LOG_TERMINAL) << "-s, --support"; - Alog(LOG_TERMINAL) << "-v, --version"; - Alog(LOG_TERMINAL) << ""; - Alog(LOG_TERMINAL) << "Further support is available from http://www.anope.org"; - Alog(LOG_TERMINAL) << "Or visit us on IRC at irc.anope.org #anope"; - return -1; + Log(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::Build(); + Log(LOG_TERMINAL) << "Anope IRC Services (http://www.anope.org)"; + Log(LOG_TERMINAL) << "Usage ./" << SERVICES_BIN << " [options] ..."; + Log(LOG_TERMINAL) << "-c, --config=filename.conf"; + Log(LOG_TERMINAL) << "-d, --debug[=level]"; + Log(LOG_TERMINAL) << " --dir=services_directory"; + Log(LOG_TERMINAL) << "-h, --help"; + Log(LOG_TERMINAL) << " --log=log_filename"; + Log(LOG_TERMINAL) << "-e, --noexpire"; + Log(LOG_TERMINAL) << "-n, --nofork"; + Log(LOG_TERMINAL) << " --nothird"; + Log(LOG_TERMINAL) << " --protocoldebug"; + Log(LOG_TERMINAL) << "-r, --readonly"; + Log(LOG_TERMINAL) << "-s, --support"; + Log(LOG_TERMINAL) << "-v, --version"; + Log(LOG_TERMINAL) << ""; + Log(LOG_TERMINAL) << "Further support is available from http://www.anope.org"; + Log(LOG_TERMINAL) << "Or visit us on IRC at irc.anope.org #anope"; + throw FatalException(); } if (GetCommandLineArgument("nofork", 'n')) @@ -264,10 +266,7 @@ int init_primary(int ac, char **av) if (level > 0) debug = level; else - { - Alog(LOG_TERMINAL) << "Invalid option given to --debug"; - return -1; - } + throw FatalException("Invalid option given to --debug"); } else ++debug; @@ -276,49 +275,36 @@ int init_primary(int ac, char **av) if (GetCommandLineArgument("config", 'c', Arg)) { if (Arg.empty()) - { - Alog(LOG_TERMINAL) << "The --config option requires a file name"; - return -1; - } + throw FatalException("The --config option requires a file name"); services_conf = Arg; } if (GetCommandLineArgument("dir", 0, Arg)) { if (Arg.empty()) - { - Alog(LOG_TERMINAL) << "The --dir option requires a directory name"; - return -1; - } + throw FatalException("The --dir option requires a directory name"); services_dir = Arg; } if (GetCommandLineArgument("log", 0, Arg)) { if (Arg.empty()) - { - Alog(LOG_TERMINAL) << "The --log option requires a file name"; - return -1; - } + throw FatalException("The --log option requires a file name"); log_filename = Arg; } /* Chdir to Services data directory. */ if (chdir(services_dir.c_str()) < 0) { - fprintf(stderr, "chdir(%s): %s\n", services_dir.c_str(), strerror(errno)); - return -1; + throw FatalException("Unable to chdir to " + services_dir + ": " + Anope::string(strerror(errno))); } - /* Open logfile, and complain if we didn't. */ - if (open_log() < 0) - { - openlog_errno = errno; - if (started_from_term) - fprintf(stderr, "Warning: unable to open log file %s: %s\n", log_filename.c_str(), strerror(errno)); - else - openlog_failed = 1; - } + Log(LOG_TERMINAL) << "Anope " << Anope::Version() << ", " << Anope::Build(); +#ifdef _WIN32 + Log(LOG_TERMINAL) << "Using configuration file " << services_dir << "\\" << services_conf; +#else + Log(LOG_TERMINAL) << "Using configuration file " << services_dir << "/" << services_conf; +#endif /* Read configuration file; exit if there are problems. */ try @@ -327,17 +313,17 @@ int init_primary(int ac, char **av) } catch (const ConfigException &ex) { - Alog(LOG_TERMINAL) << ex.GetReason(); - Alog(LOG_TERMINAL) << "*** Support resources: Read through the services.conf self-contained"; - Alog(LOG_TERMINAL) << "*** documentation. Read the documentation files found in the 'docs'"; - Alog(LOG_TERMINAL) << "*** folder. Visit our portal located at http://www.anope.org/. Join"; - Alog(LOG_TERMINAL) << "*** our support channel on /server irc.anope.org channel #anope."; - return -1; + Log(LOG_TERMINAL) << ex.GetReason(); + Log(LOG_TERMINAL) << "*** Support resources: Read through the services.conf self-contained"; + Log(LOG_TERMINAL) << "*** documentation. Read the documentation files found in the 'docs'"; + Log(LOG_TERMINAL) << "*** folder. Visit our portal located at http://www.anope.org/. Join"; + Log(LOG_TERMINAL) << "*** our support channel on /server irc.anope.org channel #anope."; + throw FatalException("Configuration file failed to validate"); } /* Add IRCD Protocol Module; exit if there are errors */ if (protocol_module_init()) - return -1; + throw FatalException("Unable to load protocol module"); /* Create me */ Me = new Server(NULL, Config->ServerName, 0, Config->ServerDesc, Config->Numeric); @@ -377,19 +363,7 @@ int init_primary(int ac, char **av) /* Load the socket engine */ if (ModuleManager::LoadModule(Config->SocketEngine, NULL)) - { - Alog(LOG_TERMINAL) << "Unable to load socket engine " << Config->SocketEngine; - return -1; - } - - return 0; -} - -int init_secondary(int ac, char **av) -{ -#ifndef _WIN32 - int started_from_term = isatty(0) && isatty(1) && isatty(2); -#endif + throw FatalException("Unable to load socket engine " + Config->SocketEngine); /* Add Core MSG handles */ moduleAddMsgs(); @@ -399,15 +373,13 @@ int init_secondary(int ac, char **av) { int i; if ((i = fork()) < 0) - { - perror("fork()"); - return -1; - } + throw FatalException("Unable to fork"); else if (i != 0) { - Alog(LOG_TERMINAL) << "PID " << i; + Log(LOG_TERMINAL) << "PID " << i; exit(0); } + if (started_from_term) { close(0); @@ -415,22 +387,15 @@ int init_secondary(int ac, char **av) close(2); } if (setpgid(0, 0) < 0) - { - perror("setpgid()"); - return -1; - } + throw FatalException("Unable to setpgid()"); } #else if (!SupportedWindowsVersion()) - { - Alog() << GetWindowsVersion() << " is not a supported version of Windows"; - - return -1; - } + throw FatalException(GetWindowsVersion() + " is not a supported version of Windows"); if (!nofork) { - Alog(LOG_TERMINAL) << "PID " << GetCurrentProcessId(); - Alog() << "Launching Anope into the background"; + Log(LOG_TERMINAL) << "PID " << GetCurrentProcessId(); + Log() << "Launching Anope into the background"; FreeConsole(); } #endif @@ -439,13 +404,9 @@ int init_secondary(int ac, char **av) write_pidfile(); /* Announce ourselves to the logfile. */ - Alog() << "Anope " << Anope::Version() << " (ircd protocol: " << version_protocol << ") starting up" << (debug || readonly ? " (options:" : "") << (debug ? " debug" : "") << (readonly ? " readonly" : "") << (debug || readonly ? ")" : ""); + Log() << "Anope " << Anope::Version() << " (ircd protocol: " << version_protocol << ") starting up" << (debug || readonly ? " (options:" : "") << (debug ? " debug" : "") << (readonly ? " readonly" : "") << (debug || readonly ? ")" : ""); start_time = time(NULL); - /* If in read-only mode, close the logfile again. */ - if (readonly) - close_log(); - /* Set signal handlers. Catch certain signals to let us do things or * panic as necessary, and ignore all others. */ @@ -457,7 +418,7 @@ int init_secondary(int ac, char **av) /* Initialize multi-language support */ lang_init(); - Alog(LOG_DEBUG) << "Loaded languages"; + Log(LOG_DEBUG) << "Loaded languages"; /* Initialize subservices */ ns_init(); @@ -476,14 +437,12 @@ int init_secondary(int ac, char **av) add_entropy_userkeys(); /* Load up databases */ - Alog() << "Loading databases..."; + Log() << "Loading databases..."; EventReturn MOD_RESULT; FOREACH_RESULT(I_OnLoadDatabase, OnLoadDatabase()); - Alog() << "Databases loaded"; + Log() << "Databases loaded"; FOREACH_MOD(I_OnPostLoadDatabases, OnPostLoadDatabases()); - - return 0; } /*************************************************************************/ diff --git a/src/language.cpp b/src/language.cpp index 32f96b461..9d629f599 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -65,7 +65,7 @@ static void load_lang(int index, const char *filename) FILE *f; int32 num, i; - Alog(LOG_DEBUG) << "Loading language " << index << " from file `languages/" << filename << "'"; + Log(LOG_DEBUG) << "Loading language " << index << " from file `languages/" << filename << "'"; snprintf(buf, sizeof(buf), "languages/%s", filename); #ifndef _WIN32 const char *mode = "r"; @@ -74,16 +74,15 @@ static void load_lang(int index, const char *filename) #endif if (!(f = fopen(buf, mode))) { - log_perror("Failed to load language %d (%s)", index, filename); - return; + throw CoreException("Failed to load language " + stringify(index) + " (" + stringify(filename) + ")"); } else if (read_int32(&num, f) < 0) { - Alog() << "Failed to read number of strings for language " << index << "(" << filename << ")"; + Log() << "Failed to read number of strings for language " << index << "(" << filename << ")"; return; } else if (num != NUM_STRINGS) - Alog() << "Warning: Bad number of strings (" << num << " , wanted " << NUM_STRINGS << ") for language " << index << " (" << filename << ")"; + Log() << "Warning: Bad number of strings (" << num << " , wanted " << NUM_STRINGS << ") for language " << index << " (" << filename << ")"; langtexts[index] = static_cast(scalloc(sizeof(char *), NUM_STRINGS)); if (num > NUM_STRINGS) num = NUM_STRINGS; @@ -93,7 +92,7 @@ static void load_lang(int index, const char *filename) fseek(f, i * 8 + 4, SEEK_SET); if (read_int32(&pos, f) < 0 || read_int32(&len, f) < 0) { - Alog() << "Failed to read entry " << i << " in language " << index << " (" << filename << ") TOC"; + Log() << "Failed to read entry " << i << " in language " << index << " (" << filename << ") TOC"; while (--i >= 0) { if (langtexts[index][i]) @@ -107,7 +106,7 @@ static void load_lang(int index, const char *filename) langtexts[index][i] = NULL; else if (len >= 65536) { - Alog() << "Entry " << i << " in language " << index << " (" << filename << ") is too long (over 64k) -- corrupt TOC?"; + Log() << "Entry " << i << " in language " << index << " (" << filename << ") is too long (over 64k) -- corrupt TOC?"; while (--i >= 0) { if (langtexts[index][i]) @@ -119,7 +118,7 @@ static void load_lang(int index, const char *filename) } else if (len < 0) { - Alog() << "Entry " << i << " in language " << index << " (" << filename << ") has negative length -- corrupt TOC?"; + Log() << "Entry " << i << " in language " << index << " (" << filename << ") has negative length -- corrupt TOC?"; while (--i >= 0) { if (langtexts[index][i]) @@ -135,7 +134,7 @@ static void load_lang(int index, const char *filename) fseek(f, pos, SEEK_SET); if (fread(langtexts[index][i], 1, len, f) != len) { - Alog() << "Failed to read string " << i << " in language " << index << "(" << filename << ")"; + Log() << "Failed to read string " << i << " in language " << index << "(" << filename << ")"; while (--i >= 0) { if (langtexts[index][i]) @@ -225,7 +224,7 @@ void lang_init() Config->NSDefLanguage = DEF_LANGUAGE; if (!langtexts[DEF_LANGUAGE]) - fatal("Unable to load default language"); + throw CoreException("Unable to load default language"); for (i = 0; i < NUM_LANGS; ++i) { if (!langtexts[i]) diff --git a/src/log.cpp b/src/log.cpp deleted file mode 100644 index 62fa29600..000000000 --- a/src/log.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* Logging routines. - * - * (C) 2003-2010 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "services.h" - -static FILE *logfile; - -static int curday = 0; - -/*************************************************************************/ - -static int get_logname(Anope::string &name, struct tm *tm) -{ - char timestamp[32]; - time_t t; - - if (!tm) - { - time(&t); - tm = localtime(&t); - } - - /* fix bug 577 */ - strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm); - name = Anope::string("logs/") + timestamp + "." + log_filename; - curday = tm->tm_yday; - - return 1; -} - -/*************************************************************************/ - -static void remove_log() -{ - time_t t; - struct tm tm; - - Anope::string name; - - if (!Config->KeepLogs) - return; - - time(&t); - t -= (60 * 60 * 24 * Config->KeepLogs); - tm = *localtime(&t); - - /* removed if from here cause get_logchan is always 1 */ - get_logname(name, &tm); - DeleteFile(name.c_str()); -} - -/*************************************************************************/ - -static void checkday() -{ - time_t t; - struct tm tm; - - time(&t); - tm = *localtime(&t); - - if (curday != tm.tm_yday) - { - close_log(); - remove_log(); - open_log(); - } -} - -/*************************************************************************/ - -/* Open the log file. Return -1 if the log file could not be opened, else - * return 0. */ - -int open_log() -{ - Anope::string name; - - if (logfile) - return 0; - - /* if removed again.. get_logname is always 1 */ - get_logname(name, NULL); - logfile = fopen(name.c_str(), "a"); - - if (logfile) - setbuf(logfile, NULL); - return logfile ? 0 : -1; -} - -/*************************************************************************/ - -/* Close the log file. */ - -void close_log() -{ - if (!logfile) - return; - fclose(logfile); - logfile = NULL; -} - -/*************************************************************************/ - -/* added cause this is used over and over in the code */ -Anope::string log_gettimestamp() -{ - time_t t; - struct tm tm; - char tbuf[256]; - - time(&t); - tm = *localtime(&t); -#if HAVE_GETTIMEOFDAY - if (debug) - { - char *s; - struct timeval tv; - gettimeofday(&tv, NULL); - strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S", &tm); - s = tbuf + strlen(tbuf); - s += snprintf(s, sizeof(tbuf) - (s - tbuf), ".%06d", static_cast(tv.tv_usec)); - strftime(s, sizeof(tbuf) - (s - tbuf) - 1, " %Y]", &tm); - } - else -#endif - strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S %Y]", &tm); - return tbuf; -} - -/*************************************************************************/ - -/* Like alog(), but tack a ": " and a system error message (as returned by - * strerror()) onto the end. - */ - -void log_perror(const char *fmt, ...) -{ - va_list args; - int errno_save = errno; - char str[BUFSIZE]; - - checkday(); - - if (!fmt) - return; - - va_start(args, fmt); - vsnprintf(str, sizeof(str), fmt, args); - va_end(args); - - Anope::string buf = log_gettimestamp(); - - if (logfile) - fprintf(logfile, "%s %s : %s\n", buf.c_str(), str, strerror(errno_save)); - if (nofork) - fprintf(stderr, "%s %s : %s\n", buf.c_str(), str, strerror(errno_save)); - errno = errno_save; -} - -/*************************************************************************/ - -/* We've hit something we can't recover from. Let people know what - * happened, then go down. - */ - -void fatal(const char *fmt, ...) -{ - va_list args; - char buf2[4096]; - - checkday(); - - if (!fmt) - return; - - va_start(args, fmt); - vsnprintf(buf2, sizeof(buf2), fmt, args); - va_end(args); - - Anope::string buf = log_gettimestamp(); - - if (logfile) - fprintf(logfile, "%s FATAL: %s\n", buf.c_str(), buf2); - if (nofork) - fprintf(stderr, "%s FATAL: %s\n", buf.c_str(), buf2); - if (UplinkSock) - ircdproto->SendGlobops(NULL, "FATAL ERROR! %s", buf2); - - /* one of the many places this needs to be called from */ - ModuleRunTimeDirCleanUp(); - - exit(1); -} - -/*************************************************************************/ - -/* Same thing, but do it like perror(). */ - -void fatal_perror(const char *fmt, ...) -{ - va_list args; - char buf2[4096]; - int errno_save = errno; - - checkday(); - - if (!fmt) - return; - - va_start(args, fmt); - vsnprintf(buf2, sizeof(buf2), fmt, args); - va_end(args); - - Anope::string buf = log_gettimestamp(); - - if (logfile) - fprintf(logfile, "%s FATAL: %s: %s\n", buf.c_str(), buf2, strerror(errno_save)); - if (nofork) - fprintf(stderr, "%s FATAL: %s: %s\n", buf.c_str(), buf2, strerror(errno_save)); - if (UplinkSock) - ircdproto->SendGlobops(NULL, "FATAL ERROR! %s: %s", buf2, strerror(errno_save)); - - /* one of the many places this needs to be called from */ - ModuleRunTimeDirCleanUp(); - - exit(1); -} - -Alog::Alog(LogLevel val) : Level(val) -{ - if (Level >= LOG_DEBUG) - buf << "Debug: "; -} - -Alog::~Alog() -{ - if (Level >= LOG_DEBUG && (Level - LOG_DEBUG + 1) > debug) - return; - - int errno_save = errno; - - checkday(); - - Anope::string tbuf = log_gettimestamp(); - - if (logfile) - fprintf(logfile, "%s %s\n", tbuf.c_str(), buf.str().c_str()); - if (nofork) - std::cout << tbuf << " " << buf.str() << std::endl; - else if (Level == LOG_TERMINAL) // XXX dont use this yet unless you know we're at terminal and not daemonized - std::cout << buf.str() << std::endl; - if (Config && !Config->LogChannel.empty() && LogChan && !debug && findchan(Config->LogChannel)) - ircdproto->SendPrivmsg(Global, Config->LogChannel, "%s", buf.str().c_str()); - errno = errno_save; -} diff --git a/src/logger.cpp b/src/logger.cpp new file mode 100644 index 000000000..14e5f6d1e --- /dev/null +++ b/src/logger.cpp @@ -0,0 +1,399 @@ +/* Logging routines. + * + * (C) 2003-2010 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +#include "services.h" + +void InitLogChannels(ServerConfig *config) +{ + for (unsigned i = 0; i < config->LogInfos.size(); ++i) + { + LogInfo *l = config->LogInfos[i]; + + for (std::list::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) + { + const Anope::string &target = *sit; + + if (target[0] == '#') + { + Channel *c = findchan(target); + if (!c) + c = new Channel(target); + c->SetFlag(CH_LOGCHAN); + c->SetFlag(CH_PERSIST); + + for (botinfo_map::const_iterator bit = BotListByNick.begin(), bit_end = BotListByNick.end(); bit != bit_end; ++bit) + { + BotInfo *bi = bit->second; + + if (bi->HasFlag(BI_CORE) && !c->FindUser(bi)) + { + bi->Join(c); + for (unsigned j = 0; j < config->BotModeList.size(); ++j) + c->SetMode(OperServ, config->BotModeList[j], bi->nick, false); + } + } + } + } + } +} + +static Anope::string GetTimeStamp() +{ + char tbuf[256]; + time_t t; + + if (time(&t) < 0) + throw CoreException("time() failed"); + tm tm = *localtime(&t); +#if HAVE_GETTIMEOFDAY + if (debug) + { + char *s; + struct timeval tv; + gettimeofday(&tv, NULL); + strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S", &tm); + s = tbuf + strlen(tbuf); + s += snprintf(s, sizeof(tbuf) - (s - tbuf), ".%06d", static_cast(tv.tv_usec)); + strftime(s, sizeof(tbuf) - (s - tbuf) - 1, " %Y]", &tm); + } + else +#endif + strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S %Y]", &tm); + + return tbuf; +} + +static Anope::string GetLogDate(time_t t = time(NULL)) +{ + char timestamp[32]; + + time(&t); + tm *tm = localtime(&t); + + strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm); + + return timestamp; +} + +static inline Anope::string CreateLogName(const Anope::string &file, time_t time = time(NULL)) +{ + return "logs/" + file + "." + GetLogDate(time); +} + +LogFile::LogFile(const Anope::string &name) : filename(name), stream(name.c_str(), std::ios_base::out) +{ +} + +Anope::string LogFile::GetName() const +{ + return this->filename; +} + +Log::Log(LogType type, const Anope::string &category, BotInfo *b) : bi(b), Type(type), Category(category) +{ + if (b) + this->Sources.push_back(b->nick); +} + +Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) +{ + if (!u || !c) + throw CoreException("Invalid pointers passed to Log::Log"); + + if (type != LOG_COMMAND && type != LOG_OVERRIDE && type != LOG_ADMIN) + throw CoreException("This constructor does not support this log type"); + + this->bi = c->service ? c->service : Global; + this->Category = (c->service ? c->service->nick + "/" : "") + c->name; + this->Sources.push_back(this->bi->nick); + this->Sources.push_back(u->nick); + this->Sources.push_back(c->name); + if (ci) + this->Sources.push_back(ci->name); + + if (type == LOG_ADMIN) + buf << "ADMIN: "; + else if (type == LOG_OVERRIDE) + buf << "OVERRIDE: "; + else + buf << "COMMAND: "; + buf << u->GetMask() << " used " << c->name << " "; + if (ci) + buf << "on " << ci->name << " "; +} + +Log::Log(User *u, Channel *c, const Anope::string &category) : Type(LOG_CHANNEL) +{ + if (!c) + throw CoreException("Invalid pointers passed to Log::Log"); + + this->bi = whosends(c->ci); + this->Category = category; + if (this->bi) + this->Sources.push_back(this->bi->nick); + if (u) + this->Sources.push_back(u->nick); + this->Sources.push_back(c->name); + + buf << "CHANNEL: "; + if (u) + buf << u->GetMask() << " " << this->Category << " " << c->name << " "; + else + buf << this->Category << " " << c->name << " "; +} + +Log::Log(User *u, const Anope::string &category) : bi(Global), Type(LOG_USER), Category(category) +{ + if (!u) + throw CoreException("Invalid pointers passed to Log::Log"); + + if (this->bi) + this->Sources.push_back(this->bi->nick); + this->Sources.push_back(u->nick); + + buf << "USERS: " << u->GetMask() << " "; +} + +Log::Log(Server *s, const Anope::string &category) : bi(OperServ), Type(LOG_SERVER), Category(category) +{ + if (!s) + throw CoreException("Invalid pointer passed to Log::Log"); + + if (this->bi) + this->Sources.push_back(this->bi->nick); + this->Sources.push_back(s->GetName()); + + buf << "SERVER: " << s->GetName() << " (" << s->GetDescription() << ") "; +} + +Log::Log(BotInfo *b, const Anope::string &category) : bi(b), Type(LOG_USER), Category(category) +{ + if (!b) + throw CoreException("Invalid opinter passed to Log::Log"); + + this->Sources.push_back(bi->nick); +} + +Log::~Log() +{ + if (nofork && debug && this->Type >= LOG_NORMAL && this->Type <= LOG_DEBUG + debug - 1) + std::cout << GetTimeStamp() << " Debug: " << this->buf.str() << std::endl; + else if (this->Type == LOG_TERMINAL) + std::cout << this->buf.str() << std::endl; + for (unsigned i = 0; Config && i < Config->LogInfos.size(); ++i) + { + LogInfo *l = Config->LogInfos[i]; + l->ProcessMessage(this); + } +} + +LogInfo::LogInfo(int logage, bool normal, bool rawio, bool ldebug) : LogAge(logage), Normal(normal), RawIO(rawio), Debug(ldebug) +{ +} + +LogInfo::~LogInfo() +{ + for (std::map::iterator it = this->Logfiles.begin(), it_end = this->Logfiles.end(); it != it_end; ++it) + { + LogFile *f = it->second; + + if (f && f->stream.is_open()) + f->stream.close(); + delete f; + } + this->Logfiles.clear(); +} + +void LogInfo::AddType(std::list &list, const Anope::string &type) +{ + for (std::list::iterator it = list.begin(), it_end = list.end(); it != it_end; ++it) + { + if (Anope::Match(type, *it)) + { + Log() << "Log: Type " << type << " is already covered by " << *it; + return; + } + } + + list.push_back(type); +} + +bool LogInfo::HasType(std::list &list, const Anope::string &type) const +{ + for (std::list::iterator it = list.begin(), it_end = list.end(); it != it_end; ++it) + { + Anope::string cat = *it; + bool inverse = false; + if (cat[0] == '~') + { + cat.erase(cat.begin()); + inverse = true; + } + if (Anope::Match(type, cat)) + { + return !inverse; + } + } + + return false; +} + +std::list &LogInfo::GetList(LogType type) +{ + static std::list empty; + + switch (type) + { + case LOG_ADMIN: + case LOG_OVERRIDE: + case LOG_COMMAND: + return this->Commands; + case LOG_SERVER: + return this->Servers; + case LOG_CHANNEL: + return this->Channels; + case LOG_USER: + return this->Users; + default: + return empty; + } +} + +bool LogInfo::HasType(LogType type) +{ + switch (type) + { + case LOG_ADMIN: + case LOG_OVERRIDE: + case LOG_COMMAND: + case LOG_SERVER: + case LOG_CHANNEL: + case LOG_USER: + return !this->GetList(type).empty(); + case LOG_NORMAL: + return this->Normal; + case LOG_TERMINAL: + return true; + case LOG_RAWIO: + return this->RawIO; + case LOG_DEBUG: + return this->Debug; + // LOG_DEBUG_[234] + default: + break; + } + + return false; +} + +void LogInfo::ProcessMessage(const Log *l) +{ + static time_t lastwarn = time(NULL); + + if (!l) + throw CoreException("Bad values passed to LogInfo::ProcessMessages"); + + if (!this->HasType(l->Type)) + return; + else if (!l->Category.empty() && !this->HasType(this->GetList(l->Type), l->Category)) + return; + + if (!this->Sources.empty()) + { + bool log = false; + for (std::list::const_iterator it = this->Sources.begin(), it_end = this->Sources.end(); it != it_end; ++it) + { + if (std::find(l->Sources.begin(), l->Sources.end(), *it) != l->Sources.end()) + { + log = true; + break; + } + } + if (!log) + return; + } + + for (std::list::iterator it = this->Targets.begin(), it_end = this->Targets.end(); it != it_end; ++it) + { + const Anope::string &target = *it; + + if (target[0] == '#') + { + if (UplinkSock && !debug && Me && Me->IsSynced()) + { + Channel *c = findchan(target); + if (!c || !l->bi) + continue; + ircdproto->SendPrivmsg(l->bi, c->name, "%s", l->buf.str().c_str()); + } + } + else + { + LogFile *log = NULL; + std::map::iterator lit = this->Logfiles.find(target); + if (lit != this->Logfiles.end()) + { + log = lit->second; + if (log && log->GetName() != CreateLogName(target)) + { + delete log; + log = new LogFile(CreateLogName(target)); + + if (this->LogAge) + { + Anope::string oldlog = CreateLogName(target, time(NULL) - 86400 * this->LogAge); + if (IsFile(oldlog)) + { + DeleteFile(oldlog.c_str()); + Log(LOG_DEBUG) << "Deleted old logfile " << oldlog; + } + } + } + if (!log || !log->stream.is_open()) + { + time_t now = time(NULL); + if (log && lastwarn + 300 > now) + { + lastwarn = now; + Log() << "Unable to open logfile " << log->GetName(); + } + delete log; + log = NULL; + this->Logfiles.erase(lit); + continue; + } + } + else if (lit == this->Logfiles.end()) + { + log = new LogFile(CreateLogName(target)); + + if (!log->stream.is_open()) + { + time_t now = time(NULL); + if (lastwarn + 300 > now) + { + lastwarn = now; + Log() << "Unable to open logfile " << log->GetName(); + delete log; + log = NULL; + continue; + } + } + + this->Logfiles[target] = log; + } + + if (log) + log->stream << GetTimeStamp() << " " << l->buf.str() << std::endl; + } + } +} + diff --git a/src/mail.cpp b/src/mail.cpp index 354c7e2e7..666355b0a 100644 --- a/src/mail.cpp +++ b/src/mail.cpp @@ -4,9 +4,9 @@ MailThread::~MailThread() { if (Success) - Alog() << "Successfully delivered mail for " << MailTo << " (" << Addr << ")"; + Log() << "Successfully delivered mail for " << MailTo << " (" << Addr << ")"; else - Alog() << "Error delivering mail for " << MailTo << " (" << Addr << ")"; + Log() << "Error delivering mail for " << MailTo << " (" << Addr << ")"; } void MailThread::Run() diff --git a/src/main.cpp b/src/main.cpp index bcb67b6fa..79dcd3b00 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,7 +43,6 @@ Anope::string orig_cwd; /* Original current working directory */ Anope::string log_filename = "services.log"; /* -log filename */ int debug = 0; /* -debug */ bool readonly = false; /* -readonly */ -bool LogChan = false; /* -logchan */ bool nofork = false; /* -nofork */ bool nothird = false; /* -nothrid */ bool noexpire = false; /* -noexpire */ @@ -138,7 +137,7 @@ extern void expire_all() FOREACH_MOD(I_OnPreDatabaseExpire, OnPreDatabaseExpire()); - Alog(LOG_DEBUG) << "Running ex