Author: Kev <klmitch@mit.edu>
[ircu2.10.12-pk.git] / ircd / whocmds.c
index 0c2b5b4a525144b4c01080ddebdf459917c00cd3..39a9bc7507a0b1a1e0e1a5b81612db39ab55d83b 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Id$
- *
- * $Id$
  */
+#include "config.h"
+
 #include "whocmds.h"
-#include "IPcheck.h"
 #include "channel.h"
 #include "client.h"
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_chattr.h"
+#include "ircd_policy.h"
+#include "ircd_reply.h"
+#include "ircd_snprintf.h"
 #include "ircd_string.h"
 #include "list.h"
 #include "match.h"
@@ -84,7 +86,7 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan,
       !IsChannelService(acptr))
   {
     struct Membership* chan;
-    for (chan = acptr->user->channel; chan && !chptr; chan = chan->next_channel)
+    for (chan = cli_user(acptr)->channel; chan && !chptr; chan = chan->next_channel)
       if (PubChannel(chan->channel) &&
           (acptr == sptr || !IsZombie(chan)))
         chptr = chan->channel;
@@ -114,35 +116,35 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan,
 
   if (!fields || (fields & WHO_FIELD_UID))
   {
-    char *p2 = acptr->user->username;
+    char *p2 = cli_user(acptr)->username;
     *(p1++) = ' ';
     while ((*p2) && (*(p1++) = *(p2++)));
   }
 
   if (fields & WHO_FIELD_NIP)
   {
-    const char* p2 = ircd_ntoa((const char*) &acptr->ip);
+    const char* p2 = ircd_ntoa((const char*) &(cli_ip(acptr)));
     *(p1++) = ' ';
     while ((*p2) && (*(p1++) = *(p2++)));
   }
 
   if (!fields || (fields & WHO_FIELD_HOS))
   {
-    char *p2 = acptr->user->host;
+    char *p2 = cli_user(acptr)->host;
     *(p1++) = ' ';
     while ((*p2) && (*(p1++) = *(p2++)));
   }
 
   if (!fields || (fields & WHO_FIELD_SER))
   {
-    char *p2 = acptr->user->server->name;
+    char *p2 = cli_name(cli_user(acptr)->server);
     *(p1++) = ' ';
     while ((*p2) && (*(p1++) = *(p2++)));
   }
 
   if (!fields || (fields & WHO_FIELD_NIC))
   {
-    char *p2 = acptr->name;
+    char *p2 = cli_name(acptr);
     *(p1++) = ' ';
     while ((*p2) && (*(p1++) = *(p2++)));
   }
@@ -150,18 +152,33 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan,
   if (!fields || (fields & WHO_FIELD_FLA))
   {
     *(p1++) = ' ';
-    if (acptr->user->away)
+    if (cli_user(acptr)->away)
       *(p1++) = 'G';
     else
       *(p1++) = 'H';
-    if (IsAnOper(acptr))
+    if (IsAnOper(acptr) &&
+       (HasPriv(acptr, PRIV_DISPLAY) || HasPriv(sptr, PRIV_SEE_OPERS)))
       *(p1++) = '*';
-    if (chptr && is_chan_op(acptr, chptr))
-      *(p1++) = '@';
-    else if (chptr && has_voice(acptr, chptr))
-      *(p1++) = '+';
-    else if (chptr && is_zombie(acptr, chptr))
-      *(p1++) = '!';
+    if (fields) {
+      /* If you specified flags then we assume you know how to parse
+       * multiple channel status flags, as this is currently the only
+       * way to know if someone has @'s *and* is +'d.
+       */
+      if (chptr && is_chan_op(acptr, chptr))
+        *(p1++) = '@';
+      if (chptr && has_voice(acptr, chptr))
+        *(p1++) = '+';
+      if (chptr && is_zombie(acptr, chptr))
+        *(p1++) = '!';
+    }
+    else {
+      if (chptr && is_chan_op(acptr, chptr))
+        *(p1++) = '@';
+      else if (chptr && has_voice(acptr, chptr))
+        *(p1++) = '+';
+      else if (chptr && is_zombie(acptr, chptr))
+        *(p1++) = '!';
+    }
     if (IsDeaf(acptr))
       *(p1++) = 'd';
     if (IsAnOper(sptr))
@@ -180,12 +197,28 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan,
     *p1++ = ' ';
     if (!fields)
       *p1++ = ':';              /* Place colon here for default reply */
-    p1 = sprintf_irc(p1, "%d", acptr->hopcount);
+#ifdef HEAD_IN_SAND_WHO_HOPCOUNT
+    strcat(p1, sptr == acptr ? "0" : "3");
+    p1++;
+#else
+    p1 = sprintf_irc(p1, "%d", cli_hopcount(acptr));
+#endif
+  }
+
+  if (fields & WHO_FIELD_IDL)
+  {
+    *p1++ = ' ';
+    if (MyUser(acptr)) {
+           p1 = sprintf_irc(p1, "%d", CurrentTime - cli_user(acptr)->last);
+    }    
+    else {
+           *p1++ = '0';
+    }
   }
 
   if (!fields || (fields & WHO_FIELD_REN))
   {
-    char *p2 = acptr->info;
+    char *p2 = cli_info(acptr);
     *p1++ = ' ';
     if (fields)
       *p1++ = ':';              /* Place colon here for special reply */
@@ -196,7 +229,29 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan,
      need to terminate buf1 */
   *p1 = '\0';
   p1 = buf1;
-  sendto_one(sptr, rpl_str(fields ? RPL_WHOSPCRPL : RPL_WHOREPLY),
-      me.name, sptr->name, ++p1);
+  send_reply(sptr, fields ? RPL_WHOSPCRPL : RPL_WHOREPLY, ++p1);
 }
 
+int
+count_users(char *mask)
+{
+  struct Client *acptr;
+  int count = 0;
+  char namebuf[USERLEN + HOSTLEN + 2];
+  char ipbuf[USERLEN + 16 + 2];
+
+  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
+    if (!IsUser(acptr))
+      continue;
+
+    ircd_snprintf(0, namebuf, sizeof(namebuf), "%s@%s",
+                 cli_user(acptr)->username, cli_user(acptr)->host);
+    ircd_snprintf(0, ipbuf, sizeof(ipbuf), "%s@%s", cli_user(acptr)->username,
+                 ircd_ntoa((const char *) &(cli_ip(acptr))));
+
+    if (!match(mask, namebuf) || !match(mask, ipbuf))
+      count++;
+  }
+
+  return count;
+}