]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd.cpp
Added some missing parameter checking in m_swhois
[user/henk/code/inspircd.git] / src / inspircd.cpp
index 779061e833e005907eaa118658ae4dcbbc342aa7..858862e9dfa79c0ce06d05fbe9d3ddf1096fef84 100644 (file)
 #include "inspircd.h"
 #include "configreader.h"
 #include <signal.h>
-#ifndef WIN32
 
+#ifndef WIN32
 #include <dirent.h>
 #include <unistd.h>
 #include <sys/resource.h>
+#include <dlfcn.h>
+#include <getopt.h>
 
-/* This is just to be completely certain that the change which fixed getrusage on RH7 doesn't break anything else -- Om */  
+/* Some systems don't define RUSAGE_SELF. This should fix them. */
 #ifndef RUSAGE_SELF
-#define RUSAGE_SELF 0
+       #define RUSAGE_SELF 0
 #endif
 
 #endif
+
 #include <exception>
 #include <fstream>
 #include "modules.h"
 #include "command_parse.h"
 #include "exitcodes.h"
 
-#ifndef WIN32
-#include <dlfcn.h>
-#include <getopt.h>
-#else
+#ifdef WIN32
+
+/* This MUST remain static and delcared outside the class, so that WriteProcessMemory can reference it properly */
 static DWORD owner_processid = 0;
 
-bool WindowsForkStart(InspIRCd * Instance)
+DWORD WindowsForkStart(InspIRCd * Instance)
 {
        /* Windows implementation of fork() :P */
-       // Build the command line arguments.
-       string command_line;
-       for(int i = 0; i < Instance->Config->argc; ++i)
-               command_line += Instance->Config->argv[i];
 
        char module[MAX_PATH];
        if(!GetModuleFileName(NULL, module, MAX_PATH))
+       {
+               printf("GetModuleFileName() failed.\n");
                return false;
+       }
 
        STARTUPINFO startupinfo;
        PROCESS_INFORMATION procinfo;
@@ -64,34 +65,50 @@ bool WindowsForkStart(InspIRCd * Instance)
        // Fill in the startup info struct
        GetStartupInfo(&startupinfo);
 
-       // Create the "startup" event
-       HANDLE fork_event = CreateEvent(0, TRUE, FALSE, "InspStartup");
-       if(!fork_event)
-       {
-               printf("CreateEvent: %s\n", dlerror());
-               return false;
-       }
+       /* Default creation flags create the processes suspended */
+       DWORD startupflags = CREATE_SUSPENDED;
+
+       /* On windows 2003/XP and above, we can use the value
+        * CREATE_PRESERVE_CODE_AUTHZ_LEVEL which gives more access
+        * to the process which we may require on these operating systems.
+        */
+       OSVERSIONINFO vi;
+       vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+       GetVersionEx(&vi);
+       if ((vi.dwMajorVersion >= 5) && (vi.dwMinorVersion > 0))
+               startupflags |= CREATE_PRESERVE_CODE_AUTHZ_LEVEL;
 
        // Launch our "forked" process.
-       BOOL bSuccess = CreateProcess ( module, module, 
-               0,                                                                      // PROCESS_SECURITY_ATTRIBUTES
-               0,                                                                      // THREAD_SECURITY_ATTRIBUTES
-               TRUE,                                                           // We went to inherit handles.
-               CREATE_SUSPENDED |                                      // Suspend the primary thread of the new process
-               CREATE_PRESERVE_CODE_AUTHZ_LEVEL,       // Allow us full access to the process
-               0,                                                                      // ENVIRONMENT
-               0,                                                                      // CURRENT_DIRECTORY
-               &startupinfo,                                           // startup info
-               &procinfo);                                                     // process info
+       BOOL bSuccess = CreateProcess ( module, // Module (exe) filename
+               strdup(GetCommandLine()),       // Command line (exe plus parameters from the OS)
+                                               // NOTE: We cannot return the direct value of the
+                                               // GetCommandLine function here, as the pointer is
+                                               // passed straight to the child process, and will be
+                                               // invalid once we exit as it goes out of context.
+                                               // strdup() seems ok, though.
+               0,                              // PROCESS_SECURITY_ATTRIBUTES
+               0,                              // THREAD_SECURITY_ATTRIBUTES
+               TRUE,                           // We went to inherit handles.
+               startupflags,                   // Allow us full access to the process and suspend it.
+               0,                              // ENVIRONMENT
+               0,                              // CURRENT_DIRECTORY
+               &startupinfo,                   // startup info
+               &procinfo);                     // process info
 
        if(!bSuccess)
+       {
+               printf("CreateProcess() error: %s\n", dlerror());
                return false;
+       }
 
        // Set the owner process id in the target process.
        SIZE_T written = 0;
        DWORD pid = GetCurrentProcessId();
        if(!WriteProcessMemory(procinfo.hProcess, &owner_processid, &pid, sizeof(DWORD), &written) || written != sizeof(DWORD))
+       {
+               printf("WriteProcessMemory() failed: %s\n", dlerror());
                return false;
+       }
 
        // Resume the other thread (let it start)
        ResumeThread(procinfo.hThread);
@@ -99,19 +116,29 @@ bool WindowsForkStart(InspIRCd * Instance)
        // Wait for the new process to kill us. If there is some error, the new process will end and we will end up at the next line.
        WaitForSingleObject(procinfo.hProcess, INFINITE);
 
-       // If we hit this it means startup failed. :(
-       return true;
+       // If we hit this it means startup failed, default to 14 if this fails.
+       DWORD ExitCode = 14;
+       GetExitCodeProcess(procinfo.hProcess, &ExitCode);
+       CloseHandle(procinfo.hThread);
+       CloseHandle(procinfo.hProcess);
+       return ExitCode;
 }
 
 void WindowsForkKillOwner(InspIRCd * Instance)
 {
        HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, owner_processid);
        if(!hProcess || !owner_processid)
-               exit(1);
+       {
+               printf("Could not open process id %u: %s.\n", owner_processid, dlerror());
+               Instance->Exit(14);
+       }
 
        // die die die
        if(!TerminateProcess(hProcess, 0))
-               exit(1);
+       {
+               printf("Could not TerminateProcess(): %s\n", dlerror());
+               Instance->Exit(14);
+       }
 
        CloseHandle(hProcess);
 }
@@ -135,7 +162,7 @@ const char* ExitCodes[] =
                "Internal error", /* 3 */
                "Config file error", /* 4 */
                "Logfile error", /* 5 */
-               "Fork failed", /* 6 */
+               "POSIX fork failed", /* 6 */
                "Bad commandline parameters", /* 7 */
                "No ports could be bound", /* 8 */
                "Can't write PID file", /* 9 */
@@ -143,7 +170,7 @@ const char* ExitCodes[] =
                "Refusing to start up as root", /* 11 */
                "Found a <die> tag!", /* 12 */
                "Couldn't load module on startup", /* 13 */
-               "", /* 14 */
+               "Could not create windows forked process", /* 14 */
                "Received SIGTERM", /* 15 */
 };
 
@@ -348,6 +375,7 @@ void InspIRCd::QuickExit(int status)
 bool InspIRCd::DaemonSeed()
 {
 #ifdef WINDOWS
+       printf_c("InspIRCd Process ID: \033[1;32m%lu\033[0m\n", GetCurrentProcessId());
        return true;
 #else
        signal(SIGTERM, InspIRCd::QuickExit);
@@ -461,12 +489,12 @@ InspIRCd::InspIRCd(int argc, char** argv)
 
        struct option longopts[] =
        {
-               { "nofork",             no_argument,            &do_nofork,             1       },
-               { "logfile",    required_argument,      NULL,                   'f'     },
-               { "config",             required_argument,      NULL,                   'c'     },
-               { "debug",              no_argument,            &do_debug,              1       },
-               { "nolog",              no_argument,            &do_nolog,              1       },
-               { "runasroot",  no_argument,            &do_root,               1       },
+               { "nofork",     no_argument,            &do_nofork,     1       },
+               { "logfile",    required_argument,      NULL,           'f'     },
+               { "config",     required_argument,      NULL,           'c'     },
+               { "debug",      no_argument,            &do_debug,      1       },
+               { "nolog",      no_argument,            &do_nolog,      1       },
+               { "runasroot",  no_argument,            &do_root,       1       },
                { "version",    no_argument,            &do_version,    1       },
                { 0, 0, 0, 0 }
        };
@@ -478,12 +506,10 @@ InspIRCd::InspIRCd(int argc, char** argv)
                        case 'f':
                                /* Log filename was set */
                                strlcpy(LogFileName, optarg, MAXBUF);
-                               printf("LOG: Setting logfile to %s\n", LogFileName);
                        break;
                        case 'c':
                                /* Config filename was set */
                                strlcpy(ConfigFileName, optarg, MAXBUF);
-                               printf("CONFIG: Setting config file to %s\n", ConfigFileName);
                        break;
                        case 0:
                                /* getopt_long_only() set an int variable, just keep going */
@@ -507,8 +533,9 @@ InspIRCd::InspIRCd(int argc, char** argv)
        // Handle forking
        if(!do_nofork && !owner_processid)
        {
-               if(WindowsForkStart(this))
-                       Exit(0);
+               DWORD ExitCode = WindowsForkStart(this);
+               if(ExitCode)
+                       Exit(ExitCode);
        }
 
        // Set up winsock
@@ -928,9 +955,11 @@ bool InspIRCd::LoadModule(const char* filename)
                                return false;
                        }
                }
+               Module* m = NULL;
+               ircd_module* a = NULL;
                try
                {
-                       ircd_module* a = new ircd_module(this, modfile);
+                       a = new ircd_module(this, modfile);
                        factory[this->ModCount+1] = a;
                        if (factory[this->ModCount+1]->LastError())
                        {
@@ -940,14 +969,13 @@ bool InspIRCd::LoadModule(const char* filename)
                        }
                        if ((long)factory[this->ModCount+1]->factory != -1)
                        {
-                               Module* m = factory[this->ModCount+1]->factory->CreateModule(this);
+                               m = factory[this->ModCount+1]->factory->CreateModule(this);
 
                                Version v = m->GetVersion();
 
                                if (v.API != API_VERSION)
                                {
                                        delete m;
-                                       delete a;
                                        this->Log(DEFAULT,"Unable to load %s: Incorrect module API version: %d (our version: %d)",modfile,v.API,API_VERSION);
                                        snprintf(MODERR,MAXBUF,"Loader/Linker error: Incorrect module API version: %d (our version: %d)",v.API,API_VERSION);
                                        return false;
@@ -1213,7 +1241,7 @@ void FileLogger::WriteLogLine(const std::string &line)
        {
                int written = fprintf(log,"%s",buffer.c_str());
 #ifdef WINDOWS
-               buffer = "";
+               buffer.clear();
 #else
                if ((written >= 0) && (written < (int)buffer.length()))
                {
@@ -1228,7 +1256,7 @@ void FileLogger::WriteLogLine(const std::string &line)
                else
                {
                        /* Wrote the whole buffer, and no need for write callback */
-                       buffer = "";
+                       buffer.clear();
                }
 #endif
                if (writeops++ % 20)
@@ -1259,7 +1287,7 @@ void FileLogger::Close()
                fclose(log);
        }
 
-       buffer = "";
+       buffer.clear();
 }
 
 FileLogger::FileLogger(InspIRCd* Instance, FILE* logfile) : ServerInstance(Instance), log(logfile), writeops(0)
@@ -1268,7 +1296,7 @@ FileLogger::FileLogger(InspIRCd* Instance, FILE* logfile) : ServerInstance(Insta
        {
                irc::sockets::NonBlocking(fileno(log));
                this->SetFd(fileno(log));
-               buffer = "";
+               buffer.clear();
        }
 }