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