]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/cmd_stats.cpp
Checks for negative fd's when adding them to the socketengine so we can generate...
[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 #include "inspircd_config.h"
18 #include "inspircd.h"
19 #include "configreader.h"
20 #include "hash_map.h"
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/resource.h>
24 #ifndef RUSAGE_SELF
25 #define   RUSAGE_SELF     0
26 #define   RUSAGE_CHILDREN     -1
27 #endif
28 #include "users.h"
29 #include "ctables.h"
30 #include "globals.h"
31 #include "modules.h"
32 #include "dynamic.h"
33 #include "wildcard.h"
34 #include "message.h"
35 #include "commands.h"
36 #include "mode.h"
37 #include "xline.h"
38 #include "inspstring.h"
39 #include "dnsqueue.h"
40 #include "helperfuncs.h"
41 #include "hashcomp.h"
42 #include "socketengine.h"
43 #include "command_parse.h"
44 #include "commands/cmd_stats.h"
45
46 extern ServerConfig* Config;
47 extern InspIRCd* ServerInstance;
48 extern int MODCOUNT;
49 extern ModuleList modules;
50 extern FactoryList factory;
51 extern time_t TIME;
52 extern user_hash clientlist;
53 extern chan_hash chanlist;
54
55 void cmd_stats::Handle (char **parameters, int pcnt, userrec *user)
56 {
57         if (pcnt != 1)
58         {
59                 return;
60         }
61         if (parameters[0][1])
62         {
63                 /* make the stats query 1 character long */
64                 parameters[0][1] = 0;
65         }
66
67         if ((*Config->OperOnlyStats) && (strchr(Config->OperOnlyStats,*parameters[0])) && (!*user->oper))
68         {
69                 WriteServ(user->fd,"481 %s :Permission denied - STATS %c is oper-only",user->nick,*parameters[0]);
70                 return;
71         }
72
73
74         int MOD_RESULT = 0;
75         FOREACH_RESULT(I_OnStats,OnStats(*parameters[0],user));
76         if (MOD_RESULT)
77                 return;
78
79         if (*parameters[0] == 'c')
80         {
81                 /* This stats symbol must be handled by a linking module */
82         }
83         
84         if (*parameters[0] == 'i')
85         {
86                 int idx = 0;
87                 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
88                 {
89                         WriteServ(user->fd,"215 %s I * * * %d %d %s *",user->nick,MAXCLIENTS,idx,Config->ServerName);
90                         idx++;
91                 }
92         }
93         
94         if (*parameters[0] == 'y')
95         {
96                 int idx = 0;
97                 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
98                 {
99                         WriteServ(user->fd,"218 %s Y %d %d 0 %d %d",user->nick,idx,120,i->flood,i->registration_timeout);
100                         idx++;
101                 }
102         }
103
104         if (*parameters[0] == 'U')
105         {
106                 char ulined[MAXBUF];
107                 for (int i = 0; i < Config->ConfValueEnum(Config->config_data, "uline"); i++)
108                 {
109                         Config->ConfValue(Config->config_data, "uline","server", i, ulined, MAXBUF);
110                         WriteServ(user->fd,"248 %s U %s",user->nick,ulined);
111                 }
112         }
113         
114         if (*parameters[0] == 'P')
115         {
116                 int idx = 0;
117                 for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++)
118                 {
119                         if (*i->second->oper)
120                         {
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));
122                                 idx++;
123                         }
124                 }
125                 WriteServ(user->fd,"249 %s :%d OPER(s)",user->nick,idx);
126         }
127         
128         if (*parameters[0] == 'k')
129         {
130                 stats_k(user);
131         }
132
133         if (*parameters[0] == 'g')
134         {
135                 stats_g(user);
136         }
137
138         if (*parameters[0] == 'q')
139         {
140                 stats_q(user);
141         }
142
143         if (*parameters[0] == 'Z')
144         {
145                 stats_z(user);
146         }
147
148         if (*parameters[0] == 'e')
149         {
150                 stats_e(user);
151         }
152
153         /* stats m (list number of times each command has been used, plus bytecount) */
154         if (*parameters[0] == 'm')
155         {
156                 for (nspace::hash_map<std::string,command_t*>::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++)
157                 {
158                         if (i->second->use_count)
159                         {
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);
162                         }
163                 }
164                         
165         }
166
167         /* stats z (debug and memory info) */
168         if (*parameters[0] == 'z')
169         {
170                 rusage R;
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))
178                 {
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);
184                 }
185         }
186
187         if (*parameters[0] == 'T')
188         {
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));
195         }
196         
197         /* stats o */
198         if (*parameters[0] == 'o')
199         {
200                 for (int i = 0; i < Config->ConfValueEnum(Config->config_data, "oper"); i++)
201                 {
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);
209                 }
210         }
211         
212         /* stats l (show user I/O stats) */
213         if (*parameters[0] == 'l')
214         {
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++)
217                 {
218                         if (isnick(i->second->nick))
219                         {
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);
221                         }
222                         else
223                         {
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);
225                         }
226                         
227                 }
228         }
229         
230         /* stats u (show server uptime) */
231         if (*parameters[0] == 'u')
232         {
233                 time_t current_time = 0;
234                 current_time = TIME;
235                 time_t server_uptime = current_time - ServerInstance->startup_time;
236                 struct tm* stime;
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)
241                 {
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);
243                 }
244                 else
245                 {
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);
247                 }
248         }
249
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);
252         
253 }