Use a separate interface for loggers.
[strongswan.git] / src / libcharon / bus / listeners / file_logger.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2006 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <time.h>
20
21 #include "file_logger.h"
22
23
24 typedef struct private_file_logger_t private_file_logger_t;
25
26 /**
27 * Private data of a file_logger_t object
28 */
29 struct private_file_logger_t {
30
31 /**
32 * Public data.
33 */
34 file_logger_t public;
35
36 /**
37 * output file
38 */
39 FILE *out;
40
41 /**
42 * Maximum level to log, for each group
43 */
44 level_t levels[DBG_MAX];
45
46 /**
47 * strftime() format of time prefix, if any
48 */
49 char *time_format;
50
51 /**
52 * Print the name/# of the IKE_SA?
53 */
54 bool ike_name;
55 };
56
57 METHOD(logger_t, log_, void,
58 private_file_logger_t *this, debug_t group, level_t level, int thread,
59 ike_sa_t* ike_sa, char *format, va_list args)
60 {
61 if (level <= this->levels[group])
62 {
63 char buffer[8192], timestr[128], namestr[128] = "";
64 char *current = buffer, *next;
65 struct tm tm;
66 time_t t;
67
68 if (this->time_format)
69 {
70 t = time(NULL);
71 localtime_r(&t, &tm);
72 strftime(timestr, sizeof(timestr), this->time_format, &tm);
73 }
74 if (this->ike_name && ike_sa)
75 {
76 if (ike_sa->get_peer_cfg(ike_sa))
77 {
78 snprintf(namestr, sizeof(namestr), " <%s|%d>",
79 ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa));
80 }
81 else
82 {
83 snprintf(namestr, sizeof(namestr), " <%d>",
84 ike_sa->get_unique_id(ike_sa));
85 }
86 }
87 else
88 {
89 namestr[0] = '\0';
90 }
91
92 /* write in memory buffer first */
93 vsnprintf(buffer, sizeof(buffer), format, args);
94
95 /* prepend a prefix in front of every line */
96 while (current)
97 {
98 next = strchr(current, '\n');
99 if (next)
100 {
101 *(next++) = '\0';
102 }
103 if (this->time_format)
104 {
105 fprintf(this->out, "%s %.2d[%N]%s %s\n",
106 timestr, thread, debug_names, group, namestr, current);
107 }
108 else
109 {
110 fprintf(this->out, "%.2d[%N]%s %s\n",
111 thread, debug_names, group, namestr, current);
112 }
113 current = next;
114 }
115 }
116 }
117
118 METHOD(file_logger_t, set_level, void,
119 private_file_logger_t *this, debug_t group, level_t level)
120 {
121 if (group < DBG_ANY)
122 {
123 this->levels[group] = level;
124 }
125 else
126 {
127 for (group = 0; group < DBG_MAX; group++)
128 {
129 this->levels[group] = level;
130 }
131 }
132 }
133
134 METHOD(file_logger_t, destroy, void,
135 private_file_logger_t *this)
136 {
137 if (this->out != stdout && this->out != stderr)
138 {
139 fclose(this->out);
140 }
141 free(this);
142 }
143
144 /*
145 * Described in header.
146 */
147 file_logger_t *file_logger_create(FILE *out, char *time_format, bool ike_name)
148 {
149 private_file_logger_t *this;
150
151 INIT(this,
152 .public = {
153 .logger = {
154 .log = _log_,
155 },
156 .set_level = _set_level,
157 .destroy = _destroy,
158 },
159 .out = out,
160 .time_format = time_format,
161 .ike_name = ike_name,
162 );
163
164 set_level(this, DBG_ANY, LEVEL_SILENT);
165
166 return &this->public;
167 }
168