]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd.cpp
Added IOHookModule stuff to allow for different modules to hook different ports
[user/henk/code/inspircd.git] / src / inspircd.cpp
index 0a1eb14e68c2ebd7be73406da624222aeabfe70c..c370c7f842d462f0fa6610dcbfc35f4f3e33c3a6 100644 (file)
@@ -21,7 +21,6 @@ using namespace std;
 #include "inspircd_config.h"
 #include "inspircd.h"
 #include "inspircd_io.h"
-#include "inspircd_util.h"
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/errno.h>
@@ -38,7 +37,6 @@ using namespace std;
 #include <sstream>
 #include <vector>
 #include <deque>
-#include <sched.h>
 #ifdef THREADED_DNS
 #include <pthread.h>
 #endif
@@ -59,8 +57,8 @@ using namespace std;
 #include "socketengine.h"
 #include "userprocess.h"
 #include "socket.h"
-#include "dns.h"
 #include "typedefs.h"
+#include "command_parse.h"
 
 InspIRCd* ServerInstance;
 
@@ -70,6 +68,7 @@ int WHOWAS_MAX = 100;  // default 100 people maximum in the WHOWAS list
 extern std::vector<Module*> modules;
 extern std::vector<ircd_module*> factory;
 std::vector<InspSocket*> module_sockets;
+std::vector<userrec*> local_users;
 
 extern int MODCOUNT;
 int openSockfd[MAXSOCKS];
@@ -87,26 +86,15 @@ SocketEngine* SE = NULL;
 // by an integer, meaning there is no need for a scan/search operation.
 userrec* fd_ref_table[65536];
 
-serverstats* stats = new serverstats;
 Server* MyServer = new Server;
 ServerConfig *Config = new ServerConfig;
 
 user_hash clientlist;
 chan_hash chanlist;
 whowas_hash whowas;
-command_table cmdlist;
 servernamelist servernames;
-int BoundPortCount = 0;
-std::vector<userrec*> all_opers;
 char lowermap[255];
 
-
-void AddOper(userrec* user)
-{
-       log(DEBUG,"Oper added to optimization list");
-       all_opers.push_back(user);
-}
-
 void AddServerName(std::string servername)
 {
        log(DEBUG,"Adding server name: %s",servername.c_str());
@@ -129,19 +117,6 @@ const char* FindServerNamePtr(std::string servername)
        return FindServerNamePtr(servername);
 }
 
-void DeleteOper(userrec* user)
-{
-        for (std::vector<userrec*>::iterator a = all_opers.begin(); a < all_opers.end(); a++)
-        {
-                if (*a == user)
-                {
-                        log(DEBUG,"Oper removed from optimization list");
-                        all_opers.erase(a);
-                        return;
-                }
-        }
-}
-
 std::string InspIRCd::GetRevision()
 {
        /* w00t got me to replace a bunch of strtok_r
@@ -159,272 +134,20 @@ std::string InspIRCd::GetRevision()
        return single;
 }
 
-
-/* This function pokes and hacks at a parameter list like the following:
- *
- * PART #winbot,#darkgalaxy :m00!
- *
- * to turn it into a series of individual calls like this:
- *
- * PART #winbot :m00!
- * PART #darkgalaxy :m00!
- *
- * The seperate calls are sent to a callback function provided by the caller
- * (the caller will usually call itself recursively). The callback function
- * must be a command handler. Calling this function on a line with no list causes
- * no action to be taken. You must provide a starting and ending parameter number
- * where the range of the list can be found, useful if you have a terminating
- * parameter as above which is actually not part of the list, or parameters
- * before the actual list as well. This code is used by many functions which
- * can function as "one to list" (see the RFC) */
-
-int loop_call(handlerfunc fn, char **parameters, int pcnt, userrec *u, int start, int end, int joins)
-{
-       char plist[MAXBUF];
-       char *param;
-       char *pars[32];
-       char blog[32][MAXBUF];
-       char blog2[32][MAXBUF];
-       int j = 0, q = 0, total = 0, t = 0, t2 = 0, total2 = 0;
-       char keystr[MAXBUF];
-       char moo[MAXBUF];
-
-       for (int i = 0; i <32; i++)
-               strcpy(blog[i],"");
-
-       for (int i = 0; i <32; i++)
-               strcpy(blog2[i],"");
-
-       strcpy(moo,"");
-       for (int i = 0; i <10; i++)
-       {
-               if (!parameters[i])
-               {
-                       parameters[i] = moo;
-               }
-       }
-       if (joins)
-       {
-               if (pcnt > 1) /* we have a key to copy */
-               {
-                       strlcpy(keystr,parameters[1],MAXBUF);
-               }
-       }
-
-       if (!parameters[start])
-       {
-               return 0;
-       }
-       if (!strchr(parameters[start],','))
-       {
-               return 0;
-       }
-       strcpy(plist,"");
-       for (int i = start; i <= end; i++)
-       {
-               if (parameters[i])
-               {
-                       strlcat(plist,parameters[i],MAXBUF);
-               }
-       }
-       
-       j = 0;
-       param = plist;
-
-       t = strlen(plist);
-       for (int i = 0; i < t; i++)
-       {
-               if (plist[i] == ',')
-               {
-                       plist[i] = '\0';
-                       strlcpy(blog[j++],param,MAXBUF);
-                       param = plist+i+1;
-                       if (j>20)
-                       {
-                               WriteServ(u->fd,"407 %s %s :Too many targets in list, message not delivered.",u->nick,blog[j-1]);
-                               return 1;
-                       }
-               }
-       }
-       strlcpy(blog[j++],param,MAXBUF);
-       total = j;
-
-       if ((joins) && (keystr) && (total>0)) // more than one channel and is joining
-       {
-               strcat(keystr,",");
-       }
-       
-       if ((joins) && (keystr))
-       {
-               if (strchr(keystr,','))
-               {
-                       j = 0;
-                       param = keystr;
-                       t2 = strlen(keystr);
-                       for (int i = 0; i < t2; i++)
-                       {
-                               if (keystr[i] == ',')
-                               {
-                                       keystr[i] = '\0';
-                                       strlcpy(blog2[j++],param,MAXBUF);
-                                       param = keystr+i+1;
-                               }
-                       }
-                       strlcpy(blog2[j++],param,MAXBUF);
-                       total2 = j;
-               }
-       }
-
-       for (j = 0; j < total; j++)
-       {
-               if (blog[j])
-               {
-                       pars[0] = blog[j];
-               }
-               for (q = end; q < pcnt-1; q++)
-               {
-                       if (parameters[q+1])
-                       {
-                               pars[q-end+1] = parameters[q+1];
-                       }
-               }
-               if ((joins) && (parameters[1]))
-               {
-                       if (pcnt > 1)
-                       {
-                               pars[1] = blog2[j];
-                       }
-                       else
-                       {
-                               pars[1] = NULL;
-                       }
-               }
-               /* repeatedly call the function with the hacked parameter list */
-               if ((joins) && (pcnt > 1))
-               {
-                       if (pars[1])
-                       {
-                               // pars[1] already set up and containing key from blog2[j]
-                               fn(pars,2,u);
-                       }
-                       else
-                       {
-                               pars[1] = parameters[1];
-                               fn(pars,2,u);
-                       }
-               }
-               else
-               {
-                       fn(pars,pcnt-(end-start),u);
-               }
-       }
-
-       return 1;
-}
-
-
-
-void kill_link(userrec *user,const char* r)
-{
-       user_hash::iterator iter = clientlist.find(user->nick);
-       
-       char reason[MAXBUF];
-       
-       strncpy(reason,r,MAXBUF);
-
-       if (strlen(reason)>MAXQUIT)
-       {
-               reason[MAXQUIT-1] = '\0';
-       }
-
-       log(DEBUG,"kill_link: %s '%s'",user->nick,reason);
-       Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason);
-       log(DEBUG,"closing fd %lu",(unsigned long)user->fd);
-
-       if (user->registered == 7) {
-               FOREACH_MOD OnUserQuit(user,reason);
-               WriteCommonExcept(user,"QUIT :%s",reason);
-       }
-
-       user->FlushWriteBuf();
-
-       FOREACH_MOD OnUserDisconnect(user);
-
-       if (user->fd > -1)
-       {
-               FOREACH_MOD OnRawSocketClose(user->fd);
-               SE->DelFd(user->fd);
-               user->CloseSocket();
-       }
-
-       // this must come before the WriteOpers so that it doesnt try to fill their buffer with anything
-       // if they were an oper with +s.
-        if (user->registered == 7) {
-                purge_empty_chans(user);
-               // fix by brain: only show local quits because we only show local connects (it just makes SENSE)
-               if (user->fd > -1)
-                       WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason);
-               AddWhoWas(user);
-       }
-
-       if (iter != clientlist.end())
-       {
-               log(DEBUG,"deleting user hash value %lu",(unsigned long)user);
-               if (user->fd > -1)
-                       fd_ref_table[user->fd] = NULL;
-               clientlist.erase(iter);
-       }
-       delete user;
-}
-
-void kill_link_silent(userrec *user,const char* r)
+void InspIRCd::MakeLowerMap()
 {
-       user_hash::iterator iter = clientlist.find(user->nick);
-       
-       char reason[MAXBUF];
-       
-       strncpy(reason,r,MAXBUF);
-
-       if (strlen(reason)>MAXQUIT)
-       {
-               reason[MAXQUIT-1] = '\0';
-       }
-
-       log(DEBUG,"kill_link: %s '%s'",user->nick,reason);
-       Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason);
-       log(DEBUG,"closing fd %lu",(unsigned long)user->fd);
-
-       user->FlushWriteBuf();
-
-       if (user->registered == 7) {
-               FOREACH_MOD OnUserQuit(user,reason);
-               WriteCommonExcept(user,"QUIT :%s",reason);
-       }
-
-       FOREACH_MOD OnUserDisconnect(user);
-
-        if (user->fd > -1)
-        {
-               FOREACH_MOD OnRawSocketClose(user->fd);
-               SE->DelFd(user->fd);
-               user->CloseSocket();
-        }
-
-        if (user->registered == 7) {
-                purge_empty_chans(user);
-        }
-       
-       if (iter != clientlist.end())
-       {
-               log(DEBUG,"deleting user hash value %lu",(unsigned long)user);
-                if (user->fd > -1)
-                        fd_ref_table[user->fd] = NULL;
-               clientlist.erase(iter);
-       }
-       delete user;
+       // initialize the lowercase mapping table
+       for (unsigned int cn = 0; cn < 256; cn++)
+               lowermap[cn] = cn;
+       // lowercase the uppercase chars
+       for (unsigned int cn = 65; cn < 91; cn++)
+               lowermap[cn] = tolower(cn);
+       // now replace the specific chars for scandanavian comparison
+       lowermap[(unsigned)'['] = '{';
+       lowermap[(unsigned)']'] = '}';
+       lowermap[(unsigned)'\\'] = '|';
 }
 
-
 InspIRCd::InspIRCd(int argc, char** argv)
 {
        Start();
@@ -455,27 +178,19 @@ InspIRCd::InspIRCd(int argc, char** argv)
        }
 
        strlcpy(Config->MyExecutable,argv[0],MAXBUF);
-       
-       // initialize the lowercase mapping table
-       for (unsigned int cn = 0; cn < 256; cn++)
-               lowermap[cn] = cn;
-       // lowercase the uppercase chars
-       for (unsigned int cn = 65; cn < 91; cn++)
-               lowermap[cn] = tolower(cn);
-       // now replace the specific chars for scandanavian comparison
-       lowermap[(unsigned)'['] = '{';
-       lowermap[(unsigned)']'] = '}';
-       lowermap[(unsigned)'\\'] = '|';
 
+       this->MakeLowerMap();
 
         OpenLog(argv, argc);
         Config->ClearStack();
         Config->Read(true,NULL);
         CheckRoot();
-        SetupCommandTable();
+       this->ModeGrok = new ModeParser();
+       this->Parser = new CommandParser();
+       this->stats = new serverstats();
         AddServerName(Config->ServerName);
         CheckDie();
-        BoundPortCount = BindPorts();
+        stats->BoundPortCount = BindPorts();
 
         printf("\n");
         if (!Config->nofork)
@@ -493,368 +208,10 @@ InspIRCd::InspIRCd(int argc, char** argv)
         SE = new SocketEngine();
 
         /* We must load the modules AFTER initializing the socket engine, now */
-        LoadAllModules();
-
-        printf("\nInspIRCd is now running!\n");
 
        return;
 }
 
-template<typename T> inline string ConvToStr(const T &in)
-{
-       stringstream tmp;
-       if (!(tmp << in)) return string();
-       return tmp.str();
-}
-
-/* re-allocates a nick in the user_hash after they change nicknames,
- * returns a pointer to the new user as it may have moved */
-
-userrec* ReHashNick(char* Old, char* New)
-{
-       //user_hash::iterator newnick;
-       user_hash::iterator oldnick = clientlist.find(Old);
-
-       log(DEBUG,"ReHashNick: %s %s",Old,New);
-       
-       if (!strcasecmp(Old,New))
-       {
-               log(DEBUG,"old nick is new nick, skipping");
-               return oldnick->second;
-       }
-       
-       if (oldnick == clientlist.end()) return NULL; /* doesnt exist */
-
-       log(DEBUG,"ReHashNick: Found hashed nick %s",Old);
-
-       userrec* olduser = oldnick->second;
-       clientlist[New] = olduser;
-       clientlist.erase(oldnick);
-
-       log(DEBUG,"ReHashNick: Nick rehashed as %s",New);
-       
-       return clientlist[New];
-}
-
-/* adds or updates an entry in the whowas list */
-void AddWhoWas(userrec* u)
-{
-       whowas_hash::iterator iter = whowas.find(u->nick);
-       WhoWasUser *a = new WhoWasUser();
-       strlcpy(a->nick,u->nick,NICKMAX);
-       strlcpy(a->ident,u->ident,IDENTMAX);
-       strlcpy(a->dhost,u->dhost,160);
-       strlcpy(a->host,u->host,160);
-       strlcpy(a->fullname,u->fullname,MAXGECOS);
-       strlcpy(a->server,u->server,256);
-       a->signon = u->signon;
-
-       /* MAX_WHOWAS:   max number of /WHOWAS items
-        * WHOWAS_STALE: number of hours before a WHOWAS item is marked as stale and
-        *               can be replaced by a newer one
-        */
-       
-       if (iter == whowas.end())
-       {
-               if (whowas.size() >= (unsigned)WHOWAS_MAX)
-               {
-                       for (whowas_hash::iterator i = whowas.begin(); i != whowas.end(); i++)
-                       {
-                               // 3600 seconds in an hour ;)
-                               if ((i->second->signon)<(TIME-(WHOWAS_STALE*3600)))
-                               {
-                                       // delete the old one
-                                       if (i->second) delete i->second;
-                                       // replace with new one
-                                       i->second = a;
-                                       log(DEBUG,"added WHOWAS entry, purged an old record");
-                                       return;
-                               }
-                       }
-                       // no space left and user doesnt exist. Don't leave ram in use!
-                       log(DEBUG,"Not able to update whowas (list at WHOWAS_MAX entries and trying to add new?), freeing excess ram");
-                       delete a;
-               }
-               else
-               {
-                       log(DEBUG,"added fresh WHOWAS entry");
-                       whowas[a->nick] = a;
-               }
-       }
-       else
-       {
-               log(DEBUG,"updated WHOWAS entry");
-               if (iter->second) delete iter->second;
-               iter->second = a;
-       }
-}
-
-#ifdef THREADED_DNS
-void* dns_task(void* arg)
-{
-       userrec* u = (userrec*)arg;
-       log(DEBUG,"DNS thread for user %s",u->nick);
-       DNS dns1;
-       DNS dns2;
-       std::string host;
-       std::string ip;
-       if (dns1.ReverseLookup(u->ip))
-       {
-               log(DEBUG,"DNS Step 1");
-               while (!dns1.HasResult())
-               {
-                       usleep(100);
-               }
-               host = dns1.GetResult();
-               if (host != "")
-               {
-                       log(DEBUG,"DNS Step 2: '%s'",host.c_str());
-                       if (dns2.ForwardLookup(host))
-                       {
-                               while (!dns2.HasResult())
-                               {
-                                       usleep(100);
-                               }
-                               ip = dns2.GetResultIP();
-                               log(DEBUG,"DNS Step 3 '%s'(%d) '%s'(%d)",ip.c_str(),ip.length(),u->ip,strlen(u->ip));
-                               if (ip == std::string(u->ip))
-                               {
-                                       log(DEBUG,"DNS Step 4");
-                                       if (host.length() < 160)
-                                       {
-                                               log(DEBUG,"DNS Step 5");
-                                               strcpy(u->host,host.c_str());
-                                               strcpy(u->dhost,host.c_str());
-                                       }
-                               }
-                       }
-               }
-       }
-       u->dns_done = true;
-       return NULL;
-}
-#endif
-
-/* add a client connection to the sockets list */
-void AddClient(int socket, char* host, int port, bool iscached, char* ip)
-{
-       string tempnick;
-       char tn2[MAXBUF];
-       user_hash::iterator iter;
-
-       tempnick = ConvToStr(socket) + "-unknown";
-       sprintf(tn2,"%lu-unknown",(unsigned long)socket);
-
-       iter = clientlist.find(tempnick);
-
-       // fix by brain.
-       // as these nicknames are 'RFC impossible', we can be sure nobody is going to be
-       // using one as a registered connection. As theyre per fd, we can also safely assume
-       // that we wont have collisions. Therefore, if the nick exists in the list, its only
-       // used by a dead socket, erase the iterator so that the new client may reclaim it.
-       // this was probably the cause of 'server ignores me when i hammer it with reconnects'
-       // issue in earlier alphas/betas
-       if (iter != clientlist.end())
-       {
-               userrec* goner = iter->second;
-               delete goner;
-               clientlist.erase(iter);
-       }
-
-       /*
-        * It is OK to access the value here this way since we know
-        * it exists, we just created it above.
-        *
-        * At NO other time should you access a value in a map or a
-        * hash_map this way.
-        */
-       clientlist[tempnick] = new userrec();
-
-       NonBlocking(socket);
-       log(DEBUG,"AddClient: %lu %s %d %s",(unsigned long)socket,host,port,ip);
-
-       clientlist[tempnick]->fd = socket;
-       strlcpy(clientlist[tempnick]->nick, tn2,NICKMAX);
-       strlcpy(clientlist[tempnick]->host, host,160);
-       strlcpy(clientlist[tempnick]->dhost, host,160);
-       clientlist[tempnick]->server = (char*)FindServerNamePtr(Config->ServerName);
-       strlcpy(clientlist[tempnick]->ident, "unknown",IDENTMAX);
-       clientlist[tempnick]->registered = 0;
-       clientlist[tempnick]->signon = TIME + Config->dns_timeout;
-       clientlist[tempnick]->lastping = 1;
-       clientlist[tempnick]->port = port;
-       strlcpy(clientlist[tempnick]->ip,ip,16);
-
-       // set the registration timeout for this user
-       unsigned long class_regtimeout = 90;
-       int class_flood = 0;
-       long class_threshold = 5;
-       long class_sqmax = 262144;      // 256kb
-       long class_rqmax = 4096;        // 4k
-
-       for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
-       {
-               if (match(clientlist[tempnick]->host,i->host) && (i->type == CC_ALLOW))
-               {
-                       class_regtimeout = (unsigned long)i->registration_timeout;
-                       class_flood = i->flood;
-                       clientlist[tempnick]->pingmax = i->pingtime;
-                       class_threshold = i->threshold;
-                       class_sqmax = i->sendqmax;
-                       class_rqmax = i->recvqmax;
-                       break;
-               }
-       }
-
-       clientlist[tempnick]->nping = TIME+clientlist[tempnick]->pingmax + Config->dns_timeout;
-       clientlist[tempnick]->timeout = TIME+class_regtimeout;
-       clientlist[tempnick]->flood = class_flood;
-       clientlist[tempnick]->threshold = class_threshold;
-       clientlist[tempnick]->sendqmax = class_sqmax;
-       clientlist[tempnick]->recvqmax = class_rqmax;
-
-       ucrec a;
-       a.channel = NULL;
-       a.uc_modes = 0;
-       for (int i = 0; i < MAXCHANS; i++)
-               clientlist[tempnick]->chans.push_back(a);
-
-       if (clientlist.size() > Config->SoftLimit)
-       {
-               kill_link(clientlist[tempnick],"No more connections allowed");
-               return;
-       }
-
-       if (clientlist.size() >= MAXCLIENTS)
-       {
-               kill_link(clientlist[tempnick],"No more connections allowed");
-               return;
-       }
-
-       // this is done as a safety check to keep the file descriptors within range of fd_ref_table.
-       // its a pretty big but for the moment valid assumption:
-       // file descriptors are handed out starting at 0, and are recycled as theyre freed.
-       // therefore if there is ever an fd over 65535, 65536 clients must be connected to the
-       // irc server at once (or the irc server otherwise initiating this many connections, files etc)
-       // which for the time being is a physical impossibility (even the largest networks dont have more
-       // than about 10,000 users on ONE server!)
-       if ((unsigned)socket > 65534)
-       {
-               kill_link(clientlist[tempnick],"Server is full");
-               return;
-       }
-               
-
-        char* e = matches_exception(ip);
-       if (!e)
-       {
-               char* r = matches_zline(ip);
-               if (r)
-               {
-                       char reason[MAXBUF];
-                       snprintf(reason,MAXBUF,"Z-Lined: %s",r);
-                       kill_link(clientlist[tempnick],reason);
-                       return;
-               }
-       }
-       fd_ref_table[socket] = clientlist[tempnick];
-       SE->AddFd(socket,true,X_ESTAB_CLIENT);
-}
-
-/* shows the message of the day, and any other on-logon stuff */
-void FullConnectUser(userrec* user)
-{
-       stats->statsConnects++;
-        user->idle_lastmsg = TIME;
-        log(DEBUG,"ConnectUser: %s",user->nick);
-
-        if ((strcmp(Passwd(user),"")) && (!user->haspassed))
-        {
-                kill_link(user,"Invalid password");
-                return;
-        }
-        if (IsDenied(user))
-        {
-                kill_link(user,"Unauthorised connection");
-                return;
-        }
-
-        char match_against[MAXBUF];
-        snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host);
-       char* e = matches_exception(match_against);
-       if (!e)
-       {
-               char* r = matches_gline(match_against);
-               if (r)
-               {
-                       char reason[MAXBUF];
-                       snprintf(reason,MAXBUF,"G-Lined: %s",r);
-                       kill_link_silent(user,reason);
-                       return;
-               }
-               r = matches_kline(user->host);
-               if (r)
-               {
-                       char reason[MAXBUF];
-                       snprintf(reason,MAXBUF,"K-Lined: %s",r);
-                       kill_link_silent(user,reason);
-                       return;
-               }
-       }
-
-
-        WriteServ(user->fd,"NOTICE Auth :Welcome to \002%s\002!",Config->Network);
-        WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Config->Network,user->nick,user->ident,user->host);
-        WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,Config->ServerName,VERSION);
-        WriteServ(user->fd,"003 %s :This server was created %s %s",user->nick,__TIME__,__DATE__);
-        WriteServ(user->fd,"004 %s %s %s iowghraAsORVSxNCWqBzvdHtGI lvhopsmntikrRcaqOALQbSeKVfHGCuzN",user->nick,Config->ServerName,VERSION);
-        // the neatest way to construct the initial 005 numeric, considering the number of configure constants to go in it...
-        std::stringstream v;
-        v << "WALLCHOPS MODES=13 CHANTYPES=# PREFIX=(ohv)@%+ MAP SAFELIST MAXCHANNELS=" << MAXCHANS;
-        v << " MAXBANS=60 NICKLEN=" << NICKMAX;
-        v << " TOPICLEN=" << MAXTOPIC << " KICKLEN=" << MAXKICK << " MAXTARGETS=20 AWAYLEN=" << MAXAWAY << " CHANMODES=ohvb,k,l,psmnti NETWORK=";
-        v << Config->Network;
-        std::string data005 = v.str();
-        FOREACH_MOD On005Numeric(data005);
-        // anfl @ #ratbox, efnet reminded me that according to the RFC this cant contain more than 13 tokens per line...
-        // so i'd better split it :)
-        std::stringstream out(data005);
-        std::string token = "";
-        std::string line5 = "";
-        int token_counter = 0;
-        while (!out.eof())
-        {
-                out >> token;
-                line5 = line5 + token + " ";
-                token_counter++;
-                if ((token_counter >= 13) || (out.eof() == true))
-                {
-                        WriteServ(user->fd,"005 %s %s:are supported by this server",user->nick,line5.c_str());
-                        line5 = "";
-                        token_counter = 0;
-                }
-        }
-        ShowMOTD(user);
-
-       // fix 3 by brain, move registered = 7 below these so that spurious modes and host changes dont go out
-       // onto the network and produce 'fake direction'
-       FOREACH_MOD OnUserConnect(user);
-       FOREACH_MOD OnGlobalConnect(user);
-       user->registered = 7;
-       WriteOpers("*** Client connecting on port %lu: %s!%s@%s [%s]",(unsigned long)user->port,user->nick,user->ident,user->host,user->ip);
-}
-
-
-/* shows the message of the day, and any other on-logon stuff */
-void ConnectUser(userrec *user)
-{
-       // dns is already done, things are fast. no need to wait for dns to complete just pass them straight on
-       if ((user->dns_done) && (user->registered >= 3) && (AllModulesReportReady(user)))
-       {
-               FullConnectUser(user);
-       }
-}
-
 std::string InspIRCd::GetVersionString()
 {
        char versiondata[MAXBUF];
@@ -867,498 +224,6 @@ std::string InspIRCd::GetVersionString()
        return versiondata;
 }
 
-void handle_version(char **parameters, int pcnt, userrec *user)
-{
-       WriteServ(user->fd,"351 %s :%s",user->nick,ServerInstance->GetVersionString().c_str());
-}
-
-
-bool is_valid_cmd(const char* commandname, int pcnt, userrec * user)
-{
-       for (unsigned int i = 0; i < cmdlist.size(); i++)
-       {
-               if (!strcasecmp(cmdlist[i].command,commandname))
-               {
-                       if (cmdlist[i].handler_function)
-                       {
-                               if ((pcnt>=cmdlist[i].min_params) && (strcasecmp(cmdlist[i].source,"<core>")))
-                               {
-                                       if ((strchr(user->modes,cmdlist[i].flags_needed)) || (!cmdlist[i].flags_needed))
-                                       {
-                                               if (cmdlist[i].flags_needed)
-                                               {
-                                                       if ((user->HasPermission((char*)commandname)) || (is_uline(user->server)))
-                                                       {
-                                                               return true;
-                                                       }
-                                                       else
-                                                       {
-                                                               return false;
-                                                       }
-                                               }
-                                               return true;
-                                       }
-                               }
-                       }
-               }
-       }
-       return false;
-}
-
-// calls a handler function for a command
-
-void call_handler(const char* commandname,char **parameters, int pcnt, userrec *user)
-{
-       for (unsigned int i = 0; i < cmdlist.size(); i++)
-       {
-               if (!strcasecmp(cmdlist[i].command,commandname))
-               {
-                       if (cmdlist[i].handler_function)
-                       {
-                               if (pcnt>=cmdlist[i].min_params)
-                               {
-                                       if ((strchr(user->modes,cmdlist[i].flags_needed)) || (!cmdlist[i].flags_needed))
-                                       {
-                                               if (cmdlist[i].flags_needed)
-                                               {
-                                                       if ((user->HasPermission((char*)commandname)) || (is_uline(user->server)))
-                                                       {
-                                                               cmdlist[i].handler_function(parameters,pcnt,user);
-                                                       }
-                                               }
-                                               else
-                                               {
-                                                       cmdlist[i].handler_function(parameters,pcnt,user);
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-
-void force_nickchange(userrec* user,const char* newnick)
-{
-       char nick[MAXBUF];
-       int MOD_RESULT = 0;
-       
-       strcpy(nick,"");
-
-       FOREACH_RESULT(OnUserPreNick(user,newnick));
-       if (MOD_RESULT) {
-               stats->statsCollisions++;
-               kill_link(user,"Nickname collision");
-               return;
-       }
-       if (matches_qline(newnick))
-       {
-               stats->statsCollisions++;
-               kill_link(user,"Nickname collision");
-               return;
-       }
-       
-       if (user)
-       {
-               if (newnick)
-               {
-                       strncpy(nick,newnick,MAXBUF);
-               }
-               if (user->registered == 7)
-               {
-                       char* pars[1];
-                       pars[0] = nick;
-                       handle_nick(pars,1,user);
-               }
-       }
-}
-                               
-
-int process_parameters(char **command_p,char *parameters)
-{
-       int j = 0;
-       int q = strlen(parameters);
-       if (!q)
-       {
-               /* no parameters, command_p invalid! */
-               return 0;
-       }
-       if (parameters[0] == ':')
-       {
-               command_p[0] = parameters+1;
-               return 1;
-       }
-       if (q)
-       {
-               if ((strchr(parameters,' ')==NULL) || (parameters[0] == ':'))
-               {
-                       /* only one parameter */
-                       command_p[0] = parameters;
-                       if (parameters[0] == ':')
-                       {
-                               if (strchr(parameters,' ') != NULL)
-                               {
-                                       command_p[0]++;
-                               }
-                       }
-                       return 1;
-               }
-       }
-       command_p[j++] = parameters;
-       for (int i = 0; i <= q; i++)
-       {
-               if (parameters[i] == ' ')
-               {
-                       command_p[j++] = parameters+i+1;
-                       parameters[i] = '\0';
-                       if (command_p[j-1][0] == ':')
-                       {
-                               *command_p[j-1]++; /* remove dodgy ":" */
-                               break;
-                               /* parameter like this marks end of the sequence */
-                       }
-               }
-       }
-       return j; /* returns total number of items in the list */
-}
-
-void process_command(userrec *user, char* cmd)
-{
-       char *parameters;
-       char *command;
-       char *command_p[127];
-       char p[MAXBUF], temp[MAXBUF];
-       int j, items, cmd_found;
-
-       for (int i = 0; i < 127; i++)
-               command_p[i] = NULL;
-
-       if (!user)
-       {
-               return;
-       }
-       if (!cmd)
-       {
-               return;
-       }
-       if (!cmd[0])
-       {
-               return;
-       }
-       
-       int total_params = 0;
-       if (strlen(cmd)>2)
-       {
-               for (unsigned int q = 0; q < strlen(cmd)-1; q++)
-               {
-                       if ((cmd[q] == ' ') && (cmd[q+1] == ':'))
-                       {
-                               total_params++;
-                               // found a 'trailing', we dont count them after this.
-                               break;
-                       }
-                       if (cmd[q] == ' ')
-                               total_params++;
-               }
-       }
-
-       // another phidjit bug...
-       if (total_params > 126)
-       {
-               *(strchr(cmd,' ')) = '\0';
-               WriteServ(user->fd,"421 %s %s :Too many parameters given",user->nick,cmd);
-               return;
-       }
-
-       strlcpy(temp,cmd,MAXBUF);
-       
-       std::string tmp = cmd;
-       for (int i = 0; i <= MODCOUNT; i++)
-       {
-               std::string oldtmp = tmp;
-               modules[i]->OnServerRaw(tmp,true,user);
-               if (oldtmp != tmp)
-               {
-                       log(DEBUG,"A Module changed the input string!");
-                       log(DEBUG,"New string: %s",tmp.c_str());
-                       log(DEBUG,"Old string: %s",oldtmp.c_str());
-                       break;
-               }
-       }
-       strlcpy(cmd,tmp.c_str(),MAXBUF);
-       strlcpy(temp,cmd,MAXBUF);
-
-       if (!strchr(cmd,' '))
-       {
-               /* no parameters, lets skip the formalities and not chop up
-                * the string */
-               log(DEBUG,"About to preprocess command with no params");
-               items = 0;
-               command_p[0] = NULL;
-               parameters = NULL;
-               for (unsigned int i = 0; i <= strlen(cmd); i++)
-               {
-                       cmd[i] = toupper(cmd[i]);
-               }
-               command = cmd;
-       }
-       else
-       {
-               strcpy(cmd,"");
-               j = 0;
-               /* strip out extraneous linefeeds through mirc's crappy pasting (thanks Craig) */
-               for (unsigned int i = 0; i < strlen(temp); i++)
-               {
-                       if ((temp[i] != 10) && (temp[i] != 13) && (temp[i] != 0) && (temp[i] != 7))
-                       {
-                               cmd[j++] = temp[i];
-                               cmd[j] = 0;
-                       }
-               }
-               /* split the full string into a command plus parameters */
-               parameters = p;
-               strcpy(p," ");
-               command = cmd;
-               if (strchr(cmd,' '))
-               {
-                       for (unsigned int i = 0; i <= strlen(cmd); i++)
-                       {
-                               /* capitalise the command ONLY, leave params intact */
-                               cmd[i] = toupper(cmd[i]);
-                               /* are we nearly there yet?! :P */
-                               if (cmd[i] == ' ')
-                               {
-                                       command = cmd;
-                                       parameters = cmd+i+1;
-                                       cmd[i] = '\0';
-                                       break;
-                               }
-                       }
-               }
-               else
-               {
-                       for (unsigned int i = 0; i <= strlen(cmd); i++)
-                       {
-                               cmd[i] = toupper(cmd[i]);
-                       }
-               }
-
-       }
-       cmd_found = 0;
-       
-       if (strlen(command)>MAXCOMMAND)
-       {
-               WriteServ(user->fd,"421 %s %s :Command too long",user->nick,command);
-               return;
-       }
-       
-       for (unsigned int x = 0; x < strlen(command); x++)
-       {
-               if (((command[x] < 'A') || (command[x] > 'Z')) && (command[x] != '.'))
-               {
-                       if (((command[x] < '0') || (command[x]> '9')) && (command[x] != '-'))
-                       {
-                               if (strchr("@!\"$%^&*(){}[]_=+;:'#~,<>/?\\|`",command[x]))
-                               {
-                                       stats->statsUnknown++;
-                                       WriteServ(user->fd,"421 %s %s :Unknown command",user->nick,command);
-                                       return;
-                               }
-                       }
-               }
-       }
-
-       for (unsigned int i = 0; i != cmdlist.size(); i++)
-       {
-               if (cmdlist[i].command[0])
-               {
-                       if (strlen(command)>=(strlen(cmdlist[i].command))) if (!strncmp(command, cmdlist[i].command,MAXCOMMAND))
-                       {
-                               if (parameters)
-                               {
-                                       if (parameters[0])
-                                       {
-                                               items = process_parameters(command_p,parameters);
-                                       }
-                                       else
-                                       {
-                                               items = 0;
-                                               command_p[0] = NULL;
-                                       }
-                               }
-                               else
-                               {
-                                       items = 0;
-                                       command_p[0] = NULL;
-                               }
-                               
-                               if (user)
-                               {
-                                       /* activity resets the ping pending timer */
-                                       user->nping = TIME + user->pingmax;
-                                       if ((items) < cmdlist[i].min_params)
-                                       {
-                                               log(DEBUG,"process_command: not enough parameters: %s %s",user->nick,command);
-                                               WriteServ(user->fd,"461 %s %s :Not enough parameters",user->nick,command);
-                                               return;
-                                       }
-                                       if ((!strchr(user->modes,cmdlist[i].flags_needed)) && (cmdlist[i].flags_needed))
-                                       {
-                                               log(DEBUG,"process_command: permission denied: %s %s",user->nick,command);
-                                               WriteServ(user->fd,"481 %s :Permission Denied- You do not have the required operator privilages",user->nick);
-                                               cmd_found = 1;
-                                               return;
-                                       }
-                                       if ((cmdlist[i].flags_needed) && (!user->HasPermission(command)))
-                                       {
-                                               log(DEBUG,"process_command: permission denied: %s %s",user->nick,command);
-                                               WriteServ(user->fd,"481 %s :Permission Denied- Oper type %s does not have access to command %s",user->nick,user->oper,command);
-                                               cmd_found = 1;
-                                               return;
-                                       }
-                                       /* if the command isnt USER, PASS, or NICK, and nick is empty,
-                                        * deny command! */
-                                       if ((strncmp(command,"USER",4)) && (strncmp(command,"NICK",4)) && (strncmp(command,"PASS",4)))
-                                       {
-                                               if ((!isnick(user->nick)) || (user->registered != 7))
-                                               {
-                                                       log(DEBUG,"process_command: not registered: %s %s",user->nick,command);
-                                                       WriteServ(user->fd,"451 %s :You have not registered",command);
-                                                       return;
-                                               }
-                                       }
-                                       if ((user->registered == 7) && (!strchr(user->modes,'o')))
-                                       {
-                                               std::stringstream dcmds(Config->DisabledCommands);
-                                               while (!dcmds.eof())
-                                               {
-                                                       std::string thiscmd;
-                                                       dcmds >> thiscmd;
-                                                       if (!strcasecmp(thiscmd.c_str(),command))
-                                                       {
-                                                               // command is disabled!
-                                                               WriteServ(user->fd,"421 %s %s :This command has been disabled.",user->nick,command);
-                                                               return;
-                                                       }
-                                               }
-                                       }
-                                       if ((user->registered == 7) || (!strncmp(command,"USER",4)) || (!strncmp(command,"NICK",4)) || (!strncmp(command,"PASS",4)))
-                                       {
-                                               if (cmdlist[i].handler_function)
-                                               {
-                                                       
-                                                       /* ikky /stats counters */
-                                                       if (temp)
-                                                       {
-                                                               cmdlist[i].use_count++;
-                                                               cmdlist[i].total_bytes+=strlen(temp);
-                                                       }
-
-                                                       int MOD_RESULT = 0;
-                                                       FOREACH_RESULT(OnPreCommand(command,command_p,items,user));
-                                                       if (MOD_RESULT == 1) {
-                                                               return;
-                                                       }
-
-                                                       /* WARNING: nothing may come after the
-                                                        * command handler call, as the handler
-                                                        * may free the user structure! */
-
-                                                       cmdlist[i].handler_function(command_p,items,user);
-                                               }
-                                               return;
-                                       }
-                                       else
-                                       {
-                                               WriteServ(user->fd,"451 %s :You have not registered",command);
-                                               return;
-                                       }
-                               }
-                               cmd_found = 1;
-                       }
-               }
-       }
-       if ((!cmd_found) && (user))
-       {
-               stats->statsUnknown++;
-               WriteServ(user->fd,"421 %s %s :Unknown command",user->nick,command);
-       }
-}
-
-bool removecommands(const char* source)
-{
-       bool go_again = true;
-       while (go_again)
-       {
-               go_again = false;
-               for (std::deque<command_t>::iterator i = cmdlist.begin(); i != cmdlist.end(); i++)
-               {
-                       if (!strcmp(i->source,source))
-                       {
-                               log(DEBUG,"removecommands(%s) Removing dependent command: %s",i->source,i->command);
-                               cmdlist.erase(i);
-                               go_again = true;
-                               break;
-                       }
-               }
-       }
-       return true;
-}
-
-
-void process_buffer(const char* cmdbuf,userrec *user)
-{
-       if (!user)
-       {
-               log(DEFAULT,"*** BUG *** process_buffer was given an invalid parameter");
-               return;
-       }
-       char cmd[MAXBUF];
-       if (!cmdbuf)
-       {
-               log(DEFAULT,"*** BUG *** process_buffer was given an invalid parameter");
-               return;
-       }
-       if (!cmdbuf[0])
-       {
-               return;
-       }
-       while (*cmdbuf == ' ') cmdbuf++; // strip leading spaces
-
-       strlcpy(cmd,cmdbuf,MAXBUF);
-       if (!cmd[0])
-       {
-               return;
-       }
-       int sl = strlen(cmd)-1;
-       if ((cmd[sl] == 13) || (cmd[sl] == 10))
-       {
-               cmd[sl] = '\0';
-       }
-       sl = strlen(cmd)-1;
-       if ((cmd[sl] == 13) || (cmd[sl] == 10))
-       {
-               cmd[sl] = '\0';
-       }
-       sl = strlen(cmd)-1;
-       while (cmd[sl] == ' ') // strip trailing spaces
-       {
-               cmd[sl] = '\0';
-               sl = strlen(cmd)-1;
-       }
-
-       if (!cmd[0])
-       {
-               return;
-       }
-        log(DEBUG,"CMDIN: %s %s",user->nick,cmd);
-       tidystring(cmd);
-       if ((user) && (cmd))
-       {
-               process_command(user,cmd);
-       }
-}
-
 char* InspIRCd::ModuleError()
 {
        return MODERR;
@@ -1435,7 +300,7 @@ bool InspIRCd::UnloadModule(const char* filename)
                        log(DEBUG,"Erasing module entry...");
                        erase_factory(j);
                         log(DEBUG,"Removing dependent commands...");
-                        removecommands(filename);
+                        Parser->RemoveCommands(filename);
                        log(DEFAULT,"Module %s unloaded",filename);
                        MODCOUNT--;
                        return true;
@@ -1526,8 +391,14 @@ int InspIRCd::Run()
        char* target;
        unsigned int numberactive;
         sockaddr_in sock_us;     // our port number
-        socklen_t uslen;         // length of our port number
+       socklen_t uslen;         // length of our port number
+
+       /* Until THIS point, ServerInstance == NULL */
+       
+        LoadAllModules(this);
 
+        printf("\nInspIRCd is now running!\n");
+       
        if (!Config->nofork)
        {
                freopen("/dev/null","w",stdout);
@@ -1537,7 +408,7 @@ int InspIRCd::Run()
        /* Add the listening sockets used for client inbound connections
         * to the socket engine
         */
-       for (int count = 0; count < BoundPortCount; count++)
+       for (int count = 0; count < stats->BoundPortCount; count++)
                SE->AddFd(openSockfd[count],true,X_LISTEN);
 
        WritePID(Config->PID);
@@ -1656,7 +527,10 @@ int InspIRCd::Run()
                                                 */
                                                if (incomingSockfd >= 0)
                                                {
-                                                       FOREACH_MOD OnRawSocketAccept(incomingSockfd, target, in_port);
+                                                       if (Config->GetIOHook(in_port))
+                                                       {
+                                                               Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, target, in_port);
+                                                       }
                                                        stats->statsAccept++;
                                                        AddClient(incomingSockfd, target, in_port, false, target);
                                                        log(DEBUG,"Adding client on port %lu fd=%lu",(unsigned long)in_port,(unsigned long)incomingSockfd);