- wrote logger_manager
[strongswan.git] / Source / charon / logger.c
1 /**
2 * @file logger.c
3 *
4 * @brief Logger object, allows fine-controlled logging
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <syslog.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <time.h>
28
29 #include "logger.h"
30 #include "daemon.h"
31 #include "types.h"
32 #include "allocator.h"
33
34 /**
35 * Maximum length of al log entry (only used for logger_s.log)
36 */
37 #define MAX_LOG 8192
38
39 /**
40 * @brief The logger object.
41 */
42 typedef struct private_logger_s private_logger_t;
43 struct private_logger_s {
44 /**
45 * Public data
46 */
47 logger_t public;
48 /**
49 * Detail-level of logger.
50 */
51 logger_level_t level;
52 /**
53 * Name of logger.
54 */
55 char *name;
56 /**
57 * File to write log output to .
58 * NULL for syslog.
59 */
60 FILE *output;
61
62 /* private functions */
63 /**
64 * Logs a message to the associated log file.
65 */
66 void (*log_to_file) (private_logger_t *this, char *format, ...);
67 };
68
69 /**
70 * Implements logger_t-function log.
71 * @see logger_s.log.
72 *
73 * Yes, logg is wrong written :-).
74 */
75 static status_t logg(private_logger_t *this, logger_level_t loglevel, char *format, ...)
76 {
77 if ((this->level & loglevel) == loglevel)
78 {
79 char buffer[MAX_LOG];
80 va_list args;
81
82 if (this->output == NULL)
83 {
84 /* syslog */
85 snprintf(buffer, MAX_LOG, "%s: %s", this->name, format);
86 va_start(args, format);
87 vsyslog(LOG_INFO, buffer, args);
88 va_end(args);
89 }
90 else
91 {
92 /* File output */
93 snprintf(buffer, MAX_LOG, "File %s: %s", this->name, format);
94 va_start(args, format);
95 this->log_to_file(this, buffer, args);
96 va_end(args);
97 }
98
99 }
100 return SUCCESS;
101 }
102
103 /**
104 * Implements private_logger_t-function log_to_file.
105 * @see private_logger_s.log_to_file.
106 */
107 static void log_to_file(private_logger_t *this,char *format, ...)
108 {
109 char buffer[MAX_LOG];
110 va_list args;
111 time_t current_time;
112 current_time = time(NULL);
113
114 snprintf(buffer, MAX_LOG, "%s\n", format);
115 va_start(args, format);
116 vfprintf(this->output, buffer, args);
117 va_end(args);
118 }
119
120 /**
121 * Implements logger_t-function destroy.
122 * @see logger_s.log_bytes.
123 */
124 static status_t log_bytes(private_logger_t *this, logger_level_t loglevel, char *label, char *bytes, size_t len)
125 {
126 if ((this->level & loglevel) == loglevel)
127 {
128 char buffer[64];
129 char *buffer_pos;
130 char *bytes_pos, *bytes_roof;
131 int i;
132
133 if (this->output == NULL)
134 {
135 syslog(LOG_INFO, "%s: %s (%d bytes)", this->name, label, len);
136 }else
137 {
138 this->log_to_file(this,"%s: %s (%d bytes)", this->name, label, len);
139 }
140
141 bytes_pos = bytes;
142 bytes_roof = bytes + len;
143 buffer_pos = buffer;
144
145 for (i = 1; bytes_pos < bytes_roof; i++)
146 {
147 static const char hexdig[] = "0123456789ABCDEF";
148 *buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
149 *buffer_pos++ = hexdig[ *bytes_pos & 0xF];
150 if ((i % 16) == 0)
151 {
152 *buffer_pos++ = '\0';
153 buffer_pos = buffer;
154 if (this->output == NULL)
155 {
156 syslog(LOG_INFO, "| %s", buffer);
157 }
158 else
159 {
160 this->log_to_file(this, "| %s", buffer);
161 }
162 }
163 else if ((i % 8) == 0)
164 {
165 *buffer_pos++ = ' ';
166 *buffer_pos++ = ' ';
167 *buffer_pos++ = ' ';
168 }
169 else if ((i % 4) == 0)
170 {
171 *buffer_pos++ = ' ';
172 *buffer_pos++ = ' ';
173 }
174 else
175 {
176 *buffer_pos++ = ' ';
177 }
178
179 bytes_pos++;
180 }
181
182 *buffer_pos++ = '\0';
183 buffer_pos = buffer;
184 if (this->output == NULL)
185 {
186 syslog(LOG_INFO, "| %s", buffer);
187 }
188 else
189 {
190 this->log_to_file(this, "| %s", buffer);
191 }
192 }
193
194 return SUCCESS;
195 }
196
197
198 /**
199 * Implements logger_t-function log_chunk.
200 * @see logger_s.log_chunk.
201 */
202 static status_t log_chunk(logger_t *this, logger_level_t loglevel, char *label, chunk_t *chunk)
203 {
204 this->log_bytes(this, loglevel, label, chunk->ptr, chunk->len);
205 return SUCCESS;
206 }
207
208
209 /**
210 * Implements logger_t-function enable_level.
211 * @see logger_s.enable_level.
212 */
213 static status_t enable_level(private_logger_t *this, logger_level_t log_level)
214 {
215 this->level |= log_level;
216 return SUCCESS;
217 }
218
219 /**
220 * Implements logger_t-function disable_level.
221 * @see logger_s.disable_level.
222 */
223 static status_t disable_level(private_logger_t *this, logger_level_t log_level)
224 {
225 this->level &= ~log_level;
226 return SUCCESS;
227 }
228
229 /**
230 * Implements logger_t-function destroy.
231 * @see logger_s.destroy.
232 */
233 static status_t destroy(private_logger_t *this)
234 {
235 allocator_free(this);
236 return SUCCESS;
237 }
238
239 /*
240 * Described in Header
241 */
242 logger_t *logger_create(char *logger_name, logger_level_t log_level,FILE * output)
243 {
244 private_logger_t *this = allocator_alloc_thing(private_logger_t);
245
246 if (this == NULL)
247 {
248 return NULL;
249 }
250
251 this->public.log = (status_t(*)(logger_t*,logger_level_t,char*,...))logg;
252 this->public.log_bytes = (status_t(*)(logger_t*, logger_level_t, char*,char*,size_t))log_bytes;
253 this->public.log_chunk = log_chunk;
254 this->public.enable_level = (status_t(*)(logger_t*,logger_level_t))enable_level;
255 this->public.disable_level = (status_t(*)(logger_t*,logger_level_t))disable_level;
256 this->public.destroy = (status_t(*)(logger_t*))destroy;
257
258 this->log_to_file = log_to_file;
259
260 /* private variables */
261 this->level = log_level;
262 this->name = logger_name;
263 this->output = output;
264
265
266 if (output == NULL)
267 {
268 openlog(DEAMON_NAME, 0, LOG_DAEMON);
269 }
270
271 return (logger_t*)this;
272 }