#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;
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;
// Fill in the startup info struct
GetStartupInfo(&startupinfo);
- // Create the "startup" event
- HANDLE fork_event = CreateEvent(0, TRUE, FALSE, "InspStartup");
- if(!fork_event)
- 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);
DWORD ExitCode = 14;
GetExitCodeProcess(procinfo.hProcess, &ExitCode);
CloseHandle(procinfo.hThread);
+ CloseHandle(procinfo.hProcess);
return ExitCode;
}
{
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, owner_processid);
if(!hProcess || !owner_processid)
+ {
+ printf("Could not open process id %u: %s.\n", owner_processid, dlerror());
Instance->Exit(14);
+ }
// die die die
if(!TerminateProcess(hProcess, 0))
+ {
+ printf("Could not TerminateProcess(): %s\n", dlerror());
Instance->Exit(14);
+ }
CloseHandle(hProcess);
}
"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 */
"Refusing to start up as root", /* 11 */
"Found a <die> tag!", /* 12 */
"Couldn't load module on startup", /* 13 */
- "Could not create forked process", /* 14 */
+ "Could not create windows forked process", /* 14 */
"Received SIGTERM", /* 15 */
};
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 }
};
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 */
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())
{
}
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;
{
int written = fprintf(log,"%s",buffer.c_str());
#ifdef WINDOWS
- buffer = "";
+ buffer.clear();
#else
if ((written >= 0) && (written < (int)buffer.length()))
{
else
{
/* Wrote the whole buffer, and no need for write callback */
- buffer = "";
+ buffer.clear();
}
#endif
if (writeops++ % 20)
fclose(log);
}
- buffer = "";
+ buffer.clear();
}
FileLogger::FileLogger(InspIRCd* Instance, FILE* logfile) : ServerInstance(Instance), log(logfile), writeops(0)
{
irc::sockets::NonBlocking(fileno(log));
this->SetFd(fileno(log));
- buffer = "";
+ buffer.clear();
}
}