]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd_io.cpp
Added implementation of strlcpy and strlcat for systems that dont have it
[user/henk/code/inspircd.git] / src / inspircd_io.cpp
index b267e98ca8f12b20cffdfaed13d6183a798174a7..d412cee9320f22165a03c19c989090e63783ba99 100644 (file)
@@ -2,7 +2,7 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  Inspire is copyright (C) 2002-2003 ChatSpike-Dev.
+ *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
  *                       E-mail:
  *                <brain@chatspike.net>
  *               <Craig@chatspike.net>
  * ---------------------------------------------------
  */
 
-#ifdef __linux__ 
+#include <sys/time.h>
 #include <sys/resource.h>
-#endif
-
 #include <sys/types.h>
 #include <string>
 #include <unistd.h>
@@ -27,6 +25,7 @@
 #include "inspircd.h"
 #include "inspircd_io.h"
 #include "inspircd_util.h"
+#include "inspstring.h"
 
 using namespace std;
 
@@ -52,8 +51,8 @@ void Killed(int status)
 
 void Rehash(int status)
 {
-  ReadConfig();
   WriteOpers("Rehashing config file %s due to SIGHUP",CONFIG_FILE);
+  ReadConfig(false,NULL);
 }
 
 
@@ -62,7 +61,7 @@ void Start (void)
 {
   printf("\033[1;37mInspire Internet Relay Chat Server, compiled " __DATE__ " at " __TIME__ "\n");
   printf("(C) ChatSpike Development team.\033[0;37m\n\n");
-  printf("\033[1;37mDevelopers:\033[0;37m     Brain, FrostyCoolSlug, RD\n");
+  printf("\033[1;37mDevelopers:\033[0;37m     Brain, FrostyCoolSlug\n");
   printf("\033[1;37mDocumentation:\033[0;37m  FrostyCoolSlug, w00t\n");
   printf("\033[1;37mTesters:\033[0;37m        typobox43, piggles, Lord_Zathras, CC\n");
   printf("\033[1;37mName concept:\033[0;37m   Lord_Zathras\n\n");
@@ -90,15 +89,13 @@ int DaemonSeed (void)
   else if (childpid > 0)
     exit (0);
   setsid ();
-  umask (077);
+  umask (007);
   /* close stdout, stdin, stderr */
   close(0);
   close(1);
   close(2);
 
-  #ifdef __linux__ 
   setpriority(PRIO_PROCESS,(int)getpid(),15); /* ircd sets to low process priority so it doesnt hog the box */
-  #endif
   
   return (TRUE);
 }
@@ -118,28 +115,170 @@ bool FileExists (const char* file)
   else { fclose (input); return(true); }
 }
 
+/* ConfProcess does the following things to a config line in the following order:
+ *
+ * Processes the line for syntax errors as shown below
+ *      (1) Line void of quotes or equals (a malformed, illegal tag format)
+ *      (2) Odd number of quotes on the line indicating a missing quote
+ *      (3) number of equals signs not equal to number of quotes / 2 (missing an equals sign)
+ *      (4) Spaces between the opening bracket (<) and the keyword
+ *      (5) Spaces between a keyword and an equals sign
+ *      (6) Spaces between an equals sign and a quote
+ * Removes trailing spaces
+ * Removes leading spaces
+ * Converts tabs to spaces
+ * Turns multiple spaces that are outside of quotes into single spaces
+ */
+
+std::string ConfProcess(char* buffer, long linenumber, std::stringstream* errorstream, bool &error, std::string filename)
+{
+       long number_of_quotes = 0;
+       long number_of_equals = 0;
+       bool has_open_bracket = false;
+       bool in_quotes = false;
+       error = false;
+       if (!buffer)
+       {
+               return "";
+       }
+       // firstly clean up the line by stripping spaces from the start and end
+       while ((buffer[0] == ' ') && (strlen(buffer)>0)) buffer++;
+       while ((buffer[strlen(buffer)-1] == ' ') && (strlen(buffer)>0)) buffer[strlen(buffer)-1] = '\0';
+       // empty lines are syntactically valid
+       if (!strcmp(buffer,""))
+               return "";
+       else if (buffer[0] == '#')
+               return "";
+       for (int c = 0; c < strlen(buffer); c++)
+       {
+               if (buffer[c] == 9)
+                       buffer[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))
+               {
+                       has_open_bracket = true;
+                       if (strlen(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'))
+                       {
+                               *errorstream << "Invalid characters in identifier at " << filename << ":" << linenumber << endl;
+                               error = true;
+                               return "";
+                       }
+               }
+               if (buffer[c] == '"')
+               {
+                       number_of_quotes++;
+                       in_quotes = (!in_quotes);
+               }
+               if ((buffer[c] == '=') && (!in_quotes))
+               {
+                       number_of_equals++;
+                       if (strlen(buffer) == c)
+                       {
+                               *errorstream << "Variable without a value at " << filename << ":" << linenumber << endl;
+                               error = true;
+                               return "";
+                       }
+                       else if (buffer[c+1] != '"')
+                       {
+                               *errorstream << "Variable name not followed immediately by its value at " << filename << ":" << linenumber << endl;
+                               error = true;
+                               return "";
+                       }
+                       else if (!c)
+                       {
+                               *errorstream << "Value without a variable (line starts with '=') at " << filename << ":" << linenumber << endl;
+                               error = true;
+                               return "";
+                       }
+                       else if (buffer[c-1] == '\xA0')
+                       {
+                               *errorstream << "Variable name not followed immediately by its value at " << filename << ":" << linenumber << endl;
+                               error = true;
+                               return "";
+                       }
+               }
+       }
+       // no quotes, and no equals. something freaky.
+       if ((!number_of_quotes) || (!number_of_equals))
+       {
+               *errorstream << "Malformed tag at " << filename << ":" << linenumber << endl;
+               error = true;
+               return "";
+       }
+       // odd number of quotes. thats just wrong.
+       if ((number_of_quotes % 2) != 0)
+       {
+               *errorstream << "Missing \" at " << filename << ":" << linenumber << endl;
+               error = true;
+               return "";
+       }
+       if (number_of_equals < (number_of_quotes/2))
+       {
+               *errorstream << "Missing '=' at " << filename << ":" << linenumber << endl;
+       }
+       if (number_of_equals > (number_of_quotes/2))
+       {
+               *errorstream << "Too many '=' at " << filename << ":" << linenumber << endl;
+       }
+
+       std::string parsedata = buffer;
+       // turn multispace into single space
+       while (parsedata.find("\xA0\xA0") != std::string::npos)
+       {
+               parsedata.erase(parsedata.find("\xA0\xA0"),1);
+       }
 
-bool LoadConf(const char* filename, std::stringstream *target)
+       // turn our hardspace back into softspace
+       for (int d = 0; d < parsedata.length(); d++)
+       {
+               if (parsedata[d] == '\xA0')
+                       parsedata[d] = ' ';
+       }
+
+       // and we're done, the line is fine!
+       return parsedata;
+}
+
+bool LoadConf(const char* filename, std::stringstream *target, std::stringstream* errorstream)
 {
+       target->str("");
+       errorstream->str("");
+       long linenumber = 1;
        FILE* conf = fopen(filename,"r");
        if (!FileExists(filename))
        {
+               *errorstream << "File " << filename << " not found." << endl;
                return false;
        }
        char buffer[MAXBUF];
        if (conf)
        {
-               target->clear();
                while (!feof(conf))
                {
                        if (fgets(buffer, MAXBUF, conf))
                        {
                                if ((!feof(conf)) && (buffer) && (strlen(buffer)))
                                {
-                                       if (buffer[0] != '#')
+                                       if ((buffer[0] != '#') && (buffer[0] != '\r')  && (buffer[0] != '\n'))
                                        {
-                                               *target << std::string(buffer);
+                                               bool error = false;
+                                               std::string data = ConfProcess(buffer,linenumber++,errorstream,error,filename);
+                                               if (error)
+                                               {
+                                                       return false;
+                                               }
+                                               *target << data;
                                        }
+                                       else linenumber++;
                                }
                        }
                }
@@ -400,7 +539,7 @@ int ReadConf(std::stringstream *config, const char* tag, const char* var, int in
                                                                        key[j] = '\0';
                                                                }
                                                        }
-                                                       strcpy(result,key);
+                                                       strlcpy(result,key,MAXBUF);
                                                        return 1;
                                                }
                                        }