]> git.stg.codes - ssmd.git/blob - 3rdparty/snmp++/src/log.cpp
Initial adding
[ssmd.git] / 3rdparty / snmp++ / src / log.cpp
1 /*_############################################################################
2   _## 
3   _##  log.cpp  
4   _##
5   _##  SNMP++v3.2.25
6   _##  -----------------------------------------------
7   _##  Copyright (c) 2001-2010 Jochen Katz, Frank Fock
8   _##
9   _##  This software is based on SNMP++2.6 from Hewlett Packard:
10   _##  
11   _##    Copyright (c) 1996
12   _##    Hewlett-Packard Company
13   _##  
14   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15   _##  Permission to use, copy, modify, distribute and/or sell this software 
16   _##  and/or its documentation is hereby granted without fee. User agrees 
17   _##  to display the above copyright notice and this license notice in all 
18   _##  copies of the software and any documentation of the software. User 
19   _##  agrees to assume all liability for the use of the software; 
20   _##  Hewlett-Packard and Jochen Katz make no representations about the 
21   _##  suitability of this software for any purpose. It is provided 
22   _##  "AS-IS" without warranty of any kind, either express or implied. User 
23   _##  hereby grants a royalty-free license to any and all derivatives based
24   _##  upon this software code base. 
25   _##  
26   _##  Stuttgart, Germany, Thu Sep  2 00:07:47 CEST 2010 
27   _##  
28   _##########################################################################*/
29
30 #ifndef WIN32
31 #include <unistd.h>
32 #else
33 #include <process.h>
34 #endif
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <time.h>
38 #include <signal.h>
39 #include <string.h>
40
41 #include <snmp_pp/log.h>
42
43 #ifdef WIN32
44 #ifdef __BCPLUSPLUS__
45 #define _getpid getpid
46 #endif
47 #endif
48
49 #if defined (CPU) && CPU == PPC603
50 #include <taskLib.h>
51 #endif
52
53 #ifdef SNMP_PP_NAMESPACE
54 using namespace Snmp_pp;
55 #endif
56
57 // default log filter: logs with level less or equal filter value are logged
58 // error, warning, event, info, debug:
59 static unsigned char default_logfilter[] = { 9, 9, 4, 6, 7, 15};
60
61 #undef   LOG_INDENT
62
63
64 /*--------------------------- class LogEntry --------------------------*/
65
66  /**
67   * Initialize a log entry, showing timestamp, class, and level.
68   * 
69   */  
70 void LogEntry::init(void)
71 {
72 #ifdef WIN32
73         int pid = _getpid();
74 #elif defined (CPU) && CPU == PPC603
75         int pid = taskIdSelf();
76 #else
77         int pid = getpid();
78 #endif
79
80         add_timestamp();
81         add_string(": ");
82         add_integer(pid);
83         add_string(": ");
84
85         char buf[20];
86         sprintf(buf, "(%X)", get_level());
87         add_string(buf);
88
89         switch (type & 0xF0) {
90         case DEBUG_LOG:   add_string("DEBUG  : "); break;
91         case INFO_LOG:    add_string("INFO   : "); break;
92         case WARNING_LOG: add_string("WARNING: "); break;
93         case ERROR_LOG:   add_string("ERROR  : "); break;
94         case EVENT_LOG:   add_string("EVENT  : "); break;
95         case USER_LOG:    add_string("USER   : "); break;
96         }
97
98 #ifdef LOG_INDENT
99         // indent log by level
100         for (int i=0; i<(type & 0x0F); i++) 
101                 add_string(" ");
102 #endif
103 }
104
105 /**
106  * Add a string value to the log entry.
107  *
108  * @param l - A numeric value.
109  */
110 LogEntry& LogEntry::operator+=(const char* s)
111 {
112         // The convention for Agent++ log messages is that the
113         // timestamp, etc. is followed by the class and method name,
114         // then by the list of arguments.
115         if (count == 0) 
116                 add_string(s);
117         else {
118           if (count == 1) 
119                 add_string(": ");
120           else 
121                 add_string(", ");
122
123           add_string("(");
124           add_string(s);
125           add_string(")");
126         }
127         count++;
128         return *this;
129 }
130
131 /**
132  * Add a numeric value to the log entry.
133  *
134  * @param l - A numeric value.
135  */
136 LogEntry& LogEntry::operator+=(const long l)
137 {
138         if (count == 1) 
139                 add_string(": ");
140         else 
141                 add_string(", ");
142
143         count++;
144         add_string("(");
145         add_integer(l);
146         add_string(")");
147         return *this;
148 }
149
150 /**
151  * Add an integer to the log.
152  *
153  * @param s - An integer value.
154  * @return TRUE if the value has been added and FALSE if the log
155  *         entry is full.
156  */
157 bool LogEntry::add_integer(long l)
158 {
159         char buf[40];
160         sprintf(buf, "%ld", l);
161         return add_string(buf);
162 }
163
164 /**
165  * Add the current time to the log entry.
166  */
167 bool LogEntry::add_timestamp(void)
168 {
169         return add_string(DefaultLog::log()->now());
170 }
171
172
173 /*------------------------- class LogEntryImpl ------------------------*/
174
175 /**
176  * Constructor for the standard log entry implementation.
177  */  
178 LogEntryImpl::LogEntryImpl(unsigned char t) : LogEntry(t)
179 {
180         value = new char[MAX_LOG_SIZE];
181         value[0] = '\0';
182         ptr = value;
183         output_stopped = FALSE;
184 }
185
186 /**
187  * Destructor for the standard log entry implementation.
188  */  
189 LogEntryImpl::~LogEntryImpl()
190 {
191         delete [] value;
192 }
193
194 /**
195  * Add a string to the log.
196  *
197  * @param s - A string value.
198  * @return TRUE if the value has been added and FALSE if the log
199  *         entry is full.
200  */
201 bool LogEntryImpl::add_string(const char* s)
202 {
203         if (output_stopped)
204                 return FALSE;
205
206         size_t len = strlen(s);
207         if (len <= bytes_left()) {
208                 strcat(ptr, s);
209                 ptr += len;
210                 return TRUE;
211         }
212
213         if (bytes_left() >= 3) {
214                 strcat(ptr, "...");
215                 ptr += 3;
216         }
217         output_stopped = TRUE;
218         return FALSE;
219 }       
220
221
222 /*-------------------------- class AgentLog ---------------------------*/
223
224 /**
225  * Default constructor.
226  */
227 AgentLog::AgentLog()
228 {
229         for (int i=0; i<LOG_TYPES; i++)
230                 logfilter[i] = default_logfilter[i];
231 }
232
233 void AgentLog::set_filter(int logclass, unsigned char filter)
234
235         int idx = (logclass/16)-1;
236         if ((idx >=0) && (idx < LOG_TYPES) && (filter<16)) 
237                 logfilter[idx] = filter; 
238 }
239
240 unsigned char AgentLog::get_filter(int logclass) const
241 {
242         int idx = (logclass/16)-1;      
243         if ((idx >= 0) && (idx < LOG_TYPES)) { 
244                 return logfilter[idx]; 
245         }
246         return 0;
247 }
248
249 const char* AgentLog::now(char* buf)
250 {
251         if (buf == NULL) buf = static_buf;
252
253         time_t t;
254         time(&t);
255         struct tm *stm = localtime(&t);
256         if (stm)
257                 strftime(buf, 18, "%Y%m%d.%H:%M:%S", localtime(&t));
258         else
259                 buf[0] = 0;
260         return buf;
261 }       
262
263 /*static*/ const char* AgentLog::get_current_time() 
264 {
265         char* buf = new char[18];
266         strcpy(buf, DefaultLog::log()->now());
267         return buf;
268 }       
269
270
271 /*------------------------ class AgentLogImpl -------------------------*/
272
273 /**
274  * Default constructor. Log is directed to stdout.
275  */
276 AgentLogImpl::AgentLogImpl(FILE* fp) : AgentLog()
277 {
278         set_dest(fp);
279 }
280
281 /**
282  * Constructor with file name of a log file. Log is directed
283  * to the given file.
284  *
285  * @param fname - The file name of a log file.
286  */ 
287 AgentLogImpl::AgentLogImpl(const char* fname) : AgentLog()
288 {
289         set_dest(fname);
290 }
291
292 /**
293  * Destructor.
294  */
295 AgentLogImpl::~AgentLogImpl()
296 {
297         if (close_needed) fclose(logfile);
298 }
299
300 /**
301  * Set destination of logs to a given file.
302  * 
303  * @param fname - A file name. "" directs logs to stdout.
304  */
305 void AgentLogImpl::set_dest(const char* fname)
306 {
307         close_needed = FALSE;
308         if ((!fname) || (strlen(fname) == 0)) 
309                 logfile = stdout;
310         else {
311                 logfile = fopen(fname, "a");
312                 if (logfile == NULL)
313                         logfile = stdout;
314                 else
315                         close_needed = TRUE;
316         }
317 }
318
319 /**
320  * Set destination of logs to a given file.
321  * 
322  * @param fname - A pointer to an open log file. 0 directs logs to stdout.
323  */
324 void AgentLogImpl::set_dest(FILE* fp)
325 {
326         logfile = fp ? fp : stdout;
327         close_needed = FALSE;
328 }
329
330 /**
331  * Create a new LogEntry.
332  *
333  * @param t - The type of the log entry.
334  * @return A new instance of LogEntry (or of a derived class).
335  */
336 LogEntry* AgentLogImpl::create_log_entry(unsigned char t) const
337 {
338         return new LogEntryImpl(t);
339 }
340
341 /**
342  * Add a LogEntry to the receiver Log.
343  *
344  * @param log - A log entry.
345  * @return The receiver log itself.
346  */
347 AgentLog& AgentLogImpl::operator+=(const LogEntry* log)
348 {
349         fprintf(logfile, "%s\n", log->get_value());
350
351         // check if critical error
352         if ((log->get_class() == ERROR_LOG) && (log->get_level() == 0))
353         {
354           fprintf(logfile, "Exiting now\n");
355           raise(SIGTERM);
356         }
357
358         return *this;
359 }
360
361
362 // define the default logs
363
364 #ifdef _THREADS
365 #ifndef _WIN32THREADS
366 #if !(defined (CPU) && CPU == PPC603)
367 pthread_mutex_t logmutex = PTHREAD_MUTEX_INITIALIZER;
368 #endif
369 #endif
370 #endif
371
372 AgentLog* DefaultLog::instance = 0;
373 LogEntry* DefaultLog::entry = 0;
374 SnmpSynchronized DefaultLog::mutex;
375
376 /*------------------------ class DefaultLog -------------------------*/
377
378 void DefaultLog::cleanup() 
379 {
380   mutex.lock(); 
381   if (instance) delete instance; 
382   instance = 0; 
383   mutex.unlock();
384 }
385
386 AgentLog* DefaultLog::init_ts(AgentLog* logger)
387
388   AgentLog* r = instance;
389   if (!instance) { 
390     mutex.lock(); 
391     if (!instance) { 
392       instance = logger;
393       r = instance;
394     } 
395     mutex.unlock(); 
396   }
397   return r;
398 }
399
400 AgentLog* DefaultLog::log() 
401
402   AgentLog* r = instance;
403   if (!r) {
404     r = new AgentLogImpl();
405     AgentLog* l = init_ts(r);
406     if (r != l) delete r;
407     r = l;
408   } 
409   return r; 
410 }