Move check_if_ipmask() from support.* to match.*.
[ircu2.10.12-pk.git] / ircd / hash.c
index 375ebea455dd6374b29c4cc27978041a42794850..21539c34391f3cddc0a20e0dc9ffa71a803cfd82 100644 (file)
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Id$
  */
+#include "config.h"
 
-#include "sys.h"
-#include <stdlib.h>
-#include <limits.h>
-#include "h.h"
-#include "struct.h"
-#include "common.h"
 #include "hash.h"
+#include "client.h"
 #include "channel.h"
-#include "send.h"
-#include "s_serv.h"
+#include "ircd_chattr.h"
+#include "ircd_string.h"
 #include "ircd.h"
-#include "support.h"
+#include "msg.h"
+#include "send.h"
+#include "struct.h"
+#include "sys.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
 
-RCSTAG_CC("$Id$");
 
 /************************* Nemesi's hash alghoritm ***********************/
 
@@ -166,27 +171,29 @@ static HASHMEMS hash_weight_table[CHAR_MAX - CHAR_MIN + 1];
    size tables could be supported but the rehash routine should also
    rebuild the transformation maps, I kept the tables of equal size 
    so that I can use one hash function and one transformation map */
-static aClient *clientTable[HASHSIZE];
-static aChannel *channelTable[HASHSIZE];
+static struct Client *clientTable[HASHSIZE];
+static struct Channel *channelTable[HASHSIZE];
 
 /* This is what the hash function will consider "equal" chars, this function 
    MUST be transitive, if HASHEQ(y,x)&&HASHEQ(y,z) then HASHEQ(y,z), and MUST
    be symmetric, if HASHEQ(a,b) then HASHEQ(b,a), obvious ok but... :) */
-#define HASHEQ(x,y) (((char) toLower((char) x)) == ((char) toLower((char) y)))
+#define HASHEQ(x,y) ((ToLower(x)) == (ToLower(y)))
 
-/* hash_init
+/* init_hash
  * Initialize the maps used by hash functions and clear the tables */
-void hash_init(void)
+void init_hash(void)
 {
-  int i, j;
-  unsigned long l, m;
+  int           i;
+  int           j;
+  unsigned long l;
+  unsigned long m;
 
   /* Clear the hash tables first */
   for (l = 0; l < HASHSIZE; l++)
   {
-    channelTable[l] = (aChannel *)NULL;
-    clientTable[l] = (aClient *)NULL;
-  };
+    channelTable[l] = 0;
+    clientTable[l]  = 0;
+  }
 
   /* Here is to what we "map" a char before working on it */
   for (i = CHAR_MIN; i <= CHAR_MAX; i++)
@@ -197,10 +204,12 @@ void hash_init(void)
      possible to change the HASHEQ macro and not touch here. 
      I don't actually care about the 32768 loops since it happens 
      only once at startup */
-  for (i = CHAR_MIN; i <= CHAR_MAX; i++)
-    for (j = CHAR_MIN; j < i; j++)
+  for (i = CHAR_MIN; i <= CHAR_MAX; i++) {
+    for (j = CHAR_MIN; j < i; j++) {
       if (HASHEQ(i, j))
-       hash_weight(i) = hash_weight(j);
+        hash_weight(i) = hash_weight(j);
+    }
+  }
 
   /* And this is our hash-loop "transformation" function, 
      basically it will be hash_map[x] == ((x*HASHSHIFT)%HASHSIZE)
@@ -211,7 +220,7 @@ void hash_init(void)
     l *= (unsigned long)HASHSHIFT;
     l %= (unsigned long)HASHSIZE;
     hash_map[m] = (HASHMEMS) l;
-  };
+  }
 }
 
 /* These are the actual hash functions, since they are static
@@ -224,9 +233,9 @@ void hash_init(void)
    strhash("") _will_ coredump, it's responsibility
    the caller to eventually check BadPtr(nick). */
 
-static HASHREGS strhash(register char *n)
+static HASHREGS strhash(const char *n)
 {
-  register HASHREGS hash = hash_weight(*n++);
+  HASHREGS hash = hash_weight(*n++);
   while (*n)
     hash = hash_map[hash] + hash_weight(*n++);
   return hash_map[hash];
@@ -243,8 +252,8 @@ static HASHREGS strhash(register char *n)
    on 16000 real channel names, 1000 loops. I left the code here
    as a bookmark if a strnhash is evetually needed in the future.
 
-   static HASHREGS strnhash(register char *n, register int i) {
-   register HASHREGS hash = hash_weight(*n++);
+   static HASHREGS strnhash(const char *n, int i) {
+   HASHREGS hash = hash_weight(*n++);
    i--;
    while(*n && i--)
    hash = hash_map[hash] + hash_weight(*n++);
@@ -271,11 +280,11 @@ static HASHREGS strhash(register char *n)
  * cptr must have a non-null name or expect a coredump, the name is
  * infact taken from cptr->name
  */
-int hAddClient(aClient *cptr)
+int hAddClient(struct Client *cptr)
 {
-  register HASHREGS hashv = strhash(cptr->name);
+  HASHREGS hashv = strhash(cli_name(cptr));
 
-  cptr->hnext = clientTable[hashv];
+  cli_hnext(cptr) = clientTable[hashv];
   clientTable[hashv] = cptr;
 
   return 0;
@@ -288,11 +297,11 @@ int hAddClient(aClient *cptr)
  * As before the name is taken from chptr->name, we do hash its entire
  * lenght since this proved to be statistically faster
  */
-int hAddChannel(aChannel *chptr)
+int hAddChannel(struct Channel *chptr)
 {
-  register HASHREGS hashv = strhash(chptr->chname);
+  HASHREGS hashv = strhash(chptr->chname);
 
-  chptr->hnextch = channelTable[hashv];
+  chptr->hnext = channelTable[hashv];
   channelTable[hashv] = chptr;
 
   return 0;
@@ -302,24 +311,24 @@ int hAddChannel(aChannel *chptr)
  * hRemClient
  * Removes a Client's name from the hash linked list
  */
-int hRemClient(aClient *cptr)
+int hRemClient(struct Client *cptr)
 {
-  register HASHREGS hashv = strhash(cptr->name);
-  register aClient *tmp = clientTable[hashv];
+  HASHREGS hashv = strhash(cli_name(cptr));
+  struct Client *tmp = clientTable[hashv];
 
-  if (tmp == cptr)
-  {
-    clientTable[hashv] = cptr->hnext;
+  if (tmp == cptr) {
+    clientTable[hashv] = cli_hnext(cptr);
+    cli_hnext(cptr) = cptr;
     return 0;
   }
-  while (tmp)
-  {
-    if (tmp->hnext == cptr)
-    {
-      tmp->hnext = tmp->hnext->hnext;
+
+  while (tmp) {
+    if (cli_hnext(tmp) == cptr) {
+      cli_hnext(tmp) = cli_hnext(cli_hnext(tmp));
+      cli_hnext(cptr) = cptr;
       return 0;
     }
-    tmp = tmp->hnext;
+    tmp = cli_hnext(tmp);
   }
   return -1;
 }
@@ -340,13 +349,14 @@ int hRemClient(aClient *cptr)
  * There isn't an equivalent function for channels since they
  * don't change name.
  */
-int hChangeClient(aClient *cptr, char *newname)
+int hChangeClient(struct Client *cptr, const char *newname)
 {
-  register HASHREGS newhash = strhash(newname);
+  HASHREGS newhash = strhash(newname);
 
+  assert(0 != cptr);
   hRemClient(cptr);
 
-  cptr->hnext = clientTable[newhash];
+  cli_hnext(cptr) = clientTable[newhash];
   clientTable[newhash] = cptr;
   return 0;
 }
@@ -355,26 +365,25 @@ int hChangeClient(aClient *cptr, char *newname)
  * hRemChannel
  * Removes the channel's name from the corresponding hash linked list
  */
-int hRemChannel(aChannel *chptr)
+int hRemChannel(struct Channel *chptr)
 {
-  register HASHREGS hashv = strhash(chptr->chname);
-  register aChannel *tmp = channelTable[hashv];
+  HASHREGS hashv = strhash(chptr->chname);
+  struct Channel *tmp = channelTable[hashv];
 
-  if (tmp == chptr)
-  {
-    channelTable[hashv] = chptr->hnextch;
+  if (tmp == chptr) {
+    channelTable[hashv] = chptr->hnext;
+    chptr->hnext = chptr;
     return 0;
-  };
+  }
 
-  while (tmp)
-  {
-    if (tmp->hnextch == chptr)
-    {
-      tmp->hnextch = tmp->hnextch->hnextch;
+  while (tmp) {
+    if (tmp->hnext == chptr) {
+      tmp->hnext = tmp->hnext->hnext;
+      chptr->hnext = chptr;
       return 0;
-    };
-    tmp = tmp->hnextch;
-  };
+    }
+    tmp = tmp->hnext;
+  }
 
   return -1;
 }
@@ -386,25 +395,25 @@ int hRemChannel(aChannel *chptr)
  * returns NULL. If it finds one moves it to the top of the list
  * and returns it.
  */
-aClient *hSeekClient(char *name, int TMask)
+struct Client* hSeekClient(const char *name, int TMask)
 {
-  register HASHREGS hashv = strhash(name);
-  register aClient *cptr = clientTable[hashv];
-  register aClient *prv;
-
-  if (cptr)
-    if ((!IsStatMask(cptr, TMask)) || strCasediff(name, cptr->name))
-      while (prv = cptr, cptr = cptr->hnext)
-       if (IsStatMask(cptr, TMask) && (!strCasediff(name, cptr->name)))
-       {
-         prv->hnext = cptr->hnext;
-         cptr->hnext = clientTable[hashv];
-         clientTable[hashv] = cptr;
-         break;
-       };
-
+  HASHREGS hashv      = strhash(name);
+  struct Client *cptr = clientTable[hashv];
+
+  if (cptr) {
+    if (0 == (cli_status(cptr) & TMask) || 0 != ircd_strcmp(name, cli_name(cptr))) {
+      struct Client* prev;
+      while (prev = cptr, cptr = cli_hnext(cptr)) {
+        if ((cli_status(cptr) & TMask) && (0 == ircd_strcmp(name, cli_name(cptr)))) {
+          cli_hnext(prev) = cli_hnext(cptr);
+          cli_hnext(cptr) = clientTable[hashv];
+          clientTable[hashv] = cptr;
+          break;
+        }
+      }
+    }
+  }
   return cptr;
-
 }
 
 /*
@@ -413,23 +422,24 @@ aClient *hSeekClient(char *name, int TMask)
  * if can't find one returns NULL, if can find it moves
  * it to the top of the list and returns it.
  */
-aChannel *hSeekChannel(char *name)
+struct Channel* hSeekChannel(const char *name)
 {
-  register HASHREGS hashv = strhash(name);
-  register aChannel *chptr = channelTable[hashv];
-  register aChannel *prv;
-
-  if (chptr)
-    if (strCasediff(name, chptr->chname))
-      while (prv = chptr, chptr = chptr->hnextch)
-       if (!strCasediff(name, chptr->chname))
-       {
-         prv->hnextch = chptr->hnextch;
-         chptr->hnextch = channelTable[hashv];
-         channelTable[hashv] = chptr;
-         break;
-       };
-
+  HASHREGS hashv = strhash(name);
+  struct Channel *chptr = channelTable[hashv];
+
+  if (chptr) {
+    if (0 != ircd_strcmp(name, chptr->chname)) {
+      struct Channel* prev;
+      while (prev = chptr, chptr = chptr->hnext) {
+        if (0 == ircd_strcmp(name, chptr->chname)) {
+          prev->hnext = chptr->hnext;
+          chptr->hnext = channelTable[hashv];
+          channelTable[hashv] = chptr;
+          break;
+        }
+      }
+    }
+  }
   return chptr;
 
 }
@@ -439,13 +449,50 @@ aChannel *hSeekChannel(char *name)
    coders are able to SIGCORE the server and look into what goes
    on themselves :-) */
 
-int m_hash(aClient *UNUSED(cptr), aClient *sptr, int UNUSED(parc), char *parv[])
+int m_hash(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
 {
-  sendto_one(sptr, "NOTICE %s :SUSER SSERV", parv[0]);
-  sendto_one(sptr, "NOTICE %s :SBSDC IRCDC", parv[0]);
-  sendto_one(sptr, "NOTICE %s :CHANC SMISC", parv[0]);
-  sendto_one(sptr, "NOTICE %s :HASHC VERSH", parv[0]);
-  sendto_one(sptr, "NOTICE %s :MAKEF HOSTID", parv[0]);
+  int max_chain = 0;
+  int buckets   = 0;
+  int count     = 0;
+  struct Client*  cl;
+  struct Channel* ch;
+  int i;
+  
+  sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Hash Table Statistics", sptr);
+
+  for (i = 0; i < HASHSIZE; ++i) {
+    if ((cl = clientTable[i])) {
+      int len = 0;
+      ++buckets;
+      for ( ; cl; cl = cli_hnext(cl))
+        ++len; 
+      if (len > max_chain)
+        max_chain = len;
+      count += len;
+    }
+  } 
+
+  sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Client: entries: %d buckets: %d "
+               "max chain: %d", sptr, count, buckets, max_chain);
+
+  buckets = 0;
+  count   = 0;
+  max_chain = 0;
+
+  for (i = 0; i < HASHSIZE; ++i) {
+    if ((ch = channelTable[i])) {
+      int len = 0;
+      ++buckets;
+      for ( ; ch; ch = ch->hnext)
+        ++len; 
+      if (len > max_chain)
+        max_chain = len;
+      count += len;
+    }
+  } 
+
+  sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Channel: entries: %d buckets: %d "
+               "max chain: %d", sptr, count, buckets, max_chain);
   return 0;
 }
 
@@ -454,62 +501,65 @@ int m_hash(aClient *UNUSED(cptr), aClient *sptr, int UNUSED(parc), char *parv[])
    lowest 12 bits of the hash value are used, deletion is not supported,
    only addition, test for existence and cleanup of the table are.. */
 
-#define JUPEHASHBITS 12                /* 4096 entries, 64 nick jupes allowed */
+#define JUPEHASHBITS 12         /* 4096 entries, 64 nick jupes allowed */
 #define JUPEHASHSIZE (1<<JUPEHASHBITS)
 #define JUPEHASHMASK (JUPEHASHSIZE-1)
 #define JUPEMAX      (1<<(JUPEHASHBITS-6))
 
-static char jupeTable[JUPEHASHSIZE][NICKLEN + 1];      /* About 40k */
+static char jupeTable[JUPEHASHSIZE][NICKLEN + 1];       /* About 40k */
 static int jupesCount;
 
 /*
  * isNickJuped()
  * Tells if a nick is juped (nonzero returned) or not (zero) 
  */
-int isNickJuped(char *nick)
+int isNickJuped(const char *nick)
 {
-  register int pos;
+  int pos;
 
-  if (nick && *nick)
-    for (pos = strhash(nick); (pos &= JUPEHASHMASK), jupeTable[pos][0]; pos++)
-      if (!strCasediff(nick, jupeTable[pos]))
-       return 1;
-  return 0;                    /* A bogus pointer is NOT a juped nick, right ? :) */
+  if (nick && *nick) {
+    for (pos = strhash(nick); (pos &= JUPEHASHMASK), jupeTable[pos][0]; pos++) {
+      if (0 == ircd_strcmp(nick, jupeTable[pos]))
+        return 1;
+    }
+  }
+  return 0;                     /* A bogus pointer is NOT a juped nick, right ? :) */
 }
 
 /*
  * addNickJupes()
  * Adds a (comma separated list of) nick jupes to the table 
  */
-int addNickJupes(char *nicks)
+int addNickJupes(const char *nicks)
 {
-  static char temp[512];
-  char *one, *p;
-  register int pos;
+  static char temp[BUFSIZE + 1];
+  char* one;
+  char* p;
+  int   pos;
 
   if (nicks && *nicks)
   {
-    strncpy(temp, nicks, 512);
-    temp[512] = '\000';
+    ircd_strncpy(temp, nicks, BUFSIZE);
+    temp[BUFSIZE] = '\0';
     p = NULL;
-    for (one = strtoken(&p, temp, ","); one; one = strtoken(&p, NULL, ","))
+    for (one = ircd_strtok(&p, temp, ","); one; one = ircd_strtok(&p, NULL, ","))
     {
       if (!*one)
-       continue;
+        continue;
       pos = strhash(one);
-    loop:
+loop:
       pos &= JUPEHASHMASK;
       if (!jupeTable[pos][0])
       {
-       if (jupesCount == JUPEMAX)
-         return 1;             /* Error: Jupe table is full ! */
-       jupesCount++;
-       strncpy(jupeTable[pos], one, NICKLEN);
-       jupeTable[pos][NICKLEN] = '\000';       /* Better safe than sorry :) */
-       continue;
+        if (jupesCount == JUPEMAX)
+          return 1;             /* Error: Jupe table is full ! */
+        jupesCount++;
+        ircd_strncpy(jupeTable[pos], one, NICKLEN);
+        jupeTable[pos][NICKLEN] = '\000';       /* Better safe than sorry :) */
+        continue;
       }
-      if (!strCasediff(one, jupeTable[pos]))
-       continue;
+      if (0 == ircd_strcmp(one, jupeTable[pos]))
+        continue;
       ++pos;
       goto loop;
     }
@@ -523,7 +573,7 @@ int addNickJupes(char *nicks)
  */
 void clearNickJupes(void)
 {
-  register int i;
+  int i;
   jupesCount = 0;
   for (i = 0; i < JUPEHASHSIZE; i++)
     jupeTable[i][0] = '\000';