1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
18 #include "inspircd_config.h"
19 #include "configreader.h"
22 #include <sys/errno.h>
30 #include "connection.h"
40 #include "inspstring.h"
41 #include "helperfuncs.h"
46 static char TIMESTR[26];
47 static time_t LAST = 0;
50 * Write a line of text `text' to the logfile (and stdout, if in nofork) if the level `level'
51 * is greater than the configured loglevel.
53 void InspIRCd::Log(int level, const char* text, ...)
56 char textbuffer[MAXBUF];
58 va_start(argsPtr, text);
59 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
62 InspIRCd::Log(level, std::string(textbuffer));
65 void InspIRCd::Log(int level, const std::string &text)
67 extern InspIRCd* ServerInstance;
69 if (!ServerInstance || !ServerInstance->Config)
72 /* If we were given -debug we output all messages, regardless of configured loglevel */
73 if ((level < ServerInstance->Config->LogLevel) && !ServerInstance->Config->forcedebug)
76 if (ServerInstance->Time() != LAST)
78 time_t local = ServerInstance->Time();
79 struct tm *timeinfo = localtime(&local);
81 strlcpy(TIMESTR,asctime(timeinfo),26);
83 LAST = ServerInstance->Time();
86 if (ServerInstance->Config->log_file && ServerInstance->Config->writelog)
88 fprintf(ServerInstance->Config->log_file,"%s %s\n",TIMESTR,text.c_str());
89 fflush(ServerInstance->Config->log_file);
92 if (ServerInstance->Config->nofork)
94 printf("%s %s\n", TIMESTR, text.c_str());
98 std::string InspIRCd::GetServerDescription(const char* servername)
100 std::string description = "";
102 FOREACH_MOD_I(this,I_OnGetServerDescription,OnGetServerDescription(servername,description));
104 if (description != "")
110 // not a remote server that can be found, it must be me.
111 return Config->ServerDesc;
115 /* XXX - We don't use WriteMode for this because WriteMode is very slow and
116 * this isnt. Basically WriteMode has to iterate ALL the users 'n' times for
117 * the number of modes provided, e.g. if you send WriteMode 'og' to write to
118 * opers with globops, and you have 2000 users, thats 4000 iterations. WriteOpers
119 * uses the oper list, which means if you have 2000 users but only 5 opers,
120 * it iterates 5 times.
122 void InspIRCd::WriteOpers(const char* text, ...)
124 char textbuffer[MAXBUF];
127 va_start(argsPtr, text);
128 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
131 this->WriteOpers(std::string(textbuffer));
134 void InspIRCd::WriteOpers(const std::string &text)
136 for (std::vector<userrec*>::iterator i = this->all_opers.begin(); i != this->all_opers.end(); i++)
139 if (IS_LOCAL(a) && a->modes[UM_SERVERNOTICE])
141 // send server notices to all with +s
142 a->WriteServ("NOTICE %s :%s",a->nick,text.c_str());
147 void InspIRCd::ServerNoticeAll(char* text, ...)
152 char textbuffer[MAXBUF];
153 char formatbuffer[MAXBUF];
155 va_start (argsPtr, text);
156 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
159 snprintf(formatbuffer,MAXBUF,"NOTICE $%s :%s",Config->ServerName,textbuffer);
161 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
164 t->WriteServ(std::string(formatbuffer));
168 void InspIRCd::ServerPrivmsgAll(char* text, ...)
173 char textbuffer[MAXBUF];
174 char formatbuffer[MAXBUF];
176 va_start (argsPtr, text);
177 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
180 snprintf(formatbuffer,MAXBUF,"PRIVMSG $%s :%s",Config->ServerName,textbuffer);
182 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
185 t->WriteServ(std::string(formatbuffer));
189 void InspIRCd::WriteMode(const char* modes, int flags, const char* text, ...)
191 char textbuffer[MAXBUF];
195 if ((!text) || (!modes) || (!flags))
197 log(DEFAULT,"*** BUG *** WriteMode was given an invalid parameter");
201 va_start(argsPtr, text);
202 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
204 modelen = strlen(modes);
206 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
208 userrec* t = (userrec*)(*i);
209 bool send_to_user = false;
215 for (int n = 0; n < modelen; n++)
217 if (!t->modes[modes[n]-65])
219 send_to_user = false;
224 else if (flags == WM_OR)
226 send_to_user = false;
228 for (int n = 0; n < modelen; n++)
230 if (t->modes[modes[n]-65])
240 t->WriteServ("NOTICE %s :%s",t->nick,textbuffer);
245 /* Find a user record by nickname and return a pointer to it */
247 userrec* InspIRCd::FindNick(const std::string &nick)
249 user_hash::iterator iter = clientlist.find(nick);
251 if (iter == clientlist.end())
252 /* Couldn't find it */
258 userrec* InspIRCd::FindNick(const char* nick)
260 user_hash::iterator iter;
265 iter = clientlist.find(nick);
267 if (iter == clientlist.end())
273 /* find a channel record by channel name and return a pointer to it */
275 chanrec* InspIRCd::FindChan(const char* chan)
277 chan_hash::iterator iter;
282 iter = chanlist.find(chan);
284 if (iter == chanlist.end())
285 /* Couldn't find it */
291 chanrec* InspIRCd::FindChan(const std::string &chan)
293 chan_hash::iterator iter = chanlist.find(chan);
295 if (iter == chanlist.end())
296 /* Couldn't find it */
304 * sends out an error notice to all connected clients (not to be used
307 void InspIRCd::SendError(const char *s)
309 for (std::vector<userrec*>::const_iterator i = this->local_users.begin(); i != this->local_users.end(); i++)
311 userrec* t = (userrec*)(*i);
312 if (t->registered == REG_ALL)
314 t->WriteServ("NOTICE %s :%s",t->nick,s);
318 // fix - unregistered connections receive ERROR, not NOTICE
319 t->Write("ERROR :%s",s);
324 void InspIRCd::Error(int status)
330 signal(SIGALRM, SIG_IGN);
331 signal(SIGPIPE, SIG_IGN);
332 signal(SIGTERM, SIG_IGN);
333 signal(SIGABRT, SIG_IGN);
334 signal(SIGSEGV, SIG_IGN);
335 signal(SIGURG, SIG_IGN);
336 signal(SIGKILL, SIG_IGN);
337 log(DEFAULT,"*** fell down a pothole in the road to perfection ***");
339 log(DEFAULT,"Please report the backtrace lines shown below with any bugreport to the bugtracker at http://www.inspircd.org/bugtrack/");
340 size = backtrace(array, 30);
341 strings = backtrace_symbols(array, size);
342 for (size_t i = 0; i < size; i++) {
343 log(DEFAULT,"[%d] %s", i, strings[i]);
347 log(DEFAULT,"You do not have execinfo.h so i could not backtrace -- on FreeBSD, please install the libexecinfo port.");
349 signal(SIGSEGV, SIG_DFL);
350 if (raise(SIGSEGV) == -1)
352 log(DEFAULT,"What the hell, i couldnt re-raise SIGSEGV! Error: %s",strerror(errno));
357 // this function counts all users connected, wether they are registered or NOT.
358 int InspIRCd::usercnt()
360 return clientlist.size();
363 // this counts only registered users, so that the percentages in /MAP don't mess up when users are sitting in an unregistered state
364 int InspIRCd::registered_usercount()
368 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
370 c += (i->second->registered == REG_ALL);
376 int InspIRCd::usercount_invisible()
380 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
382 c += ((i->second->registered == REG_ALL) && (i->second->modes[UM_INVISIBLE]));
388 int InspIRCd::usercount_opers()
392 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
394 if (*(i->second->oper))
400 int InspIRCd::usercount_unknown()
404 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
406 userrec* t = (userrec*)(*i);
407 if (t->registered != REG_ALL)
414 long InspIRCd::chancount()
416 return chanlist.size();
419 long InspIRCd::local_count()
423 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
425 userrec* t = (userrec*)(*i);
426 if (t->registered == REG_ALL)
433 bool InspIRCd::IsChannel(const char *chname)
437 /* check for no name - don't check for !*chname, as if it is empty, it won't be '#'! */
438 if (!chname || *chname != '#')
443 c = (char *)chname + 1;
457 /* too long a name - note funky pointer arithmetic here. */
458 if ((c - chname) > CHANMAX)
466 void InspIRCd::OpenLog(char** argv, int argc)
468 if (!*this->LogFileName)
470 if (Config->logpath == "")
472 Config->logpath = ServerConfig::GetFullProgDir(argv,argc) + "/ircd.log";
477 Config->log_file = fopen(this->LogFileName,"a+");
479 if (!Config->log_file)
481 printf("ERROR: Could not write to logfile %s, bailing!\n\n",Config->logpath.c_str());
487 Config->log_file = fopen(Config->logpath.c_str(),"a+");
489 if (!Config->log_file)
491 printf("ERROR: Could not write to logfile %s, bailing!\n\n",Config->logpath.c_str());
496 void InspIRCd::CheckRoot()
500 printf("WARNING!!! You are running an irc server as ROOT!!! DO NOT DO THIS!!!\n\n");
501 log(DEFAULT,"InspIRCd: startup: not starting with UID 0!");
506 void InspIRCd::CheckDie()
508 if (*Config->DieValue)
510 printf("WARNING: %s\n\n",Config->DieValue);
511 log(DEFAULT,"Uh-Oh, somebody didn't read their config file: '%s'",Config->DieValue);
516 /* We must load the modules AFTER initializing the socket engine, now */
517 void InspIRCd::LoadAllModules()
519 char configToken[MAXBUF];
520 Config->module_names.clear();
523 for (int count = 0; count < Config->ConfValueEnum(Config->config_data, "module"); count++)
525 Config->ConfValue(Config->config_data, "module","name",count,configToken,MAXBUF);
526 printf("[\033[1;32m*\033[0m] Loading module:\t\033[1;32m%s\033[0m\n",configToken);
528 if (!this->LoadModule(configToken))
530 log(DEFAULT,"Exiting due to a module loader error.");
531 printf("\nThere was an error loading a module: %s\n\n",this->ModuleError());
535 printf("\nA total of \033[1;32m%d\033[0m module%s been loaded.\n", this->ModCount+1, this->ModCount+1 == 1 ? " has" : "s have");
536 log(DEFAULT,"Total loaded modules: %d", this->ModCount+1);