1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
17 #include "inspircd_config.h"
19 #include "configreader.h"
21 #include <sys/types.h>
23 #include <sys/resource.h>
26 #define RUSAGE_CHILDREN -1
38 #include "inspstring.h"
40 #include "helperfuncs.h"
42 #include "socketengine.h"
43 #include "command_parse.h"
44 #include "commands/cmd_stats.h"
46 extern ServerConfig* Config;
47 extern InspIRCd* ServerInstance;
49 extern ModuleList modules;
50 extern FactoryList factory;
52 extern user_hash clientlist;
53 extern chan_hash chanlist;
55 void cmd_stats::Handle (char **parameters, int pcnt, userrec *user)
63 /* make the stats query 1 character long */
67 if ((*Config->OperOnlyStats) && (strchr(Config->OperOnlyStats,*parameters[0])) && (!*user->oper))
69 WriteServ(user->fd,"481 %s :Permission denied - STATS %c is oper-only",user->nick,*parameters[0]);
75 FOREACH_RESULT(I_OnStats,OnStats(*parameters[0],user));
79 if (*parameters[0] == 'c')
81 /* This stats symbol must be handled by a linking module */
84 if (*parameters[0] == 'i')
87 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
89 WriteServ(user->fd,"215 %s I * * * %d %d %s *",user->nick,MAXCLIENTS,idx,Config->ServerName);
94 if (*parameters[0] == 'y')
97 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
99 WriteServ(user->fd,"218 %s Y %d %d 0 %d %d",user->nick,idx,120,i->flood,i->registration_timeout);
104 if (*parameters[0] == 'U')
107 for (int i = 0; i < Config->ConfValueEnum(Config->config_data, "uline"); i++)
109 Config->ConfValue(Config->config_data, "uline","server", i, ulined, MAXBUF);
110 WriteServ(user->fd,"248 %s U %s",user->nick,ulined);
114 if (*parameters[0] == 'P')
117 for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++)
119 if (*i->second->oper)
121 WriteServ(user->fd,"249 %s :%s (%s@%s) Idle: %d",user->nick,i->second->nick,i->second->ident,i->second->dhost,(TIME - i->second->idle_lastmsg));
125 WriteServ(user->fd,"249 %s :%d OPER(s)",user->nick,idx);
128 if (*parameters[0] == 'k')
133 if (*parameters[0] == 'g')
138 if (*parameters[0] == 'q')
143 if (*parameters[0] == 'Z')
148 if (*parameters[0] == 'e')
153 /* stats m (list number of times each command has been used, plus bytecount) */
154 if (*parameters[0] == 'm')
156 for (nspace::hash_map<std::string,command_t*>::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++)
158 if (i->second->use_count)
160 /* RPL_STATSCOMMANDS */
161 WriteServ(user->fd,"212 %s %s %d %d",user->nick,i->second->command.c_str(),i->second->use_count,i->second->total_bytes);
167 /* stats z (debug and memory info) */
168 if (*parameters[0] == 'z')
171 WriteServ(user->fd,"249 %s :Users(HASH_MAP) %d (%d bytes, %d buckets)",user->nick,clientlist.size(),clientlist.size()*sizeof(userrec),clientlist.bucket_count());
172 WriteServ(user->fd,"249 %s :Channels(HASH_MAP) %d (%d bytes, %d buckets)",user->nick,chanlist.size(),chanlist.size()*sizeof(chanrec),chanlist.bucket_count());
173 WriteServ(user->fd,"249 %s :Commands(VECTOR) %d (%d bytes)",user->nick,ServerInstance->Parser->cmdlist.size(),ServerInstance->Parser->cmdlist.size()*sizeof(command_t));
174 WriteServ(user->fd,"249 %s :MOTD(VECTOR) %d, RULES(VECTOR) %d",user->nick,Config->MOTD.size(),Config->RULES.size());
175 WriteServ(user->fd,"249 %s :Modules(VECTOR) %d (%d)",user->nick,modules.size(),modules.size()*sizeof(Module));
176 WriteServ(user->fd,"249 %s :ClassFactories(VECTOR) %d (%d)",user->nick,factory.size(),factory.size()*sizeof(ircd_module));
177 if (!getrusage(RUSAGE_SELF,&R))
179 WriteServ(user->fd,"249 %s :Total allocation: %luK (0x%lx)",user->nick,R.ru_maxrss,R.ru_maxrss);
180 WriteServ(user->fd,"249 %s :Signals: %lu (0x%lx)",user->nick,R.ru_nsignals,R.ru_nsignals);
181 WriteServ(user->fd,"249 %s :Page faults: %lu (0x%lx)",user->nick,R.ru_majflt,R.ru_majflt);
182 WriteServ(user->fd,"249 %s :Swaps: %lu (0x%lx)",user->nick,R.ru_nswap,R.ru_nswap);
183 WriteServ(user->fd,"249 %s :Context Switches: %lu (0x%lx)",user->nick,R.ru_nvcsw+R.ru_nivcsw,R.ru_nvcsw+R.ru_nivcsw);
187 if (*parameters[0] == 'T')
189 WriteServ(user->fd,"249 %s :accepts %d refused %d",user->nick,ServerInstance->stats->statsAccept,ServerInstance->stats->statsRefused);
190 WriteServ(user->fd,"249 %s :unknown commands %d",user->nick,ServerInstance->stats->statsUnknown);
191 WriteServ(user->fd,"249 %s :nick collisions %d",user->nick,ServerInstance->stats->statsCollisions);
192 WriteServ(user->fd,"249 %s :dns requests %d succeeded %d failed %d",user->nick,ServerInstance->stats->statsDns,ServerInstance->stats->statsDnsGood,ServerInstance->stats->statsDnsBad);
193 WriteServ(user->fd,"249 %s :connections %d",user->nick,ServerInstance->stats->statsConnects);
194 WriteServ(user->fd,"249 %s :bytes sent %dK recv %dK",user->nick,(ServerInstance->stats->statsSent / 1024),(ServerInstance->stats->statsRecv / 1024));
198 if (*parameters[0] == 'o')
200 for (int i = 0; i < Config->ConfValueEnum(Config->config_data, "oper"); i++)
202 char LoginName[MAXBUF];
203 char HostName[MAXBUF];
204 char OperType[MAXBUF];
205 Config->ConfValue(Config->config_data, "oper","name", i, LoginName, MAXBUF);
206 Config->ConfValue(Config->config_data, "oper","host", i, HostName, MAXBUF);
207 Config->ConfValue(Config->config_data, "oper","type", i, OperType, MAXBUF);
208 WriteServ(user->fd,"243 %s O %s * %s %s 0",user->nick,HostName,LoginName,OperType);
212 /* stats l (show user I/O stats) */
213 if (*parameters[0] == 'l')
215 WriteServ(user->fd,"211 %s :server:port nick bytes_in cmds_in bytes_out cmds_out",user->nick);
216 for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++)
218 if (isnick(i->second->nick))
220 WriteServ(user->fd,"211 %s :%s:%d %s %d %d %d %d",user->nick,i->second->server,i->second->port,i->second->nick,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out);
224 WriteServ(user->fd,"211 %s :%s:%d (unknown@%d) %d %d %d %d",user->nick,i->second->server,i->second->port,i->second->fd,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out);
230 /* stats u (show server uptime) */
231 if (*parameters[0] == 'u')
233 time_t current_time = 0;
235 time_t server_uptime = current_time - ServerInstance->startup_time;
237 stime = gmtime(&server_uptime);
238 /* i dont know who the hell would have an ircd running for over a year nonstop, but
239 * Craig suggested this, and it seemed a good idea so in it went */
240 if (stime->tm_year > 70)
242 WriteServ(user->fd,"242 %s :Server up %d years, %d days, %.2d:%.2d:%.2d",user->nick,(stime->tm_year-70),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec);
246 WriteServ(user->fd,"242 %s :Server up %d days, %.2d:%.2d:%.2d",user->nick,stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec);
250 WriteServ(user->fd,"219 %s %s :End of /STATS report",user->nick,parameters[0]);
251 WriteOpers("*** Notice: Stats '%s' requested by %s (%s@%s)",parameters[0],user->nick,user->ident,user->host);