diff options
Diffstat (limited to 'src/commands')
-rw-r--r-- | src/commands/cmd_away.cpp | 11 | ||||
-rw-r--r-- | src/commands/cmd_clearcache.cpp | 4 | ||||
-rw-r--r-- | src/commands/cmd_commands.cpp | 15 | ||||
-rw-r--r-- | src/commands/cmd_eline.cpp | 11 | ||||
-rw-r--r-- | src/commands/cmd_invite.cpp | 6 | ||||
-rw-r--r-- | src/commands/cmd_ison.cpp | 15 | ||||
-rw-r--r-- | src/commands/cmd_join.cpp | 11 | ||||
-rw-r--r-- | src/commands/cmd_kick.cpp | 1 | ||||
-rw-r--r-- | src/commands/cmd_links.cpp | 11 | ||||
-rw-r--r-- | src/commands/cmd_loadmodule.cpp | 1 | ||||
-rw-r--r-- | src/commands/cmd_lusers.cpp | 11 | ||||
-rw-r--r-- | src/commands/cmd_motd.cpp | 63 | ||||
-rw-r--r-- | src/commands/cmd_names.cpp | 11 | ||||
-rw-r--r-- | src/commands/cmd_nick.cpp | 1 | ||||
-rw-r--r-- | src/commands/cmd_oper.cpp | 1 | ||||
-rw-r--r-- | src/commands/cmd_rehash.cpp | 4 | ||||
-rw-r--r-- | src/commands/cmd_stats.cpp | 352 | ||||
-rw-r--r-- | src/commands/cmd_userhost.cpp | 25 | ||||
-rw-r--r-- | src/commands/cmd_version.cpp | 13 |
19 files changed, 357 insertions, 210 deletions
diff --git a/src/commands/cmd_away.cpp b/src/commands/cmd_away.cpp index cd47e49ef..fa3f7fae9 100644 --- a/src/commands/cmd_away.cpp +++ b/src/commands/cmd_away.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_AWAY_H -#define CMD_AWAY_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /AWAY. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -48,9 +40,6 @@ class CommandAway : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - /** Handle /AWAY */ CmdResult CommandAway::Handle (const std::vector<std::string>& parameters, User *user) diff --git a/src/commands/cmd_clearcache.cpp b/src/commands/cmd_clearcache.cpp index b47017c07..5914f9a8f 100644 --- a/src/commands/cmd_clearcache.cpp +++ b/src/commands/cmd_clearcache.cpp @@ -20,10 +20,6 @@ #include "inspircd.h" -#include "users.h" -#include "channels.h" -#include "ctables.h" - /** Handle /CLEARCACHE. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these diff --git a/src/commands/cmd_commands.cpp b/src/commands/cmd_commands.cpp index 2d4d42a1f..36408b363 100644 --- a/src/commands/cmd_commands.cpp +++ b/src/commands/cmd_commands.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_COMMANDS_H -#define CMD_COMMANDS_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /COMMANDS. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -48,9 +40,6 @@ class CommandCommands : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - /** Handle /COMMANDS */ CmdResult CommandCommands::Handle (const std::vector<std::string>&, User *user) @@ -59,6 +48,10 @@ CmdResult CommandCommands::Handle (const std::vector<std::string>&, User *user) list.reserve(ServerInstance->Parser->cmdlist.size()); for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) { + // Don't show S2S commands to users + if (i->second->flags_needed == FLAG_SERVERONLY) + continue; + Module* src = i->second->creator; char buffer[MAXBUF]; snprintf(buffer, MAXBUF, ":%s %03d %s :%s %s %d %d", diff --git a/src/commands/cmd_eline.cpp b/src/commands/cmd_eline.cpp index 0523d052f..15487bd8e 100644 --- a/src/commands/cmd_eline.cpp +++ b/src/commands/cmd_eline.cpp @@ -21,14 +21,6 @@ #include "inspircd.h" #include "xline.h" -#ifndef CMD_ELINE_H -#define CMD_ELINE_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /ELINE. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -49,9 +41,6 @@ class CommandEline : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - /** Handle /ELINE */ CmdResult CommandEline::Handle (const std::vector<std::string>& parameters, User *user) diff --git a/src/commands/cmd_invite.cpp b/src/commands/cmd_invite.cpp index 3baa9cb03..200cce4a3 100644 --- a/src/commands/cmd_invite.cpp +++ b/src/commands/cmd_invite.cpp @@ -132,10 +132,10 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use { // pinched from ircu - invite with not enough parameters shows channels // youve been invited to but haven't joined yet. - InvitedList* il = IS_LOCAL(user)->GetInviteList(); - for (InvitedList::iterator i = il->begin(); i != il->end(); i++) + InviteList& il = IS_LOCAL(user)->GetInviteList(); + for (InviteList::const_iterator i = il.begin(); i != il.end(); ++i) { - user->WriteNumeric(RPL_INVITELIST, "%s :%s",user->nick.c_str(),i->first.c_str()); + user->WriteNumeric(RPL_INVITELIST, "%s :%s",user->nick.c_str(), (*i)->chan->name.c_str()); } user->WriteNumeric(RPL_ENDOFINVITELIST, "%s :End of INVITE list",user->nick.c_str()); } diff --git a/src/commands/cmd_ison.cpp b/src/commands/cmd_ison.cpp index 978c1ad5b..1a50239ee 100644 --- a/src/commands/cmd_ison.cpp +++ b/src/commands/cmd_ison.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_ISON_H -#define CMD_ISON_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /ISON. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -38,7 +30,9 @@ class CommandIson : public Command public: /** Constructor for ison. */ - CommandIson ( Module* parent) : Command(parent,"ISON",0,0) { syntax = "<nick> {nick}"; } + CommandIson ( Module* parent) : Command(parent,"ISON", 1) { + syntax = "<nick> {nick}"; + } /** Handle command. * @param parameters The parameters to the comamnd * @param pcnt The number of parameters passed to teh command @@ -48,9 +42,6 @@ class CommandIson : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - /** Handle /ISON */ CmdResult CommandIson::Handle (const std::vector<std::string>& parameters, User *user) diff --git a/src/commands/cmd_join.cpp b/src/commands/cmd_join.cpp index 1dc1d7f92..6124fcc1c 100644 --- a/src/commands/cmd_join.cpp +++ b/src/commands/cmd_join.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_JOIN_H -#define CMD_JOIN_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /JOIN. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -48,9 +40,6 @@ class CommandJoin : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - /** Handle /JOIN */ CmdResult CommandJoin::Handle (const std::vector<std::string>& parameters, User *user) diff --git a/src/commands/cmd_kick.cpp b/src/commands/cmd_kick.cpp index f4001d7db..3c5fb0052 100644 --- a/src/commands/cmd_kick.cpp +++ b/src/commands/cmd_kick.cpp @@ -40,7 +40,6 @@ class CommandKick : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; - /** Handle /KICK */ CmdResult CommandKick::Handle (const std::vector<std::string>& parameters, User *user) diff --git a/src/commands/cmd_links.cpp b/src/commands/cmd_links.cpp index 80b8d7f56..f4152ebc5 100644 --- a/src/commands/cmd_links.cpp +++ b/src/commands/cmd_links.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_LINKS_H -#define CMD_LINKS_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /LINKS. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -48,9 +40,6 @@ class CommandLinks : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - /** Handle /LINKS */ CmdResult CommandLinks::Handle (const std::vector<std::string>&, User *user) diff --git a/src/commands/cmd_loadmodule.cpp b/src/commands/cmd_loadmodule.cpp index 74bd74dd3..9d60613a2 100644 --- a/src/commands/cmd_loadmodule.cpp +++ b/src/commands/cmd_loadmodule.cpp @@ -40,7 +40,6 @@ class CommandLoadmodule : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; - /** Handle /LOADMODULE */ CmdResult CommandLoadmodule::Handle (const std::vector<std::string>& parameters, User *user) diff --git a/src/commands/cmd_lusers.cpp b/src/commands/cmd_lusers.cpp index a3892dbce..e9e36b3d1 100644 --- a/src/commands/cmd_lusers.cpp +++ b/src/commands/cmd_lusers.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_LUSERS_H -#define CMD_LUSERS_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /LUSERS. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -51,9 +43,6 @@ class CommandLusers : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - /** Handle /LUSERS */ CmdResult CommandLusers::Handle (const std::vector<std::string>&, User *user) diff --git a/src/commands/cmd_motd.cpp b/src/commands/cmd_motd.cpp index 9a236137d..8e227723e 100644 --- a/src/commands/cmd_motd.cpp +++ b/src/commands/cmd_motd.cpp @@ -30,7 +30,7 @@ class CommandMotd : public Command public: /** Constructor for motd. */ - CommandMotd ( Module* parent) : Command(parent,"MOTD",0,1) { ServerInstance->ProcessedMotdEscapes = false; syntax = "[<servername>]"; } + CommandMotd ( Module* parent) : Command(parent,"MOTD",0,1) { syntax = "[<servername>]"; } /** Handle command. * @param parameters The parameters to the comamnd * @param pcnt The number of parameters passed to teh command @@ -46,61 +46,6 @@ class CommandMotd : public Command } }; -/* - * Replace all color codes from the special[] array to actual - * color code chars using C++ style escape sequences. You - * can append other chars to replace if you like (such as %U - * being underline). -- Justasic - */ -void ProcessColors(ConfigFileCache::iterator &file) -{ - static struct special_chars - { - std::string character; - std::string replace; - special_chars(const std::string &c, const std::string &r) : character(c), replace(r) { } - } - - special[] = { - special_chars("\\002", "\002"), // Bold - special_chars("\\037", "\037"), // underline - special_chars("\\003", "\003"), // Color - special_chars("\\0017", "\017"), // Stop colors - special_chars("\\u", "\037"), // Alias for underline - special_chars("\\b", "\002"), // Alias for Bold - special_chars("\\x", "\017"), // Alias for stop - special_chars("\\c", "\003"), // Alias for color - special_chars("", "") - }; - - for(file_cache::iterator it = file->second.begin(); it != file->second.end(); it++) - { - std::string ret = *it; - for(int i = 0; special[i].character.empty() == false; ++i) - { - std::string::size_type pos = ret.find(special[i].character); - if(pos != std::string::npos && ret[pos-1] == '\\' && ret[pos] == '\\') - continue; // Skip double slashes. - - // Replace all our characters in the array - while(pos != std::string::npos) - { - ret = ret.substr(0, pos) + special[i].replace + ret.substr(pos + special[i].character.size()); - pos = ret.find(special[i].character, pos + special[i].replace.size()); - } - } - - // Replace double slashes with a single slash before we return - std::string::size_type pos = ret.find("\\\\"); - while(pos != std::string::npos) - { - ret = ret.substr(0, pos) + "\\" + ret.substr(pos + 2); - pos = ret.find("\\\\", pos + 1); - } - *it = ret; - } -} - /** Handle /MOTD */ CmdResult CommandMotd::Handle (const std::vector<std::string>& parameters, User *user) @@ -120,12 +65,6 @@ CmdResult CommandMotd::Handle (const std::vector<std::string>& parameters, User return CMD_SUCCESS; } - if(!ServerInstance->ProcessedMotdEscapes) - { - ProcessColors(motd); - ServerInstance->ProcessedMotdEscapes = true; - } - user->SendText(":%s %03d %s :%s message of the day", ServerInstance->Config->ServerName.c_str(), RPL_MOTDSTART, user->nick.c_str(), ServerInstance->Config->ServerName.c_str()); diff --git a/src/commands/cmd_names.cpp b/src/commands/cmd_names.cpp index f34afb361..0c06b636f 100644 --- a/src/commands/cmd_names.cpp +++ b/src/commands/cmd_names.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_NAMES_H -#define CMD_NAMES_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /NAMES. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -48,9 +40,6 @@ class CommandNames : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - /** Handle /NAMES */ CmdResult CommandNames::Handle (const std::vector<std::string>& parameters, User *user) diff --git a/src/commands/cmd_nick.cpp b/src/commands/cmd_nick.cpp index 5e600ad1c..a079e59d0 100644 --- a/src/commands/cmd_nick.cpp +++ b/src/commands/cmd_nick.cpp @@ -21,7 +21,6 @@ #include "inspircd.h" -#include "xline.h" /** Handle /NICK. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work diff --git a/src/commands/cmd_oper.cpp b/src/commands/cmd_oper.cpp index 2fd7744ee..e3f79d347 100644 --- a/src/commands/cmd_oper.cpp +++ b/src/commands/cmd_oper.cpp @@ -20,7 +20,6 @@ #include "inspircd.h" -#include "hashcomp.h" bool OneOfMatches(const char* host, const char* ip, const char* hostlist); diff --git a/src/commands/cmd_rehash.cpp b/src/commands/cmd_rehash.cpp index ff326faf2..1fa6e5731 100644 --- a/src/commands/cmd_rehash.cpp +++ b/src/commands/cmd_rehash.cpp @@ -20,7 +20,7 @@ #include "inspircd.h" -#include "xline.h" + /** Handle /REHASH. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -88,8 +88,6 @@ CmdResult CommandRehash::Handle (const std::vector<std::string>& parameters, Use /* Don't do anything with the logs here -- logs are restarted * after the config thread has completed. */ - - ServerInstance->ProcessedMotdEscapes = false; // Reprocess our motd file --Justasic ServerInstance->RehashUsersAndChans(); FOREACH_MOD(I_OnGarbageCollect, OnGarbageCollect()); diff --git a/src/commands/cmd_stats.cpp b/src/commands/cmd_stats.cpp index 2ed5eedcd..6b21d0db6 100644 --- a/src/commands/cmd_stats.cpp +++ b/src/commands/cmd_stats.cpp @@ -20,19 +20,8 @@ #include "inspircd.h" -#ifndef WIN32 - #include <sys/resource.h> - /* This is just to be completely certain that the change which fixed getrusage on RH7 doesn't break anything else -- Om */ - #ifndef RUSAGE_SELF - #define RUSAGE_SELF 0 - #endif -#else - #include <psapi.h> - #include "inspircd_win32wrapper.h" - #pragma comment(lib, "psapi.lib") -#endif - #include "xline.h" +#include "commands/cmd_whowas.h" /** Handle /STATS. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work @@ -41,6 +30,7 @@ */ class CommandStats : public Command { + void DoStats(char statschar, User* user, string_list &results); public: /** Constructor for stats. */ @@ -60,13 +50,349 @@ class CommandStats : public Command } }; +void CommandStats::DoStats(char statschar, User* user, string_list &results) +{ + std::string sn(ServerInstance->Config->ServerName); + + bool isPublic = ServerInstance->Config->UserStats.find(statschar) != std::string::npos; + bool isRemoteOper = IS_REMOTE(user) && IS_OPER(user); + bool isLocalOperWithPrivs = IS_LOCAL(user) && user->HasPrivPermission("servers/auspex"); + + if (!isPublic && !isRemoteOper && !isLocalOperWithPrivs) + { + ServerInstance->SNO->WriteToSnoMask('t', + "%s '%c' denied for %s (%s@%s)", + (IS_LOCAL(user) ? "Stats" : "Remote stats"), + statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); + results.push_back(sn + " 481 " + user->nick + " :Permission denied - STATS " + statschar + " requires the servers/auspex priv."); + return; + } + + ModResult MOD_RESULT; + FIRST_MOD_RESULT(OnStats, MOD_RESULT, (statschar, user, results)); + if (MOD_RESULT == MOD_RES_DENY) + { + results.push_back(sn+" 219 "+user->nick+" "+statschar+" :End of /STATS report"); + ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)", + (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); + return; + } + + switch (statschar) + { + /* stats p (show listening ports) */ + case 'p': + { + for (std::vector<ListenSocket*>::const_iterator i = ServerInstance->ports.begin(); i != ServerInstance->ports.end(); ++i) + { + ListenSocket* ls = *i; + std::string ip = ls->bind_addr; + if (ip.empty()) + ip.assign("*"); + std::string type = ls->bind_tag->getString("type", "clients"); + std::string hook = ls->bind_tag->getString("ssl", "plaintext"); + + results.push_back(sn+" 249 "+user->nick+" :"+ ip + ":"+ConvToStr(ls->bind_port)+ + " (" + type + ", " + hook + ")"); + } + } + break; + + /* These stats symbols must be handled by a linking module */ + case 'n': + case 'c': + break; + + case 'i': + { + for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) + { + ConnectClass* c = *i; + std::stringstream res; + res << sn << " 215 " << user->nick << " I " << c->name << ' '; + if (c->type == CC_ALLOW) + res << '+'; + if (c->type == CC_DENY) + res << '-'; + + if (c->type == CC_NAMED) + res << '*'; + else + res << c->host; + + res << ' ' << c->config->getString("port", "*") << ' '; + + res << c->GetRecvqMax() << ' ' << c->GetSendqSoftMax() << ' ' << c->GetSendqHardMax() + << ' ' << c->GetCommandRate() << ' ' << c->GetPenaltyThreshold(); + if (c->fakelag) + res << '*'; + results.push_back(res.str()); + } + } + break; + + case 'Y': + { + int idx = 0; + for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) + { + ConnectClass* c = *i; + results.push_back(sn+" 215 "+user->nick+" i NOMATCH * "+c->GetHost()+" "+ConvToStr(c->limit ? c->limit : ServerInstance->SE->GetMaxFds())+" "+ConvToStr(idx)+" "+ServerInstance->Config->ServerName+" *"); + results.push_back(sn+" 218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(c->GetPingTime())+" 0 "+ConvToStr(c->GetSendqHardMax())+" :"+ + ConvToStr(c->GetRecvqMax())+" "+ConvToStr(c->GetRegTimeout())); + idx++; + } + } + break; + + case 'U': + { + for(std::map<irc::string, bool>::iterator i = ServerInstance->Config->ulines.begin(); i != ServerInstance->Config->ulines.end(); ++i) + { + results.push_back(sn+" 248 "+user->nick+" U "+std::string(i->first.c_str())); + } + } + break; + + case 'P': + { + int idx = 0; + for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); i++) + { + if (IS_OPER(i->second) && !ServerInstance->ULine(i->second->server)) + { + results.push_back(sn+" 249 "+user->nick+" :"+i->second->nick+" ("+i->second->ident+"@"+i->second->dhost+") Idle: "+ + (IS_LOCAL(i->second) ? ConvToStr(ServerInstance->Time() - i->second->idle_lastmsg) + " secs" : "unavailable")); + idx++; + } + } + results.push_back(sn+" 249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)"); + } + break; + + case 'k': + ServerInstance->XLines->InvokeStats("K",216,user,results); + break; + case 'g': + ServerInstance->XLines->InvokeStats("G",223,user,results); + break; + case 'q': + ServerInstance->XLines->InvokeStats("Q",217,user,results); + break; + case 'Z': + ServerInstance->XLines->InvokeStats("Z",223,user,results); + break; + case 'e': + ServerInstance->XLines->InvokeStats("E",223,user,results); + break; + case 'E': + results.push_back(sn+" 249 "+user->nick+" :Total events: "+ConvToStr(ServerInstance->SE->TotalEvents)); + results.push_back(sn+" 249 "+user->nick+" :Read events: "+ConvToStr(ServerInstance->SE->ReadEvents)); + results.push_back(sn+" 249 "+user->nick+" :Write events: "+ConvToStr(ServerInstance->SE->WriteEvents)); + results.push_back(sn+" 249 "+user->nick+" :Error events: "+ConvToStr(ServerInstance->SE->ErrorEvents)); + break; + + /* stats m (list number of times each command has been used, plus bytecount) */ + case 'm': + for (Commandtable::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) + { + if (i->second->use_count) + { + /* RPL_STATSCOMMANDS */ + results.push_back(sn+" 212 "+user->nick+" "+i->second->name+" "+ConvToStr(i->second->use_count)+" "+ConvToStr(i->second->total_bytes)); + } + } + break; + + /* stats z (debug and memory info) */ + case 'z': + { + results.push_back(sn+" 249 "+user->nick+" :Users: "+ConvToStr(ServerInstance->Users->clientlist->size())); + results.push_back(sn+" 249 "+user->nick+" :Channels: "+ConvToStr(ServerInstance->chanlist->size())); + results.push_back(sn+" 249 "+user->nick+" :Commands: "+ConvToStr(ServerInstance->Parser->cmdlist.size())); + + if (!ServerInstance->Config->WhoWasGroupSize == 0 && !ServerInstance->Config->WhoWasMaxGroups == 0) + { + Module* whowas = ServerInstance->Modules->Find("cmd_whowas.so"); + if (whowas) + { + WhowasRequest req(NULL, whowas, WhowasRequest::WHOWAS_STATS); + req.user = user; + req.Send(); + results.push_back(sn+" 249 "+user->nick+" :"+req.value); + } + } + + float kbitpersec_in, kbitpersec_out, kbitpersec_total; + char kbitpersec_in_s[30], kbitpersec_out_s[30], kbitpersec_total_s[30]; + + ServerInstance->SE->GetStats(kbitpersec_in, kbitpersec_out, kbitpersec_total); + + snprintf(kbitpersec_total_s, 30, "%03.5f", kbitpersec_total); + snprintf(kbitpersec_out_s, 30, "%03.5f", kbitpersec_out); + snprintf(kbitpersec_in_s, 30, "%03.5f", kbitpersec_in); + + results.push_back(sn+" 249 "+user->nick+" :Bandwidth total: "+ConvToStr(kbitpersec_total_s)+" kilobits/sec"); + results.push_back(sn+" 249 "+user->nick+" :Bandwidth out: "+ConvToStr(kbitpersec_out_s)+" kilobits/sec"); + results.push_back(sn+" 249 "+user->nick+" :Bandwidth in: "+ConvToStr(kbitpersec_in_s)+" kilobits/sec"); + +#ifndef WIN32 + /* Moved this down here so all the not-windows stuff (look w00tie, I didn't say win32!) is in one ifndef. + * Also cuts out some identical code in both branches of the ifndef. -- Om + */ + rusage R; + + /* Not sure why we were doing '0' with a RUSAGE_SELF comment rather than just using RUSAGE_SELF -- Om */ + if (!getrusage(RUSAGE_SELF,&R)) /* RUSAGE_SELF */ + { + results.push_back(sn+" 249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K"); + results.push_back(sn+" 249 "+user->nick+" :Signals: "+ConvToStr(R.ru_nsignals)); + results.push_back(sn+" 249 "+user->nick+" :Page faults: "+ConvToStr(R.ru_majflt)); + results.push_back(sn+" 249 "+user->nick+" :Swaps: "+ConvToStr(R.ru_nswap)); + results.push_back(sn+" 249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw)); + + char percent[30]; + + float n_elapsed = (ServerInstance->Time() - ServerInstance->stats->LastSampled.tv_sec) * 1000000 + + (ServerInstance->Time_ns() - ServerInstance->stats->LastSampled.tv_nsec) / 1000; + float n_eaten = ((R.ru_utime.tv_sec - ServerInstance->stats->LastCPU.tv_sec) * 1000000 + R.ru_utime.tv_usec - ServerInstance->stats->LastCPU.tv_usec); + float per = (n_eaten / n_elapsed) * 100; + + snprintf(percent, 30, "%03.5f%%", per); + results.push_back(sn+" 249 "+user->nick+" :CPU Use (now): "+percent); + + n_elapsed = ServerInstance->Time() - ServerInstance->startup_time; + n_eaten = (float)R.ru_utime.tv_sec + R.ru_utime.tv_usec / 100000.0; + per = (n_eaten / n_elapsed) * 100; + snprintf(percent, 30, "%03.5f%%", per); + results.push_back(sn+" 249 "+user->nick+" :CPU Use (total): "+percent); + } +#else + PROCESS_MEMORY_COUNTERS MemCounters; + if (GetProcessMemoryInfo(GetCurrentProcess(), &MemCounters, sizeof(MemCounters))) + { + results.push_back(sn+" 249 "+user->nick+" :Total allocation: "+ConvToStr((MemCounters.WorkingSetSize + MemCounters.PagefileUsage) / 1024)+"K"); + results.push_back(sn+" 249 "+user->nick+" :Pagefile usage: "+ConvToStr(MemCounters.PagefileUsage / 1024)+"K"); + results.push_back(sn+" 249 "+user->nick+" :Page faults: "+ConvToStr(MemCounters.PageFaultCount)); + results.push_back(sn+" 249 "+user->nick+" :CPU Usage: " + ConvToStr(getcpu()) + "%"); + } +#endif + } + break; + + case 'T': + { + char buffer[MAXBUF]; + results.push_back(sn+" 249 "+user->nick+" :accepts "+ConvToStr(ServerInstance->stats->statsAccept)+" refused "+ConvToStr(ServerInstance->stats->statsRefused)); + results.push_back(sn+" 249 "+user->nick+" :unknown commands "+ConvToStr(ServerInstance->stats->statsUnknown)); + results.push_back(sn+" 249 "+user->nick+" :nick collisions "+ConvToStr(ServerInstance->stats->statsCollisions)); + results.push_back(sn+" 249 "+user->nick+" :dns requests "+ConvToStr(ServerInstance->stats->statsDnsGood+ServerInstance->stats->statsDnsBad)+" succeeded "+ConvToStr(ServerInstance->stats->statsDnsGood)+" failed "+ConvToStr(ServerInstance->stats->statsDnsBad)); + results.push_back(sn+" 249 "+user->nick+" :connection count "+ConvToStr(ServerInstance->stats->statsConnects)); + snprintf(buffer,MAXBUF," 249 %s :bytes sent %5.2fK recv %5.2fK", + user->nick.c_str(),ServerInstance->stats->statsSent / 1024.0,ServerInstance->stats->statsRecv / 1024.0); + results.push_back(sn+buffer); + } + break; + + /* stats o */ + case 'o': + { + ConfigTagList tags = ServerInstance->Config->ConfTags("oper"); + for(ConfigIter i = tags.first; i != tags.second; ++i) + { + ConfigTag* tag = i->second; + results.push_back(sn+" 243 "+user->nick+" O "+tag->getString("host")+" * "+ + tag->getString("name") + " " + tag->getString("type")+" 0"); + } + } + break; + case 'O': + { + for(OperIndex::iterator i = ServerInstance->Config->oper_blocks.begin(); i != ServerInstance->Config->oper_blocks.end(); i++) + { + // just the types, not the actual oper blocks... + if (i->first[0] != ' ') + continue; + OperInfo* tag = i->second; + tag->init(); + std::string umodes; + std::string cmodes; + for(char c='A'; c < 'z'; c++) + { + ModeHandler* mh = ServerInstance->Modes->FindMode(c, MODETYPE_USER); + if (mh && mh->NeedsOper() && tag->AllowedUserModes[c - 'A']) + umodes.push_back(c); + mh = ServerInstance->Modes->FindMode(c, MODETYPE_CHANNEL); + if (mh && mh->NeedsOper() && tag->AllowedChanModes[c - 'A']) + cmodes.push_back(c); + } + results.push_back(sn+" 243 "+user->nick+" O "+tag->NameStr() + " " + umodes + " " + cmodes); + } + } + break; + + /* stats l (show user I/O stats) */ + case 'l': + results.push_back(sn+" 211 "+user->nick+" :nick[ident@host] sendq cmds_out bytes_out cmds_in bytes_in time_open"); + for (std::vector<LocalUser*>::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) + { + LocalUser* i = *n; + results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age)); + } + break; + + /* stats L (show user I/O stats with IP addresses) */ + case 'L': + results.push_back(sn+" 211 "+user->nick+" :nick[ident@ip] sendq cmds_out bytes_out cmds_in bytes_in time_open"); + for (std::vector<LocalUser*>::iterator n = ServerInstance->Users->local_users.begin(); n != ServerInstance->Users->local_users.end(); n++) + { + LocalUser* i = *n; + results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->eh.getSendQSize())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age)); + } + break; + + /* stats u (show server uptime) */ + case 'u': + { + time_t current_time = 0; + current_time = ServerInstance->Time(); + time_t server_uptime = current_time - ServerInstance->startup_time; + struct tm* stime; + stime = gmtime(&server_uptime); + /* i dont know who the hell would have an ircd running for over a year nonstop, but + * Craig suggested this, and it seemed a good idea so in it went */ + if (stime->tm_year > 70) + { + char buffer[MAXBUF]; + snprintf(buffer,MAXBUF," 242 %s :Server up %d years, %d days, %.2d:%.2d:%.2d",user->nick.c_str(),(stime->tm_year-70),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec); + results.push_back(sn+buffer); + } + else + { + char buffer[MAXBUF]; + snprintf(buffer,MAXBUF," 242 %s :Server up %d days, %.2d:%.2d:%.2d",user->nick.c_str(),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec); + results.push_back(sn+buffer); + } + } + break; + + default: + break; + } + + results.push_back(sn+" 219 "+user->nick+" "+statschar+" :End of /STATS report"); + ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)", + (IS_LOCAL(user) ? "Stats" : "Remote stats"), statschar, user->nick.c_str(), user->ident.c_str(), user->host.c_str()); + return; +} + CmdResult CommandStats::Handle (const std::vector<std::string>& parameters, User *user) { if (parameters.size() > 1 && parameters[1] != ServerInstance->Config->ServerName) return CMD_SUCCESS; string_list values; char search = parameters[0][0]; - ServerInstance->DoStats(search, user, values); + DoStats(search, user, values); for (size_t i = 0; i < values.size(); i++) user->SendText(":%s", values[i].c_str()); diff --git a/src/commands/cmd_userhost.cpp b/src/commands/cmd_userhost.cpp index c19ad5b6f..af7d3ceca 100644 --- a/src/commands/cmd_userhost.cpp +++ b/src/commands/cmd_userhost.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_USERHOST_H -#define CMD_USERHOST_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /USERHOST. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -38,7 +30,9 @@ class CommandUserhost : public Command public: /** Constructor for userhost. */ - CommandUserhost ( Module* parent) : Command(parent,"USERHOST",0,1) { syntax = "<nick>{,<nick>}"; } + CommandUserhost ( Module* parent) : Command(parent,"USERHOST", 1, 5) { + syntax = "<nick> {<nick>}"; + } /** Handle command. * @param parameters The parameters to the comamnd * @param pcnt The number of parameters passed to teh command @@ -48,9 +42,6 @@ class CommandUserhost : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - CmdResult CommandUserhost::Handle (const std::vector<std::string>& parameters, User *user) { std::string retbuf = std::string("302 ") + user->nick + " :"; @@ -64,13 +55,9 @@ CmdResult CommandUserhost::Handle (const std::vector<std::string>& parameters, U retbuf = retbuf + u->nick; if (IS_OPER(u)) - { - retbuf = retbuf + "*="; - } - else - { - retbuf = retbuf + "="; - } + retbuf = retbuf + "*"; + + retbuf = retbuf + "="; if (IS_AWAY(u)) retbuf += "-"; diff --git a/src/commands/cmd_version.cpp b/src/commands/cmd_version.cpp index 9b19c0ee0..6fae329bd 100644 --- a/src/commands/cmd_version.cpp +++ b/src/commands/cmd_version.cpp @@ -20,14 +20,6 @@ #include "inspircd.h" -#ifndef CMD_VERSION_H -#define CMD_VERSION_H - -// include the common header files - -#include "users.h" -#include "channels.h" - /** Handle /VERSION. These command handlers can be reloaded by the core, * and handle basic RFC1459 commands. Commands within modules work * the same way, however, they can be fully unloaded, where these @@ -48,11 +40,6 @@ class CommandVersion : public Command CmdResult Handle(const std::vector<std::string>& parameters, User *user); }; -#endif - - - - CmdResult CommandVersion::Handle (const std::vector<std::string>&, User *user) { user->WriteNumeric(RPL_VERSION, "%s :%s",user->nick.c_str(),ServerInstance->GetVersionString(IS_OPER(user)).c_str()); |