-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
+/* ---------------------------------------------------------------------
+ *
+ * +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
*
- * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- * E-mail:
- * <brain@chatspike.net>
- * <Craig@chatspike.net>
+ * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
+ * E-mail:
+ * <brain@chatspike.net>
+ * <Craig@chatspike.net>
*
- * Written by Craig Edwards, Craig McLure, and others.
- * This program is free but copyrighted software; see
- * the file COPYING for details.
+ * Written by Craig Edwards, Craig McLure, and others.
+ * This program is free but copyrighted software; you can redistribute
+ * it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2
+ * (two) ONLY.
*
- * ---------------------------------------------------
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * ---------------------------------------------------------------------
*/
-/* Now with added unF! ;) */
-
-using namespace std;
-
+#include <algorithm>
#include "inspircd_config.h"
#include "inspircd.h"
-#include "inspircd_io.h"
+#include "configreader.h"
#include <fcntl.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
+#include <signal.h>
#include <time.h>
#include <string>
#include <exception>
#include <stdexcept>
#include <new>
-#ifdef GCC3
-#include <ext/hash_map>
-#else
-#include <hash_map>
-#endif
#include <map>
#include <sstream>
+#include <fstream>
#include <vector>
#include <deque>
#ifdef THREADED_DNS
#include "helperfuncs.h"
#include "hashcomp.h"
#include "socketengine.h"
+#include "inspircd_se_config.h"
#include "userprocess.h"
#include "socket.h"
#include "typedefs.h"
InspIRCd* ServerInstance;
-int WHOWAS_STALE = 48; // default WHOWAS Entries last 2 days before they go 'stale'
-int WHOWAS_MAX = 100; // default 100 people maximum in the WHOWAS list
-
-extern std::vector<Module*> modules;
-extern std::vector<ircd_module*> factory;
+extern ModuleList modules;
+extern FactoryList factory;
std::vector<InspSocket*> module_sockets;
std::vector<userrec*> local_users;
extern int MODCOUNT;
extern char LOG_FILE[MAXBUF];
-int openSockfd[MAX_DESCRIPTORS];
-int yield_depth;
+
int iterations = 0;
-sockaddr_in client,server;
+
+insp_sockaddr client, server;
socklen_t length;
extern InspSocket* socket_ref[MAX_DESCRIPTORS];
-
time_t TIME = time(NULL), OLDTIME = time(NULL);
// This table references users by file descriptor.
// its an array to make it VERY fast, as all lookups are referenced
// by an integer, meaning there is no need for a scan/search operation.
userrec* fd_ref_table[MAX_DESCRIPTORS];
-
Server* MyServer = new Server;
ServerConfig *Config = new ServerConfig;
-
user_hash clientlist;
chan_hash chanlist;
-
servernamelist servernames;
char lowermap[255];
-void AddServerName(std::string servername)
+void AddServerName(const std::string &servername)
{
log(DEBUG,"Adding server name: %s",servername.c_str());
- for (servernamelist::iterator a = servernames.begin(); a < servernames.end(); a++)
- {
- if (*a == servername)
- return;
+
+ if(find(servernames.begin(), servernames.end(), servername) == servernames.end())
+ servernames.push_back(servername); /* Wasn't already there. */
+}
+
+const char* FindServerNamePtr(const std::string &servername)
+{
+ servernamelist::iterator iter = find(servernames.begin(), servernames.end(), servername);
+
+ if(iter == servernames.end())
+ {
+ AddServerName(servername);
+ iter = --servernames.end();
}
- servernames.push_back(servername);
+
+ return iter->c_str();
+}
+
+bool FindServerName(const std::string &servername)
+{
+ return (find(servernames.begin(), servernames.end(), servername) != servernames.end());
}
-const char* FindServerNamePtr(std::string servername)
+void Exit(int status)
{
- for (servernamelist::iterator a = servernames.begin(); a < servernames.end(); a++)
+ if (Config->log_file)
+ fclose(Config->log_file);
+ send_error("Server shutdown.");
+ exit (status);
+}
+
+void InspIRCd::Start()
+{
+ 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:\t\t\033[1;32mBrain, FrostyCoolSlug, w00t, Om, Special\033[0m\n");
+ printf("Others:\t\t\t\033[1;32mSee /INFO Output\033[0m\n");
+ printf("Name concept:\t\t\033[1;32mLord_Zathras\033[0m\n\n");
+}
+
+void Killed(int status)
+{
+ if (Config->log_file)
+ fclose(Config->log_file);
+ send_error("Server terminated.");
+ exit(status);
+}
+
+void Rehash(int status)
+{
+ WriteOpers("Rehashing config file %s due to SIGHUP",CleanFilename(CONFIG_FILE));
+ fclose(Config->log_file);
+ OpenLog(NULL,0);
+ Config->Read(false,NULL);
+ FOREACH_MOD(I_OnRehash,OnRehash(""));
+}
+
+void InspIRCd::SetSignals()
+{
+ signal (SIGALRM, SIG_IGN);
+ signal (SIGHUP, Rehash);
+ signal (SIGPIPE, SIG_IGN);
+ signal (SIGTERM, Exit);
+ signal (SIGSEGV, Error);
+}
+
+bool InspIRCd::DaemonSeed()
+{
+ int childpid;
+ if ((childpid = fork ()) < 0)
+ return (ERROR);
+ else if (childpid > 0)
+ {
+ /* We wait a few seconds here, so that the shell prompt doesnt come back over the output */
+ sleep(6);
+ exit (0);
+ }
+ setsid ();
+ umask (007);
+ printf("InspIRCd Process ID: \033[1;32m%lu\033[0m\n",(unsigned long)getpid());
+
+ rlimit rl;
+ if (getrlimit(RLIMIT_CORE, &rl) == -1)
+ {
+ log(DEFAULT,"Failed to getrlimit()!");
+ return false;
+ }
+ else
{
- if (*a == servername)
- return a->c_str();
+ rl.rlim_cur = rl.rlim_max;
+ if (setrlimit(RLIMIT_CORE, &rl) == -1)
+ log(DEFAULT,"setrlimit() failed, cannot increase coredump size.");
}
- AddServerName(servername);
- return FindServerNamePtr(servername);
+
+ return true;
}
-bool FindServerName(std::string servername)
+void InspIRCd::WritePID(const std::string &filename)
{
- for (servernamelist::iterator a = servernames.begin(); a < servernames.end(); a++)
+ std::ofstream outfile(filename.c_str());
+ if (outfile.is_open())
{
- if (*a == servername)
- return true;
+ 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);
}
- return false;
}
std::string InspIRCd::GetRevision()
InspIRCd::InspIRCd(int argc, char** argv)
{
- Start();
+ this->Start();
module_sockets.clear();
+ init_dns();
this->startup_time = time(NULL);
srand(time(NULL));
log(DEBUG,"*** InspIRCd starting up!");
OpenLog(argv, argc);
this->stats = new serverstats();
+ this->Parser = new CommandParser();
Config->ClearStack();
Config->Read(true,NULL);
CheckRoot();
this->ModeGrok = new ModeParser();
- this->Parser = new CommandParser();
AddServerName(Config->ServerName);
CheckDie();
+ InitializeDisabledCommands(Config->DisabledCommands, this);
stats->BoundPortCount = BindPorts(true);
for(int t = 0; t < 255; t++)
memset(&Config->implement_lists,0,sizeof(Config->implement_lists));
printf("\n");
- SetSignals();
+ this->SetSignals();
if (!Config->nofork)
{
- if (!DaemonSeed())
+ if (!this->DaemonSeed())
{
printf("ERROR: could not go into daemon mode. Shutting down.\n");
Exit(ERROR);
/* Because of limitations in kqueue on freebsd, we must fork BEFORE we
* initialize the socket engine.
*/
- SE = new SocketEngine();
+ SocketEngineFactory* SEF = new SocketEngineFactory();
+ SE = SEF->Create();
+ delete SEF;
/* We must load the modules AFTER initializing the socket engine, now */
return MODERR;
}
-void InspIRCd::erase_factory(int j)
+void InspIRCd::EraseFactory(int j)
{
int v = 0;
for (std::vector<ircd_module*>::iterator t = factory.begin(); t != factory.end(); t++)
}
}
-void InspIRCd::erase_module(int j)
+void InspIRCd::EraseModule(int j)
{
int v1 = 0;
for (std::vector<Module*>::iterator m = modules.begin(); m!= modules.end(); m++)
{
if (v1 == j)
{
- delete *m;
+ DELETE(*m);
modules.erase(m);
modules.push_back(NULL);
break;
// found the module
log(DEBUG,"Deleting module...");
- erase_module(j);
+ this->EraseModule(j);
log(DEBUG,"Erasing module entry...");
- erase_factory(j);
+ this->EraseFactory(j);
log(DEBUG,"Removing dependent commands...");
Parser->RemoveCommands(filename);
log(DEFAULT,"Module %s unloaded",filename);
InspSocket* s = NULL;
InspSocket* s_del = NULL;
unsigned int numberactive;
- sockaddr_in sock_us; // our port number
+ insp_sockaddr sock_us; // our port number
socklen_t uslen; // length of our port number
- if (yield_depth > 100)
- return;
-
- yield_depth++;
-
/* time() seems to be a pretty expensive syscall, so avoid calling it too much.
* Once per loop iteration is pleanty.
*/
}
TickMissedTimers(TIME);
expire_run = true;
- yield_depth--;
return;
}
else if ((TIME % 5) == 1)
* servers... so its nice and easy, just one call.
*/
if (!(numberactive = SE->Wait(activefds)))
- {
- yield_depth--;
return;
- }
/**
* Now process each of the fd's. For users, we have a fast
if ((s) && (!s->Poll()))
{
- log(DEBUG,"inspircd.cpp: Socket poll returned false, close and bail");
+ log(DEBUG,"Socket poll returned false, close and bail");
SE->DelFd(s->GetFd());
socket_ref[activefds[activefd]] = NULL;
for (std::vector<InspSocket*>::iterator a = module_sockets.begin(); a < module_sockets.end(); a++)
{
- s_del = (InspSocket*)*a;
+ s_del = *a;
if ((s_del) && (s_del->GetFd() == activefds[activefd]))
{
module_sockets.erase(a);
}
}
s->Close();
- delete s;
+ DELETE(s);
}
else if (!s)
{
#endif
break;
+ case X_ESTAB_CLASSDNS:
+ /* Handles instances of the Resolver class,
+ * a simple class extended by modules for
+ * nonblocking resolving of addresses.
+ */
+
+ dns_deal_with_classes(activefds[activefd]);
+ break;
+
case X_LISTEN:
log(DEBUG,"Type: X_LISTEN_MODULE: fd=%d",activefds[activefd]);
{
try
{
- Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, (char*)inet_ntoa(client.sin_addr), in_port);
+ Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, inet_ntoa(client.sin_addr), in_port);
}
catch (ModuleException& modexcept)
{
break;
}
}
- yield_depth--;
}
int InspIRCd::Run()
/* Add the listening sockets used for client inbound connections
* to the socket engine
*/
- for (int count = 0; count < stats->BoundPortCount; count++)
- SE->AddFd(openSockfd[count],true,X_LISTEN);
+ for (unsigned long count = 0; count < stats->BoundPortCount; count++)
+ SE->AddFd(Config->openSockfd[count],true,X_LISTEN);
- WritePID(Config->PID);
+ this->WritePID(Config->PID);
/* main loop, this never returns */
expire_run = false;
- yield_depth = 0;
iterations = 0;
while (true)
int main(int argc, char** argv)
{
+ /* TEST SUITE FOR TOKENSTREAM
+ *
+ * Expected output:
+ *
+ * String: 'PRIVMSG #test FOO BAR'
+ * Token 0 = 'PRIVMSG'
+ * Token 1 = '#test'
+ * Token 2 = 'FOO'
+ * Token 3 = 'BAR'
+ * String: 'PRIVMSG #test :FOO BAR BAZ'
+ * Token 0 = 'PRIVMSG'
+ * Token 1 = '#test'
+ * Token 2 = 'FOO BAR BAZ'
+ * String: ':PRIVMSG #test :FOO BAR BAZ'
+ * Token 0 = ':PRIVMSG'
+ * String: 'AAAAAAA'
+ * Token 0 = 'AAAAAAA'
+ * String: ''
+ * NumItems = 0
+ *
+ std::string a = "PRIVMSG #test FOO BAR";
+ printf("String: '%s'\n",a.c_str());
+ irc::tokenstream test(a);
+ printf("Token 0 = '%s'\n",test.GetToken().c_str());
+ printf("Token 1 = '%s'\n",test.GetToken().c_str());
+ printf("Token 2 = '%s'\n",test.GetToken().c_str());
+ printf("Token 3 = '%s'\n",test.GetToken().c_str());
+ printf("Token 4 = '%s'\n",test.GetToken().c_str());
+
+ std::string b = "PRIVMSG #test :FOO BAR BAZ";
+ printf("String: '%s'\n",b.c_str());
+ irc::tokenstream test2(b);
+ printf("Token 0 = '%s'\n",test2.GetToken().c_str());
+ printf("Token 1 = '%s'\n",test2.GetToken().c_str());
+ printf("Token 2 = '%s'\n",test2.GetToken().c_str());
+ printf("Token 3 = '%s'\n",test2.GetToken().c_str());
+
+ std::string c = ":PRIVMSG #test :FOO BAR BAZ";
+ printf("String: '%s'\n",c.c_str());
+ irc::tokenstream test3(c);
+ printf("Token 0 = '%s'\n",test3.GetToken().c_str());
+
+ c = "AAAAAAA";
+ printf("String: '%s'\n",c.c_str());
+ irc::tokenstream test4(c);
+ printf("Token 0 = '%s'\n",test4.GetToken().c_str());
+ printf("Token 1 = '%s'\n",test4.GetToken().c_str());
+
+ c = "";
+ printf("String: '%s'\n",c.c_str());
+ irc::tokenstream test5(c);
+ printf("Token 0 = '%s'\n",test5.GetToken().c_str());
+
+ exit(0);
+ */
try
{
ServerInstance = new InspIRCd(argc, argv);
ServerInstance->Run();
- delete ServerInstance;
+ DELETE(ServerInstance);
}
catch (std::bad_alloc)
{