00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "wvlogrcv.h"
00010 #include "wvstringlist.h"
00011 #include "strutils.h"
00012 #include <ctype.h>
00013
00014 #ifdef _WIN32
00015 #include <io.h>
00016 #define snprintf _snprintf
00017 #endif
00018
00019 WvLogRcvBaseList WvLog::receivers;
00020 int WvLog::num_receivers = 0, WvLog::num_logs = 0;
00021 WvLogRcvBase *WvLog::default_receiver = NULL;
00022
00023 char *WvLogRcv::loglevels[WvLog::NUM_LOGLEVELS] = {
00024 "Crit",
00025 "Err",
00026 "Warn",
00027 "Notice",
00028 "Info",
00029 "*1",
00030 "*2",
00031 "*3",
00032 "*4",
00033 "*5",
00034 };
00035
00036
00037
00038
00039
00040
00041
00042 WvLog::WvLog(WvStringParm _app, LogLevel _loglevel, const WvLog *par)
00043 : app(_app)
00044 {
00045 parent = par;
00046 loglevel = _loglevel;
00047 num_logs++;
00048 }
00049
00050
00051 WvLog::WvLog(const WvLog &l)
00052 {
00053 parent = l.parent ? l.parent : &l;
00054 app = parent->app;
00055 loglevel = parent->loglevel;
00056 num_logs++;
00057 }
00058
00059
00060 WvLog::~WvLog()
00061 {
00062 num_logs--;
00063 if (!num_logs && default_receiver)
00064 {
00065 num_receivers++;
00066 delete default_receiver;
00067 default_receiver = NULL;
00068 }
00069 }
00070
00071
00072 bool WvLog::isok() const
00073 {
00074 return true;
00075 }
00076
00077
00078 bool WvLog::pre_select(SelectInfo &si)
00079 {
00080
00081 if (si.wants.writable)
00082 return true;
00083 else
00084 return WvStream::pre_select(si);
00085 }
00086
00087
00088 size_t WvLog::uwrite(const void *_buf, size_t len)
00089 {
00090 if (!num_receivers)
00091 {
00092 if (!default_receiver)
00093 {
00094
00095 default_receiver = new WvLogConsole(dup(2));
00096 num_receivers--;
00097 }
00098 default_receiver->log(parent ? parent : this, loglevel,
00099 (const char *)_buf, len);
00100 return len;
00101 }
00102 else if (default_receiver)
00103 {
00104
00105 num_receivers++;
00106 delete default_receiver;
00107 default_receiver = NULL;
00108 }
00109
00110 WvLogRcvBaseList::Iter i(receivers);
00111 for (i.rewind(); i.next(); )
00112 {
00113 WvLogRcvBase &rc = *i;
00114 rc.log(parent ? parent : this, loglevel, (const char *)_buf, len);
00115 }
00116
00117 return len;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 WvLogRcvBase::WvLogRcvBase()
00127 {
00128 WvLog::receivers.append(this, false);
00129 WvLog::num_receivers++;
00130 }
00131
00132
00133 WvLogRcvBase::~WvLogRcvBase()
00134 {
00135 WvLog::receivers.unlink(this);
00136 WvLog::num_receivers--;
00137 }
00138
00139
00140 const char *WvLogRcvBase::appname(const WvLog *log) const
00141 {
00142 return log->app;
00143 }
00144
00145
00146
00147
00148
00149
00150
00151 WvLogRcv::WvLogRcv(WvLog::LogLevel _max_level) : custom_levels(5)
00152 {
00153 last_source = NULL;
00154 last_level = WvLog::NUM_LOGLEVELS;
00155 max_level = _max_level;
00156 at_newline = true;
00157 }
00158
00159
00160 WvLogRcv::~WvLogRcv()
00161 {
00162 }
00163
00164
00165 void WvLogRcv::_make_prefix()
00166 {
00167 prefix = WvString("%s<%s>: ",
00168 appname(last_source), loglevels[last_level]);
00169 prelen = prefix.len();
00170 }
00171
00172
00173 void WvLogRcv::_begin_line()
00174 {
00175 mid_line(prefix, prelen);
00176 }
00177
00178
00179 void WvLogRcv::_end_line()
00180 {
00181
00182 }
00183
00184
00185
00186
00187 static bool my_isprint(char _c)
00188 {
00189 unsigned char c = _c;
00190 if (isprint(c) || c >= 128)
00191 return true;
00192 else
00193 return false;
00194 }
00195
00196
00197 void WvLogRcv::log(const WvLog *source, int _loglevel,
00198 const char *_buf, size_t len)
00199 {
00200 WvLog::LogLevel loglevel = (WvLog::LogLevel)_loglevel;
00201 char hex[5];
00202 WvLog::LogLevel threshold = max_level;
00203 WvString srcname = source->app;
00204 strlwr(srcname.edit());
00205
00206 Src_LvlDict::Iter i(custom_levels);
00207 i.rewind();
00208
00209
00210 while (i.next())
00211 {
00212 if (strstr(srcname, i->src))
00213 {
00214 threshold = i->lvl;
00215 break;
00216 }
00217 }
00218
00219 if (loglevel > threshold)
00220 return;
00221
00222
00223
00224
00225 if (source != last_source || loglevel != last_level)
00226 {
00227 end_line();
00228 last_source = source;
00229 last_level = loglevel;
00230 _make_prefix();
00231 }
00232
00233 const char *buf = (const char *)_buf, *bufend = buf + len, *cptr;
00234
00235
00236
00237 while (buf < bufend)
00238 {
00239 if (buf[0] == '\n' || buf[0] == '\r')
00240 {
00241 end_line();
00242 buf++;
00243 continue;
00244 }
00245
00246 begin_line();
00247
00248 if (buf[0] == '\t')
00249 {
00250 mid_line(" ", 1);
00251 buf++;
00252 continue;
00253 }
00254 else if (!my_isprint(buf[0]))
00255 {
00256 snprintf(hex, 5, "[%02x]", buf[0]);
00257 mid_line(hex, 4);
00258 buf++;
00259 continue;
00260 }
00261
00262
00263 for (cptr = buf; cptr < bufend; cptr++)
00264 {
00265 if (*cptr == '\n' || !my_isprint(*cptr))
00266 break;
00267 }
00268
00269 if (*cptr == '\n')
00270 {
00271 mid_line((const char *)buf, cptr - buf);
00272 buf = cptr;
00273 }
00274 else if (!my_isprint(*cptr))
00275 {
00276 mid_line(buf, cptr - buf);
00277 buf = cptr;
00278 }
00279 else
00280 {
00281 mid_line(buf, bufend - buf);
00282 buf = bufend;
00283 }
00284 }
00285 }
00286
00287
00288
00289
00290 bool WvLogRcv::set_custom_levels(WvString descr)
00291 {
00292 custom_levels.zap();
00293
00294
00295 WvStringList lst;
00296 WvStringList::Iter i(lst);
00297 lst.split(descr, ",= ");
00298 if (!lst.count())
00299 return true;
00300 WvString src("");
00301
00302 for (i.rewind(); i.next(); )
00303 {
00304 if (src != "")
00305 {
00306 if (atoi(*i) > 0 && atoi(*i) <= WvLog::NUM_LOGLEVELS)
00307 {
00308 custom_levels.add(new Src_Lvl(src, atoi(*i)), true);
00309 src = "";
00310 }
00311 else
00312 return false;
00313 }
00314 else
00315 {
00316 src = *i;
00317 strlwr(trim_string(src.edit()));
00318 }
00319 }
00320 if (src != "")
00321 return false;
00322
00323 return true;
00324 }
00325
00326
00327
00328
00329
00330
00331 WvLogConsole::WvLogConsole(int _fd, WvLog::LogLevel _max_level) :
00332 WvFDStream(_fd), WvLogRcv(_max_level)
00333 {
00334 }
00335
00336
00337 WvLogConsole::~WvLogConsole()
00338 {
00339 end_line();
00340 }
00341
00342
00343 void WvLogConsole::_mid_line(const char *str, size_t len)
00344 {
00345 uwrite(str, len);
00346 }