Allow /stats to accept long names for the displayed statistics.
authorMichael Poole <mdpoole@troilus.org>
Sun, 12 Sep 2004 03:53:44 +0000 (03:53 +0000)
committerMichael Poole <mdpoole@troilus.org>
Sun, 12 Sep 2004 03:53:44 +0000 (03:53 +0000)
git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1135 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

26 files changed:
ChangeLog
include/class.h
include/gline.h
include/ircd_features.h
include/listener.h
include/motd.h
include/msgq.h
include/res.h
include/s_debug.h
include/s_misc.h
include/s_stats.h
include/userload.h
ircd/class.c
ircd/gline.c
ircd/ircd_features.c
ircd/ircd_res.c
ircd/listener.c
ircd/m_stats.c
ircd/motd.c
ircd/msgq.c
ircd/s_debug.c
ircd/s_err.c
ircd/s_misc.c
ircd/s_stats.c
ircd/s_user.c
ircd/userload.c

index 4320de59ec5eb2e9fb3a7c7b4783aca16a945e2a..d03fc41b63f3d5e5b3ceed886db7baa9105d80ca 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2004-09-11  Michael Poole <mdpoole@troilus.org>
+
+       * include/s_stats.h: Add sd_name to struct StatDesc.  Stop
+       publishing the statsinfo and statsmap arrays; replace them with
+       stats_find().  Change argument list of StatFunc() to work with
+       names.
+
+       * ircd/m_stats.c: Use stats_find() instead of statsmap[].  Use the
+       full argument instead of just the first character in reports.
+
+       * ircd/s_stats.c: Adapt individual stats handler functions to new
+       argument list.  Add long names to statsinfo[].  Add new functions
+       stats_cmp(), stats_search(), stats_find().  Sort statsinfo[] in
+       stats_init().
+
+       * ircd/s_err.c: Change ENDOFSTATS to display a string rather than
+       a single character.
+
+       * ircd/s_user.c: Send an error to the user when a message loses
+       its target in transit.
+
+       * include/class.h include/gline.h include/ircd_features.h
+       include/listener.h include/motd.h include/msgq.h include/res.h
+       include/s_debug.h include/s_misc.h include/userload.h ircd/class.c
+       ircd/gline.c ircd/ircd_features.c ircd/ircd_res.c ircd/listener.c
+       ircd/motd.c ircd/msgq.c ircd/s_debug.c ircd/s_misc.c
+       ircd/userload.c: Adjust stats handlers to new argument list.
+
 2004-09-11  Michael Poole <mdpoole@troilus.org>
 
        * include/numeric.h, ircd/s_err.c: Remove RPL_TRACEPING, and
index e5d0b54bdf2396015f7a6b9df67988fb7c736da6..d5901b3fa44f6fb44e15a37588cb573371b3e4a2 100644 (file)
@@ -88,7 +88,7 @@ extern void add_class(char *name, unsigned int ping,
                       unsigned int confreq, unsigned int maxli,
                       unsigned int sendq);
 extern void check_class(void);
-extern void report_classes(struct Client *sptr, struct StatDesc *sd, int stat,
+extern void report_classes(struct Client *sptr, const struct StatDesc *sd,
                            char *param);
 extern unsigned int get_sendq(struct Client* cptr);
 
index 50ef60862c566ef2f55a94c79cb90d790096cb85..f3f88eb172c4be74cfa2afd3116c6345180c1200 100644 (file)
@@ -95,7 +95,7 @@ extern void gline_free(struct Gline *gline);
 extern void gline_burst(struct Client *cptr);
 extern int gline_resend(struct Client *cptr, struct Gline *gline);
 extern int gline_list(struct Client *sptr, char *userhost);
-extern void gline_stats(struct Client *sptr, struct StatDesc *sd, int stat,
+extern void gline_stats(struct Client *sptr, const struct StatDesc *sd,
                         char *param);
 extern int gline_memory_count(size_t *gl_size);
 
index e5135877917e9fb99e7ee6891f749db8cce47873..58a0d61b510b86959fa6e8d5decb76c0a213b504 100644 (file)
@@ -160,7 +160,7 @@ extern int feature_get(struct Client* from, const char* const* fields,
 extern void feature_unmark(void);
 extern void feature_mark(void);
 
-extern void feature_report(struct Client* to, struct StatDesc* sd, int stat,
+extern void feature_report(struct Client* to, const struct StatDesc* sd,
                            char* param);
 
 extern int feature_int(enum Feature feat);
index f33564e7ce5a411ee69397c88782ffad2f07f6a1..1dcbba6d4da16b00759ba63fb71b5f1ca285d4e7 100644 (file)
@@ -62,7 +62,7 @@ extern void        close_listeners(void);
 extern void        count_listener_memory(int* count_out, size_t* size_out);
 extern const char* get_listener_name(const struct Listener* listener);
 extern void        mark_listeners_closing(void);
-extern void show_ports(struct Client* client, struct StatDesc* sd, int stat,
+extern void show_ports(struct Client* client, const struct StatDesc* sd,
                        char* param);
 extern void        release_listener(struct Listener* listener);
 
index 130ce162bbd63d71699fdbd1d5c001de08ac2f03..785511239dcc6103c40d891d8140ae95cf9dfe2a 100644 (file)
@@ -86,7 +86,7 @@ void motd_add(const char *hostmask, const char *path);
 void motd_clear(void);
 
 /* This is called to report T-lines */
-void motd_report(struct Client *to, struct StatDesc *sd, int stat,
+void motd_report(struct Client *to, const struct StatDesc *sd,
                  char *param);
 void motd_memory_count(struct Client *cptr);
 
index cde01bb227c57a1bb2b9aae551128204f43a5b87..afee6e93fbac75693d7c896971c663f498ee6f9c 100644 (file)
@@ -84,7 +84,7 @@ extern void msgq_clean(struct MsgBuf *mb);
 extern void msgq_add(struct MsgQ *mq, struct MsgBuf *mb, int prio);
 extern void msgq_count_memory(struct Client *cptr,
                               size_t *msg_alloc, size_t *msg_used);
-extern void msgq_histogram(struct Client *cptr, struct StatDesc *sd, int stat,
+extern void msgq_histogram(struct Client *cptr, const struct StatDesc *sd,
                            char *param);
 extern unsigned int msgq_bufleft(struct MsgBuf *mb);
 
index d2c54e9bc7125731624b67f402a730e0276e60c3..bb22a14ebaf22ef70d1a895356e2703b22692055 100644 (file)
@@ -126,7 +126,7 @@ extern void restart_resolver(void);
 extern void add_local_domain(char *hname, size_t size);
 extern size_t cres_mem(struct Client* cptr);
 extern void delete_resolver_queries(const void *vptr);
-extern void report_dns_servers(struct Client *source_p, struct StatDesc *sd, int stat, char *param);
+extern void report_dns_servers(struct Client *source_p, const struct StatDesc *sd, char *param);
 extern void gethost_byname(const char *name, const struct DNSQuery *query);
 extern void gethost_byaddr(const struct irc_in_addr *addr, const struct DNSQuery *query);
 
index 9b3f5e3c8a9440b9f5dbbc4effedab175b7769a4..35e84d0053c97e70a50cebab2e67f125106f5cd3 100644 (file)
@@ -49,7 +49,7 @@ struct StatDesc;
 
 extern void vdebug(int level, const char *form, va_list vl);
 extern void debug(int level, const char *form, ...);
-extern void send_usage(struct Client *cptr, struct StatDesc *sd, int stat,
+extern void send_usage(struct Client *cptr, const struct StatDesc *sd,
                        char *param);
 
 #else /* !DEBUGMODE */
@@ -61,7 +61,7 @@ extern void send_usage(struct Client *cptr, struct StatDesc *sd, int stat,
 
 extern const char* debug_serveropts(void);
 extern void debug_init(int use_tty);
-extern void count_memory(struct Client *cptr, struct StatDesc *sd, int stat,
+extern void count_memory(struct Client *cptr, const struct StatDesc *sd,
                          char *param);
 
 #endif /* INCLUDED_s_debug_h */
index 8c2983b8ed6c8f354ef7fd85819a03a9ef396f3f..655bff1bbaa60855782721e977723a16bc4722a1 100644 (file)
@@ -75,7 +75,7 @@ extern const char* get_client_host(const struct Client *cptr);
 extern void get_sockhost(struct Client *cptr, char *host);
 extern int vexit_client_msg(struct Client *cptr, struct Client *bcptr,
     struct Client *sptr, const char *pattern, va_list vl);
-extern void tstats(struct Client *cptr, struct StatDesc *sd, int stat,
+extern void tstats(struct Client *cptr, const struct StatDesc *sd,
                    char *param);
 
 extern struct ServerStatistics* ServerStats;
index 2298fa3c5cd0f7cc3062e26877009ed4c11c42db..67b4e4722072157006977df279f6e482a9754543 100644 (file)
@@ -32,12 +32,13 @@ struct Client;
 
 struct StatDesc;
 
-/* Source of /stats, stats descriptor, stats char, extra param (might be 0) */
-typedef void (*StatFunc)(struct Client *, struct StatDesc *, int, char *);
+/* Source of /stats, stats descriptor, extra param (might be 0) */
+typedef void (*StatFunc)(struct Client *, const struct StatDesc *, char *);
 
 struct StatDesc
 {
   char         sd_c;           /* stats character */
+  char        *sd_name;        /* full name for stats */
   unsigned int sd_flags;       /* flags to control the stats */
   enum Feature sd_control;     /* feature controlling stats */
   StatFunc     sd_func;        /* function to dispatch to */
@@ -50,9 +51,7 @@ struct StatDesc
 #define STAT_FLAG_CASESENS 0x04    /* Flag is case-sensitive */
 #define STAT_FLAG_VARPARAM 0x08    /* may have an extra parameter */
 
-extern struct StatDesc statsinfo[];
-extern struct StatDesc *statsmap[];
-
 extern void stats_init(void);
+const struct StatDesc *stats_find(const char *name_or_char);
 
 #endif /* INCLUDED_s_stats_h */
index d44c16aee19014068a1370f564f314a92d8c8150..2f95ade26ce2e7eeeeca9cbafffd4570c910f232 100644 (file)
@@ -43,7 +43,7 @@ struct current_load_st {
  */
 
 extern void update_load(void);
-extern void calc_load(struct Client *sptr, struct StatDesc *sd, int stat,
+extern void calc_load(struct Client *sptr, const struct StatDesc *sd,
                       char *param);
 extern void initload(void);
 
index bf099f964f5a66ed8ca05478e5a1129bc8654eb8..41ed4e62aa501f51324424fa2fe593fe9fcadf3d 100644 (file)
@@ -232,7 +232,7 @@ struct ConnectionClass* find_class(const char *name)
 }
 
 void
-report_classes(struct Client *sptr, struct StatDesc *sd, int stat,
+report_classes(struct Client *sptr, const struct StatDesc *sd,
                char *param)
 {
   struct ConnectionClass *cltmp;
index 0fea0ce109a462eb90d8b5e725ed1198dcb50527..d94cfa8a608345e36374f8598f41609aa431e80b 100644 (file)
@@ -760,7 +760,7 @@ gline_list(struct Client *sptr, char *userhost)
 }
 
 void
-gline_stats(struct Client *sptr, struct StatDesc *sd, int stat,
+gline_stats(struct Client *sptr, const struct StatDesc *sd,
             char *param)
 {
   struct Gline *gline;
index 6a8f31b6365f9d7a5f1b67966f99da8e06a3db44..61e23ed20f0b6010510d87b667093eb2b76316d7 100644 (file)
@@ -713,7 +713,7 @@ feature_init(void)
 
 /* report all F-lines */
 void
-feature_report(struct Client* to, struct StatDesc* sd, int stat, char* param)
+feature_report(struct Client* to, const struct StatDesc* sd, char* param)
 {
   int i;
 
index fbc1315f5a61c65430db5f846c24863460b1c26b..4946e4beae3d0b19866188c369bd82166f7325cf 100644 (file)
@@ -859,7 +859,7 @@ make_dnsreply(struct reslist *request)
 }
 
 void
-report_dns_servers(struct Client *source_p, struct StatDesc *sd, int stat, char *param)
+report_dns_servers(struct Client *source_p, const struct StatDesc *sd, char *param)
 {
   int i;
   char ipaddr[128];
index 0556ce98eb82f0155d7f0589e6c93bd0038ec51e..08167710234fca559430c35468a961466381f60b 100644 (file)
@@ -118,7 +118,7 @@ void count_listener_memory(int* count_out, size_t* size_out)
  * side effects - show ports
  * author       - Dianora
  */
-void show_ports(struct Client* sptr, struct StatDesc* sd, int stat,
+void show_ports(struct Client* sptr, const struct StatDesc* sd,
                 char* param)
 {
   struct Listener *listener = 0;
index aeb99958e8600ecd2542d365037eb87adbcbc741..34a7464f12699b892673f2d823ae2b5fc3f40aa0 100644 (file)
 int
 m_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-  unsigned char stat = parc > 1 ? parv[1][0] : '\0';
-  struct StatDesc *sd;
+  const struct StatDesc *sd;
   char *param = 0;
 
   /* If we didn't find a descriptor and this is my client, send them help */
-  if (!(sd = statsmap[(int)stat])) {
-    stat = '*';
-    sd = statsmap[(int)stat];
-  }
+  if ((parc < 2) || !(sd = stats_find(parv[1])))
+      parv[1] = "*", sd = stats_find("*");
 
   assert(sd != 0);
 
@@ -152,8 +149,8 @@ m_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   assert(sd->sd_func != 0);
 
   /* Ok, dispatch the stats function */
-  (*sd->sd_func)(sptr, sd, stat, param);
+  (*sd->sd_func)(sptr, sd, param);
 
   /* Done sending them the stats */
-  return send_reply(sptr, RPL_ENDOFSTATS, stat);
+  return send_reply(sptr, RPL_ENDOFSTATS, parv[1]);
 }
index 11b606427e4cdf0be65ce666ae81ff8d2820f290..bfe0cfc28fd2f0dbad60ff88f744f50e87353598 100644 (file)
@@ -372,7 +372,7 @@ motd_clear(void)
 
 /* This is called to report T-lines */
 void
-motd_report(struct Client *to, struct StatDesc *sd, int stat, char *param)
+motd_report(struct Client *to, const struct StatDesc *sd, char *param)
 {
   struct Motd *ptr;
 
index 043c8590fec7480214106e6e680018560882317d..01523a46ccffce27fcfe095e45a088b9252dd23d 100644 (file)
@@ -576,7 +576,7 @@ msgq_bufleft(struct MsgBuf *mb)
  * requesting client
  */
 void
-msgq_histogram(struct Client *cptr, struct StatDesc *sd, int stat, char *param)
+msgq_histogram(struct Client *cptr, const struct StatDesc *sd, char *param)
 {
   struct MsgSizes tmp = MQData.sizes; /* All hail structure copy! */
   int i;
index b861345d923c7cee70bb64e178bb2a00141bf42b..5c9ec6ef133fee7edbfb1b6be0715f2d756b5777 100644 (file)
@@ -170,7 +170,7 @@ static void debug_enumerator(struct Client* cptr, const char* msg)
  * different field names for "struct rusage".
  * -avalon
  */
-void send_usage(struct Client *cptr, struct StatDesc *sd, int stat,
+void send_usage(struct Client *cptr, const struct StatDesc *sd,
                 char *param)
 {
   os_get_rusage(cptr, CurrentTime - cli_since(&me), debug_enumerator);
@@ -180,7 +180,7 @@ void send_usage(struct Client *cptr, struct StatDesc *sd, int stat,
 }
 #endif /* DEBUGMODE */
 
-void count_memory(struct Client *cptr, struct StatDesc *sd, int stat,
+void count_memory(struct Client *cptr, const struct StatDesc *sd,
                   char *param)
 {
   struct Client *acptr;
index 46feebfb3c150f0aa54c1c06a55c709413ea0fb4..15a239669705e8c8c47bdc772c506b13243401be 100644 (file)
@@ -470,7 +470,7 @@ static Numeric replyTable[] = {
 /* 218 */
   { RPL_STATSYLINE, "%c %s %d %d %d %ld %d", "218" },
 /* 219 */
-  { RPL_ENDOFSTATS, "%c :End of /STATS report", "219" },
+  { RPL_ENDOFSTATS, "%s :End of /STATS report", "219" },
 /* 220 */
   { 0 },
 /* 221 */
index 16162a6de1ec40469fc6f874aa0cb8bb1ef21a66..052d864e6053c2a6ed7ee5f58aef2763847814a7 100644 (file)
@@ -551,7 +551,7 @@ void initstats(void)
   memset(&ircst, 0, sizeof(ircst));
 }
 
-void tstats(struct Client *cptr, struct StatDesc *sd, int stat, char *param)
+void tstats(struct Client *cptr, const struct StatDesc *sd, char *param)
 {
   struct Client *acptr;
   int i;
index 89ef883446b68bb879f4bd579d8bb7a8f5c0a21c..16985c879b0f49e326bf9cee0f16c8e10cec94c3 100644 (file)
@@ -64,7 +64,7 @@
  * m_stats/s_stats
  *
  * Report configuration lines and other statistics from this
- * server. 
+ * server.
  *
  * Note: The info is reported in the order the server uses
  *       it--not reversed as in ircd.conf!
@@ -80,8 +80,14 @@ static unsigned int report_array[17][3] = {
   {0, 0}
 };
 
+/* The statsinfo array should only be used in this file, but just TRY
+ * telling the compiler that you want to forward declare a static array,
+ * and see how it responds.  So we forward declare it "extern".
+ */
+extern struct StatDesc statsinfo[];
+
 static void
-stats_configured_links(struct Client *sptr, struct StatDesc* sd, int stat,
+stats_configured_links(struct Client *sptr, const struct StatDesc* sd,
                        char* param)
 {
   static char null[] = "<NULL>";
@@ -90,7 +96,7 @@ stats_configured_links(struct Client *sptr, struct StatDesc* sd, int stat,
   unsigned int *p;
   unsigned short int port;
   char c, *host, *pass, *name;
-  
+
   mask = sd->sd_funcdata;
 
   for (tmp = GlobalConfList; tmp; tmp = tmp->next) 
@@ -135,29 +141,26 @@ stats_configured_links(struct Client *sptr, struct StatDesc* sd, int stat,
  * {CONF_CRULEAUTO, RPL_STATSDLINE, 'd'},
  */
 static void
-stats_crule_list(struct Client* to, struct StatDesc *sd, int stat,
+stats_crule_list(struct Client* to, const struct StatDesc *sd,
                  char *param)
 {
-  int mask;
   const struct CRuleConf* p = conf_get_crule_list();
 
-  mask = (stat == 'D') ? CRULE_ALL : CRULE_MASK;
-
   for ( ; p; p = p->next)
   {
-    if (p->type & mask)
-      send_reply(to, RPL_STATSDLINE, stat, p->hostmask, p->rule);
+    if (p->type & sd->sd_funcdata)
+      send_reply(to, RPL_STATSDLINE, sd->sd_c, p->hostmask, p->rule);
   }
 }
 
 static void
-stats_engine(struct Client *to, struct StatDesc *sd, int stat, char *param)
+stats_engine(struct Client *to, const struct StatDesc *sd, char *param)
 {
   send_reply(to, RPL_STATSENGINE, engine_name());
 }
 
 static void
-stats_access(struct Client *to, struct StatDesc *sd, int stat, char *param)
+stats_access(struct Client *to, const struct StatDesc *sd, char *param)
 {
   struct ConfItem *aconf;
   int wilds = 0;
@@ -165,7 +168,7 @@ stats_access(struct Client *to, struct StatDesc *sd, int stat, char *param)
 
   if (!param)
   {
-    stats_configured_links(to, sd, stat, param);
+    stats_configured_links(to, sd, param);
     return;
   }
 
@@ -204,7 +207,7 @@ report_deny_list(struct Client* to)
 }
 
 static void
-stats_klines(struct Client *sptr, struct StatDesc *sd, int stat, char *mask)
+stats_klines(struct Client *sptr, const struct StatDesc *sd, char *mask)
 {
   int wilds = 0;
   int count = 3;
@@ -212,10 +215,10 @@ stats_klines(struct Client *sptr, struct StatDesc *sd, int stat, char *mask)
   char *user  = 0;
   char *host;
   const struct DenyConf* conf;
+
   if (!IsAnOper(sptr))
     limit_query = 1;
-  
+
   if (!mask)
   {
     if (limit_query)
@@ -256,7 +259,7 @@ stats_klines(struct Client *sptr, struct StatDesc *sd, int stat, char *mask)
 }
 
 static void
-stats_links(struct Client* sptr, struct StatDesc* sd, int stat, char* name)
+stats_links(struct Client* sptr, const struct StatDesc* sd, char* name)
 {
   struct Client *acptr;
   int i;
@@ -301,7 +304,7 @@ stats_links(struct Client* sptr, struct StatDesc* sd, int stat, char* name)
 
 /* hopefuly this will be where we'll spit out info about loaded modules */
 static void
-stats_modules(struct Client* to, struct StatDesc* sd, int stat, char* param)
+stats_modules(struct Client* to, const struct StatDesc* sd, char* param)
 {
 crypt_mechs_t* mechs;
 
@@ -333,7 +336,7 @@ crypt_mechs_t* mechs;
 }
 
 static void
-stats_commands(struct Client* to, struct StatDesc* sd, int stat, char* param)
+stats_commands(struct Client* to, const struct StatDesc* sd, char* param)
 {
   struct Message *mptr;
 
@@ -343,7 +346,7 @@ stats_commands(struct Client* to, struct StatDesc* sd, int stat, char* param)
 }
 
 static void
-stats_quarantine(struct Client* to, struct StatDesc* sd, int stat, char* param)
+stats_quarantine(struct Client* to, const struct StatDesc* sd, char* param)
 {
   struct qline *qline;
 
@@ -354,9 +357,9 @@ stats_quarantine(struct Client* to, struct StatDesc* sd, int stat, char* param)
     send_reply(to, RPL_STATSQLINE, qline->chname, qline->reason);
   }
 }
+
 static void
-stats_mapping(struct Client *to, struct StatDesc* sd, int stat, char* param)
+stats_mapping(struct Client *to, const struct StatDesc* sd, char* param)
 {
   struct s_map *map;
 
@@ -371,7 +374,7 @@ stats_mapping(struct Client *to, struct StatDesc* sd, int stat, char* param)
 }
 
 static void
-stats_uptime(struct Client* to, struct StatDesc* sd, int stat, char* param)
+stats_uptime(struct Client* to, const struct StatDesc* sd, char* param)
 {
   time_t nowr;
 
@@ -382,20 +385,25 @@ stats_uptime(struct Client* to, struct StatDesc* sd, int stat, char* param)
 }
 
 static void
-stats_servers_verbose(struct Client* sptr, struct StatDesc* sd, int stat,
+stats_servers_verbose(struct Client* sptr, const struct StatDesc* sd,
                      char* param)
 {
   struct Client *acptr;
-  
+  const char *fmt;
+
   /*
    * lowercase 'v' is for human-readable,
    * uppercase 'V' is for machine-readable
    */
-  if (stat == 'v')
+  if (sd->sd_funcdata) {
     send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE,
                "%-20s %-20s Flags Hops Numeric   Lag  RTT   Up Down "
                "Clients/Max Proto %-10s :Info", "Servername", "Uplink",
                "LinkTS");
+    fmt = "%-20s %-20s %c%c%c%c  %4i %s %-4i %5i %4i %4i %4i %5i %5i P%-2i   %Tu :%s";
+  } else {
+    fmt = "%s %s %c%c%c%c %i %s %i %i %i %i %i %i %i P%i %Tu :%s";
+  }
 
   for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr))
   {
@@ -404,10 +412,7 @@ stats_servers_verbose(struct Client* sptr, struct StatDesc* sd, int stat,
     /* narrow search */
     if (param && match(param, cli_name(acptr)))
       continue;
-    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE, stat == 'v' ?
-               "%-20s %-20s %c%c%c%c  %4i %s %-4i %5i %4i %4i %4i %5i %5i "
-               "P%-2i   %Tu :%s" :
-               "%s %s %c%c%c%c %i %s %i %i %i %i %i %i %i P%i %Tu :%s",
+    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE, fmt,
                cli_name(acptr),
                cli_name(cli_serv(acptr)->up),
                IsBurst(acptr) ? 'B' : '-',
@@ -431,7 +436,7 @@ stats_servers_verbose(struct Client* sptr, struct StatDesc* sd, int stat,
 
 #ifdef DEBUGMODE
 static void
-stats_meminfo(struct Client* to, struct StatDesc* sd, int stat, char* param)
+stats_meminfo(struct Client* to, const struct StatDesc* sd, char* param)
 {
   class_send_meminfo(to);
   send_listinfo(to, 0);
@@ -439,122 +444,152 @@ stats_meminfo(struct Client* to, struct StatDesc* sd, int stat, char* param)
 #endif
 
 static void
-stats_help(struct Client* to, struct StatDesc* sd, int stat, char* param)
+stats_help(struct Client* to, const struct StatDesc* sd, char* param)
 {
   struct StatDesc *asd;
 
   /* only if it's my user */
   if (MyUser(to))
-    for (asd = statsinfo; asd->sd_c; asd++)
-      if (asd->sd_c != sd->sd_c) /* don't send the help for us */
-        sendcmdto_one(&me, CMD_NOTICE, to, "%C :%c - %s", to, asd->sd_c,
-                      asd->sd_desc);
+    for (asd = statsinfo; asd->sd_name; asd++)
+      if (asd != sd) /* don't send the help for us */
+        sendcmdto_one(&me, CMD_NOTICE, to, "%C :%c (%s) - %s", to, asd->sd_c,
+                      asd->sd_name, asd->sd_desc);
 }
 
 /* This array of structures contains information about all single-character
  * stats.  Struct StatDesc is defined in s_stats.h.
  */
 struct StatDesc statsinfo[] = {
-  { 'a', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_a,
+  { 'a', "nameservers", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_a,
     report_dns_servers, 0,
     "DNS servers." },
-  { 'c', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_c,
+  { 'c', "connect", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_c,
     stats_configured_links, CONF_SERVER,
     "Remote server connection lines." },
-  { 'd', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_d,
-    stats_crule_list, 0,
+  { 'd', "maskrules", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_d,
+    stats_crule_list, CRULE_MASK,
     "Dynamic routing configuration." },
-  { 'e', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_e,
+  { 'D', "crules", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_d,
+    stats_crule_list, CRULE_ALL,
+    "Dynamic routing configuration." },
+  { 'e', "engine", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_e,
     stats_engine, 0,
     "Report server event loop engine." },
-  { 'f', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_f,
+  { 'f', "features", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_f,
     feature_report, 0,
     "Feature settings." },
-  { 'g', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_g,
+  { 'g', "glines", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_g,
     gline_stats, 0,
     "Global bans (G-lines)." },
-  { 'h', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_h,
+  { 'h', "hubs", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_h,
     stats_configured_links, (CONF_HUB | CONF_LEAF),
     "Hubs information." },
-  { 'i', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_i,
+  { 'i', "access", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_i,
     stats_access, CONF_CLIENT,
     "Connection authorization lines." },
-  { 'j', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_j,
+  { 'j', "histogram", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_j,
     msgq_histogram, 0,
     "Message length histogram." },
-  { 'k', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_k,
+  { 'k', "klines", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_k,
     stats_klines, 0,
     "Local bans (K-Lines)." },
-  { 'l', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS), 
+  { 'l', "links", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS),
     FEAT_HIS_STATS_l,
     stats_links, 0,
     "Current connections information." },
-  { 'L', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS), 
+  { 'L', "modules", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS),
     FEAT_HIS_STATS_L,
     stats_modules, 0,
-    "Dynamicly loaded modules." },
-#if 0
-  { 'M', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_M,
-    stats_memtotal, 0,
-    "Memory allocation & leak monitoring." },
-#endif
-  { 'm', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_m,
+    "Dynamically loaded modules." },
+  { 'm', "commands", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_m,
     stats_commands, 0,
     "Message usage information." },
-  { 'o', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_o,
+  { 'o', "operators", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_o,
     stats_configured_links, CONF_OPERATOR,
     "Operator information." },
-  { 'p', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_p,
+  { 'p', "ports", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_p,
     show_ports, 0,
     "Listening ports." },
-  { 'q', (STAT_FLAG_OPERONLY | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_q,
+  { 'q', "quarantines", (STAT_FLAG_OPERONLY | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_q,
     stats_quarantine, 0,
     "Quarantined channels list." },
-  { 'R', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_R,
+  { 'R', "mappings", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_R,
     stats_mapping, 0,
     "Service mappings." },
 #ifdef DEBUGMODE
-  { 'r', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_r,
+  { 'r', "usage", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_r,
     send_usage, 0,
     "System resource usage (Debug only)." },
 #endif
-  { 'T', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_T,
+  { 'T', "motds", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_T,
     motd_report, 0,
     "Configured Message Of The Day files." },
-  { 't', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_t,
+  { 't', "locals", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_t,
     tstats, 0,
     "Local connection statistics (Total SND/RCV, etc)." },
-  { 'U', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_U,
+  { 'U', "uworld", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_U,
     stats_configured_links, CONF_UWORLD,
     "Service server & nick jupes information." },
-  { 'u', (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_u,
+  { 'u', "uptime", (STAT_FLAG_OPERFEAT | STAT_FLAG_CASESENS), FEAT_HIS_STATS_u,
     stats_uptime, 0,
     "Current uptime & highest connection count." },
-  { 'v', (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM), FEAT_HIS_STATS_v,
+  { 'v', "vservers", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS), FEAT_HIS_STATS_v,
+    stats_servers_verbose, 1,
+    "Verbose server information." },
+  { 'V', "vserversmach", (STAT_FLAG_OPERFEAT | STAT_FLAG_VARPARAM | STAT_FLAG_CASESENS), FEAT_HIS_STATS_v,
     stats_servers_verbose, 0,
     "Verbose server information." },
-  { 'w', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_w,
+  { 'w', "userload", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_w,
     calc_load, 0,
     "Userload statistics." },
 #ifdef DEBUGMODE
-  { 'x', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_x,
+  { 'x', "memusage", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_x,
     stats_meminfo, 0,
     "List usage information (Debug only)." },
 #endif
-  { 'y', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_y,
+  { 'y', "classes", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_y,
     report_classes, 0,
     "Connection classes." },
-  { 'z', STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_z,
+  { 'z', "memory", STAT_FLAG_OPERFEAT, FEAT_HIS_STATS_z,
     count_memory, 0,
     "Memory/Structure allocation information." },
-  { '*', (STAT_FLAG_CASESENS | STAT_FLAG_VARPARAM), FEAT_LAST_F,
+  { '*', "help", (STAT_FLAG_CASESENS | STAT_FLAG_VARPARAM), FEAT_LAST_F,
     stats_help, 0,
     "Send help for stats." },
   { '\0', 0, FEAT_LAST_F, 0, 0, 0 }
 };
 
 /* This array is for mapping from characters to statistics descriptors */
-struct StatDesc *statsmap[256];
+static struct StatDesc *statsmap[256];
+static int statscount;
+
+static int
+stats_cmp(const void *a_, const void *b_)
+{
+  const struct StatDesc *a = a_;
+  const struct StatDesc *b = b_;
+  return ircd_strcmp(a->sd_name, b->sd_name);
+}
+
+static int
+stats_search(const void *key, const void *sd_)
+{
+  const struct StatDesc *sd = sd_;
+  return ircd_strcmp(key, sd->sd_name);
+}
+
+/* Look up a stats handler.  If name_or_char is just one character
+ * long, use that as a character index; otherwise, look it up by
+ * name in statsinfo.
+ */
+const struct StatDesc *
+stats_find(const char *name_or_char)
+{
+  if (!name_or_char[1])
+    return statsmap[(int)name_or_char[0]];
+  else
+    return bsearch(name_or_char, statsinfo, statscount, sizeof(statsinfo[0]), stats_search);
+}
 
 /* Function to build the statsmap from the statsinfo array */
 void
@@ -567,10 +602,16 @@ stats_init(void)
   for (i = 0; i < 256; i++)
     statsmap[i] = 0;
 
+  /* Count number of stats entries and sort them. */
+  for (statscount = 0, sd = statsinfo; sd->sd_name; sd++, statscount++) {}
+  qsort(statsinfo, statscount, sizeof(statsinfo[0]), stats_cmp);
+
   /* Build the mapping */
-  for (sd = statsinfo; sd->sd_c; sd++)
+  for (sd = statsinfo; sd->sd_name; sd++)
   {
-    if (sd->sd_flags & STAT_FLAG_CASESENS)
+    if (!sd->sd_c)
+      continue;
+    else if (sd->sd_flags & STAT_FLAG_CASESENS)
       /* case sensitive character... */
       statsmap[(int)sd->sd_c] = sd;
     else
index 02571b0fb5933c1f7eff34e7e5c9ed269438850a..c2ac9cec30f77acba70b768a26fa9a50ca17e967 100644 (file)
@@ -218,8 +218,10 @@ int hunt_server_cmd(struct Client *from, const char *cmd, const char *tok,
       send_reply(from, ERR_NOSUCHSERVER, to);
       return (HUNTED_NOSUCH);
     }
-  } else if (!(acptr = FindNServer(to)))
+  } else if (!(acptr = FindNServer(to))) {
+    send_reply(from, SND_EXPLICIT | ERR_NOSUCHSERVER, "* :Server has disconnected");
     return (HUNTED_NOSUCH);        /* Server broke off in the meantime */
+  }
 
   if (IsMe(acptr))
     return (HUNTED_ISME);
index ae05bf21ab63421ed2f64c1942f0abe8372674a1..af8404e2fa6fef54e56586ff0555033d2562d5a0 100644 (file)
@@ -202,7 +202,7 @@ void update_load(void)
 }
 
 void
-calc_load(struct Client *sptr, struct StatDesc *sd, int stat, char *param)
+calc_load(struct Client *sptr, const struct StatDesc *sd, char *param)
 {
   /* *INDENT-OFF* */
   static const char *header =