00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "inspircd.h"
00017
00018 #include "filelogger.h"
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 void LogManager::SetupNoFork()
00048 {
00049 if (!noforkstream)
00050 {
00051 FileWriter* fw = new FileWriter(ServerInstance, stdout);
00052 noforkstream = new FileLogStream(ServerInstance, ServerInstance->Config->forcedebug ? DEBUG : DEFAULT, fw);
00053 }
00054 else
00055 {
00056 noforkstream->ChangeLevel(ServerInstance->Config->forcedebug ? DEBUG : DEFAULT);
00057 }
00058 AddLogType("*", noforkstream, false);
00059 }
00060
00061 void LogManager::OpenFileLogs()
00062 {
00063
00064 if (ServerInstance->Config->nofork)
00065 {
00066 SetupNoFork();
00067 }
00068
00069 if (!ServerInstance->Config->writelog)
00070 {
00071 return;
00072 }
00073 ConfigReader* Conf = new ConfigReader(ServerInstance);
00074 std::map<std::string, FileWriter*> logmap;
00075 std::map<std::string, FileWriter*>::iterator i;
00076 for (int index = 0; index < Conf->Enumerate("log"); ++index)
00077 {
00078 std::string method = Conf->ReadValue("log", "method", index);
00079 if (method != "file")
00080 {
00081 continue;
00082 }
00083 std::string type = Conf->ReadValue("log", "type", index);
00084 std::string level = Conf->ReadValue("log", "level", index);
00085 int loglevel = DEFAULT;
00086 if (level == "debug" || ServerInstance->Config->forcedebug)
00087 {
00088 loglevel = DEBUG;
00089 ServerInstance->Config->debugging = true;
00090 }
00091 else if (level == "verbose")
00092 {
00093 loglevel = VERBOSE;
00094 }
00095 else if (level == "default")
00096 {
00097 loglevel = DEFAULT;
00098 }
00099 else if (level == "sparse")
00100 {
00101 loglevel = SPARSE;
00102 }
00103 else if (level == "none")
00104 {
00105 loglevel = NONE;
00106 }
00107 FileWriter* fw;
00108 std::string target = Conf->ReadValue("log", "target", index);
00109 if ((i = logmap.find(target)) == logmap.end())
00110 {
00111 FILE* f = fopen(target.c_str(), "a");
00112 fw = new FileWriter(ServerInstance, f);
00113 logmap.insert(std::make_pair(target, fw));
00114 }
00115 else
00116 {
00117 fw = i->second;
00118 }
00119 FileLogStream* fls = new FileLogStream(ServerInstance, loglevel, fw);
00120 AddLogTypes(type, fls, true);
00121 }
00122 }
00123
00124 void LogManager::CloseLogs()
00125 {
00126 std::map<std::string, std::vector<LogStream*> >().swap(LogStreams);
00127 std::map<LogStream*, std::vector<std::string> >().swap(GlobalLogStreams);
00128 for (std::map<LogStream*, int>::iterator i = AllLogStreams.begin(); i != AllLogStreams.end(); ++i)
00129 {
00130 delete i->first;
00131 }
00132 std::map<LogStream*, int>().swap(AllLogStreams);
00133 }
00134
00135 void LogManager::AddLogTypes(const std::string &types, LogStream* l, bool autoclose)
00136 {
00137 irc::spacesepstream css(types);
00138 std::string tok;
00139 std::vector<std::string> excludes;
00140 while (css.GetToken(tok))
00141 {
00142 if (tok.empty())
00143 {
00144 continue;
00145 }
00146 if (tok.at(0) == '-')
00147 {
00148
00149 excludes.push_back(tok.substr(1));
00150 }
00151 else
00152 {
00153 AddLogType(tok, l, autoclose);
00154 }
00155 }
00156
00157
00158 for (std::vector<std::string>::iterator i = excludes.begin(); i != excludes.end(); ++i)
00159 {
00160 if (*i == "*")
00161 {
00162
00163 DelLogStream(l);
00164 return;
00165 }
00166 DelLogType(*i, l);
00167 }
00168
00169 std::map<LogStream *, std::vector<std::string> >::iterator gi = GlobalLogStreams.find(l);
00170 if (gi != GlobalLogStreams.end())
00171 {
00172 gi->second.swap(excludes);
00173 }
00174 }
00175
00176 bool LogManager::AddLogType(const std::string &type, LogStream *l, bool autoclose)
00177 {
00178 std::map<std::string, std::vector<LogStream *> >::iterator i = LogStreams.find(type);
00179
00180 if (i != LogStreams.end())
00181 {
00182 i->second.push_back(l);
00183 }
00184 else
00185 {
00186 std::vector<LogStream *> v;
00187 v.push_back(l);
00188 LogStreams[type] = v;
00189 }
00190
00191 if (type == "*")
00192 {
00193 GlobalLogStreams.insert(std::make_pair(l, std::vector<std::string>()));
00194 }
00195
00196 if (autoclose)
00197 {
00198 std::map<LogStream*, int>::iterator ai = AllLogStreams.find(l);
00199 if (ai == AllLogStreams.end())
00200 {
00201 AllLogStreams.insert(std::make_pair(l, 1));
00202 }
00203 else
00204 {
00205 ++ai->second;
00206 }
00207 }
00208
00209 return true;
00210 }
00211
00212 void LogManager::DelLogStream(LogStream* l)
00213 {
00214 for (std::map<std::string, std::vector<LogStream*> >::iterator i = LogStreams.begin(); i != LogStreams.end(); ++i)
00215 {
00216 std::vector<LogStream*>::iterator it;
00217 while ((it = std::find(i->second.begin(), i->second.end(), l)) != i->second.end())
00218 {
00219 if (it == i->second.end())
00220 continue;
00221 i->second.erase(it);
00222 }
00223 }
00224 std::map<LogStream *, std::vector<std::string> >::iterator gi = GlobalLogStreams.find(l);
00225 if (gi != GlobalLogStreams.end())
00226 {
00227 GlobalLogStreams.erase(gi);
00228 }
00229 std::map<LogStream*, int>::iterator ai = AllLogStreams.begin();
00230 if (ai == AllLogStreams.end())
00231 {
00232 return;
00233 }
00234 delete ai->first;
00235 AllLogStreams.erase(ai);
00236 }
00237
00238 bool LogManager::DelLogType(const std::string &type, LogStream *l)
00239 {
00240 std::map<std::string, std::vector<LogStream *> >::iterator i = LogStreams.find(type);
00241 if (type == "*")
00242 {
00243 std::map<LogStream *, std::vector<std::string> >::iterator gi = GlobalLogStreams.find(l);
00244 if (gi != GlobalLogStreams.end()) GlobalLogStreams.erase(gi);
00245 }
00246
00247 if (i != LogStreams.end())
00248 {
00249 std::vector<LogStream *>::iterator it = std::find(i->second.begin(), i->second.end(), l);
00250
00251 if (it != i->second.end())
00252 {
00253 i->second.erase(it);
00254 if (i->second.size() == 0)
00255 {
00256 LogStreams.erase(i);
00257 }
00258 }
00259 else
00260 {
00261 return false;
00262 }
00263 }
00264 else
00265 {
00266 return false;
00267 }
00268
00269 std::map<LogStream*, int>::iterator ai = AllLogStreams.find(l);
00270 if (ai == AllLogStreams.end())
00271 {
00272 return true;
00273 }
00274
00275 if ((--ai->second) < 1)
00276 {
00277 AllLogStreams.erase(ai);
00278 delete l;
00279 }
00280
00281 return true;
00282 }
00283
00284 void LogManager::Log(const std::string &type, int loglevel, const char *fmt, ...)
00285 {
00286 if (Logging)
00287 {
00288 return;
00289 }
00290
00291 va_list a;
00292 static char buf[65536];
00293
00294 va_start(a, fmt);
00295 vsnprintf(buf, 65536, fmt, a);
00296 va_end(a);
00297
00298 this->Log(type, loglevel, std::string(buf));
00299 }
00300
00301 void LogManager::Log(const std::string &type, int loglevel, const std::string &msg)
00302 {
00303 if (Logging)
00304 {
00305 return;
00306 }
00307
00308 Logging = true;
00309
00310 for (std::map<LogStream *, std::vector<std::string> >::iterator gi = GlobalLogStreams.begin(); gi != GlobalLogStreams.end(); ++gi)
00311 {
00312 if (std::find(gi->second.begin(), gi->second.end(), type) != gi->second.end())
00313 {
00314 continue;
00315 }
00316 gi->first->OnLog(loglevel, type, msg);
00317 }
00318
00319 std::map<std::string, std::vector<LogStream *> >::iterator i = LogStreams.find(type);
00320
00321 if (i != LogStreams.end())
00322 {
00323 for (std::vector<LogStream *>::iterator it = i->second.begin(); it != i->second.end(); ++it)
00324 {
00325 (*it)->OnLog(loglevel, type, msg);
00326 }
00327 }
00328
00329 Logging = false;
00330 }
00331
00332
00333 FileWriter::FileWriter(InspIRCd* Instance, FILE* logfile)
00334 : ServerInstance(Instance), log(logfile), writeops(0)
00335 {
00336 }
00337
00338 void FileWriter::HandleEvent(EventType ev, int)
00339 {
00340 }
00341
00342 void FileWriter::WriteLogLine(const std::string &line)
00343 {
00344 if (log)
00345 {
00346 fprintf(log,"%s",line.c_str());
00347 if (writeops++ % 20)
00348 {
00349 fflush(log);
00350 }
00351 }
00352 }
00353
00354 void FileWriter::Close()
00355 {
00356 if (log)
00357 {
00358 fflush(log);
00359 fclose(log);
00360 }
00361 }
00362
00363 FileWriter::~FileWriter()
00364 {
00365 }
00366