]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd_io.cpp
Missing a changeover
[user/henk/code/inspircd.git] / src / inspircd_io.cpp
index 39cb8db62c038e60227f242cc538f4d5d90b2380..4fa87a5f18392776cd7920cc8488b2b46ab2a712 100644 (file)
@@ -5,7 +5,7 @@
  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
  *                       E-mail:
  *                <brain@chatspike.net>
- *               <Craig@chatspike.net>
+ *                <Craig@chatspike.net>
  *     
  * Written by Craig Edwards, Craig McLure, and others.
  * This program is free but copyrighted software; see
@@ -25,6 +25,7 @@ using namespace std;
 #include <sstream>
 #include <iostream>
 #include <fstream>
+#include "message.h"
 #include "inspircd.h"
 #include "inspircd_io.h"
 #include "inspstring.h"
@@ -149,18 +150,6 @@ bool ServerConfig::CheckOnce(char* tag, bool bail, userrec* user)
        return true;
 }
 
-typedef bool (*Validator)(const char*, const char*, void*);
-
-enum ConfigDataType { DT_NOTHING, DT_INTEGER, DT_CHARPTR, DT_BOOLEAN };
-
-struct InitialConfig {
-       char* tag;
-       char* value;
-       void* val;
-       int datatype;
-       Validator validation_function;
-};
-
 bool NoValidation(const char* tag, const char* value, void* data)
 {
        log(DEBUG,"No validation for <%s:%s>",tag,value);
@@ -170,95 +159,95 @@ bool NoValidation(const char* tag, const char* value, void* data)
 bool ValidateTempDir(const char* tag, const char* value, void* data)
 {
        char* x = (char*)data;
-        if (!*x)
-               strlcpy(x,"/tmp",1024);
+       if (!*x)
+               strlcpy(x,"/tmp",1024);
        return true;
 }
  
 bool ValidateMaxTargets(const char* tag, const char* value, void* data)
 {
        int* x = (int*)data;
-        if ((*x < 0) || (*x > 31))
-        {
-                log(DEFAULT,"WARNING: <options:maxtargets> value is greater than 31 or less than 0, set to 20.");
-                *x = 20;
-        }
+       if ((*x < 0) || (*x > 31))
+       {
+               log(DEFAULT,"WARNING: <options:maxtargets> value is greater than 31 or less than 0, set to 20.");
+               *x = 20;
+       }
        return true;
 }
 
 bool ValidateSoftLimit(const char* tag, const char* value, void* data)
 {
        int* x = (int*)data;    
-        if ((*x < 1) || (*x > MAXCLIENTS))
-        {
-                log(DEFAULT,"WARNING: <options:softlimit> value is greater than %d or less than 0, set to %d.",MAXCLIENTS,MAXCLIENTS);
-                *x = MAXCLIENTS;
-        }
+       if ((*x < 1) || (*x > MAXCLIENTS))
+       {
+               log(DEFAULT,"WARNING: <options:softlimit> value is greater than %d or less than 0, set to %d.",MAXCLIENTS,MAXCLIENTS);
+               *x = MAXCLIENTS;
+       }
        return true;
 }
 
 bool ValidateMaxConn(const char* tag, const char* value, void* data)
 {
        int* x = (int*)data;    
-        if (*x > SOMAXCONN)
-                log(DEFAULT,"WARNING: <options:somaxconn> value may be higher than the system-defined SOMAXCONN value!");
-        if (!*x)
-                *x = SOMAXCONN;
+       if (*x > SOMAXCONN)
+               log(DEFAULT,"WARNING: <options:somaxconn> value may be higher than the system-defined SOMAXCONN value!");
+       if (!*x)
+               *x = SOMAXCONN;
        return true;
 }
 
 bool ValidateDnsTimeout(const char* tag, const char* value, void* data)
 {
        int* x = (int*)data;
-        if (!*x)
-                *x = 5;
+       if (!*x)
+               *x = 5;
        return true;
 }
 
 bool ValidateDnsServer(const char* tag, const char* value, void* data)
 {
        char* x = (char*)data;
-        if (!*x)
-        {
-                // attempt to look up their nameserver from /etc/resolv.conf
-                log(DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in /etc/resolv.conf...");
-                ifstream resolv("/etc/resolv.conf");
-                std::string nameserver;
-                bool found_server = false;
-         
-                if (resolv.is_open())
-                {
-                        while (resolv >> nameserver)
-                        {
-                                if ((nameserver == "nameserver") && (!found_server))
-                                {
-                                        resolv >> nameserver;
-                                        strlcpy(x,nameserver.c_str(),MAXBUF);
-                                        found_server = true;
-                                        log(DEFAULT,"<dns:server> set to '%s' as first resolver in /etc/resolv.conf.",nameserver.c_str());
-                                }
-                        }
-                                
-                        if (!found_server)
-                        {
-                                log(DEFAULT,"/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!");
-                                strlcpy(x,"127.0.0.1",MAXBUF);
-                        }
-                }
-                else
-                {
-                        log(DEFAULT,"/etc/resolv.conf can't be opened! Defaulting to nameserver '127.0.0.1'!");
-                        strlcpy(x,"127.0.0.1",MAXBUF);
-                }
-        }
+       if (!*x)
+       {
+               // attempt to look up their nameserver from /etc/resolv.conf
+               log(DEFAULT,"WARNING: <dns:server> not defined, attempting to find working server in /etc/resolv.conf...");
+               ifstream resolv("/etc/resolv.conf");
+               std::string nameserver;
+               bool found_server = false;
+
+               if (resolv.is_open())
+               {
+                       while (resolv >> nameserver)
+                       {
+                               if ((nameserver == "nameserver") && (!found_server))
+                               {
+                                       resolv >> nameserver;
+                                       strlcpy(x,nameserver.c_str(),MAXBUF);
+                                       found_server = true;
+                                       log(DEFAULT,"<dns:server> set to '%s' as first resolver in /etc/resolv.conf.",nameserver.c_str());
+                               }
+                       }
+
+                       if (!found_server)
+                       {
+                               log(DEFAULT,"/etc/resolv.conf contains no viable nameserver entries! Defaulting to nameserver '127.0.0.1'!");
+                               strlcpy(x,"127.0.0.1",MAXBUF);
+                       }
+               }
+               else
+               {
+                       log(DEFAULT,"/etc/resolv.conf can't be opened! Defaulting to nameserver '127.0.0.1'!");
+                       strlcpy(x,"127.0.0.1",MAXBUF);
+               }
+       }
        return true;
 }
 
 bool ValidateModPath(const char* tag, const char* value, void* data)
 {
        char* x = (char*)data;  
-        if (!*x)
-                strlcpy(x,MOD_PATH,MAXBUF);
+       if (!*x)
+               strlcpy(x,MOD_PATH,MAXBUF);
        return true;
 }
 
@@ -268,62 +257,62 @@ bool ValidateServerName(const char* tag, const char* value, void* data)
        char* x = (char*)data;
        if (!strchr(x,'.'))
        {
-                log(DEFAULT,"WARNING: <server:name> '%s' is not a fully-qualified domain name. Changed to '%s%c'",x,x,'.');
-                charlcat(x,'.',MAXBUF);
-        }
+               log(DEFAULT,"WARNING: <server:name> '%s' is not a fully-qualified domain name. Changed to '%s%c'",x,x,'.');
+               charlcat(x,'.',MAXBUF);
+       }
        strlower(x);
        return true;
 }
 
 bool ValidateNetBufferSize(const char* tag, const char* value, void* data)
 {
-        if ((!Config->NetBufferSize) || (Config->NetBufferSize > 65535) || (Config->NetBufferSize < 1024))
-        {
-                log(DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
-                Config->NetBufferSize = 10240;
-        }
+       if ((!Config->NetBufferSize) || (Config->NetBufferSize > 65535) || (Config->NetBufferSize < 1024))
+       {
+               log(DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
+               Config->NetBufferSize = 10240;
+       }
        return true;
 }
 
 bool ValidateMaxWho(const char* tag, const char* value, void* data)
 {
-        if ((!Config->MaxWhoResults) || (Config->MaxWhoResults > 65535) || (Config->MaxWhoResults < 1))
-        {
-                log(DEFAULT,"No MaxWhoResults specified or size out of range, setting to default of 128.");
-                Config->MaxWhoResults = 128;
-        }
+       if ((!Config->MaxWhoResults) || (Config->MaxWhoResults > 65535) || (Config->MaxWhoResults < 1))
+       {
+               log(DEFAULT,"No MaxWhoResults specified or size out of range, setting to default of 128.");
+               Config->MaxWhoResults = 128;
+       }
        return true;
 }
 
 bool ValidateLogLevel(const char* tag, const char* value, void* data)
 {
        const char* dbg = (const char*)data;
-        Config->LogLevel = DEFAULT;                        
-        if (!strcmp(dbg,"debug"))
-        {
-                Config->LogLevel = DEBUG;
-                Config->debugging = 1;
-        }
-        else if (!strcmp(dbg,"verbose"))
-                Config->LogLevel = VERBOSE;
-        else if (!strcmp(dbg,"default"))
-                Config->LogLevel = DEFAULT;
-        else if (!strcmp(dbg,"sparse"))
-                Config->LogLevel = SPARSE;
-        else if (!strcmp(dbg,"none"))
-                Config->LogLevel = NONE;
+       Config->LogLevel = DEFAULT;
+       if (!strcmp(dbg,"debug"))
+       {
+               Config->LogLevel = DEBUG;
+               Config->debugging = 1;
+       }
+       else if (!strcmp(dbg,"verbose"))
+               Config->LogLevel = VERBOSE;
+       else if (!strcmp(dbg,"default"))
+               Config->LogLevel = DEFAULT;
+       else if (!strcmp(dbg,"sparse"))
+               Config->LogLevel = SPARSE;
+       else if (!strcmp(dbg,"none"))
+               Config->LogLevel = NONE;
        return true;
 }
 
 bool ValidateMotd(const char* tag, const char* value, void* data)
 {
-        readfile(Config->MOTD,Config->motd);
+       readfile(Config->MOTD,Config->motd);
        return true;
 }
 
 bool ValidateRules(const char* tag, const char* value, void* data)
 {
-        readfile(Config->RULES,Config->rules);
+       readfile(Config->RULES,Config->rules);
        return true;
 }
 
@@ -331,12 +320,17 @@ bool ValidateRules(const char* tag, const char* value, void* data)
 void ServerConfig::Read(bool bail, userrec* user)
 {
        char debug[MAXBUF];
+       char CM1[MAXBUF],CM2[MAXBUF];
+       char ServName[MAXBUF],Value[MAXBUF];
+       char dataline[1024];
+       ConnectClass c;
+       std::stringstream errstr;
 
        static InitialConfig Values[] = {
                {"options",     "softlimit",            &this->SoftLimit,               DT_INTEGER, ValidateSoftLimit},
                {"options",     "somaxconn",            &this->MaxConn,                 DT_INTEGER, ValidateMaxConn},
                {"server",      "name",                 &this->ServerName,              DT_CHARPTR, ValidateServerName},
-               {"server",      "description",          &this->ServerDesc,              DT_CHARPTR, ValidateServerName},
+               {"server",      "description",          &this->ServerDesc,              DT_CHARPTR, NoValidation},
                {"server",      "network",              &this->Network,                 DT_CHARPTR, NoValidation},
                {"admin",       "name",                 &this->AdminName,               DT_CHARPTR, NoValidation},
                {"admin",       "email",                &this->AdminEmail,              DT_CHARPTR, NoValidation},
@@ -364,13 +358,6 @@ void ServerConfig::Read(bool bail, userrec* user)
                {"options",     "tempdir",              &this->TempDir,                 DT_CHARPTR, ValidateTempDir},
                {NULL}
        };
-
-       //
-       char timeout[MAXBUF],flood[MAXBUF],pfreq[MAXBUF],thold[MAXBUF],sqmax[MAXBUF],rqmax[MAXBUF];
-       char localmax[MAXBUF],globalmax[MAXBUF],ServName[MAXBUF],Value[MAXBUF];
-
-       ConnectClass c;
-       std::stringstream errstr;
        
        include_stack.clear();
 
@@ -386,8 +373,6 @@ void ServerConfig::Read(bool bail, userrec* user)
                }
                else
                {
-                       char dataline[1024];
-
                        if (user)
                        {
                                WriteServ(user->fd,"NOTICE %s :There were errors in the configuration file:",user->nick);
@@ -459,67 +444,55 @@ void ServerConfig::Read(bool bail, userrec* user)
        {
                *Value = 0;
                ConfValue("connect","allow",i,Value,&Config->config_f);
-               ConfValue("connect","timeout",i,timeout,&Config->config_f);
-               ConfValue("connect","flood",i,flood,&Config->config_f);
-               ConfValue("connect","pingfreq",i,pfreq,&Config->config_f);
-               ConfValue("connect","threshold",i,thold,&Config->config_f);
-               ConfValue("connect","sendq",i,sqmax,&Config->config_f);
-               ConfValue("connect","recvq",i,rqmax,&Config->config_f);
-               ConfValue("connect","localmax",i,localmax,&Config->config_f);
-               ConfValue("connect","globalmax",i,globalmax,&Config->config_f);
-
                if (*Value)
                {
                        c.host = Value;
                        c.type = CC_ALLOW;
-                       strlcpy(Value,"",MAXBUF);
+                       *Value = 0;
                        ConfValue("connect","password",i,Value,&Config->config_f);
                        c.pass = Value;
-                       c.registration_timeout = 90; // default is 2 minutes
-                       c.pingtime = 120;
-                       c.flood = atoi(flood);
-                       c.threshold = 5;
-                       c.sendqmax = 262144; // 256k
-                       c.recvqmax = 4096;   // 4k
-                       c.maxlocal = 3;
-                       c.maxglobal = 3;
-
-                       if (atoi(localmax)>0)
+                       c.registration_timeout = ConfValueInteger("connect","timeout",i,&Config->config_f); // default is 2 minutes
+                       c.pingtime = ConfValueInteger("connect","pingfreq",i,&Config->config_f);
+                       c.flood = ConfValueInteger("connect","flood",i,&Config->config_f);
+                       c.threshold = ConfValueInteger("connect","threshold",i,&Config->config_f);
+                       c.sendqmax = ConfValueInteger("connect","sendq",i,&Config->config_f);
+                       c.recvqmax = ConfValueInteger("connect","recvq",i,&Config->config_f);
+                       c.maxlocal = ConfValueInteger("connect","localmax",i,&Config->config_f);
+                       c.maxglobal = ConfValueInteger("connect","globalmax",i,&Config->config_f);
+
+                       
+                       if (c.maxlocal == 0)
                        {
-                               c.maxlocal = atoi(localmax);
+                               c.maxlocal = 3;
                        }
 
-                       if (atoi(globalmax)>0)
+                       if (c.maxglobal == 0)
                        {
-                               c.maxglobal = atoi(globalmax);
+                               c.maxglobal = 3;
                        }
 
-                       if (atoi(thold)>0)
-                       {
-                               c.threshold = atoi(thold);
-                       }
-                       else
+                       if (c.threshold == 0)
                        {
                                c.threshold = 1;
                                c.flood = 999;
                                log(DEFAULT,"Warning: Connect allow line '%s' has no flood/threshold settings. Setting this tag to 999 lines in 1 second.",c.host.c_str());
                        }
 
-                       if (atoi(sqmax)>0)
+                       if (c.sendqmax == 0)
                        {
-                               c.sendqmax = atoi(sqmax);
+                               c.sendqmax = 262114;
                        }
-                       if (atoi(rqmax)>0)
+                       if (c.recvqmax == 0)
                        {
-                               c.recvqmax = atoi(rqmax);
+                               c.recvqmax = 4096;
                        }
-                       if (atoi(timeout)>0)
+                       if (c.registration_timeout == 0)
                        {
-                               c.registration_timeout = atoi(timeout);
+                               c.registration_timeout = 90;
                        }
-                       if (atoi(pfreq)>0)
+                       if (c.pingtime == 0)
                        {
-                               c.pingtime = atoi(pfreq);
+                               c.pingtime = 120;
                        }
 
                        Classes.push_back(c);
@@ -546,7 +519,6 @@ void ServerConfig::Read(bool bail, userrec* user)
        }
 
        maxbans.clear();
-       char CM1[MAXBUF],CM2[MAXBUF];
 
        for (int count = 0; count < Config->ConfValueEnum("banlist",&Config->config_f); count++)
        {
@@ -702,9 +674,9 @@ void Start (void)
 {
        printf("\033[1;32mInspire Internet Relay Chat Server, compiled %s at %s\n",__DATE__,__TIME__);
        printf("(C) ChatSpike Development team.\033[0m\n\n");
-       printf("Developers:\033[1;32m Brain, FrostyCoolSlug, w00t, Om\033[0m\n");
-       printf("Others:\033[1;32m See /INFO Output\033[0m\n");
-       printf("Name concept:\033[1;32m   Lord_Zathras\033[0m\n\n");
+       printf("Developers:\t\t\033[1;32mBrain, FrostyCoolSlug, w00t, Om\033[0m\n");
+       printf("Others:\t\t\t\033[1;32mSee /INFO Output\033[0m\n");
+       printf("Name concept:\t\t\033[1;32mLord_Zathras\033[0m\n\n");
 }
 
 void WritePID(std::string filename)
@@ -809,6 +781,8 @@ std::string ServerConfig::ConfProcess(char* buffer, long linenumber, std::string
        long number_of_equals = 0;
        bool has_open_bracket = false;
        bool in_quotes = false;
+       char* trailing;
+
        error = false;
        if (!buffer)
        {
@@ -819,61 +793,62 @@ std::string ServerConfig::ConfProcess(char* buffer, long linenumber, std::string
                if (*d == 9)
                        *d = ' ';
        while (*buffer == ' ') buffer++;
-       while ((buffer[strlen(buffer)-1] == ' ') && (*buffer)) buffer[strlen(buffer)-1] = '\0';
+       trailing = buffer + strlen(buffer) - 1;
+       while (*trailing == ' ') *trailing-- = '\0';
 
        // empty lines are syntactically valid, as are comments
        if (!(*buffer) || buffer[0] == '#')
                return "";
 
-       for (unsigned int c = 0; c < strlen(buffer); c++)
+       for (char* c = buffer; *c; c++)
        {
                // convert all spaces that are OUTSIDE quotes into hardspace (0xA0) as this will make them easier to
                // search and replace later :)
-               if ((!in_quotes) && (buffer[c] == ' '))
-                       buffer[c] = '\xA0';
-               if ((buffer[c] == '<') && (!in_quotes))
+               if ((!in_quotes) && (*c == ' '))
+                       *c = '\xA0';
+               if ((*c == '<') && (!in_quotes))
                {
                        has_open_bracket = true;
-                       if (strlen(buffer) == 1)
+                       if (!(*(buffer+1)))
                        {
                                *errorstream << "Tag without identifier at " << filename << ":" << linenumber << endl;
                                error = true;
                                return "";
                        }
-                       else if ((tolower(buffer[c+1]) < 'a') || (tolower(buffer[c+1]) > 'z'))
+                       else if ((tolower(*(c+1)) < 'a') || (tolower(*(c+1)) > 'z'))
                        {
                                *errorstream << "Invalid characters in identifier at " << filename << ":" << linenumber << endl;
                                error = true;
                                return "";
                        }
                }
-               if (buffer[c] == '"')
+               if (*c == '"')
                {
                        number_of_quotes++;
                        in_quotes = (!in_quotes);
                }
-               if ((buffer[c] == '=') && (!in_quotes))
+               if ((*c == '=') && (!in_quotes))
                {
                        number_of_equals++;
-                       if (strlen(buffer) == c)
+                       if (*(c+1) == 0)
                        {
                                *errorstream << "Variable without a value at " << filename << ":" << linenumber << endl;
                                error = true;
                                return "";
                        }
-                       else if (buffer[c+1] != '"')
+                       else if (*(c+1) != '"')
                        {
                                *errorstream << "Variable name not followed immediately by its value at " << filename << ":" << linenumber << endl;
                                error = true;
                                return "";
                        }
-                       else if (!c)
+                       else if (c == buffer)
                        {
                                *errorstream << "Value without a variable (line starts with '=') at " << filename << ":" << linenumber << endl;
                                error = true;
                                return "";
                        }
-                       else if (buffer[c-1] == '\xA0')
+                       else if (*(c-1) == '\xA0')
                        {
                                *errorstream << "Variable name not followed immediately by its value at " << filename << ":" << linenumber << endl;
                                error = true;
@@ -882,7 +857,7 @@ std::string ServerConfig::ConfProcess(char* buffer, long linenumber, std::string
                }
        }
        // no quotes, and no equals. something freaky.
-       if ((!number_of_quotes) || (!number_of_equals) && (strlen(buffer)>2) && (buffer[0]=='<'))
+       if ((!number_of_quotes) || (!number_of_equals) && (strlen(buffer)>2) && (*buffer == '<'))
        {
                *errorstream << "Malformed tag at " << filename << ":" << linenumber << endl;
                error = true;
@@ -924,16 +899,20 @@ std::string ServerConfig::ConfProcess(char* buffer, long linenumber, std::string
 
 int ServerConfig::fgets_safe(char* buffer, size_t maxsize, FILE* &file)
 {
-       char c_read = '\0';
-       unsigned int bufptr = 0;
-       while ((!feof(file)) && (c_read != '\n') && (c_read != '\r') && (bufptr < maxsize))
+       char c_read = 0;
+       size_t n = 0;
+       char* bufptr = buffer;
+       while ((!feof(file)) && (c_read != '\n') && (c_read != '\r') && (n < maxsize))
        {
                c_read = fgetc(file);
                if ((c_read != '\n') && (c_read != '\r'))
-                       buffer[bufptr++] = c_read;
+               {
+                       *bufptr++ = c_read;
+                       n++;
+               }
        }
-       buffer[bufptr] = '\0';
-       return bufptr;
+       *bufptr = 0;
+       return bufptr - buffer;
 }
 
 bool ServerConfig::LoadConf(const char* filename, std::stringstream *target, std::stringstream* errorstream)
@@ -967,7 +946,7 @@ bool ServerConfig::LoadConf(const char* filename, std::stringstream *target, std
                {
                        if (fgets_safe(buffer, MAXBUF, conf))
                        {
-                               if ((!feof(conf)) && (buffer) && (strlen(buffer)))
+                               if ((!feof(conf)) && (buffer) && (*buffer))
                                {
                                        if ((buffer[0] != '#') && (buffer[0] != '\r')  && (buffer[0] != '\n'))
                                        {
@@ -977,13 +956,13 @@ bool ServerConfig::LoadConf(const char* filename, std::stringstream *target, std
                                                        char confpath[10240],newconf[10240];
                                                        // include file directive
                                                        buf += 15;      // advance to filename
-                                                       for (unsigned int j = 0; j < strlen(buf); j++)
+                                                       for (char* j = buf; *j; j++)
                                                        {
-                                                               if (buf[j] == '\\')
-                                                                       buf[j] = '/';
-                                                               if (buf[j] == '"')
+                                                               if (*j == '\\')
+                                                                       *j = '/';
+                                                               if (*j == '"')
                                                                {
-                                                                       buf[j] = '\0';
+                                                                       *j = 0;
                                                                        break;
                                                                }
                                                        }
@@ -1046,23 +1025,22 @@ int ServerConfig::EnumConf(std::stringstream *config, const char* tag)
 
        std::string x = config->str();
        const char* buf = x.c_str();
-       long bptr = 0;
-       long len = config->str().length();
+       char* bptr = (char*)buf;
        
        ptr = 0;
        in_token = 0;
        in_quotes = 0;
        lastc = '\0';
-       while (bptr<len)
+       while (*bptr)
        {
                lastc = c;
-               c = buf[bptr++];
+               c = *bptr++;
                if ((c == '#') && (lastc == '\n'))
                {
-                       while ((c != '\n') && (bptr<len))
+                       while ((c != '\n') && (*bptr))
                        {
                                lastc = c;
-                               c = buf[bptr++];
+                               c = *bptr++;
                        }
                }
                if ((c == '<') && (!in_quotes))
@@ -1070,7 +1048,7 @@ int ServerConfig::EnumConf(std::stringstream *config, const char* tag)
                        tptr = 0;
                        in_token = 1;
                        do {
-                               c = buf[bptr++];
+                               c = *bptr++;
                                if (c != ' ')
                                {
                                        c_tag[tptr++] = c;
@@ -1114,28 +1092,26 @@ int ServerConfig::EnumValues(std::stringstream *config, const char* tag, int ind
        int ptr = 0;
        char buffer[MAXBUF], c_tag[MAXBUF], c, lastc;
        int in_token, in_quotes, tptr, idx = 0;
-       
        bool correct_tag = false;
        int num_items = 0;
-
        const char* buf = config->str().c_str();
-       long bptr = 0;
-       long len = strlen(buf);
-       
+       char* bptr = (char*)buf;
+
        ptr = 0;
        in_token = 0;
        in_quotes = 0;
-       lastc = '\0';
-       while (bptr<len)
+       lastc = 0;
+
+       while (*bptr)
        {
                lastc = c;
-               c = buf[bptr++];
+               c = *bptr++;
                if ((c == '#') && (lastc == '\n'))
                {
-                       while ((c != '\n') && (bptr<len))
+                       while ((c != '\n') && (*bptr))
                        {
                                lastc = c;
-                               c = buf[bptr++];
+                               c = *bptr++;
                        }
                }
                if ((c == '<') && (!in_quotes))
@@ -1143,7 +1119,7 @@ int ServerConfig::EnumValues(std::stringstream *config, const char* tag, int ind
                        tptr = 0;
                        in_token = 1;
                        do {
-                               c = buf[bptr++];
+                               c = *bptr++;
                                if (c != ' ')
                                {
                                        c_tag[tptr++] = c;
@@ -1193,42 +1169,33 @@ int ServerConfig::EnumValues(std::stringstream *config, const char* tag, int ind
 }
 
 
-
 int ServerConfig::ConfValueEnum(char* tag, std::stringstream* config)
 {
        return EnumConf(config,tag);
 }
 
 
-
-/* Retrieves a value from the config file. If there is more than one value of the specified
- * key and section (e.g. for opers etc) then the index value specifies which to retreive, e.g.
- *
- * ConfValue("oper","name",2,result);
- */
-
 int ServerConfig::ReadConf(std::stringstream *config, const char* tag, const char* var, int index, char *result)
 {
        int ptr = 0;
        char buffer[65535], c_tag[MAXBUF], c, lastc;
        int in_token, in_quotes, tptr, idx = 0;
        char* key;
-
        std::string x = config->str();
        const char* buf = x.c_str();
-       long bptr = 0;
-       long len = config->str().length();
+       char* bptr = (char*)buf;
        
        ptr = 0;
        in_token = 0;
        in_quotes = 0;
-       lastc = '\0';
-       c_tag[0] = '\0';
-       buffer[0] = '\0';
-       while (bptr<len)
+       lastc = 0;
+       c_tag[0] = 0;
+       buffer[0] = 0;
+
+       while (*bptr)
        {
                lastc = c;
-               c = buf[bptr++];
+               c = *bptr++;
                // FIX: Treat tabs as spaces
                if (c == 9)
                        c = 32;
@@ -1237,7 +1204,7 @@ int ServerConfig::ReadConf(std::stringstream *config, const char* tag, const cha
                        tptr = 0;
                        in_token = 1;
                        do {
-                               c = buf[bptr++];
+                               c = *bptr++;
                                if (c != ' ')
                                {
                                        c_tag[tptr++] = c;
@@ -1280,11 +1247,12 @@ int ServerConfig::ReadConf(std::stringstream *config, const char* tag, const cha
                                                                key++;
                                                        }
                                                        key++;
-                                                       for (unsigned j = 0; j < strlen(key); j++)
+                                                       for (char* j = key; *j; j++)
                                                        {
-                                                               if (key[j] == '"')
+                                                               if (*j == '"')
                                                                {
-                                                                       key[j] = '\0';
+                                                                       *j = 0;
+                                                                       break;
                                                                }
                                                        }
                                                        strlcpy(result,key,MAXBUF);
@@ -1324,32 +1292,69 @@ int ServerConfig::ConfValue(char* tag, char* var, int index, char *result,std::s
        return 0;
 }
 
-
+int ServerConfig::ConfValueInteger(char* tag, char* var, int index, std::stringstream *config)
+{
+       char result[MAXBUF];
+       ReadConf(config, tag, var, index, result);
+       return atoi(result);
+}
 
 // This will bind a socket to a port. It works for UDP/TCP
 int BindSocket (int sockfd, struct sockaddr_in client, struct sockaddr_in server, int port, char* addr)
 {
        memset((char *)&server,0,sizeof(server));
        struct in_addr addy;
-       inet_aton(addr,&addy);
-       server.sin_family = AF_INET;
-       if (!*addr)
+       bool resolved = false;
+       char resolved_addr[128];
+
+       if (*addr == '*')
+               *addr = 0;
+
+       if (*addr && !inet_aton(addr,&addy))
        {
-               server.sin_addr.s_addr = htonl(INADDR_ANY);
+               /* If they gave a hostname, bind to the IP it resolves to */
+               if (CleanAndResolve(resolved_addr, addr, true))
+               {
+                       inet_aton(resolved_addr,&addy);
+                       log(DEFAULT,"Resolved binding '%s' -> '%s'",addr,resolved_addr);
+                       server.sin_addr = addy;
+                       resolved = true;
+               }
+               else
+               {
+                       log(DEFAULT,"WARNING: Could not resolve '%s' to an IP for binding to on port %d",addr,port);
+                       return(FALSE);
+               }
        }
-       else
+       server.sin_family = AF_INET;
+       if (!resolved)
        {
-               server.sin_addr = addy;
+               if (!*addr)
+               {
+                       server.sin_addr.s_addr = htonl(INADDR_ANY);
+               }
+               else
+               {
+                       server.sin_addr = addy;
+               }
        }
        server.sin_port = htons(port);
-       if (bind(sockfd,(struct sockaddr*)&server,sizeof(server))<0)
+       if (bind(sockfd,(struct sockaddr*)&server,sizeof(server)) < 0)
        {
                return(ERROR);
        }
        else
        {
-               listen(sockfd, Config->MaxConn);
-               return(TRUE);
+               log(DEBUG,"Bound port %s:%d",*addr ? addr : "*",port);
+               if (listen(sockfd, Config->MaxConn) == -1)
+               {
+                       log(DEFAULT,"ERROR in listen(): %s",strerror(errno));
+                       return(FALSE);
+               }
+               else
+               {
+                       return(TRUE);
+               }
        }
 }