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 "configreader.h"
26 static char TIMESTR[26];
27 static time_t LAST = 0;
30 * Write a line of text `text' to the logfile (and stdout, if in nofork) if the level `level'
31 * is greater than the configured loglevel.
33 void InspIRCd::Log(int level, const char* text, ...)
36 char textbuffer[MAXBUF];
38 va_start(argsPtr, text);
39 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
42 this->Log(level, std::string(textbuffer));
45 void InspIRCd::Log(int level, const std::string &text)
50 /* If we were given -debug we output all messages, regardless of configured loglevel */
51 if ((level < Config->LogLevel) && !Config->forcedebug)
56 time_t local = Time();
57 struct tm *timeinfo = localtime(&local);
59 strlcpy(TIMESTR,asctime(timeinfo),26);
64 if (Config->log_file && Config->writelog)
66 std::string out = std::string(TIMESTR) + " " + text.c_str() + "\n";
67 this->Logger->WriteLogLine(out);
72 printf("%s %s\n", TIMESTR, text.c_str());
76 std::string InspIRCd::GetServerDescription(const char* servername)
78 std::string description = "";
80 FOREACH_MOD_I(this,I_OnGetServerDescription,OnGetServerDescription(servername,description));
82 if (description != "")
88 // not a remote server that can be found, it must be me.
89 return Config->ServerDesc;
93 /* XXX - We don't use WriteMode for this because WriteMode is very slow and
94 * this isnt. Basically WriteMode has to iterate ALL the users 'n' times for
95 * the number of modes provided, e.g. if you send WriteMode 'og' to write to
96 * opers with globops, and you have 2000 users, thats 4000 iterations. WriteOpers
97 * uses the oper list, which means if you have 2000 users but only 5 opers,
98 * it iterates 5 times.
100 void InspIRCd::WriteOpers(const char* text, ...)
102 char textbuffer[MAXBUF];
105 va_start(argsPtr, text);
106 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
109 this->WriteOpers(std::string(textbuffer));
112 void InspIRCd::WriteOpers(const std::string &text)
114 for (std::vector<userrec*>::iterator i = this->all_opers.begin(); i != this->all_opers.end(); i++)
117 if (IS_LOCAL(a) && a->modes[UM_SERVERNOTICE])
119 // send server notices to all with +s
120 a->WriteServ("NOTICE %s :%s",a->nick,text.c_str());
125 void InspIRCd::ServerNoticeAll(char* text, ...)
130 char textbuffer[MAXBUF];
131 char formatbuffer[MAXBUF];
133 va_start (argsPtr, text);
134 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
137 snprintf(formatbuffer,MAXBUF,"NOTICE $%s :%s",Config->ServerName,textbuffer);
139 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
142 t->WriteServ(std::string(formatbuffer));
146 void InspIRCd::ServerPrivmsgAll(char* text, ...)
151 char textbuffer[MAXBUF];
152 char formatbuffer[MAXBUF];
154 va_start (argsPtr, text);
155 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
158 snprintf(formatbuffer,MAXBUF,"PRIVMSG $%s :%s",Config->ServerName,textbuffer);
160 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
163 t->WriteServ(std::string(formatbuffer));
167 void InspIRCd::WriteMode(const char* modes, int flags, const char* text, ...)
169 char textbuffer[MAXBUF];
173 if ((!text) || (!modes) || (!flags))
175 this->Log(DEFAULT,"*** BUG *** WriteMode was given an invalid parameter");
179 va_start(argsPtr, text);
180 vsnprintf(textbuffer, MAXBUF, text, argsPtr);
182 modelen = strlen(modes);
184 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
186 userrec* t = (userrec*)(*i);
187 bool send_to_user = false;
193 for (int n = 0; n < modelen; n++)
195 if (!t->modes[modes[n]-65])
197 send_to_user = false;
202 else if (flags == WM_OR)
204 send_to_user = false;
206 for (int n = 0; n < modelen; n++)
208 if (t->modes[modes[n]-65])
218 t->WriteServ("NOTICE %s :%s",t->nick,textbuffer);
223 /* Find a user record by nickname and return a pointer to it */
225 userrec* InspIRCd::FindNick(const std::string &nick)
227 user_hash::iterator iter = clientlist.find(nick);
229 if (iter == clientlist.end())
230 /* Couldn't find it */
236 userrec* InspIRCd::FindNick(const char* nick)
238 user_hash::iterator iter;
243 iter = clientlist.find(nick);
245 if (iter == clientlist.end())
251 /* find a channel record by channel name and return a pointer to it */
253 chanrec* InspIRCd::FindChan(const char* chan)
255 chan_hash::iterator iter;
260 iter = chanlist.find(chan);
262 if (iter == chanlist.end())
263 /* Couldn't find it */
269 chanrec* InspIRCd::FindChan(const std::string &chan)
271 chan_hash::iterator iter = chanlist.find(chan);
273 if (iter == chanlist.end())
274 /* Couldn't find it */
282 * sends out an error notice to all connected clients (not to be used
285 void InspIRCd::SendError(const char *s)
287 for (std::vector<userrec*>::const_iterator i = this->local_users.begin(); i != this->local_users.end(); i++)
289 userrec* t = (userrec*)(*i);
290 if (t->registered == REG_ALL)
292 t->WriteServ("NOTICE %s :%s",t->nick,s);
296 // fix - unregistered connections receive ERROR, not NOTICE
297 t->Write("ERROR :%s",s);
302 // this function counts all users connected, wether they are registered or NOT.
303 int InspIRCd::UserCount()
305 return clientlist.size();
308 // this counts only registered users, so that the percentages in /MAP don't mess up when users are sitting in an unregistered state
309 int InspIRCd::RegisteredUserCount()
313 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
315 c += (i->second->registered == REG_ALL);
321 int InspIRCd::InvisibleUserCount()
325 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
327 c += ((i->second->registered == REG_ALL) && (i->second->modes[UM_INVISIBLE]));
333 int InspIRCd::OperCount()
337 for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
339 if (*(i->second->oper))
345 int InspIRCd::UnregisteredUserCount()
349 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
351 userrec* t = (userrec*)(*i);
352 if (t->registered != REG_ALL)
359 long InspIRCd::ChannelCount()
361 return chanlist.size();
364 long InspIRCd::LocalUserCount()
368 for (std::vector<userrec*>::const_iterator i = local_users.begin(); i != local_users.end(); i++)
370 userrec* t = (userrec*)(*i);
371 if (t->registered == REG_ALL)
378 bool InspIRCd::IsChannel(const char *chname)
382 /* check for no name - don't check for !*chname, as if it is empty, it won't be '#'! */
383 if (!chname || *chname != '#')
388 c = (char *)chname + 1;
402 /* too long a name - note funky pointer arithmetic here. */
403 if ((c - chname) > CHANMAX)
411 bool InspIRCd::IsNick(const char* n)
417 for (char* i = (char*)n; *i; i++, p++)
419 if ((*i >= 'A') && (*i <= '}'))
421 /* "A"-"}" can occur anywhere in a nickname */
425 if ((((*i >= '0') && (*i <= '9')) || (*i == '-')) && (i > n))
427 /* "0"-"9", "-" can occur anywhere BUT the first char of a nickname */
431 /* invalid character! abort */
435 /* too long? or not -- pointer arithmetic rocks */
436 return (p < NICKMAX - 1);
439 void InspIRCd::OpenLog(char** argv, int argc)
441 if (!*this->LogFileName)
443 if (Config->logpath == "")
445 Config->logpath = ServerConfig::GetFullProgDir(argv,argc) + "/ircd.log";
450 Config->log_file = fopen(this->LogFileName,"a+");
452 if (!Config->log_file)
454 printf("ERROR: Could not write to logfile %s, bailing!\n\n",Config->logpath.c_str());
458 this->Logger = new FileLogger(this, Config->log_file);
462 Config->log_file = fopen(Config->logpath.c_str(),"a+");
464 if (!Config->log_file)
466 printf("ERROR: Could not write to logfile %s, bailing!\n\n",Config->logpath.c_str());
470 this->Logger = new FileLogger(this, Config->log_file);
473 void InspIRCd::CheckRoot()
477 printf("WARNING!!! You are running an irc server as ROOT!!! DO NOT DO THIS!!!\n\n");
478 this->Log(DEFAULT,"Cant start as root");
483 void InspIRCd::CheckDie()
485 if (*Config->DieValue)
487 printf("WARNING: %s\n\n",Config->DieValue);
488 this->Log(DEFAULT,"Died because of <die> tag: %s",Config->DieValue);
493 /* We must load the modules AFTER initializing the socket engine, now */
494 void InspIRCd::LoadAllModules()
496 char configToken[MAXBUF];
497 Config->module_names.clear();
500 for (int count = 0; count < Config->ConfValueEnum(Config->config_data, "module"); count++)
502 Config->ConfValue(Config->config_data, "module","name",count,configToken,MAXBUF);
503 printf("[\033[1;32m*\033[0m] Loading module:\t\033[1;32m%s\033[0m\n",configToken);
505 if (!this->LoadModule(configToken))
507 this->Log(DEFAULT,"There was an error loading a module: %s", this->ModuleError());
508 printf("\nThere was an error loading a module: %s\n\n",this->ModuleError());
512 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");
513 this->Log(DEFAULT,"Total loaded modules: %d", this->ModCount+1);