"Fossies" - the Fresh Open Source Software Archive

Member "bahamut-2.1.5/src/m_stats.c" (28 May 2020, 33609 Bytes) of package /linux/privat/bahamut-2.1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "m_stats.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1.4_vs_2.1.5.

    1 /* m_stats.c
    2  * Copyright (c) 2004, The Bahamut Development Team and Aaron Wiebe
    3  *
    4  *   See file AUTHORS in IRC package for additional names of
    5  *   the programmers.
    6  *
    7  *   This program is free softwmare; you can redistribute it and/or modify
    8  *   it under the terms of the GNU General Public License as published by
    9  *   the Free Software Foundation; either version 1, or (at your option)
   10  *   any later version.
   11  *
   12  *   This program is distributed in the hope that it will be useful,
   13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  *   GNU General Public License for more details.
   16  *
   17  *   You should have received a copy of the GNU General Public License
   18  *   along with this program; if not, write to the Free Software
   19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   20  */
   21 
   22 #include "struct.h"
   23 #include "common.h"
   24 #include "sys.h"
   25 #include "numeric.h"
   26 #include "msg.h"
   27 #include "channel.h"
   28 #include <sys/stat.h>
   29 #include <fcntl.h>
   30 #include "h.h"
   31 #include "zlink.h"
   32 #include "userban.h"
   33 #include "blalloc.h"
   34 #include "throttle.h"
   35 #include "whowas.h"
   36 #include "res.h"
   37 #include "sbuf.h"
   38 #include "clones.h"
   39 #include "memcount.h"
   40 
   41 #if defined(DEBUGMODE) && defined(HAVE_GETRUSAGE)
   42 #include <sys/time.h>
   43 #include <sys/resource.h>
   44 #endif
   45 
   46 extern float curSendK, curRecvK;
   47 extern aWhowas WHOWAS[];
   48 extern aCache *cachetop;
   49 #ifdef DEBUGMODE
   50 extern void report_fds(aClient *);
   51 #endif
   52 extern char *oflagtotext(int oflags); /* For stats o */
   53 extern char *cflagtotext(int cflags, int uflags); /* For stats c */
   54 extern char *iflagtotext(int iflags); /* For stats i */
   55 extern int report_spamfilters(aClient *cptr, aClient *sptr, int parc, char *parv[]); /* For stats S */
   56 
   57 /* internal function defines */
   58 
   59 static void show_opers(aClient *, char *);
   60 static void show_servers(aClient *, char *);
   61 #ifdef DEBUGMODE
   62 static void send_usage(aClient *, char *);
   63 #endif
   64 static void serv_info(aClient *, char *);
   65 static void tstats(aClient *, char *);
   66 
   67 /* support functions */
   68 /* show_opers
   69  * replies to stats p requests
   70  */
   71 
   72 
   73 #ifdef DEBUGMODE
   74 static void
   75 send_usage(aClient *cptr, char *nick)
   76 {
   77 
   78 #if defined( HAVE_GETRUSAGE )
   79     struct rusage rus;
   80     time_t      secs, rup;
   81 
   82 #ifdef  hz
   83 #define hzz hz
   84 #else
   85 #ifdef HZ
   86 #define hzz HZ
   87 #else
   88     int         hzz = 1;
   89 
   90 #endif
   91 #endif
   92 
   93     if (getrusage(RUSAGE_SELF, &rus) == -1) {
   94         sendto_one(cptr, ":%s NOTICE %s :Getruseage error: %s.",
   95                    me.name, nick, sys_errlist[errno]);
   96         return;
   97     }
   98     secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
   99     rup = timeofday - me.since;
  100     if (secs == 0)
  101         secs = 1;
  102 
  103     sendto_one(cptr,
  104                ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
  105                me.name, RPL_STATSDEBUG, nick, secs / 60, secs % 60,
  106                rus.ru_utime.tv_sec / 60, rus.ru_utime.tv_sec % 60,
  107                rus.ru_stime.tv_sec / 60, rus.ru_stime.tv_sec % 60);
  108     sendto_one(cptr, ":%s %d %s :RSS %d ShMem %d Data %d Stack %d",
  109                me.name, RPL_STATSDEBUG, nick, rus.ru_maxrss,
  110                rus.ru_ixrss / (rup * hzz), rus.ru_idrss / (rup * hzz),
  111                rus.ru_isrss / (rup * hzz));
  112     sendto_one(cptr, ":%s %d %s :Swaps %d Reclaims %d Faults %d",
  113                me.name, RPL_STATSDEBUG, nick, rus.ru_nswap,
  114                rus.ru_minflt, rus.ru_majflt);
  115     sendto_one(cptr, ":%s %d %s :Block in %d out %d",
  116                me.name, RPL_STATSDEBUG, nick, rus.ru_inblock,
  117                rus.ru_oublock);
  118     sendto_one(cptr, ":%s %d %s :Msg Rcv %d Send %d",
  119                me.name, RPL_STATSDEBUG, nick, rus.ru_msgrcv, rus.ru_msgsnd);
  120     sendto_one(cptr, ":%s %d %s :Signals %d Context Vol. %d Invol %d",
  121                me.name, RPL_STATSDEBUG, nick, rus.ru_nsignals,
  122                rus.ru_nvcsw, rus.ru_nivcsw);
  123 #else
  124 #if defined( HAVE_TIMES )
  125     struct tms  tmsbuf;
  126     time_t      secs, mins;
  127     int         hzz = 1, ticpermin;
  128     int         umin, smin, usec, ssec;
  129 
  130     ticpermin = hzz * 60;
  131 
  132     umin = tmsbuf.tms_utime / ticpermin;
  133     usec = (tmsbuf.tms_utime % ticpermin) / (float) hzz;
  134     smin = tmsbuf.tms_stime / ticpermin;
  135     ssec = (tmsbuf.tms_stime % ticpermin) / (float) hzz;
  136     secs = usec + ssec;
  137     mins = (secs / 60) + umin + smin;
  138     secs %= hzz;
  139     if (times(&tmsbuf) == -1) {
  140         sendto_one(cptr, ":%s %d %s :times(2) error: %s.",
  141                    me.name, RPL_STATSDEBUG, nick, strerror(errno));
  142         return;
  143     }
  144     secs = tmsbuf.tms_utime + tmsbuf.tms_stime;
  145 
  146     sendto_one(cptr,
  147                ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
  148                me.name, RPL_STATSDEBUG, nick, mins, secs, umin, usec,
  149                smin, ssec);
  150 #endif /* HAVE_TIMES */
  151 #endif /* HAVE_GETRUSAGE */
  152     sendto_one(cptr, ":%s %d %s :Reads %d Writes %d",
  153                me.name, RPL_STATSDEBUG, nick, readcalls, writecalls);
  154 /*    sendto_one(cptr, ":%s %d %s :DBUF alloc %d used %d",
  155                me.name, RPL_STATSDEBUG, nick, DBufCount, DBufUsedCount);
  156                */
  157     sendto_one(cptr,
  158                ":%s %d %s :Writes:  <0 %d 0 %d <16 %d <32 %d <64 %d",
  159                me.name, RPL_STATSDEBUG, nick,
  160                writeb[0], writeb[1], writeb[2], writeb[3], writeb[4]);
  161     sendto_one(cptr,
  162                ":%s %d %s :<128 %d <256 %d <512 %d <1024 %d >1024 %d",
  163                me.name, RPL_STATSDEBUG, nick,
  164                writeb[5], writeb[6], writeb[7], writeb[8], writeb[9]);
  165     return;
  166 }
  167 #endif  /* DEBUGMODE */
  168 
  169 
  170 static void 
  171 show_opers(aClient *cptr, char *name) 
  172 {
  173     aClient *cptr2;
  174     DLink *lp;
  175     int j = 0;
  176 
  177     for (lp = oper_list; lp; lp = lp->next)
  178     {
  179     cptr2 = lp->value.cptr;
  180 
  181     if (!IsAnOper(cptr))
  182     {
  183         if (cptr2->umode & UMODE_h)
  184         {
  185         sendto_one(cptr, ":%s %d %s :%s (%s@%s) Idle: %ld",
  186                me.name, RPL_STATSDEBUG, name, cptr2->name,
  187                cptr2->user->username,
  188 #ifdef USER_HOSTMASKING
  189                IsUmodeH(cptr2)?cptr2->user->mhost:
  190 #endif
  191                cptr2->user->host,
  192                (long)(timeofday - cptr2->user->last));
  193         j++;
  194         }
  195     }
  196     else
  197     {
  198         sendto_one(cptr, ":%s %d %s :%s (%s@%s) Idle: %ld",
  199                me.name, RPL_STATSDEBUG, name, cptr2->name,
  200                cptr2->user->username, cptr2->user->host,
  201                (long)(timeofday - cptr2->user->last));
  202         j++;
  203     }
  204     }
  205     sendto_one(cptr, ":%s %d %s :%d OPER%s", me.name, RPL_STATSDEBUG,
  206            name, j, (j == 1) ? "" : "s");
  207 }
  208 
  209 /* show_servers
  210  * replies to stats v requests
  211  */
  212 static void 
  213 show_servers(aClient *cptr, char *name)
  214 {
  215     aClient *cptr2;
  216     DLink *lp;
  217     int j = 0;
  218 
  219     for (lp = server_list; lp; lp = lp->next)
  220     {
  221     cptr2 = lp->value.cptr;
  222 
  223 #ifdef HIDEULINEDSERVS
  224     if(IsULine(cptr2) && !IsAnOper(cptr))
  225         continue;
  226 #endif
  227     j++;
  228     sendto_one(cptr, ":%s %d %s :%s (%s!%s@%s) Idle: %ld",
  229            me.name, RPL_STATSDEBUG, name, cptr2->name,
  230            (cptr2->serv->bynick[0] ? cptr2->serv->bynick : "Remote."),
  231            (cptr2->serv->byuser[0] ? cptr2->serv->byuser : "*"),
  232            (cptr2->serv->byhost[0] ? cptr2->serv->byhost : "*"),
  233            (long)(timeofday - cptr2->lasttime));
  234     }
  235     sendto_one(cptr, ":%s %d %s :%d Server%s", me.name, RPL_STATSDEBUG,
  236            name, j, (j == 1) ? "" : "s");
  237 }
  238 
  239 /* serv_info
  240  * replies to stats ? requests
  241  */
  242 
  243 #define _1MEG   (1024.0)
  244 #define _1GIG   (1024.0*1024.0)
  245 #define _1TER   (1024.0*1024.0*1024.0)
  246 #define _GMKs(x)    ((x > _1TER) ? "Terabytes" : ((x > _1GIG) ? \
  247                         "Gigabytes" : \
  248             ((x > _1MEG) ? "Megabytes" : "Kilobytes")))
  249 #define _GMKv(x)    ( (x > _1TER) ? (float)(x/_1TER) : ((x > _1GIG) ? \
  250             (float)(x/_1GIG) : ((x > _1MEG) ? (float)(x/_1MEG) :\
  251                         (float)x)))
  252 
  253 static void 
  254 serv_info(aClient *cptr, char *name)
  255 {
  256     static char Lformat[] = ":%s %d %s %s %u %u %u %u %u :%u %u %s";
  257     long        sendK, receiveK, uptime;
  258     aClient    *acptr;
  259     DLink      *lp;
  260     int         i = 0;
  261 
  262     sendK = receiveK = 0;
  263 
  264     for (lp = server_list; lp; lp = lp->next)
  265     {
  266         acptr = lp->value.cptr;
  267 
  268 #ifdef HIDEULINEDSERVS
  269         if (IsULine(acptr) && !IsAnOper(cptr))
  270             continue;
  271 #endif
  272         sendK += acptr->sendK;
  273         receiveK += acptr->receiveK;
  274         sendto_one(cptr, Lformat, me.name, RPL_STATSLINKINFO,
  275                     name, ( (MyClient(cptr) && IsAdmin(cptr))
  276                             ? get_client_name(acptr, FALSE)
  277                             : get_client_name(acptr, HIDEME) ),
  278                     (int) SBufLength(&acptr->sendQ),
  279                     (int) acptr->sendM, (int) acptr->sendK,
  280                     (int) acptr->receiveM, (int) acptr->receiveK,
  281                     timeofday - acptr->firsttime, timeofday - acptr->since,
  282                     IsServer(acptr) ? (DoesTS(acptr) ? "TS" : "NoTS") : "-");
  283 
  284 
  285         if(RC4EncLink(acptr))
  286             sendto_one(cptr, ":%s %d %s : - RC4 encrypted", me.name, 
  287                         RPL_STATSDEBUG, name);
  288 
  289         if(ZipOut(acptr))
  290         {
  291             unsigned long ib, ob;
  292             double rat;
  293 
  294             zip_out_get_stats(acptr->serv->zip_out, &ib, &ob, &rat);
  295             if(ib)
  296             {
  297                 sendto_one(cptr, ":%s %d %s : - [O] Zip inbytes %lu, "
  298                             "outbytes %lu (%3.2f%%)", me.name, RPL_STATSDEBUG,
  299                              name, ib, ob, rat);
  300             }
  301         }
  302 
  303         if(ZipIn(acptr))
  304         {
  305             unsigned long ib, ob;
  306             double rat;
  307 
  308             zip_in_get_stats(acptr->serv->zip_in, &ib, &ob, &rat);
  309             if(ob)
  310             {
  311                 sendto_one(cptr, ":%s %d %s : - [I] Zip inbytes %lu, "
  312                             "outbytes %lu (%3.2f%%)", me.name, RPL_STATSDEBUG,
  313                              name, ib, ob, rat);
  314             }
  315         }
  316         i++;
  317     }
  318     sendto_one(cptr, ":%s %d %s :%u total server%s",
  319            me.name, RPL_STATSDEBUG, name, i, (i == 1) ? "" : "s");
  320     sendto_one(cptr, ":%s %d %s :Sent total : %7.2f %s",
  321            me.name, RPL_STATSDEBUG, name, _GMKv(sendK), _GMKs(sendK));
  322     sendto_one(cptr, ":%s %d %s :Recv total : %7.2f %s",
  323            me.name, RPL_STATSDEBUG, name, _GMKv(receiveK),
  324            _GMKs(receiveK));
  325 
  326     uptime = (timeofday - me.since);
  327     sendto_one(cptr, ":%s %d %s :Server send: %7.2f %s (%4.1f K/s total,"
  328                      " %4.1f K/s current)", me.name, RPL_STATSDEBUG, name,
  329                      _GMKv(me.sendK), _GMKs(me.sendK), 
  330                     (float) ((float) me.sendK / (float) uptime), curSendK);
  331     sendto_one(cptr, ":%s %d %s :Server recv: %7.2f %s (%4.1f K/s total,"
  332                      " %4.1f K/s current)", me.name, RPL_STATSDEBUG, name, 
  333                     _GMKv(me.receiveK), _GMKs(me.receiveK),
  334                     (float) ((float) me.receiveK / (float) uptime), curRecvK);
  335 }
  336 
  337 /* tstats
  338  * responced to stats t requests (oddly enough)
  339  */
  340 
  341 static void 
  342 tstats(aClient *cptr, char *name)
  343 {
  344     aClient *acptr;
  345     int     i;
  346     struct stats *sp;
  347     struct stats tmp;
  348 
  349     sp = &tmp;
  350     memcpy((char *) sp, (char *) ircstp, sizeof(*sp));
  351     for (i = 0; i <= highest_fd; i++)
  352     {
  353         if (!(acptr = local[i]))
  354             continue;
  355         if (IsServer(acptr))
  356         {
  357             sp->is_sbs += acptr->sendB;
  358             sp->is_sbr += acptr->receiveB;
  359             sp->is_sks += acptr->sendK;
  360             sp->is_skr += acptr->receiveK;
  361             sp->is_sti += timeofday - acptr->firsttime;
  362             sp->is_sv++;
  363             if (sp->is_sbs > 1023)
  364             {
  365                 sp->is_sks += (sp->is_sbs >> 10);
  366                 sp->is_sbs &= 0x3ff;
  367             }
  368             if (sp->is_sbr > 1023)
  369             {
  370                 sp->is_skr += (sp->is_sbr >> 10);
  371                 sp->is_sbr &= 0x3ff;
  372             }
  373 
  374         }
  375         else if (IsClient(acptr))
  376         {
  377             sp->is_cbs += acptr->sendB;
  378             sp->is_cbr += acptr->receiveB;
  379             sp->is_cks += acptr->sendK;
  380             sp->is_ckr += acptr->receiveK;
  381             sp->is_cti += timeofday - acptr->firsttime;
  382             sp->is_cl++;
  383             if (sp->is_cbs > 1023)
  384             {
  385                 sp->is_cks += (sp->is_cbs >> 10);
  386                 sp->is_cbs &= 0x3ff;
  387             }
  388             if (sp->is_cbr > 1023)
  389             {
  390                 sp->is_ckr += (sp->is_cbr >> 10);
  391                 sp->is_cbr &= 0x3ff;
  392             }
  393 
  394         }
  395         else if (IsUnknown(acptr))
  396             sp->is_ni++;
  397     }
  398 
  399     sendto_one(cptr, ":%s %d %s :accepts %u refused %u",
  400                me.name, RPL_STATSDEBUG, name, sp->is_ac, sp->is_ref);
  401     sendto_one(cptr, ":%s %d %s :unknown commands %u prefixes %u",
  402                me.name, RPL_STATSDEBUG, name, sp->is_unco, sp->is_unpf);
  403     sendto_one(cptr, ":%s %d %s :nick collisions %u unknown closes %u",
  404                me.name, RPL_STATSDEBUG, name, sp->is_kill, sp->is_ni);
  405     sendto_one(cptr, ":%s %d %s :wrong direction %u empty %u",
  406                me.name, RPL_STATSDEBUG, name, sp->is_wrdi, sp->is_empt);
  407     sendto_one(cptr, ":%s %d %s :numerics seen %u mode fakes %u",
  408                me.name, RPL_STATSDEBUG, name, sp->is_num, sp->is_fake);
  409     sendto_one(cptr, ":%s %d %s :auth successes %u fails %u",
  410                me.name, RPL_STATSDEBUG, name, sp->is_asuc, sp->is_abad);
  411     sendto_one(cptr, ":%s %d %s :local connections %u udp packets %u",
  412                me.name, RPL_STATSDEBUG, name, sp->is_loc, sp->is_udp);
  413     sendto_one(cptr, ":%s %d %s :drones refused %u throttled rejections %u",
  414                me.name, RPL_STATSDEBUG, name, sp->is_drone, sp->is_throt);
  415     sendto_one(cptr, ":%s %d %s :banned users refused before ident/dns"
  416                      " %u after ident/dns %u", me.name, RPL_STATSDEBUG, 
  417                      name, sp->is_ref_1, sp->is_ref_2);
  418     sendto_one(cptr, ":%s %d %s :Client Server", 
  419                      me.name, RPL_STATSDEBUG, name);
  420     sendto_one(cptr, ":%s %d %s :connected %u %u",
  421                me.name, RPL_STATSDEBUG, name, sp->is_cl, sp->is_sv);
  422     sendto_one(cptr, ":%s %d %s :bytes sent %lu.%dK %lu.%dK",
  423                me.name, RPL_STATSDEBUG, name,
  424                sp->is_cks, sp->is_cbs, sp->is_sks, sp->is_sbs);
  425     sendto_one(cptr, ":%s %d %s :bytes recv %lu.%dK %lu.%dK",
  426                me.name, RPL_STATSDEBUG, name,
  427                sp->is_ckr, sp->is_cbr, sp->is_skr, sp->is_sbr);
  428     sendto_one(cptr, ":%s %d %s :time connected %lu %lu",
  429                me.name, RPL_STATSDEBUG, name,
  430            (long)sp->is_cti, (long)sp->is_sti);
  431 #ifdef FLUD
  432     sendto_one(cptr, ":%s %d %s :CTCP Floods Blocked %u",
  433                me.name, RPL_STATSDEBUG, name, sp->is_flud);
  434 #endif /* FLUD */
  435 }
  436 
  437 
  438 /*  m_stats and friends
  439  *  Carved off from s_serv.c in Feb04 by epiphani
  440  *  This mess of routines seemed to go better by themselves, seeing
  441  *  as how s_serv.c is getting massive.
  442  *
  443  * m_stats
  444  *      parv[0] = sender prefix
  445  *      parv[1] = statistics selector (defaults to Message frequency)
  446  *      parv[2] = server name (current server defaulted, if omitted)
  447  */
  448 
  449 int m_stats(aClient *cptr, aClient *sptr, int parc, char *parv[])
  450 {
  451     static char Lformat[] = ":%s %d %s %s %u %u %u %u %u :%u %u %s";
  452     static char Sformat[] = ":%s %d %s Name SendQ SendM SendBytes RcveM "
  453                             "RcveBytes :Open_since Idle TS";
  454 
  455     struct Message  *mptr;
  456     aClient         *acptr;
  457     char             stat = parc > 1 ? parv[1][0] : '\0';
  458     int              i, doall = 0, wilds = 0;
  459     char            *name;
  460     time_t           sincetime;
  461     static time_t   last_used = 0L;
  462 
  463 #ifdef NO_USER_STATS
  464     if (!IsAnOper(sptr) && !IsULine(sptr))
  465     {
  466         sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  467         return 0;
  468     }
  469 #else
  470 #ifdef NO_LOCAL_USER_STATS
  471     if (!IsAnOper(sptr) && !MyConnect(sptr))
  472     {
  473         sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  474         return 0;
  475     }
  476 #endif
  477 #endif
  478 
  479     if (hunt_server(cptr, sptr, ":%s STATS %s :%s", 2, parc, parv) != 
  480                     HUNTED_ISME)
  481         return 0;
  482 
  483     if (IsSquelch(sptr))
  484         return 0;
  485 
  486     if (!IsAnOper(sptr) && !IsULine(sptr))
  487     {
  488         /* allow remote stats p l ? u */
  489         if (!((stat == 'p') || (stat == 'P') || (stat=='?') || (stat=='u') ||
  490               (stat=='l') || (stat=='L')) && !MyConnect(sptr))
  491             return 0;
  492 
  493         /* if they're my user, penalize them. */
  494         if (MyConnect(sptr))
  495             sptr->since += 5;
  496 
  497         if ((last_used + MOTD_WAIT) > NOW)
  498             return 0;
  499         else
  500             last_used = NOW;
  501     }
  502 
  503     if (parc > 2)
  504     {
  505         name = parv[2];
  506         if (!mycmp(name, me.name))
  507             doall = 2;
  508         else if (match(name, me.name) == 0)
  509             doall = 1;
  510         if (strchr(name, '*') || strchr(name, '?'))
  511             wilds = 1;
  512     }
  513     else
  514         name = me.name;
  515 
  516     if (stat != (char) 0 && !IsULine(sptr) && !IsServer(sptr))
  517         sendto_realops_lev(SPY_LEV, "STATS %c requested by %s (%s@%s) [%s]",
  518                stat, sptr->name, sptr->user->username,
  519                sptr->user->host, sptr->user->server);
  520     switch (stat)
  521     {
  522         case 'L':
  523         case 'l':
  524         /* changed behavior totally.  This is what we do now:
  525          * #1: if the user is not opered, never return ips for anything
  526          * #2: we DON'T deny /stats l for opers.  Ever heard of /sping?
  527          *     it's easy to see if you're lagging a server, why restrict
  528          *     something used 99% of the time for good when you're not
  529          *     doing any harm?
  530          * #3: NEVER return all users on a server, UGH, just like
  531          *     /trace, this was fiercely obnoxious.  If you don't
  532          *     add an argument, you get all SERVER links.
  533          */
  534         sendto_one(sptr, Sformat, me.name, RPL_STATSLINKINFO, parv[0]);
  535         if ((parc > 2) && !(doall || wilds))
  536         {         /* Single client lookup */
  537             if (!(acptr = find_person(name, NULL)))
  538             break;
  539             /*
  540              * sincetime might be greater than timeofday,
  541              * store a new value here to avoid sending
  542              * negative since-times. -Rak
  543              */
  544             sincetime = (acptr->since > timeofday) ? 0 : 
  545                                 timeofday - acptr->since;
  546             sendto_one(sptr, Lformat, me.name, RPL_STATSLINKINFO, parv[0],
  547                         get_client_name(acptr, (IsUmodeH(acptr) && !IsAnOper(sptr))?HIDEME:TRUE),
  548                         (int) SBufLength(&acptr->sendQ),
  549                         (int) acptr->sendM, (int) acptr->sendK,
  550                         (int) acptr->receiveM, (int) acptr->receiveK,
  551                         timeofday - acptr->firsttime, sincetime,
  552                         IsServer(acptr) ? (DoesTS(acptr) ?
  553                         "TS" : "NoTS") : "-");
  554         }
  555         else
  556         {
  557             if(!(confopts & FLAGS_SHOWLINKS) && !IsAnOper(sptr))
  558             {
  559                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  560             }
  561             else for (i = 0; i <= highest_fd; i++)
  562             {
  563                 if (!(acptr = local[i]))
  564                     continue;
  565                 if(!IsServer(acptr))
  566                     continue; /* nothing but servers */
  567 #ifdef HIDEULINEDSERVS
  568                 if(IsULine(acptr) && !IsAnOper(sptr))
  569                     continue;
  570 #endif
  571                 sincetime = (acptr->since > timeofday) ? 0 : 
  572                              timeofday - acptr->since;
  573                 sendto_one(sptr, Lformat, me.name, RPL_STATSLINKINFO, parv[0],
  574                         ( (MyClient(sptr) && IsAdmin(sptr))
  575                           ? get_client_name(acptr, FALSE)
  576                           : get_client_name(acptr, HIDEME) ),
  577                         (int) SBufLength(&acptr->sendQ),
  578                         (int) acptr->sendM, (int) acptr->sendK,
  579                         (int) acptr->receiveM, (int) acptr->receiveK,
  580                         timeofday - acptr->firsttime, sincetime,
  581                         IsServer(acptr) ? (DoesTS(acptr) ?
  582                         "TS" : "NoTS") : "-");
  583             }
  584         }
  585         break;
  586         case 'C':
  587         case 'c':
  588         /* this should be fixed and combined into a more reasonable
  589          * single responce.  Will work on this later -epi
  590          */
  591 #ifdef HIDEULINEDSERVS
  592         if (!IsAnOper(sptr))
  593             sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  594         else
  595 #endif
  596         {
  597             aConnect *tmp;
  598             if(!connects)
  599                 break;
  600             for(tmp = connects; tmp; tmp = tmp->next)
  601             {
  602                 if (tmp->legal == -1)
  603                     continue;
  604 
  605                 if(IsULine(sptr) || (MyClient(sptr) && IsAdmin(sptr)))
  606                 {
  607                     sendto_one(sptr, rpl_str(RPL_STATSCLINE), me.name,
  608                            sptr->name, "C", tmp->host, tmp->name, tmp->port,
  609                            tmp->class->name);
  610                     sendto_one(sptr, rpl_str(RPL_STATSNLINE), me.name,
  611                            sptr->name, "N", tmp->host, tmp->name, cflagtotext(tmp->flags, tmp->uflags),
  612                            tmp->class->name);
  613                 }
  614                 else
  615                 {
  616                     sendto_one(sptr, rpl_str(RPL_STATSCLINE), me.name,
  617                                sptr->name, "C", "*", tmp->name, tmp->port,
  618                                tmp->class->name);
  619                     sendto_one(sptr, rpl_str(RPL_STATSNLINE), me.name,
  620                                sptr->name, "N", "*", tmp->name, cflagtotext(tmp->flags, tmp->uflags),
  621                                tmp->class->name);
  622                 }
  623             }
  624         }
  625         break;
  626 
  627         case 'D':
  628             if (!IsAnOper(sptr))
  629                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  630             else
  631             {
  632                 CloneEnt *ce;
  633 
  634                 for (ce = clones_list; ce; ce = ce->next)
  635                     if (ce->limit || ce->sllimit || ce->sglimit)
  636                         sendto_one(sptr, rpl_str(RPL_STATSCLONE), me.name,
  637                                    parv[0], ce->ent, ce->sllimit, ce->sglimit,
  638                                    ce->limit);
  639             }
  640             break;
  641 
  642         case 'd':
  643             if (!IsAnOper(sptr))
  644                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  645             else
  646             {
  647                 CloneEnt *ce;
  648                 int entries = 0;
  649 #ifdef THROTTLE_ENABLE
  650                 int sllimits = 0;
  651                 int sglimits = 0;
  652                 int hlimits = 0;
  653                 int active = 0;
  654                 int sites = 0;
  655                 unsigned long rtot;
  656 #endif
  657 
  658                 for (ce = clones_list; ce; ce = ce->next)
  659                 {
  660                     entries++;
  661 #ifdef THROTTLE_ENABLE
  662                     if (ce->sllimit)
  663                         sllimits++;
  664                     if (ce->sglimit)
  665                         sglimits++;
  666                     if (ce->limit)
  667                         hlimits++;
  668                     if (ce->gcount)
  669                     {
  670                         active++;
  671                         /* blah, but not important enough for its own flag */
  672                         if (!ce->clients)
  673                             sites++;
  674                     }
  675 #endif
  676                 }
  677 
  678 #ifdef THROTTLE_ENABLE
  679                 rtot = clones_stat.rlh + clones_stat.rls
  680                      + clones_stat.rgh + clones_stat.rgs;
  681 
  682                 sendto_one(sptr, ":%s %d %s :Default local host limit: %d"
  683                            "  site: %d", me.name, RPL_STATSDEBUG, parv[0],
  684                            local_ip_limit, local_ip24_limit);
  685                 sendto_one(sptr, ":%s %d %s :Default global host limit: %d"
  686                            "  site: %d", me.name, RPL_STATSDEBUG, parv[0],
  687                            global_ip_limit, global_ip24_limit);
  688 #endif
  689                 sendto_one(sptr, ":%s %d %s :Clone entries: %d", me.name,
  690                            RPL_STATSDEBUG, parv[0], entries);
  691 #ifdef THROTTLE_ENABLE
  692                 sendto_one(sptr, ":%s %d %s :    Active hosts: %d  sites: %d",
  693                            me.name, RPL_STATSDEBUG, parv[0], active-sites,
  694                            sites);
  695                 sendto_one(sptr, ":%s %d %s :    Soft local limits: %d"
  696                            "  global: %d", me.name, RPL_STATSDEBUG, parv[0],
  697                            sllimits, sglimits);
  698                 sendto_one(sptr, ":%s %d %s :    Hard global limits: %d",
  699                            me.name, RPL_STATSDEBUG, parv[0], hlimits);
  700                 sendto_one(sptr, ":%s %d %s :Rejected connections: %lu",
  701                            me.name, RPL_STATSDEBUG, parv[0], rtot);
  702                 sendto_one(sptr, ":%s %d %s :    Local hosts: %lu  sites: %lu",
  703                            me.name, RPL_STATSDEBUG, parv[0],
  704                            clones_stat.rlh, clones_stat.rls);
  705                 sendto_one(sptr, ":%s %d %s :    Global hosts: %lu  sites: %lu",
  706                            me.name, RPL_STATSDEBUG, parv[0],
  707                            clones_stat.rgh, clones_stat.rgs);
  708 #endif
  709             }
  710             break;
  711 
  712         case 'G':
  713             if(IsAnOper(sptr))
  714                 report_simbans_match_flags(sptr, SBAN_GCOS|SBAN_LOCAL, 0);
  715             else
  716                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  717             break;
  718         case 'g':
  719             if(IsAnOper(sptr))
  720                 report_simbans_match_flags(sptr, SBAN_GCOS|SBAN_NETWORK, 0);
  721             else
  722                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  723             break;
  724 
  725         case 'I':
  726         case 'i':
  727         {
  728             aAllow *tmp;
  729             if(!allows)
  730                 break;
  731             for(tmp = allows; tmp; tmp = tmp->next)
  732             {
  733                 if (tmp->passwd && !(IsAnOper(sptr) || IsULine(sptr)))
  734                     continue;
  735                 sendto_one(sptr, rpl_str(RPL_STATSILINE), me.name,
  736                            sptr->name, (tmp->legal == -1 ? "Ix" : "I"),
  737                            tmp->ipmask, iflagtotext(tmp->flags), tmp->hostmask, tmp->port,
  738                            tmp->class->name);
  739             }
  740             break;
  741         }
  742         case 'k':
  743             if(IsAnOper(sptr))
  744                 report_userbans_match_flags(sptr, UBAN_TEMPORARY|UBAN_LOCAL, 0);
  745             else
  746                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  747             break;
  748 
  749         case 'K':
  750             if (IsAnOper(sptr))
  751                 report_userbans_match_flags(sptr, UBAN_LOCAL, UBAN_TEMPORARY);
  752             else
  753                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  754             break;
  755 
  756         case 'A':
  757         case 'a':
  758             if(IsAnOper(sptr))
  759                 report_userbans_match_flags(sptr, UBAN_NETWORK, 0);
  760             else
  761                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  762             break;
  763 
  764         case 'M':
  765         case 'm':
  766         /*
  767          * original behaviour was not to report the command, if
  768          * the command hadn't been used. I'm going to always
  769          * report the command instead -Dianora
  770          * Why would users want to see this?  Made Oper only.
  771          */
  772             if(IsAnOper(sptr))
  773                 for (mptr = msgtab; mptr->cmd; mptr++)
  774                     sendto_one(sptr, rpl_str(RPL_STATSCOMMANDS), me.name, 
  775                             parv[0], mptr->cmd, mptr->count, mptr->bytes);
  776             break;
  777 
  778         case 'N':
  779         case 'n':
  780             sendto_one(sptr, rpl_str(RPL_STATSCOUNT), me.name, parv[0],
  781                         "User Connects Today: ", Count.today);
  782             sendto_one(sptr, rpl_str(RPL_STATSCOUNT), me.name, parv[0],
  783                         "User Connects past week: ", Count.weekly);
  784             sendto_one(sptr, rpl_str(RPL_STATSCOUNT), me.name, parv[0],
  785                         "User Connects past month: ", Count.monthly);
  786             sendto_one(sptr, rpl_str(RPL_STATSCOUNT), me.name, parv[0],
  787                         "User Connects past year: ", Count.yearly);
  788             break;
  789         case 'o':
  790         case 'O':
  791         {
  792             aOper *tmp;
  793             int i = 0;
  794             if(!opers)
  795                 break;
  796             if (IsAnOper(sptr) || IsULine(sptr))
  797             {
  798                 for(tmp = opers; tmp; tmp = tmp->next)
  799                     for(i = 0; tmp->hosts[i]; i++)
  800                         sendto_one(sptr, rpl_str(RPL_STATSOLINE), me.name,
  801                                 sptr->name, (tmp->legal == -1 ? "Ox" : "O"),
  802                                 tmp->hosts[i], tmp->nick, oflagtotext(tmp->flags),
  803                                 tmp->class->name);
  804             }
  805             else
  806             {
  807                 for(tmp = opers; tmp; tmp = tmp->next)
  808                 {
  809                     if (tmp->legal == -1)
  810                         continue;
  811                     sendto_one(sptr, rpl_str(RPL_STATSOLINE), me.name,
  812                             sptr->name, "O", "*", tmp->nick, oflagtotext(tmp->flags),
  813                             tmp->class->name);
  814                 }
  815             }
  816             break;
  817         }
  818 
  819         case 'p':
  820         case 'P':
  821             show_opers(sptr, parv[0]);
  822             break;
  823 
  824         case 'Q':
  825             if(IsAnOper(sptr))
  826             {
  827                 report_simbans_match_flags(sptr, SBAN_NICK|SBAN_LOCAL, 0);
  828                 report_simbans_match_flags(sptr, SBAN_CHAN|SBAN_LOCAL, 0);
  829             }
  830             else
  831                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  832             break;
  833         case 'q':
  834             if(IsAnOper(sptr))
  835             {
  836                 report_simbans_match_flags(sptr, SBAN_NICK|SBAN_NETWORK, 0);
  837                 report_simbans_match_flags(sptr, SBAN_CHAN|SBAN_NETWORK, 0);
  838             }
  839             else
  840                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  841             break;
  842 
  843         case 'R':
  844         case 'r':
  845 #ifdef DEBUGMODE
  846             send_usage(sptr, parv[0]);
  847 #endif
  848             break;
  849 
  850         case 'S':
  851             if (IsAnOper(sptr))
  852                 report_spamfilters(cptr, sptr, parc, parv);
  853             else
  854                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  855             break;
  856 
  857         case 's':
  858             if (IsAnOper(sptr))
  859                 list_scache(cptr, sptr, parc, parv);
  860             else
  861                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  862             break;
  863 
  864         case 'T':
  865             if (IsAnOper(sptr)) 
  866                 throttle_stats(sptr, parv[0]);
  867             else
  868                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  869             break;
  870 
  871         case 't':
  872             if (IsAnOper(sptr))
  873                 tstats(sptr, parv[0]);
  874             else
  875                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  876             break;
  877 
  878         case 'U':
  879 #ifdef HIDEULINEDSERVS
  880             if (!IsOper(sptr))
  881                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  882             else
  883 #endif
  884             {
  885                 int i;
  886                 for(i = 0; uservers[i]; i++)
  887                     sendto_one(sptr, rpl_str(RPL_STATSULINE), me.name,
  888                     sptr->name, "U", "*", uservers[i], 0, 0);
  889             }
  890             break;
  891 
  892         case 'u':
  893         {
  894             time_t now;
  895 
  896             now = timeofday - me.since;
  897             sendto_one(sptr, rpl_str(RPL_STATSUPTIME), me.name, parv[0],
  898                 now / 86400, (now / 3600) % 24, (now / 60) % 60, now % 60);
  899             break;
  900         }
  901 
  902         case 'v':
  903         case 'V':
  904             if(!(confopts & FLAGS_SHOWLINKS) && !IsAnOper(sptr))
  905             {
  906                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  907             }
  908             else show_servers(sptr, parv[0]);
  909             break;
  910 
  911 #ifdef DEBUGMODE
  912         case 'w':
  913         case 'W':
  914             if(IsAnOper(sptr))
  915                 report_fds(sptr);
  916             else
  917                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  918             break;
  919 #endif
  920 
  921         case 'Y':
  922         case 'y':
  923         {
  924             aClass *tmp;
  925             if(!classes)
  926                 break;
  927             for(tmp = classes; tmp; tmp = tmp->next)
  928                 sendto_one(sptr, rpl_str(RPL_STATSYLINE), me.name,
  929                            sptr->name, 'Y', tmp->name, tmp->pingfreq,
  930                            tmp->connfreq, tmp->ip24clones, tmp->maxlinks,
  931                            tmp->maxsendq);
  932             break;
  933         }
  934 
  935         case 'Z':
  936             if (IsAnOper(sptr))
  937                 report_memory_usage(sptr, 1);
  938             else
  939                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  940             break;
  941 
  942         case 'z':
  943             if (IsAnOper(sptr))
  944                 report_memory_usage(sptr, 0);
  945             else
  946                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
  947             break;
  948 
  949         case '?':
  950             if(!(confopts & FLAGS_SHOWLINKS) && !IsAnOper(sptr))
  951             {
  952                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,  parv[0]);
  953             }
  954             else serv_info(sptr, parv[0]);
  955             break;
  956 
  957         default:
  958             stat = '*';
  959             break;
  960     }
  961     sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, parv[0], stat);
  962     return 0;
  963 }
  964