From a8461738cd722ccdafa0f6ad127578c84cb57046 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Sun, 12 Sep 2004 03:53:44 +0000 Subject: [PATCH] Allow /stats to accept long names for the displayed statistics. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1135 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 28 ++++++ include/class.h | 2 +- include/gline.h | 2 +- include/ircd_features.h | 2 +- include/listener.h | 2 +- include/motd.h | 2 +- include/msgq.h | 2 +- include/res.h | 2 +- include/s_debug.h | 4 +- include/s_misc.h | 2 +- include/s_stats.h | 9 +- include/userload.h | 2 +- ircd/class.c | 2 +- ircd/gline.c | 2 +- ircd/ircd_features.c | 2 +- ircd/ircd_res.c | 2 +- ircd/listener.c | 2 +- ircd/m_stats.c | 13 ++- ircd/motd.c | 2 +- ircd/msgq.c | 2 +- ircd/s_debug.c | 4 +- ircd/s_err.c | 2 +- ircd/s_misc.c | 2 +- ircd/s_stats.c | 187 ++++++++++++++++++++++++---------------- ircd/s_user.c | 4 +- ircd/userload.c | 2 +- 26 files changed, 177 insertions(+), 110 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4320de5..d03fc41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2004-09-11 Michael Poole + + * 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 * include/numeric.h, ircd/s_err.c: Remove RPL_TRACEPING, and diff --git a/include/class.h b/include/class.h index e5d0b54..d5901b3 100644 --- a/include/class.h +++ b/include/class.h @@ -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); diff --git a/include/gline.h b/include/gline.h index 50ef608..f3f88eb 100644 --- a/include/gline.h +++ b/include/gline.h @@ -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); diff --git a/include/ircd_features.h b/include/ircd_features.h index e513587..58a0d61 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -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); diff --git a/include/listener.h b/include/listener.h index f33564e..1dcbba6 100644 --- a/include/listener.h +++ b/include/listener.h @@ -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); diff --git a/include/motd.h b/include/motd.h index 130ce16..7855112 100644 --- a/include/motd.h +++ b/include/motd.h @@ -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); diff --git a/include/msgq.h b/include/msgq.h index cde01bb..afee6e9 100644 --- a/include/msgq.h +++ b/include/msgq.h @@ -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); diff --git a/include/res.h b/include/res.h index d2c54e9..bb22a14 100644 --- a/include/res.h +++ b/include/res.h @@ -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); diff --git a/include/s_debug.h b/include/s_debug.h index 9b3f5e3..35e84d0 100644 --- a/include/s_debug.h +++ b/include/s_debug.h @@ -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 */ diff --git a/include/s_misc.h b/include/s_misc.h index 8c2983b..655bff1 100644 --- a/include/s_misc.h +++ b/include/s_misc.h @@ -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; diff --git a/include/s_stats.h b/include/s_stats.h index 2298fa3..67b4e47 100644 --- a/include/s_stats.h +++ b/include/s_stats.h @@ -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 */ diff --git a/include/userload.h b/include/userload.h index d44c16a..2f95ade 100644 --- a/include/userload.h +++ b/include/userload.h @@ -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); diff --git a/ircd/class.c b/ircd/class.c index bf099f9..41ed4e6 100644 --- a/ircd/class.c +++ b/ircd/class.c @@ -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; diff --git a/ircd/gline.c b/ircd/gline.c index 0fea0ce..d94cfa8 100644 --- a/ircd/gline.c +++ b/ircd/gline.c @@ -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; diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index 6a8f31b..61e23ed 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -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; diff --git a/ircd/ircd_res.c b/ircd/ircd_res.c index fbc1315..4946e4b 100644 --- a/ircd/ircd_res.c +++ b/ircd/ircd_res.c @@ -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]; diff --git a/ircd/listener.c b/ircd/listener.c index 0556ce9..0816771 100644 --- a/ircd/listener.c +++ b/ircd/listener.c @@ -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; diff --git a/ircd/m_stats.c b/ircd/m_stats.c index aeb9995..34a7464 100644 --- a/ircd/m_stats.c +++ b/ircd/m_stats.c @@ -117,15 +117,12 @@ 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]); } diff --git a/ircd/motd.c b/ircd/motd.c index 11b6064..bfe0cfc 100644 --- a/ircd/motd.c +++ b/ircd/motd.c @@ -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; diff --git a/ircd/msgq.c b/ircd/msgq.c index 043c859..01523a4 100644 --- a/ircd/msgq.c +++ b/ircd/msgq.c @@ -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; diff --git a/ircd/s_debug.c b/ircd/s_debug.c index b861345..5c9ec6e 100644 --- a/ircd/s_debug.c +++ b/ircd/s_debug.c @@ -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; diff --git a/ircd/s_err.c b/ircd/s_err.c index 46feebf..15a2396 100644 --- a/ircd/s_err.c +++ b/ircd/s_err.c @@ -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 */ diff --git a/ircd/s_misc.c b/ircd/s_misc.c index 16162a6..052d864 100644 --- a/ircd/s_misc.c +++ b/ircd/s_misc.c @@ -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; diff --git a/ircd/s_stats.c b/ircd/s_stats.c index 89ef883..16985c8 100644 --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -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[] = ""; @@ -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 diff --git a/ircd/s_user.c b/ircd/s_user.c index 02571b0..c2ac9ce 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -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); diff --git a/ircd/userload.c b/ircd/userload.c index ae05bf2..af8404e 100644 --- a/ircd/userload.c +++ b/ircd/userload.c @@ -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 = -- 2.20.1