X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Finspircd_io.cpp;h=fcbb83aaeb18a57cbc495f68cfda81a436b5f471;hb=d5fed3976bba0f1082522da9b79b6b1cc93d4c56;hp=18bee1f18bf68de58fd23b4dd11a3a6c0ec907ad;hpb=9be94a9a9cf3a7946171994c97bcf4041dd8dd48;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/inspircd_io.cpp b/src/inspircd_io.cpp index 18bee1f18..fcbb83aae 100644 --- a/src/inspircd_io.cpp +++ b/src/inspircd_io.cpp @@ -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: * * @@ -14,10 +14,8 @@ * --------------------------------------------------- */ -#ifdef __linux__ +#include #include -#endif - #include #include #include @@ -27,80 +25,107 @@ #include "inspircd.h" #include "inspircd_io.h" #include "inspircd_util.h" +#include "inspstring.h" +#include "helperfuncs.h" using namespace std; extern FILE *log_file; +extern int boundPortCount; +extern int openSockfd[MAXSOCKS]; +extern time_t TIME; +extern bool unlimitcore; void WriteOpers(char* text, ...); void Exit (int status) { - if (log_file) - fclose(log_file); - send_error("Server shutdown."); - exit (status); + if (log_file) + fclose(log_file); + send_error("Server shutdown."); + exit (status); } void Killed(int status) { - if (log_file) - fclose(log_file); - send_error("Server terminated."); - exit(status); + if (log_file) + fclose(log_file); + send_error("Server terminated."); + exit(status); } void Rehash(int status) { - ReadConfig(); - WriteOpers("Rehashing config file %s due to SIGHUP",CONFIG_FILE); + WriteOpers("Rehashing config file %s due to SIGHUP",CONFIG_FILE); + ReadConfig(false,NULL); } 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;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"); + 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\033[0m\n"); + printf("Documentation:\033[1;32m FrostyCoolSlug, w00t\033[0m\n"); + printf("Testers:\033[1;32m typobox43, piggles, Lord_Zathras, CC\033[0m\n"); + printf("Name concept:\033[1;32m Lord_Zathras\033[0m\n\n"); } - -void DeadPipe(int status) +void WritePID(std::string filename) { - signal (SIGPIPE, DeadPipe); + ofstream outfile(filename.c_str()); + if (outfile.is_open()) + { + outfile << getpid(); + outfile.close(); + } + else + { + printf("Failed to write PID-file '%s', exiting.\n",filename.c_str()); + log(DEFAULT,"Failed to write PID-file '%s', exiting.",filename.c_str()); + Exit(0); + } } + int DaemonSeed (void) { - int childpid; - signal (SIGALRM, SIG_IGN); - signal (SIGHUP, Rehash); - signal (SIGPIPE, DeadPipe); - signal (SIGTERM, Exit); - signal (SIGABRT, Exit); - signal (SIGSEGV, Error); - signal (SIGURG, Exit); - signal (SIGKILL, Exit); - if ((childpid = fork ()) < 0) - return (ERROR); - else if (childpid > 0) - exit (0); - setsid (); - umask (077); - /* 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 + int childpid; + signal (SIGALRM, SIG_IGN); + signal (SIGHUP, Rehash); + signal (SIGPIPE, SIG_IGN); + signal (SIGTERM, Exit); + signal (SIGSEGV, Error); + if ((childpid = fork ()) < 0) + return (ERROR); + else if (childpid > 0) + exit (0); + setsid (); + umask (007); + printf("InspIRCd Process ID: \033[1;32m%lu\033[0m\n",(unsigned long)getpid()); + freopen("/dev/null","w",stdout); + freopen("/dev/null","w",stderr); + + setpriority(PRIO_PROCESS,(int)getpid(),15); + + if (unlimitcore) + { + rlimit rl; + if (getrlimit(RLIMIT_CORE, &rl) == -1) + { + log(DEFAULT,"Failed to getrlimit()!"); + return(FALSE); + } + else + { + rl.rlim_cur = rl.rlim_max; + if (setrlimit(RLIMIT_CORE, &rl) == -1) + log(DEFAULT,"setrlimit() failed, cannot increase coredump size."); + } + } - return (TRUE); + return (TRUE); } @@ -112,34 +137,187 @@ int DaemonSeed (void) bool FileExists (const char* file) { - FILE *input; - - if ((input = fopen (file, "r")) == NULL) { return(false); } - else { fclose (input); return(true); } + FILE *input; + if ((input = fopen (file, "r")) == NULL) + { + return(false); + } + 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 + */ -bool LoadConf(const char* filename, std::stringstream *target) +std::string ConfProcess(char* buffer, long linenumber, std::stringstream* errorstream, bool &error, std::string filename) { - FILE* conf = fopen(filename,"r"); + 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 and converting tabs to spaces + for (int d = 0; d < strlen(buffer); d++) + if ((buffer[d]) == 9) + buffer[d] = ' '; + 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++) + { + // 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) && (strlen(buffer)>2) && (buffer[0]=='<')) + { + *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); + } + + // 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; + // first, check that the file exists before we try to do anything with it if (!FileExists(filename)) { + *errorstream << "File " << filename << " not found." << endl; return false; } + // Fix the chmod of the file to restrict it to the current user and group + chmod(filename,0600); + // now open it + FILE* conf = fopen(filename,"r"); 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++; } } } @@ -155,8 +333,7 @@ int EnumConf(std::stringstream *config, const char* tag) { int ptr = 0; char buffer[MAXBUF], c_tag[MAXBUF], c, lastc; - int in_token, in_quotes, tptr, j, idx = 0; - char* key; + int in_token, in_quotes, tptr, idx = 0; const char* buf = config->str().c_str(); long bptr = 0; @@ -220,6 +397,91 @@ int EnumConf(std::stringstream *config, const char* tag) return idx; } +/* Counts the number of values within a certain tag */ + +int EnumValues(std::stringstream *config, const char* tag, int index) +{ + 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); + + ptr = 0; + in_token = 0; + in_quotes = 0; + lastc = '\0'; + while (bptr') && (!in_quotes)) + { + in_token = 0; + if (correct_tag) + correct_tag = false; + if (!strcmp(c_tag,tag)) + { + /* correct tag, but wrong index */ + idx++; + } + c_tag[0] = '\0'; + buffer[0] = '\0'; + ptr = 0; + tptr = 0; + } + if (c != '>') + { + if ((in_token) && (c != '\n') && (c != '\r')) + { + buffer[ptr++] = c; + buffer[ptr] = '\0'; + } + } + } + return num_items+1; +} + int ConfValueEnum(char* tag, std::stringstream* config) @@ -238,30 +500,27 @@ int ConfValueEnum(char* tag, std::stringstream* config) int ReadConf(std::stringstream *config, const char* tag, const char* var, int index, char *result) { int ptr = 0; - char buffer[MAXBUF], c_tag[MAXBUF], c, lastc; + char buffer[65535], c_tag[MAXBUF], c, lastc; int in_token, in_quotes, tptr, j, idx = 0; char* key; const char* buf = config->str().c_str(); long bptr = 0; - long len = strlen(buf); + long len = config->str().length(); ptr = 0; in_token = 0; in_quotes = 0; lastc = '\0'; + c_tag[0] = '\0'; + buffer[0] = '\0'; while (bptr