blob: d12fe224cbd77ea2a8679b46db323ec89b59b840 [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39#include <ucommon-config.h>
40#include <commoncpp/config.h>
41#include <commoncpp/export.h>
42#include <commoncpp/slog.h>
43#ifdef __BORLANDC__
44#include <stdio.h>
45#include <stdarg.h>
46#else
47#include <cstdio>
48#include <cstdarg>
49#endif
50
51#ifdef HAVE_SYSLOG_H
52#include <syslog.h>
53#endif
54
55using std::streambuf;
56using std::ofstream;
57using std::ostream;
58using std::clog;
59using std::endl;
60using std::ios;
61
62using namespace COMMONCPP_NAMESPACE;
63
64Slog ost::slog;
65
66Slog::Slog(void) :
67streambuf()
68#ifdef OLD_IOSTREAM
69,ostream()
70#else
71,ostream((streambuf *)this)
72#endif
73{
74#ifdef OLD_IOSTREAM
75 init((streambuf *)this);
76#endif
77 _enable = true;
78 _level = levelDebug;
79 _clogEnable = true;
80#ifndef HAVE_SYSLOG_H
81 syslog = NULL;
82#endif
83}
84
85Slog::~Slog(void)
86{
87#ifdef HAVE_SYSLOG_H
88 closelog();
89#else
90 if(syslog)
91 fclose(syslog);
92#endif
93}
94
95void Slog::close(void)
96{
97#ifdef HAVE_SYSLOG_H
98 closelog();
99#else
100 pthread_mutex_lock(&lock);
101 if(syslog)
102 fclose(syslog);
103 syslog = NULL;
104 pthread_mutex_unlock(&lock);
105#endif
106}
107
108void Slog::open(const char *ident, Class grp)
109{
110 const char *cp;
111
112#ifdef HAVE_SYSLOG_H
113 cp = strrchr(ident, '/');
114 if(cp)
115 ident = ++cp;
116
117 int fac;
118
119 switch(grp) {
120 case classUser:
121 fac = LOG_USER;
122 break;
123
124 case classDaemon:
125 fac = LOG_DAEMON;
126 break;
127
128 case classAudit:
129#ifdef LOG_AUTHPRIV
130 fac = LOG_AUTHPRIV;
131 break;
132#endif
133 case classSecurity:
134 fac = LOG_AUTH;
135 break;
136
137 case classLocal0:
138 fac = LOG_LOCAL0;
139 break;
140
141 case classLocal1:
142 fac = LOG_LOCAL1;
143 break;
144
145 case classLocal2:
146 fac = LOG_LOCAL2;
147 break;
148
149 case classLocal3:
150 fac = LOG_LOCAL3;
151 break;
152
153 case classLocal4:
154 fac = LOG_LOCAL4;
155 break;
156
157 case classLocal5:
158 fac = LOG_LOCAL5;
159 break;
160
161 case classLocal6:
162 fac = LOG_LOCAL6;
163 break;
164
165 case classLocal7:
166 fac = LOG_LOCAL7;
167 break;
168
169 default:
170 fac = LOG_USER;
171 break;
172 }
173 openlog(ident, 0, fac);
174#else
175 char *buf;
176
177 pthread_mutex_lock(&lock);
178 if(syslog)
179 fclose(syslog);
180 buf = new char[strlen(ident) + 1];
181 strcpy(buf, ident);
182 cp = (const char *)buf;
183 buf = strrchr(buf, '.');
184 if(buf) {
185 if(!stricmp(buf, ".exe"))
186 strcpy(buf, ".log");
187 }
188 syslog = fopen(cp, "a");
189 delete[] (char *)cp;
190 pthread_mutex_unlock(&lock);
191#endif
192}
193
194void Slog::error(const char *format, ...)
195{
196 Thread *thread = Thread::get();
197 va_list args;
198 va_start(args, format);
199 overflow(EOF);
200
201 if(!thread)
202 return;
203
204 error();
205
206 vsnprintf(thread->msgbuf, sizeof(thread->msgbuf), format, args);
207 thread->msgpos = strlen(thread->msgbuf);
208 overflow(EOF);
209 va_end(args);
210}
211
212void Slog::warn(const char *format, ...)
213{
214 Thread *thread = Thread::get();
215 va_list args;
216
217 if(!thread)
218 return;
219
220 va_start(args, format);
221 overflow(EOF);
222 warn();
223 vsnprintf(thread->msgbuf, sizeof(thread->msgbuf), format, args);
224 thread->msgpos = strlen(thread->msgbuf);
225 overflow(EOF);
226 va_end(args);
227}
228
229void Slog::debug(const char *format, ...)
230{
231 Thread *thread = Thread::get();
232 va_list args;
233
234 if(!thread)
235 return;
236
237 va_start(args, format);
238 overflow(EOF);
239 debug();
240 vsnprintf(thread->msgbuf, sizeof(thread->msgbuf), format, args);
241 thread->msgpos = strlen(thread->msgbuf);
242 overflow(EOF);
243 va_end(args);
244}
245
246void Slog::emerg(const char *format, ...)
247{
248 Thread *thread = Thread::get();
249 va_list args;
250
251 if(!thread)
252 return;
253
254 va_start(args, format);
255 overflow(EOF);
256 emerg();
257 vsnprintf(thread->msgbuf, sizeof(thread->msgbuf), format, args);
258 thread->msgpos = strlen(thread->msgbuf);
259 overflow(EOF);
260 va_end(args);
261}
262
263void Slog::alert(const char *format, ...)
264{
265 Thread *thread = Thread::get();
266 va_list args;
267
268 if(!thread)
269 return;
270
271 va_start(args, format);
272 overflow(EOF);
273 alert();
274 vsnprintf(thread->msgbuf, sizeof(thread->msgbuf), format, args);
275 thread->msgpos = strlen(thread->msgbuf);
276 overflow(EOF);
277 va_end(args);
278}
279
280void Slog::critical(const char *format, ...)
281{
282 Thread *thread = Thread::get();
283 va_list args;
284
285 if(!thread)
286 return;
287
288 va_start(args, format);
289 overflow(EOF);
290 critical();
291 vsnprintf(thread->msgbuf, sizeof(thread->msgbuf), format, args);
292 thread->msgpos = strlen(thread->msgbuf);
293 overflow(EOF);
294 va_end(args);
295}
296
297void Slog::notice(const char *format, ...)
298{
299 Thread *thread = Thread::get();
300 va_list args;
301
302 if(!thread)
303 return;
304
305 va_start(args, format);
306 overflow(EOF);
307 notice();
308 vsnprintf(thread->msgbuf, sizeof(thread->msgbuf), format, args);
309 thread->msgpos = strlen(thread->msgbuf);
310 overflow(EOF);
311 va_end(args);
312}
313
314void Slog::info(const char *format, ...)
315{
316 Thread *thread = Thread::get();
317 va_list args;
318
319 if(!thread)
320 return;
321
322 va_start(args, format);
323 overflow(EOF);
324 info();
325 vsnprintf(thread->msgbuf, sizeof(thread->msgbuf), format, args);
326 thread->msgpos = strlen(thread->msgbuf);
327 overflow(EOF);
328 va_end(args);
329}
330
331int Slog::overflow(int c)
332{
333 Thread *thread = Thread::get();
334 if(!thread)
335 return c;
336
337 if(c == '\n' || !c || c == EOF) {
338 if(!thread->msgpos)
339 return c;
340
341 thread->msgbuf[thread->msgpos] = 0;
342 if (_enable)
343#ifdef HAVE_SYSLOG_H
344 ::syslog(priority, "%s", thread->msgbuf);
345#else
346 {
347 time_t now;
348 struct tm *dt;
349 time(&now);
350 dt = localtime(&now);
351 char buf[256];
352 const char *p = "unknown";
353 switch(priority) {
354 case levelEmergency:
355 p = "emerg";
356 break;
357 case levelInfo:
358 p = "info";
359 break;
360 case levelError:
361 p = "error";
362 break;
363 case levelAlert:
364 p = "alert";
365 break;
366 case levelDebug:
367 p = "debug";
368 break;
369 case levelNotice:
370 p = "notice";
371 break;
372 case levelWarning:
373 p = "warn";
374 break;
375 case levelCritical:
376 p = "crit";
377 break;
378 }
379
380 pthread_mutex_lock(&lock);
381 snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d [%s] %s\n",
382 dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday,
383 dt->tm_hour, dt->tm_min, dt->tm_sec,
384 p, thread->msgbuf);
385 if(syslog)
386 fputs(buf, syslog);
387// syslog << "[" << priority << "] " << thread->msgbuf << endl;
388 pthread_mutex_unlock(&lock);
389 }
390#endif
391 thread->msgpos = 0;
392
393 if ( _enable && _clogEnable
394#ifndef _MSWINDOWS_
395 && (getppid() > 1)
396#endif
397 )
398 clog << thread->msgbuf << endl;
399 _enable = true;
400 return c;
401 }
402
403 if (thread->msgpos < (int)(sizeof(thread->msgbuf) - 1))
404 thread->msgbuf[thread->msgpos++] = c;
405
406 return c;
407}
408
409Slog &Slog::operator()(const char *ident, Class grp, Level lev)
410{
411 Thread *thread = Thread::get();
412
413 if(!thread)
414 return *this;
415
416 thread->msgpos = 0;
417 _enable = true;
418 open(ident, grp);
419 return this->operator()(lev, grp);
420}
421
422Slog &Slog::operator()(Level lev, Class grp)
423{
424 Thread *thread = Thread::get();
425
426 if(!thread)
427 return *this;
428
429 thread->msgpos = 0;
430 if(_level >= lev)
431 _enable = true;
432 else
433 _enable = false;
434
435#ifdef HAVE_SYSLOG_H
436 switch(lev) {
437 case levelEmergency:
438 priority = LOG_EMERG;
439 break;
440 case levelAlert:
441 priority = LOG_ALERT;
442 break;
443 case levelCritical:
444 priority = LOG_CRIT;
445 break;
446 case levelError:
447 priority = LOG_ERR;
448 break;
449 case levelWarning:
450 priority = LOG_WARNING;
451 break;
452 case levelNotice:
453 priority = LOG_NOTICE;
454 break;
455 case levelInfo:
456 priority = LOG_INFO;
457 break;
458 case levelDebug:
459 priority = LOG_DEBUG;
460 break;
461 }
462 switch(grp) {
463 case classAudit:
464#ifdef LOG_AUTHPRIV
465 priority |= LOG_AUTHPRIV;
466 break;
467#endif
468 case classSecurity:
469 priority |= LOG_AUTH;
470 break;
471 case classUser:
472 priority |= LOG_USER;
473 break;
474 case classDaemon:
475 priority |= LOG_DAEMON;
476 break;
477 case classDefault:
478 priority |= LOG_USER;
479 break;
480 case classLocal0:
481 priority |= LOG_LOCAL0;
482 break;
483 case classLocal1:
484 priority |= LOG_LOCAL1;
485 break;
486 case classLocal2:
487 priority |= LOG_LOCAL2;
488 break;
489 case classLocal3:
490 priority |= LOG_LOCAL3;
491 break;
492 case classLocal4:
493 priority |= LOG_LOCAL4;
494 break;
495 case classLocal5:
496 priority |= LOG_LOCAL5;
497 break;
498 case classLocal6:
499 priority |= LOG_LOCAL6;
500 break;
501 case classLocal7:
502 priority |= LOG_LOCAL7;
503 break;
504 }
505#else
506 priority = lev;
507#endif
508 return *this;
509}
510
511Slog &Slog::operator()(void)
512{
513 return *this;
514}
515
516