X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Finspircd_io.cpp;h=fcbb83aaeb18a57cbc495f68cfda81a436b5f471;hb=d5fed3976bba0f1082522da9b79b6b1cc93d4c56;hp=9f96c463ecca1132bd0f65f7ada8fa90bb75deb3;hpb=e7f0a0fb7edf96abbddf72eadb490b5eb22447ec;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/inspircd_io.cpp b/src/inspircd_io.cpp index 9f96c463e..fcbb83aae 100644 --- a/src/inspircd_io.cpp +++ b/src/inspircd_io.cpp @@ -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 (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 + 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,21 +137,167 @@ 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 + */ + +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 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] = ' '; + } -bool LoadConf(const char* filename, std::stringstream *target) + // and we're done, the line is fine! + return parsedata; +} + +bool LoadConf(const char* filename, std::stringstream *target, std::stringstream* errorstream) { target->str(""); - FILE* conf = fopen(filename,"r"); + 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) { @@ -136,10 +307,17 @@ bool LoadConf(const char* filename, std::stringstream *target) { 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; @@ -226,8 +403,7 @@ 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, j, idx = 0; - char* key; + int in_token, in_quotes, tptr, idx = 0; bool correct_tag = false; int num_items = 0; @@ -330,7 +506,7 @@ int ReadConf(std::stringstream *config, const char* tag, const char* var, int in const char* buf = config->str().c_str(); long bptr = 0; - long len = strlen(buf); + long len = config->str().length(); ptr = 0; in_token = 0; @@ -400,7 +576,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; } } @@ -439,54 +615,51 @@ int ConfValue(char* tag, char* var, int index, char *result,std::stringstream *c -/* This will bind a socket to a port. It works for UDP/TCP */ +// 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) { - bzero((char *)&server,sizeof(server)); - struct in_addr addy; - inet_aton(addr,&addy); - - server.sin_family = AF_INET; - if (!strcmp(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) - { - return(ERROR); - } - else - { - listen(sockfd,5); - return(TRUE); - } + bzero((char *)&server,sizeof(server)); + struct in_addr addy; + inet_aton(addr,&addy); + server.sin_family = AF_INET; + if (!strcmp(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) + { + return(ERROR); + } + else + { + listen(sockfd,5); + return(TRUE); + } } -/* Open a TCP Socket */ +// Open a TCP Socket int OpenTCPSocket (void) { - int sockfd; - int on = 0; - struct linger linger = { 0 }; + int sockfd; + int on = 1; + struct linger linger = { 0 }; - if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) - return (ERROR); - else - { - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)); - /* This is BSD compatible, setting l_onoff to 0 is *NOT* http://web.irc.org/mla/ircd-dev/msg02259.html */ - linger.l_onoff = 1; - linger.l_linger = 0; - setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char*)&linger,sizeof(linger)); - return (sockfd); - } + if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) + return (ERROR); + else + { + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)); + /* This is BSD compatible, setting l_onoff to 0 is *NOT* http://web.irc.org/mla/ircd-dev/msg02259.html */ + linger.l_onoff = 1; + linger.l_linger = 1; + setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (const char*)&linger,sizeof(linger)); + return (sockfd); + } }