4 * @brief Implementation of logger_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
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>.
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
34 * Maximum length of a log entry (only used for logger_s.log).
39 * Maximum number of logged bytes per line
43 typedef struct private_logger_t private_logger_t
;
46 * @brief Private data of a logger_t object.
48 struct private_logger_t
{
54 * Detail-level of logger.
62 * File to write log output to.
68 * Should a thread_id be included in the log?
74 * prepend the logging prefix to string and store it in buffer
76 static void prepend_prefix(private_logger_t
*this, log_level_t loglevel
, const char *string
, char *buffer
)
78 char log_type
, log_details
;
79 char thread_id
[10] = "";
81 if (loglevel
& CONTROL
)
85 else if (loglevel
& ERROR
)
89 else if (loglevel
& RAW
)
93 else if (loglevel
& PRIVATE
)
97 else if (loglevel
& AUDIT
)
106 if (loglevel
& (LEVEL3
- LEVEL2
))
110 else if (loglevel
& (LEVEL2
- LEVEL1
))
114 else if (loglevel
& LEVEL1
)
123 if (this->log_thread_id
)
125 snprintf(thread_id
, sizeof(thread_id
), " @%d", (int)pthread_self());
127 snprintf(buffer
, MAX_LOG
, "[%c%c:%s]%s %s", log_type
, log_details
, this->name
, thread_id
, string
);
131 * Convert a charon-loglevel to a syslog priority
133 static int get_priority(log_level_t loglevel
)
135 if (loglevel
& AUDIT
)
137 return LOG_AUTHPRIV
|LOG_INFO
;
139 return LOG_DAEMON
|LOG_DEBUG
;
143 * Implementation of logger_t.log.
145 * Yes, logg is written wrong :-).
147 static void logg(private_logger_t
*this, log_level_t loglevel
, const char *format
, ...)
149 if ((this->level
& loglevel
) == loglevel
)
151 char buffer
[MAX_LOG
];
155 if (this->output
== NULL
)
158 prepend_prefix(this, loglevel
, format
, buffer
);
159 va_start(args
, format
);
160 vsyslog(get_priority(loglevel
), buffer
, args
);
166 prepend_prefix(this, loglevel
, format
, buffer
);
167 va_start(args
, format
);
168 vfprintf(this->output
, buffer
, args
);
170 fprintf(this->output
, "\n");
177 * Implementation of logger_t.log_bytes.
179 static void log_bytes(private_logger_t
*this, log_level_t loglevel
, const char *label
, const char *bytes
, size_t len
)
181 static pthread_mutex_t mutex
= PTHREAD_MUTEX_INITIALIZER
;
183 if ((this->level
& loglevel
) == loglevel
)
185 char thread_id
[10] = "";
186 char buffer
[MAX_LOG
];
187 char ascii_buffer
[MAX_BYTES
+1];
189 char *buffer_pos
= buffer
;
190 const char format
[] = "%s %d bytes @ %p";
191 const char *bytes_pos
= bytes
;
192 const char *bytes_roof
= bytes
+ len
;
197 if (this->log_thread_id
)
199 snprintf(thread_id
, sizeof(thread_id
), " @%d", (int)pthread_self());
202 /* since me can't do multi-line output to syslog,
203 * we must do multiple syslogs. To avoid
204 * problems in output order, lock this by a mutex.
206 pthread_mutex_lock(&mutex
);
208 prepend_prefix(this, loglevel
, format
, buffer
);
210 if (this->output
== NULL
)
212 syslog(get_priority(loglevel
), buffer
, label
, len
, bytes
);
216 fprintf(this->output
, buffer
, label
, len
, bytes
);
217 fprintf(this->output
, "\n");
220 while (bytes_pos
< bytes_roof
)
222 static char hexdig
[] = "0123456789ABCDEF";
224 *buffer_pos
++ = hexdig
[(*bytes_pos
>> 4) & 0xF];
225 *buffer_pos
++ = hexdig
[ *bytes_pos
& 0xF];
227 ascii_buffer
[i
++] = (*bytes_pos
> 31 && *bytes_pos
< 127)
230 if (++bytes_pos
== bytes_roof
|| i
== MAX_BYTES
)
232 int padding
= 3 * (MAX_BYTES
- i
);
238 *buffer_pos
++ = '\0';
239 ascii_buffer
[i
] = '\0';
241 if (this->output
== NULL
)
243 syslog(get_priority(loglevel
), "[ :%5d]%s %s %s", line_start
, thread_id
, buffer
, ascii_buffer
);
247 fprintf(this->output
, "[ :%5d]%s %s %s\n", line_start
, thread_id
, buffer
, ascii_buffer
);
250 line_start
+= MAX_BYTES
;
258 pthread_mutex_unlock(&mutex
);
263 * Implementation of logger_t.log_chunk.
265 static void log_chunk(logger_t
*this, log_level_t loglevel
, const char *label
, chunk_t chunk
)
267 this->log_bytes(this, loglevel
, label
, chunk
.ptr
, chunk
.len
);
271 * Implementation of logger_t.enable_level.
273 static void enable_level(private_logger_t
*this, log_level_t log_level
)
275 this->level
|= log_level
;
279 * Implementation of logger_t.disable_level.
281 static void disable_level(private_logger_t
*this, log_level_t log_level
)
283 this->level
&= ~log_level
;
287 * Implementation of logger_t.set_output.
289 static void set_output(private_logger_t
*this, FILE * output
)
291 this->output
= output
;
295 * Implementation of logger_t.get_level.
297 static log_level_t
get_level(private_logger_t
*this)
303 * Implementation of logger_t.destroy.
305 static void destroy(private_logger_t
*this)
312 * Described in header.
314 logger_t
*logger_create(char *logger_name
, log_level_t log_level
, bool log_thread_id
, FILE * output
)
316 private_logger_t
*this = malloc_thing(private_logger_t
);
318 /* public functions */
319 this->public.log
= (void(*)(logger_t
*,log_level_t
,const char*,...))logg
;
320 this->public.log_bytes
= (void(*)(logger_t
*, log_level_t
, const char*, const char*,size_t))log_bytes
;
321 this->public.log_chunk
= log_chunk
;
322 this->public.enable_level
= (void(*)(logger_t
*,log_level_t
))enable_level
;
323 this->public.disable_level
= (void(*)(logger_t
*,log_level_t
))disable_level
;
324 this->public.get_level
= (log_level_t(*)(logger_t
*))get_level
;
325 this->public.set_output
= (void(*)(logger_t
*,FILE*))set_output
;
326 this->public.destroy
= (void(*)(logger_t
*))destroy
;
328 if (logger_name
== NULL
)
333 /* private variables */
334 this->level
= log_level
;
335 this->log_thread_id
= log_thread_id
;
336 this->name
= malloc(strlen(logger_name
) + 1);
338 strcpy(this->name
,logger_name
);
339 this->output
= output
;
341 return (logger_t
*)this;