Author: Isomer <isomer@coders.net>
[ircu2.10.12-pk.git] / ircd / m_whois.c
index 0f2bf933b53fd10f9efb9d70f7ea0a23bb71dfad..c2b3fa191fe4fb4355e2d3bcf2cf197ba1699b3a 100644 (file)
 #include <string.h>
 
 /*
- * m_whois - generic message handler
- *
- * parv[0] = sender prefix
- * parv[1] = nickname masklist
- *
- * or
- *
- * parv[1] = target server
- * parv[2] = nickname masklist
+ * 2000-07-01: Isomer
+ *  * Rewritten to make this understandable
+ *  * You can nolonger /whois unregistered clients.
+ *  
+ *
+ * General rules:
+ *  /whois nick always shows the nick.
+ *  /whois wild* shows the nick if:
+ *   * they aren't +i and aren't on any channels.
+ *   * they are on a common channel.
+ *   * they aren't +i and are on a public channel. (not +p and not +s)
+ *   * they aren't +i and are on a private channel. (+p but not +s)
+ *  Or to look at it another way (I think):
+ *   * +i users are only shown if your on a common channel.
+ *   * users on +s channels only aren't shown.
+ *
+ *  whois doesn't show what channels a +k client is on, for the reason that
+ *  /whois X or /whois W floods a user off the server. :)
+ *
+ * nb: if the code and this comment disagree, the codes right and I screwed
+ *     up.
  */
-int m_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
-{
-  struct User*    user;
-  struct Client*  acptr;
-  struct Client*  a2cptr;
-  struct Channel* chptr;
-  char*           nick;
-  char*           tmp;
-  const char*     name;
-  char*           p = 0;
-  int             found;
-  int             len;
-  int             mlen;
-  int             total;
-  static char     buf[512];
 
-  if (parc < 2)
-  {
-    send_reply(sptr, ERR_NONICKNAMEGIVEN);
-    return 0;
-  }
-
-  if (parc > 2)
-  {
-    struct Client *acptr;
-    /* For convenience: Accept a nickname as first parameter, by replacing
-       it with the correct servername - as is needed by hunt_server() */
-    if (MyUser(sptr) && (acptr = FindUser(parv[1])))
-      parv[1] = acptr->user->server->name;
-    if (hunt_server_cmd(sptr, CMD_WHOIS, cptr, 0, "%C :%s", 1, parc, parv) !=
-        HUNTED_ISME)
-      return 0;
-    parv[1] = parv[2];
-  }
+/*
+ * Send whois information for acptr to sptr
+ */
+static void do_whois(struct Client* sptr, struct Client *acptr)
+{
+  struct Client *a2cptr=0;
+  struct Channel *chptr=0;
+  int mlen;
+  int len;
+  static char buf[512];
+  
+  const struct User* user = acptr->user;
+  const char* name = (!*acptr->name) ? "?" : acptr->name;  
+  a2cptr = user->server;
+  assert(user);
+  send_reply(sptr, RPL_WHOISUSER, name, user->username, user->host,
+                  acptr->info);
 
-  total = 0;
-  for (tmp = parv[1]; (nick = ircd_strtok(&p, tmp, ",")); tmp = 0)
+  /* Display the channels this user is on. */
+  if (!IsChannelService(acptr))
   {
-    int invis, showperson, member, wilds;
-
-    found = 0;
-    collapse(nick);
-    wilds = (strchr(nick, '?') || strchr(nick, '*'));
-    /* Do a hash lookup if the nick does not contain wilds */
-    if (wilds)
+    struct Membership* chan;
+    mlen = strlen(me.name) + strlen(sptr->name) + 12 + strlen(name);
+    len = 0;
+    *buf = '\0';
+    for (chan = user->channel; chan; chan = chan->next_channel)
     {
-      /*
-       * We're no longer allowing remote users to generate requests with wildcards.
-       */
-      if (!MyConnect(sptr))
-        continue;
-      for (acptr = GlobalClientList; (acptr = next_client(acptr, nick));
-          acptr = acptr->next)
-      {
-        if (!IsRegistered(acptr) || IsServer(acptr))
+       chptr = chan->channel;
+       
+       if (!ShowChannel(sptr, chptr))
           continue;
-        /*
-         * I'm always last :-) and acptr->next == 0!!
-         */
-        if (IsMe(acptr))
-          break;
-        /*
-         * 'Rules' established for sending a WHOIS reply:
-         *
-         * - if wildcards are being used dont send a reply if
-         *   the querier isnt any common channels and the
-         *   client in question is invisible and wildcards are
-         *   in use (allow exact matches only);
-         *
-         * - only send replies about common or public channels
-         *   the target user(s) are on;
-         */
-        user = acptr->user;
-        name = (!*acptr->name) ? "?" : acptr->name;
-
-        invis = acptr != sptr && IsInvisible(acptr);
-        member = (user && user->channel) ? 1 : 0;
-        showperson = (wilds && !invis && !member) || !wilds;
-        if (user) {
-          struct Membership* chan;
-          for (chan = user->channel; chan; chan = chan->next_channel)
-          {
-            chptr = chan->channel;
-            member = find_channel_member(sptr, chptr) ? 1 : 0;
-            if (invis && !member)
-              continue;
-            if (IsZombie(chan))
-              continue;
-            if (member || (!invis && PubChannel(chptr)))
-            {
-              showperson = 1;
-              break;
-            }
-            if (!invis && HiddenChannel(chptr) && !SecretChannel(chptr))
-              showperson = 1;
-          }
-        }
-        if (!showperson)
+          
+       if (acptr != sptr && IsZombie(chan))
           continue;
-
-        if (user)
-        {
-          a2cptr = user->server;
-         send_reply(sptr, RPL_WHOISUSER, name, user->username, user->host,
-                    acptr->info);
-        }
-        else
-        {
-          a2cptr = &me;
-         send_reply(sptr, RPL_WHOISUSER, name, "<unknown>", "<unknown>",
-                    "<unknown>");
-        }
-
-        found = 1;
-
-exact_match:
-        if (user && !IsChannelService(acptr))
-        {
-          struct Membership* chan;
-          mlen = strlen(me.name) + strlen(parv[0]) + 12 + strlen(name);
-          len = 0;
+          
+       if (len+strlen(chptr->chname) + mlen > BUFSIZE - 5) 
+       {
+          send_reply(sptr, SND_EXPLICIT | RPL_WHOISCHANNELS, "%s :%s", name, buf);
           *buf = '\0';
-          for (chan = user->channel; chan; chan = chan->next_channel)
-          {
-            chptr = chan->channel;
-            if (ShowChannel(sptr, chptr) &&
-                (acptr == sptr || !IsZombie(chan)))
-            {
-              if (len + strlen(chptr->chname) + mlen > BUFSIZE - 5)
-              {
-               send_reply(sptr, SND_EXPLICIT | RPL_WHOISCHANNELS,
-                          "%s :%s", name, buf);
-                *buf = '\0';
-                len = 0;
-              }
-              if (IsDeaf(acptr))
-                *(buf + len++) = '-';
-              if (is_chan_op(acptr, chptr))
-                *(buf + len++) = '@';
-              else if (has_voice(acptr, chptr))
-                *(buf + len++) = '+';
-              else if (IsZombie(chan))
-                *(buf + len++) = '!';
-              if (len)
-                *(buf + len) = '\0';
-              strcpy(buf + len, chptr->chname);
-              len += strlen(chptr->chname);
-              strcat(buf + len, " ");
-              len++;
-            }
-          }
-          if (buf[0] != '\0')
-           send_reply(sptr, RPL_WHOISCHANNELS, name, buf);
-        }
-
-       send_reply(sptr, RPL_WHOISSERVER, name, a2cptr->name, a2cptr->info);
-
-        if (user)
-        {
-          if (user->away)
-           send_reply(sptr, RPL_AWAY, name, user->away);
-
-          if (IsAnOper(acptr))
-           send_reply(sptr, RPL_WHOISOPERATOR, name);
-
-          if (MyConnect(acptr))
-           send_reply(sptr, RPL_WHOISIDLE, name, CurrentTime - user->last,
-                      acptr->firsttime);
-        }
-        if (found == 2 || total++ >= MAX_WHOIS_LINES)
-          break;
-      }
-    }
-    else
-    {
-      /* No wildcards */
-      if ((acptr = FindUser(nick)))
-      {
-        found = 2;              /* Make sure we exit the loop after passing it once */
-        user = acptr->user;
-        name = (!*acptr->name) ? "?" : acptr->name;
-        a2cptr = user->server;
-       send_reply(sptr, RPL_WHOISUSER, name, user->username, user->host,
-                  acptr->info);
-        goto exact_match;
-      }
-    }
-    if (!found)
-      send_reply(sptr, ERR_NOSUCHNICK, nick);
-    if (p)
-      p[-1] = ',';
-    if (!MyConnect(sptr) || total >= MAX_WHOIS_LINES)
-      break;
+          len = 0;
+       }
+       if (IsDeaf(acptr))
+         *(buf + len++) = '-';
+       if (is_chan_op(acptr, chptr))
+         *(buf + len++) = '@';
+       else if (has_voice(acptr, chptr))
+         *(buf + len++) = '+';
+       else if (IsZombie(chan))
+         *(buf + len++) = '!';
+       if (len)
+          *(buf + len) = '\0';
+       strcpy(buf + len, chptr->chname);
+       len += strlen(chptr->chname);
+       strcat(buf + len, " ");
+       len++;
+     }
+     if (buf[0] != '\0')
+        send_reply(sptr, RPL_WHOISCHANNELS, name, buf);
   }
-  send_reply(sptr, RPL_ENDOFWHOIS, parv[1]);
+  send_reply(sptr, RPL_WHOISSERVER, name, a2cptr->name, a2cptr->info);
 
-  return 0;
+  if (user)
+  {
+    if (user->away)
+       send_reply(sptr, RPL_AWAY, name, user->away);
+
+    if (IsAnOper(acptr))
+       send_reply(sptr, RPL_WHOISOPERATOR, name);
+   
+    /* Hint: if your looking to add more flags to a user, eg +h, here's
+     *       probably a good place to add them :)
+     */
+     
+    if (MyConnect(acptr))
+       send_reply(sptr, RPL_WHOISIDLE, name, CurrentTime - user->last, 
+                  acptr->firsttime);
+  }
 }
 
 /*
- * ms_whois - server message handler
- *
- * parv[0] = sender prefix
- * parv[1] = nickname masklist
- *
- * or
- *
- * parv[1] = target server
- * parv[2] = nickname masklist
+ * Search and return as many people as matched by the wild 'nick'.
+ * returns the number of people found (or, obviously, 0, if none where
+ * found).
  */
-int ms_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+static int do_wilds(struct Client* sptr,char *nick,int count)
 {
-  struct User*    user;
-  struct Client*  acptr;
-  struct Client*  a2cptr;
-  struct Channel* chptr;
-  char*           nick;
-  char*           tmp;
-  const char*     name;
-  char*           p = 0;
-  int             found;
-  int             len;
-  int             mlen;
-  int             total;
-  static char     buf[512];
-
-  if (parc < 2)
-  {
-    send_reply(sptr, ERR_NONICKNAMEGIVEN);
-    return 0;
-  }
-
-  if (parc > 2)
-  {
-    struct Client *acptr;
-    /* For convenience: Accept a nickname as first parameter, by replacing
-       it with the correct servername - as is needed by hunt_server() */
-    if (MyUser(sptr) && (acptr = FindUser(parv[1])))
-      parv[1] = acptr->user->server->name;
-    if (hunt_server_cmd(sptr, CMD_WHOIS, cptr, 0, "%C :%s", 1, parc, parv) !=
-        HUNTED_ISME)
-      return 0;
-    parv[1] = parv[2];
-  }
-
-  total = 0;
-  for (tmp = parv[1]; (nick = ircd_strtok(&p, tmp, ",")); tmp = 0)
+  struct Client *acptr; /* Current client we're concidering */
+  struct User *user;   /* the user portion of the client */
+  char *name;          /* the name of this client */
+  struct Membership* chan; 
+  int invis;           /* does +i apply? */
+  int member;          /* Is this user on any channels? */
+  int showperson;       /* Should we show this person? */
+  int found = 0 ;      /* How many were found? */
+  
+  /* Ech! This is hidious! */
+  for (acptr = GlobalClientList; (acptr = next_client(acptr, nick));
+      acptr = acptr->next)
   {
-    int invis, showperson, member, wilds;
-
-    found = 0;
-    collapse(nick);
-    wilds = (strchr(nick, '?') || strchr(nick, '*'));
-    /* Do a hash lookup if the nick does not contain wilds */
-    if (wilds)
+    if (!IsRegistered(acptr)) 
+      continue;
+      
+    if (IsServer(acptr))
+      continue;
+    /*
+     * I'm always last :-) and acptr->next == 0!!
+     *
+     * Isomer: Does this strike anyone else as being a horrible hidious
+     *         hack?
+     */
+    if (IsMe(acptr)) {
+      assert(!acptr->next);
+      break;
+    }
+    
+    /*
+     * 'Rules' established for sending a WHOIS reply:
+     *
+     * - if wildcards are being used dont send a reply if
+     *   the querier isnt any common channels and the
+     *   client in question is invisible.
+     *
+     * - only send replies about common or public channels
+     *   the target user(s) are on;
+     */
+    user = acptr->user;
+    name = (!*acptr->name) ? "?" : acptr->name;
+    assert(user);
+
+    invis = (acptr != sptr) && IsInvisible(acptr);
+    member = (user && user->channel) ? 1 : 0;
+    showperson = !invis && !member;
+    
+    /* Should we show this person now? */
+    if (showperson) {
+       found++;
+       do_whois(sptr,acptr);
+       if (count+found>MAX_WHOIS_LINES)
+         return found;
+       continue;
+    }
+    
+    /* Step through the channels this user is on */
+    for (chan = user->channel; chan; chan = chan->next_channel)
     {
-      /*
-       * We're no longer allowing remote users to generate requests with wildcards.
-       */
-      if (!MyConnect(sptr))
-        continue;
-      for (acptr = GlobalClientList; (acptr = next_client(acptr, nick));
-          acptr = acptr->next)
-      {
-        if (!IsRegistered(acptr) || IsServer(acptr))
-          continue;
-        /*
-         * I'm always last :-) and acptr->next == 0!!
-         */
-        if (IsMe(acptr))
-          break;
-        /*
-         * 'Rules' established for sending a WHOIS reply:
-         *
-         * - if wildcards are being used dont send a reply if
-         *   the querier isnt any common channels and the
-         *   client in question is invisible and wildcards are
-         *   in use (allow exact matches only);
-         *
-         * - only send replies about common or public channels
-         *   the target user(s) are on;
-         */
-        user = acptr->user;
-        name = (!*acptr->name) ? "?" : acptr->name;
-
-        invis = acptr != sptr && IsInvisible(acptr);
-        member = (user && user->channel) ? 1 : 0;
-        showperson = (wilds && !invis && !member) || !wilds;
-        if (user) {
-          struct Membership* chan;
-          for (chan = user->channel; chan; chan = chan->next_channel)
-          {
-            chptr = chan->channel;
-            member = find_channel_member(sptr, chptr) ? 1 : 0;
-            if (invis && !member)
-              continue;
-            if (IsZombie(chan))
-              continue;
-            if (member || (!invis && PubChannel(chptr)))
-            {
-              showperson = 1;
-              break;
-            }
-            if (!invis && HiddenChannel(chptr) && !SecretChannel(chptr))
-              showperson = 1;
-          }
-        }
-        if (!showperson)
-          continue;
-
-        if (user)
-        {
-          a2cptr = user->server;
-         send_reply(sptr, RPL_WHOISUSER, name, user->username, user->host,
-                    acptr->info);
-        }
-        else
-        {
-          a2cptr = &me;
-         send_reply(sptr, RPL_WHOISUSER, name, "<unknown>", "<unknown>",
-                    "<unknown>");
-        }
-
-        found = 1;
-
-exact_match:
-        if (user && !IsChannelService(acptr))
-        {
-          struct Membership* chan;
-          mlen = strlen(me.name) + strlen(parv[0]) + 12 + strlen(name);
-          len = 0;
-          *buf = '\0';
-          for (chan = user->channel; chan; chan = chan->next_channel)
-          {
-            chptr = chan->channel;
-            if (ShowChannel(sptr, chptr) &&
-                (acptr == sptr || !IsZombie(chan)))
-            {
-              if (len + strlen(chptr->chname) + mlen > BUFSIZE - 5)
-              {
-               send_reply(sptr, SND_EXPLICIT | RPL_WHOISCHANNELS, 
-                          "%s :%s", name, buf);
-                *buf = '\0';
-                len = 0;
-              }
-              if (IsDeaf(acptr))
-                *(buf + len++) = '-';
-              if (is_chan_op(acptr, chptr))
-                *(buf + len++) = '@';
-              else if (has_voice(acptr, chptr))
-                *(buf + len++) = '+';
-              else if (IsZombie(chan))
-                *(buf + len++) = '!';
-              if (len)
-                *(buf + len) = '\0';
-              strcpy(buf + len, chptr->chname);
-              len += strlen(chptr->chname);
-              strcat(buf + len, " ");
-              len++;
-            }
-          }
-          if (buf[0] != '\0')
-           send_reply(sptr, RPL_WHOISCHANNELS, name, buf);
-        }
+      struct Channel *chptr = chan->channel;
 
-       send_reply(sptr, RPL_WHOISSERVER, name, a2cptr->name, a2cptr->info);
-
-        if (user)
-        {
-          if (user->away)
-           send_reply(sptr, RPL_AWAY, name, user->away);
-
-          if (IsAnOper(acptr))
-           send_reply(sptr, RPL_WHOISOPERATOR, name);
-
-          if (MyConnect(acptr))
-           send_reply(sptr, RPL_WHOISIDLE, name, CurrentTime - user->last,
-                      acptr->firsttime);
-        }
-        if (found == 2 || total++ >= MAX_WHOIS_LINES)
-          break;
+      /* If this is a public channel, show the person */
+      if (!invis && PubChannel(chptr)) {
+        showperson = 1;
+        break;
       }
-    }
-    else
-    {
-      /* No wildcards */
-      if ((acptr = FindUser(nick)))
-      {
-        found = 2;              /* Make sure we exit the loop after passing it once */
-        user = acptr->user;
-        name = (!*acptr->name) ? "?" : acptr->name;
-        a2cptr = user->server;
-       send_reply(sptr, RPL_WHOISUSER, name, user->username, user->host,
-                  acptr->info);
-        goto exact_match;
+      
+      /* if this channel is +p and not +s, show them */
+      if (!invis && HiddenChannel(chptr) && !SecretChannel(chptr)) {
+          showperson = 1;
+          break;
       }
-    }
-    if (!found)
-      send_reply(sptr, ERR_NOSUCHNICK, nick);
-    if (p)
-      p[-1] = ',';
-    if (!MyConnect(sptr) || total >= MAX_WHOIS_LINES)
-      break;
-  }
-  send_reply(sptr, RPL_ENDOFWHOIS, parv[1]);
+      
+      member = find_channel_member(sptr, chptr) ? 1 : 0;
+      if (invis && !member)
+        continue;
 
-  return 0;
+      /* If sptr isn't really on this channel, skip it */
+      if (IsZombie(chan))
+        continue;
+       
+      /* Is this a common channel? */ 
+      if (member) {
+        showperson = 1;
+        break;
+      }
+    } /* of for (chan in channels) */
+    
+    /* Don't show this person */
+    if (!showperson)
+      continue;
+      
+    do_whois(sptr,acptr);
+    found++;
+    if (count+found>MAX_WHOIS_LINES)
+       return found;  
+  } /* of global client list */
+  
+  return found;
 }
 
 /*
- * mo_whois - oper message handler
+ * m_whois - generic message handler
  *
  * parv[0] = sender prefix
  * parv[1] = nickname masklist
  *
  * or
  *
- * parv[1] = target server
+ * parv[1] = target server, or a nickname representing a server to target.
  * parv[2] = nickname masklist
  */
-int mo_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
+int m_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-  struct User*    user;
-  struct Client*  acptr;
-  struct Client*  a2cptr;
-  struct Channel* chptr;
   char*           nick;
   char*           tmp;
-  const char*     name;
   char*           p = 0;
-  int             found;
-  int             len;
-  int             mlen;
-  int             total;
-  static char     buf[512];
+  int             found = 0;
+  int            total = 0;
 
   if (parc < 2)
   {
@@ -561,8 +344,11 @@ int mo_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   {
     struct Client *acptr;
     /* For convenience: Accept a nickname as first parameter, by replacing
-       it with the correct servername - as is needed by hunt_server() */
-    if (MyUser(sptr) && (acptr = FindUser(parv[1])))
+     * it with the correct servername - as is needed by hunt_server().
+     * This is the secret behind the /whois nick nick trick.
+     */
+    acptr = FindUser(parv[1]);
+    if (acptr)
       parv[1] = acptr->user->server->name;
     if (hunt_server_cmd(sptr, CMD_WHOIS, cptr, 0, "%C :%s", 1, parc, parv) !=
         HUNTED_ISME)
@@ -570,203 +356,64 @@ int mo_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
     parv[1] = parv[2];
   }
 
-  total = 0;
   for (tmp = parv[1]; (nick = ircd_strtok(&p, tmp, ",")); tmp = 0)
   {
-    int invis, showperson, member, wilds;
+    int wilds;
 
     found = 0;
+    
     collapse(nick);
+    
     wilds = (strchr(nick, '?') || strchr(nick, '*'));
-    /* Do a hash lookup if the nick does not contain wilds */
-    if (wilds)
-    {
-      /*
-       * We're no longer allowing remote users to generate requests with wildcards.
-       */
-      if (!MyConnect(sptr))
-        continue;
-      for (acptr = GlobalClientList; (acptr = next_client(acptr, nick));
-          acptr = acptr->next)
-      {
-        if (!IsRegistered(acptr) || IsServer(acptr))
-          continue;
-        /*
-         * I'm always last :-) and acptr->next == 0!!
-         */
-        if (IsMe(acptr))
-          break;
-        /*
-         * 'Rules' established for sending a WHOIS reply:
-         *
-         * - if wildcards are being used dont send a reply if
-         *   the querier isnt any common channels and the
-         *   client in question is invisible and wildcards are
-         *   in use (allow exact matches only);
-         *
-         * - only send replies about common or public channels
-         *   the target user(s) are on;
-         */
-        user = acptr->user;
-        name = (!*acptr->name) ? "?" : acptr->name;
-
-        invis = acptr != sptr && IsInvisible(acptr);
-        member = (user && user->channel) ? 1 : 0;
-        showperson = (wilds && !invis && !member) || !wilds;
-        if (user) {
-          struct Membership* chan;
-          for (chan = user->channel; chan; chan = chan->next_channel)
-          {
-            chptr = chan->channel;
-            member = find_channel_member(sptr, chptr) ? 1 : 0;
-            if (invis && !member)
-              continue;
-            if (IsZombie(chan))
-              continue;
-            if (member || (!invis && PubChannel(chptr)))
-            {
-              showperson = 1;
-              break;
-            }
-            if (!invis && HiddenChannel(chptr) && !SecretChannel(chptr))
-              showperson = 1;
-          }
-        }
-        if (!showperson)
-          continue;
-
-        if (user)
-        {
-          a2cptr = user->server;
-         send_reply(sptr, RPL_WHOISUSER, name, user->username, user->host,
-                    acptr->info);
-        }
-        else
-        {
-          a2cptr = &me;
-         send_reply(sptr, RPL_WHOISUSER, name, "<unknown>", "<unknown>",
-                    "<unknown>");
-        }
-
-        found = 1;
-
-exact_match:
-        if (user && !IsChannelService(acptr))
-        {
-          struct Membership* chan;
-          mlen = strlen(me.name) + strlen(parv[0]) + 12 + strlen(name);
-          len = 0;
-          *buf = '\0';
-          for (chan = user->channel; chan; chan = chan->next_channel)
-          {
-            chptr = chan->channel;
-            if (ShowChannel(sptr, chptr) &&
-                (acptr == sptr || !IsZombie(chan)))
-            {
-              if (len + strlen(chptr->chname) + mlen > BUFSIZE - 5)
-              {
-               send_reply(sptr, SND_EXPLICIT | RPL_WHOISCHANNELS,
-                          "%s :%s", name, buf);
-                *buf = '\0';
-                len = 0;
-              }
-              if (IsDeaf(acptr))
-                *(buf + len++) = '-';
-              if (is_chan_op(acptr, chptr))
-                *(buf + len++) = '@';
-              else if (has_voice(acptr, chptr))
-                *(buf + len++) = '+';
-              else if (IsZombie(chan))
-                *(buf + len++) = '!';
-              if (len)
-                *(buf + len) = '\0';
-              strcpy(buf + len, chptr->chname);
-              len += strlen(chptr->chname);
-              strcat(buf + len, " ");
-              len++;
-            }
-          }
-          if (buf[0] != '\0')
-           send_reply(sptr, RPL_WHOISCHANNELS, name, buf);
-        }
-
-       send_reply(sptr, RPL_WHOISSERVER, name, a2cptr->name, a2cptr->info);
-
-        if (user)
-        {
-          if (user->away)
-           send_reply(sptr, RPL_AWAY, name, user->away);
-
-          if (IsAnOper(acptr))
-           send_reply(sptr, RPL_WHOISOPERATOR, name);
-
-          if (MyConnect(acptr))
-           send_reply(sptr, RPL_WHOISIDLE, name, CurrentTime - user->last,
-                      acptr->firsttime);
-        }
-        if (found == 2 || total++ >= MAX_WHOIS_LINES)
-          break;
-      }
-    }
-    else
-    {
+    if (!wilds) {
+      struct Client *acptr = 0;
       /* No wildcards */
-      if ((acptr = FindUser(nick)))
-      {
-        found = 2;              /* Make sure we exit the loop after passing it once */
-        user = acptr->user;
-        name = (!*acptr->name) ? "?" : acptr->name;
-        a2cptr = user->server;
-       send_reply(sptr, RPL_WHOISUSER, name, user->username, user->host,
-                  acptr->info);
-        goto exact_match;
+      acptr = FindUser(nick);
+      if (acptr && !IsServer(acptr)) {
+        do_whois(sptr,acptr);
+        found = 1;
       }
     }
+    else /* wilds */
+       found=do_wilds(sptr,nick,total);
+
     if (!found)
       send_reply(sptr, ERR_NOSUCHNICK, nick);
+    total+=found;
+    if (total >= MAX_WHOIS_LINES) {
+      send_reply(sptr, ERR_QUERYTOOLONG, parv[1]);
+      break;
+    }
     if (p)
       p[-1] = ',';
-    if (!MyConnect(sptr) || total >= MAX_WHOIS_LINES)
-      break;
-  }
+  } /* of tokenised parm[1] */
   send_reply(sptr, RPL_ENDOFWHOIS, parv[1]);
 
   return 0;
 }
 
-  
-
-#if 0
 /*
- * m_whois
+ * ms_whois - server message handler
  *
  * parv[0] = sender prefix
  * parv[1] = nickname masklist
  *
  * or
  *
- * parv[1] = target server
+ * parv[1] = target server, or a nickname representing a server to target.
  * parv[2] = nickname masklist
  */
-int m_whois(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
+int ms_whois(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
-  struct User*    user;
-  struct Client*  acptr;
-  struct Client*  a2cptr;
-  struct Channel* chptr;
   char*           nick;
   char*           tmp;
-  char*           name;
   char*           p = 0;
-  int             found;
-  int             len;
-  int             mlen;
-  int             total;
-  static char     buf[512];
+  int             found = 0;
+  int            total = 0;
 
   if (parc < 2)
   {
-    sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); /* XXX DEAD */
+    send_reply(sptr, ERR_NONICKNAMEGIVEN);
     return 0;
   }
 
@@ -774,181 +421,49 @@ int m_whois(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   {
     struct Client *acptr;
     /* For convenience: Accept a nickname as first parameter, by replacing
-       it with the correct servername - as is needed by hunt_server() */
-    if (MyUser(sptr) && (acptr = FindUser(parv[1])))
+     * it with the correct servername - as is needed by hunt_server().
+     * This is the secret behind the /whois nick nick trick.
+     */
+    acptr = FindUser(parv[1]);
+    if (acptr)
       parv[1] = acptr->user->server->name;
-    if (hunt_server(0, cptr, sptr, "%s%s " TOK_WHOIS " %s :%s", 1, parc, parv) != /* XXX DEAD */
+    if (hunt_server_cmd(sptr, CMD_WHOIS, cptr, 0, "%C :%s", 1, parc, parv) !=
         HUNTED_ISME)
       return 0;
     parv[1] = parv[2];
   }
 
   total = 0;
+  
   for (tmp = parv[1]; (nick = ircd_strtok(&p, tmp, ",")); tmp = 0)
   {
-    int invis, showperson, member, wilds;
+    struct Client *acptr = 0;
 
     found = 0;
+    
     collapse(nick);
-    wilds = (strchr(nick, '?') || strchr(nick, '*'));
-    /* Do a hash lookup if the nick does not contain wilds */
-    if (wilds)
-    {
-      /*
-       * We're no longer allowing remote users to generate requests with wildcards.
-       */
-      if (!MyConnect(sptr))
-        continue;
-      for (acptr = GlobalClientList; (acptr = next_client(acptr, nick));
-          acptr = acptr->next)
-      {
-        if (!IsRegistered(acptr) || IsServer(acptr))
-          continue;
-        /*
-         * I'm always last :-) and acptr->next == NULL!!
-         */
-        if (IsMe(acptr))
-          break;
-        /*
-         * 'Rules' established for sending a WHOIS reply:
-         *
-         * - if wildcards are being used dont send a reply if
-         *   the querier isnt any common channels and the
-         *   client in question is invisible and wildcards are
-         *   in use (allow exact matches only);
-         *
-         * - only send replies about common or public channels
-         *   the target user(s) are on;
-         */
-        user = acptr->user;
-        name = (!*acptr->name) ? "?" : acptr->name;
+    
 
-        invis = acptr != sptr && IsInvisible(acptr);
-        member = (user && user->channel) ? 1 : 0;
-        showperson = (wilds && !invis && !member) || !wilds;
-        if (user) {
-          struct Membership* chan;
-          for (chan = user->channel; chan; chan = chan->next_channel)
-          {
-            chptr = chan->channel;
-            member = find_channel_member(sptr, chptr) ? 1 : 0;
-            if (invis && !member)
-              continue;
-            if (IsZombie(chan))
-              continue;
-            if (member || (!invis && PubChannel(chptr)))
-            {
-              showperson = 1;
-              break;
-            }
-            if (!invis && HiddenChannel(chptr) && !SecretChannel(chptr))
-              showperson = 1;
-          }
-        }
-        if (!showperson)
-          continue;
-
-        if (user)
-        {
-          a2cptr = user->server;
-          sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name, /* XXX DEAD */
-              parv[0], name, user->username, user->host, acptr->info);
-        }
-        else
-        {
-          a2cptr = &me;
-          sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name, /* XXX DEAD */
-              parv[0], name, "<unknown>", "<unknown>", "<unknown>");
-        }
-
-        found = 1;
-
-exact_match:
-        if (user && !IsChannelService(acptr))
-        {
-          struct Membership* chan;
-          mlen = strlen(me.name) + strlen(parv[0]) + 12 + strlen(name);
-          len = 0;
-          *buf = '\0';
-          for (chan = user->channel; chan; chan = chan->next_channel)
-          {
-            chptr = chan->channel;
-            if (ShowChannel(sptr, chptr) &&
-                (acptr == sptr || !IsZombie(chan)))
-            {
-              if (len + strlen(chptr->chname) + mlen > BUFSIZE - 5)
-              {
-                sendto_one(sptr, ":%s %d %s %s :%s", /* XXX DEAD */
-                    me.name, RPL_WHOISCHANNELS, parv[0], name, buf);
-                *buf = '\0';
-                len = 0;
-              }
-              if (IsDeaf(acptr))
-                *(buf + len++) = '-';
-              if (is_chan_op(acptr, chptr))
-                *(buf + len++) = '@';
-              else if (has_voice(acptr, chptr))
-                *(buf + len++) = '+';
-              else if (IsZombie(chan))
-                *(buf + len++) = '!';
-              if (len)
-                *(buf + len) = '\0';
-              strcpy(buf + len, chptr->chname);
-              len += strlen(chptr->chname);
-              strcat(buf + len, " ");
-              len++;
-            }
-          }
-          if (buf[0] != '\0')
-            sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS), /* XXX DEAD */
-                me.name, parv[0], name, buf);
-        }
-
-        sendto_one(sptr, rpl_str(RPL_WHOISSERVER), me.name, /* XXX DEAD */
-            parv[0], name, a2cptr->name, a2cptr->info);
-
-        if (user)
-        {
-          if (user->away)
-            sendto_one(sptr, rpl_str(RPL_AWAY), me.name, /* XXX DEAD */
-                parv[0], name, user->away);
-
-          if (IsAnOper(acptr))
-            sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR), /* XXX DEAD */
-                me.name, parv[0], name);
-
-          if (MyConnect(acptr))
-            sendto_one(sptr, rpl_str(RPL_WHOISIDLE), me.name, /* XXX DEAD */
-                parv[0], name, CurrentTime - user->last, acptr->firsttime);
-        }
-        if (found == 2 || total++ >= MAX_WHOIS_LINES)
-          break;
-      }
-    }
-    else
-    {
-      /* No wildcards */
-      if ((acptr = FindUser(nick)))
-      {
-        found = 2;              /* Make sure we exit the loop after passing it once */
-        user = acptr->user;
-        name = (!*acptr->name) ? "?" : acptr->name;
-        a2cptr = user->server;
-        sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name, /* XXX DEAD */
-            parv[0], name, user->username, user->host, acptr->info);
-        goto exact_match;
-      }
+    acptr = FindUser(nick);
+    if (acptr && !IsServer(acptr)) {
+      found++;
+      do_whois(sptr,acptr);
     }
+
     if (!found)
-      sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick); /* XXX DEAD */
+      send_reply(sptr, ERR_NOSUCHNICK, nick);
+      
+    total+=found;
+      
+    if (total >= MAX_WHOIS_LINES) {
+      send_reply(sptr, ERR_QUERYTOOLONG, parv[1]);
+      break;
+    }
+      
     if (p)
       p[-1] = ',';
-    if (!MyConnect(sptr) || total >= MAX_WHOIS_LINES)
-      break;
-  }
-  sendto_one(sptr, rpl_str(RPL_ENDOFWHOIS), me.name, parv[0], parv[1]); /* XXX DEAD */
+  } /* of tokenised parm[1] */
+  send_reply(sptr, RPL_ENDOFWHOIS, parv[1]);
 
   return 0;
-}
-#endif /* 0 */
-
+}
\ No newline at end of file