]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/cmd_stats.cpp
Decide that it wasn't quite appropriate :(
[user/henk/code/inspircd.git] / src / cmd_stats.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 using namespace std;
18
19 #include "inspircd_config.h"
20 #include "inspircd.h"
21 #include "inspircd_io.h"
22 #include <time.h>
23 #include <string>
24 #ifdef GCC3
25 #include <ext/hash_map>
26 #else
27 #include <hash_map>
28 #endif
29 #include <sys/types.h>
30 #include <sys/time.h>
31 #include <sys/resource.h>
32 #ifdef THREADED_DNS
33 #include <pthread.h>
34 #endif
35 #ifndef RUSAGE_SELF
36 #define   RUSAGE_SELF     0
37 #define   RUSAGE_CHILDREN     -1
38 #endif
39 #include <map>
40 #include <sstream>
41 #include <vector>
42 #include <deque>
43 #include "users.h"
44 #include "ctables.h"
45 #include "globals.h"
46 #include "modules.h"
47 #include "dynamic.h"
48 #include "wildcard.h"
49 #include "message.h"
50 #include "commands.h"
51 #include "mode.h"
52 #include "xline.h"
53 #include "inspstring.h"
54 #include "dnsqueue.h"
55 #include "helperfuncs.h"
56 #include "hashcomp.h"
57 #include "socketengine.h"
58 #include "typedefs.h"
59 #include "command_parse.h"
60 #include "cmd_stats.h"
61
62 extern ServerConfig* Config;
63 extern InspIRCd* ServerInstance;
64 extern int MODCOUNT;
65 extern std::vector<Module*> modules;
66 extern std::vector<ircd_module*> factory;
67 extern time_t TIME;
68 extern user_hash clientlist;
69 extern chan_hash chanlist;
70 extern whowas_hash whowas;
71 extern std::vector<userrec*> all_opers;
72 extern std::vector<userrec*> local_users;
73 extern userrec* fd_ref_table[MAX_DESCRIPTORS];
74
75 void cmd_stats::Handle (char **parameters, int pcnt, userrec *user)
76 {
77         if (pcnt != 1)
78         {
79                 return;
80         }
81         if (strlen(parameters[0])>1)
82         {
83                 /* make the stats query 1 character long */
84                 parameters[0][1] = '\0';
85         }
86
87         if ((*Config->OperOnlyStats) && (strchr(Config->OperOnlyStats,*parameters[0])) && (!*user->oper))
88         {
89                 WriteServ(user->fd,"481 %s :Permission denied - STATS %c is oper-only",user->nick,*parameters[0]);
90                 return;
91         }
92
93
94         int MOD_RESULT = 0;
95         FOREACH_RESULT(I_OnStats,OnStats(*parameters[0],user));
96         if (MOD_RESULT)
97                 return;
98
99         if (*parameters[0] == 'c')
100         {
101                 /* This stats symbol must be handled by a linking module */
102         }
103         
104         if (*parameters[0] == 'i')
105         {
106                 int idx = 0;
107                 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
108                 {
109                         WriteServ(user->fd,"215 %s I * * * %d %d %s *",user->nick,MAXCLIENTS,idx,Config->ServerName);
110                         idx++;
111                 }
112         }
113         
114         if (*parameters[0] == 'y')
115         {
116                 int idx = 0;
117                 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
118                 {
119                         WriteServ(user->fd,"218 %s Y %d %d 0 %d %d",user->nick,idx,120,i->flood,i->registration_timeout);
120                         idx++;
121                 }
122         }
123
124         if (*parameters[0] == 'U')
125         {
126                 char ulined[MAXBUF];
127                 for (int i = 0; i < Config->ConfValueEnum("uline",&Config->config_f); i++)
128                 {
129                         Config->ConfValue("uline","server",i,ulined,&Config->config_f);
130                         WriteServ(user->fd,"248 %s U %s",user->nick,ulined);
131                 }
132         }
133         
134         if (*parameters[0] == 'P')
135         {
136                 int idx = 0;
137                 for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++)
138                 {
139                         if (*i->second->oper)
140                         {
141                                 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));
142                                 idx++;
143                         }
144                 }
145                 WriteServ(user->fd,"249 %s :%d OPER(s)",user->nick,idx);
146         }
147         
148         if (*parameters[0] == 'k')
149         {
150                 stats_k(user);
151         }
152
153         if (*parameters[0] == 'g')
154         {
155                 stats_g(user);
156         }
157
158         if (*parameters[0] == 'q')
159         {
160                 stats_q(user);
161         }
162
163         if (*parameters[0] == 'Z')
164         {
165                 stats_z(user);
166         }
167
168         if (*parameters[0] == 'e')
169         {
170                 stats_e(user);
171         }
172
173         /* stats m (list number of times each command has been used, plus bytecount) */
174         if (*parameters[0] == 'm')
175         {
176                 for (nspace::hash_map<std::string,command_t*>::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++)
177                 {
178                         if (i->second->use_count)
179                         {
180                                 /* RPL_STATSCOMMANDS */
181                                 WriteServ(user->fd,"212 %s %s %d %d",user->nick,i->second->command.c_str(),i->second->use_count,i->second->total_bytes);
182                         }
183                 }
184                         
185         }
186
187         /* stats z (debug and memory info) */
188         if (*parameters[0] == 'z')
189         {
190                 rusage R;
191                 WriteServ(user->fd,"249 %s :Users(HASH_MAP) %d (%d bytes, %d buckets)",user->nick,clientlist.size(),clientlist.size()*sizeof(userrec),clientlist.bucket_count());
192                 WriteServ(user->fd,"249 %s :Channels(HASH_MAP) %d (%d bytes, %d buckets)",user->nick,chanlist.size(),chanlist.size()*sizeof(chanrec),chanlist.bucket_count());
193                 WriteServ(user->fd,"249 %s :Commands(VECTOR) %d (%d bytes)",user->nick,ServerInstance->Parser->cmdlist.size(),ServerInstance->Parser->cmdlist.size()*sizeof(command_t));
194                 WriteServ(user->fd,"249 %s :MOTD(VECTOR) %d, RULES(VECTOR) %d",user->nick,Config->MOTD.size(),Config->RULES.size());
195                 WriteServ(user->fd,"249 %s :Modules(VECTOR) %d (%d)",user->nick,modules.size(),modules.size()*sizeof(Module));
196                 WriteServ(user->fd,"249 %s :ClassFactories(VECTOR) %d (%d)",user->nick,factory.size(),factory.size()*sizeof(ircd_module));
197                 if (!getrusage(RUSAGE_SELF,&R))
198                 {
199                         WriteServ(user->fd,"249 %s :Total allocation: %luK (0x%lx)",user->nick,R.ru_maxrss,R.ru_maxrss);
200                         WriteServ(user->fd,"249 %s :Signals:          %lu  (0x%lx)",user->nick,R.ru_nsignals,R.ru_nsignals);
201                         WriteServ(user->fd,"249 %s :Page faults:      %lu  (0x%lx)",user->nick,R.ru_majflt,R.ru_majflt);
202                         WriteServ(user->fd,"249 %s :Swaps:            %lu  (0x%lx)",user->nick,R.ru_nswap,R.ru_nswap);
203                         WriteServ(user->fd,"249 %s :Context Switches: %lu  (0x%lx)",user->nick,R.ru_nvcsw+R.ru_nivcsw,R.ru_nvcsw+R.ru_nivcsw);
204                 }
205         }
206
207         if (*parameters[0] == 'T')
208         {
209                 WriteServ(user->fd,"249 Brain :accepts %d refused %d",ServerInstance->stats->statsAccept,ServerInstance->stats->statsRefused);
210                 WriteServ(user->fd,"249 Brain :unknown commands %d",ServerInstance->stats->statsUnknown);
211                 WriteServ(user->fd,"249 Brain :nick collisions %d",ServerInstance->stats->statsCollisions);
212                 WriteServ(user->fd,"249 Brain :dns requests %d succeeded %d failed %d",ServerInstance->stats->statsDns,ServerInstance->stats->statsDnsGood,ServerInstance->stats->statsDnsBad);
213                 WriteServ(user->fd,"249 Brain :connections %d",ServerInstance->stats->statsConnects);
214                 WriteServ(user->fd,"249 Brain :bytes sent %dK recv %dK",(ServerInstance->stats->statsSent / 1024),(ServerInstance->stats->statsRecv / 1024));
215         }
216         
217         /* stats o */
218         if (*parameters[0] == 'o')
219         {
220                 for (int i = 0; i < Config->ConfValueEnum("oper",&Config->config_f); i++)
221                 {
222                         char LoginName[MAXBUF];
223                         char HostName[MAXBUF];
224                         char OperType[MAXBUF];
225                         Config->ConfValue("oper","name",i,LoginName,&Config->config_f);
226                         Config->ConfValue("oper","host",i,HostName,&Config->config_f);
227                         Config->ConfValue("oper","type",i,OperType,&Config->config_f);
228                         WriteServ(user->fd,"243 %s O %s * %s %s 0",user->nick,HostName,LoginName,OperType);
229                 }
230         }
231         
232         /* stats l (show user I/O stats) */
233         if (*parameters[0] == 'l')
234         {
235                 WriteServ(user->fd,"211 %s :server:port nick bytes_in cmds_in bytes_out cmds_out",user->nick);
236                 for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++)
237                 {
238                         if (isnick(i->second->nick))
239                         {
240                                 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);
241                         }
242                         else
243                         {
244                                 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);
245                         }
246                         
247                 }
248         }
249         
250         /* stats u (show server uptime) */
251         if (*parameters[0] == 'u')
252         {
253                 time_t current_time = 0;
254                 current_time = TIME;
255                 time_t server_uptime = current_time - ServerInstance->startup_time;
256                 struct tm* stime;
257                 stime = gmtime(&server_uptime);
258                 /* i dont know who the hell would have an ircd running for over a year nonstop, but
259                  * Craig suggested this, and it seemed a good idea so in it went */
260                 if (stime->tm_year > 70)
261                 {
262                         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);
263                 }
264                 else
265                 {
266                         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);
267                 }
268         }
269
270         WriteServ(user->fd,"219 %s %s :End of /STATS report",user->nick,parameters[0]);
271         WriteOpers("*** Notice: Stats '%s' requested by %s (%s@%s)",parameters[0],user->nick,user->ident,user->host);
272         
273 }
274
275
276