]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd_io.cpp
Re-added required parts of connection.h
[user/henk/code/inspircd.git] / src / inspircd_io.cpp
index 7a2ad99f8c6c98a07016e0724170322f826a355e..aa5d5af65cb35137ae2b18599aa09ca7f9ab2d1f 100644 (file)
@@ -14,6 +14,9 @@
  * ---------------------------------------------------
  */
 
+using namespace std;
+
+#include "inspircd_config.h"
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/types.h>
 #include "inspircd_io.h"
 #include "inspircd_util.h"
 #include "inspstring.h"
-
-using namespace std;
+#include "helperfuncs.h"
 
 extern FILE *log_file;
+extern int boundPortCount;
+extern int openSockfd[MAXSOCKS];
+extern time_t TIME;
+extern bool unlimitcore;
+extern int MaxConn;
+std::vector<std::string> include_stack;
 
 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)
 {
-  WriteOpers("Rehashing config file %s due to SIGHUP",CONFIG_FILE);
-  ReadConfig(false,NULL);
+       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\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);
-
-  setpriority(PRIO_PROCESS,(int)getpid(),15); /* ircd sets to low process priority so it doesnt hog the box */
+       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);
 }
 
 
@@ -109,10 +140,16 @@ 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:
@@ -142,7 +179,7 @@ std::string ConfProcess(char* buffer, long linenumber, std::stringstream* errors
                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++)
+       for (unsigned int d = 0; d < strlen(buffer); d++)
                if ((buffer[d]) == 9)
                        buffer[d] = ' ';
        while ((buffer[0] == ' ') && (strlen(buffer)>0)) buffer++;
@@ -152,7 +189,7 @@ std::string ConfProcess(char* buffer, long linenumber, std::stringstream* errors
                return "";
        else if (buffer[0] == '#')
                return "";
-       for (int c = 0; c < strlen(buffer); c++)
+       for (unsigned 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 :)
@@ -239,7 +276,7 @@ std::string ConfProcess(char* buffer, long linenumber, std::stringstream* errors
        }
 
        // turn our hardspace back into softspace
-       for (int d = 0; d < parsedata.length(); d++)
+       for (unsigned int d = 0; d < parsedata.length(); d++)
        {
                if (parsedata[d] == '\xA0')
                        parsedata[d] = ' ';
@@ -249,35 +286,109 @@ std::string ConfProcess(char* buffer, long linenumber, std::stringstream* errors
        return parsedata;
 }
 
+int 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))
+       {
+               c_read = fgetc(file);
+               if ((c_read != '\n') && (c_read != '\r'))
+                       buffer[bufptr++] = c_read;
+       }
+       buffer[bufptr] = '\0';
+       return bufptr;
+}
+
 bool LoadConf(const char* filename, std::stringstream *target, std::stringstream* errorstream)
 {
        target->str("");
        errorstream->str("");
        long linenumber = 1;
-       FILE* conf = fopen(filename,"r");
+       // 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);
+       for (unsigned int t = 0; t < include_stack.size(); t++)
+       {
+               if (std::string(filename) == include_stack[t])
+               {
+                       *errorstream << "File " << filename << " is included recursively (looped inclusion)." << endl;
+                       return false;
+               }
+       }
+       include_stack.push_back(filename);
+       // now open it
+       FILE* conf = fopen(filename,"r");
        char buffer[MAXBUF];
        if (conf)
        {
                while (!feof(conf))
                {
-                       if (fgets(buffer, MAXBUF, conf))
+                       if (fgets_safe(buffer, MAXBUF, conf))
                        {
                                if ((!feof(conf)) && (buffer) && (strlen(buffer)))
                                {
                                        if ((buffer[0] != '#') && (buffer[0] != '\r')  && (buffer[0] != '\n'))
                                        {
-                                               bool error = false;
-                                               std::string data = ConfProcess(buffer,linenumber++,errorstream,error,filename);
-                                               if (error)
+                                               if (!strncmp(buffer,"<include file=\"",15))
+                                               {
+                                                       char* buf = buffer;
+                                                       char confpath[10240],newconf[10240];
+                                                       // include file directive
+                                                       buf += 15;      // advance to filename
+                                                       for (unsigned int j = 0; j < strlen(buf); j++)
+                                                       {
+                                                               if (buf[j] == '\\')
+                                                                       buf[j] = '/';
+                                                               if (buf[j] == '"')
+                                                               {
+                                                                       buf[j] = '\0';
+                                                                       break;
+                                                               }
+                                                       }
+                                                       log(DEFAULT,"Opening included file '%s'",buf);
+                                                       if (*buf != '/')
+                                                       {
+                                                               strlcpy(confpath,CONFIG_FILE,10240);
+                                                               if (strstr(confpath,"/inspircd.conf"))
+                                                               {
+                                                                       // leaves us with just the path
+                                                                       *(strstr(confpath,"/inspircd.conf")) = '\0';
+                                                               }
+                                                               snprintf(newconf,10240,"%s/%s",confpath,buf);
+                                                       }
+                                                       else snprintf(newconf,10240,"%s",buf);
+                                                       std::stringstream merge(stringstream::in | stringstream::out);
+                                                       // recursively call LoadConf and get the new data, use the same errorstream
+                                                       if (LoadConf(newconf, &merge, errorstream))
+                                                       {
+                                                               // append to the end of the file
+                                                               std::string newstuff = merge.str();
+                                                               *target << newstuff;
+                                                       }
+                                                       else
+                                                       {
+                                                               // the error propogates up to its parent recursively
+                                                               // causing the config reader to bail at the top level.
+                                                               fclose(conf);
+                                                               return false;
+                                                       }
+                                               }
+                                               else
                                                {
-                                                       return false;
+                                                       bool error = false;
+                                                       std::string data = ConfProcess(buffer,linenumber++,errorstream,error,filename);
+                                                       if (error)
+                                                       {
+                                                               return false;
+                                                       }
+                                                       *target << data;
                                                }
-                                               *target << data;
                                        }
                                        else linenumber++;
                                }
@@ -295,8 +406,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;
@@ -366,8 +476,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;
@@ -465,12 +574,12 @@ int ReadConf(std::stringstream *config, const char* tag, const char* var, int in
 {
        int ptr = 0;
        char buffer[65535], c_tag[MAXBUF], c, lastc;
-       int in_token, in_quotes, tptr, j, idx = 0;
+       int in_token, in_quotes, tptr, 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;
@@ -533,7 +642,7 @@ int ReadConf(std::stringstream *config, const char* tag, const char* var, int in
                                                                key++;
                                                        }
                                                        key++;
-                                                       for (j = 0; j < strlen(key); j++)
+                                                       for (unsigned j = 0; j < strlen(key); j++)
                                                        {
                                                                if (key[j] == '"')
                                                                {
@@ -579,54 +688,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);
-  }
+       memset((char *)&server,0,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, MaxConn);
+               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);
+       }
 }