00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "wvlogrcv.h"
00010 #include <ctype.h>
00011
00012 WvLogRcvBaseList WvLog::receivers;
00013 int WvLog::num_receivers = 0, WvLog::num_logs = 0;
00014 WvLogRcvBase *WvLog::default_receiver = NULL;
00015
00016 char *WvLogRcv::loglevels[WvLog::NUM_LOGLEVELS] = {
00017 "Crit",
00018 "Err",
00019 "Warn",
00020 "Notice",
00021 "Info",
00022 "*1",
00023 "*2",
00024 "*3",
00025 "*4",
00026 "*5",
00027 };
00028
00029
00030
00032
00033
00034
00035 WvLog::WvLog(const WvString &_app, LogLevel _loglevel, const WvLog *par)
00036 : app(_app)
00037 {
00038 app.unique();
00039 parent = par;
00040 loglevel = _loglevel;
00041 num_logs++;
00042 }
00043
00044
00045 WvLog::WvLog(const WvLog &l)
00046 {
00047 parent = l.parent ? l.parent : &l;
00048 app = parent->app;
00049 loglevel = parent->loglevel;
00050 num_logs++;
00051 }
00052
00053
00054 WvLog::~WvLog()
00055 {
00056 num_logs--;
00057 if (!num_logs && default_receiver)
00058 {
00059 num_receivers++;
00060 delete default_receiver;
00061 default_receiver = NULL;
00062 }
00063 }
00064
00065
00066 bool WvLog::isok() const
00067 {
00068 return true;
00069 }
00070
00071
00072 size_t WvLog::uwrite(const void *_buf, size_t len)
00073 {
00074 if (!num_receivers)
00075 {
00076 if (!default_receiver)
00077 {
00078
00079 default_receiver = new WvLogConsole(dup(2));
00080 num_receivers--;
00081 }
00082 default_receiver->log(parent ? parent : this, loglevel,
00083 (const char *)_buf, len);
00084 return len;
00085 }
00086 else if (default_receiver)
00087 {
00088
00089 num_receivers++;
00090 delete default_receiver;
00091 default_receiver = NULL;
00092 }
00093
00094 WvLogRcvBaseList::Iter i(receivers);
00095 for (i.rewind(); i.next(); )
00096 {
00097 WvLogRcvBase &rc = i;
00098 rc.log(parent ? parent : this, loglevel, (const char *)_buf, len);
00099 }
00100
00101 return len;
00102 }
00103
00104
00105
00107
00108
00109
00110 WvLogRcvBase::WvLogRcvBase()
00111 {
00112 WvLog::receivers.append(this, false);
00113 WvLog::num_receivers++;
00114 }
00115
00116
00117 WvLogRcvBase::~WvLogRcvBase()
00118 {
00119 WvLog::receivers.unlink(this);
00120 WvLog::num_receivers--;
00121 }
00122
00123
00124 const char *WvLogRcvBase::appname(const WvLog *log) const
00125 {
00126 return log->app;
00127 }
00128
00129
00130
00132
00133
00134
00135 WvLogRcv::WvLogRcv(WvLog::LogLevel _max_level)
00136 {
00137 last_source = NULL;
00138 last_level = WvLog::NUM_LOGLEVELS;
00139 max_level = _max_level;
00140 at_newline = true;
00141 }
00142
00143
00144 WvLogRcv::~WvLogRcv()
00145 {
00146 }
00147
00148
00149 void WvLogRcv::_make_prefix()
00150 {
00151 prefix = WvString("%s<%s>: ",
00152 appname(last_source), loglevels[last_level]);
00153 prelen = strlen(prefix);
00154 }
00155
00156
00157 void WvLogRcv::_begin_line()
00158 {
00159 mid_line(prefix, prelen);
00160 }
00161
00162
00163 void WvLogRcv::_end_line()
00164 {
00165
00166 }
00167
00168
00169 void WvLogRcv::log(const WvLog *source, int _loglevel,
00170 const char *_buf, size_t len)
00171 {
00172 WvLog::LogLevel loglevel = (WvLog::LogLevel)_loglevel;
00173 char hex[5];
00174
00175 if (loglevel > max_level)
00176 return;
00177
00178
00179
00180
00181 if (source != last_source || loglevel != last_level)
00182 {
00183 end_line();
00184 last_source = source;
00185 last_level = loglevel;
00186 _make_prefix();
00187 }
00188
00189 char *buf = (char *)_buf, *bufend = buf + len, *cptr;
00190
00191
00192
00193 while (buf < bufend)
00194 {
00195 if (buf[0] == '\n' || buf[0] == '\r')
00196 {
00197 end_line();
00198 buf++;
00199 continue;
00200 }
00201
00202 begin_line();
00203
00204 if (buf[0] == '\t')
00205 {
00206 mid_line(" ", 1);
00207 buf++;
00208 continue;
00209 }
00210 else if (!isascii(buf[0]) || !isprint(buf[0]))
00211 {
00212 snprintf(hex, 5, "[%02x]", *(unsigned char *)buf);
00213 mid_line(hex, 4);
00214 buf++;
00215 continue;
00216 }
00217
00218
00219 for (cptr = buf; cptr < bufend; cptr++)
00220 if (*cptr == '\n' || !isascii(*cptr) || !isprint(*cptr)) break;
00221
00222 if (*cptr == '\n')
00223 {
00224 mid_line(buf, cptr - buf);
00225 buf = cptr;
00226 }
00227 else if (!isascii(*cptr) || !isprint(*cptr))
00228 {
00229 mid_line(buf, cptr - buf);
00230 buf = cptr;
00231 }
00232 else
00233 {
00234 mid_line(buf, bufend - buf);
00235 buf = bufend;
00236 }
00237 }
00238 }
00239
00240
00241
00243
00244
00245
00246 WvLogConsole::WvLogConsole(int _fd, WvLog::LogLevel _max_level)
00247 : WvStream(_fd), WvLogRcv(_max_level)
00248 {
00249 }
00250
00251
00252 WvLogConsole::~WvLogConsole()
00253 {
00254 end_line();
00255 }
00256
00257
00258 void WvLogConsole::_mid_line(const char *str, size_t len)
00259 {
00260 uwrite(str, len);
00261 }