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 }