d1f469d3d668f154afc9b25db64d381a25c31057
[claws.git] / src / common / log.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  * 
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #ifdef G_OS_WIN32
27 #  include <w32lib.h>
28 #endif
29
30 #include <stdio.h>
31 #include <glib.h>
32 #include <glib/gi18n.h>
33
34 #include "utils.h"
35 #include "log.h"
36 #include "hooks.h"
37
38 static FILE *log_fp[LOG_INSTANCE_MAX] = {
39         NULL,
40         NULL
41 };
42
43 typedef struct _LogInstanceData LogInstanceData;
44
45 struct _LogInstanceData {
46         const char *hook;
47         gchar *title;
48         int *prefs_logwin_width;
49         int *prefs_logwin_height;
50 };
51
52 static LogInstanceData log_instances[LOG_INSTANCE_MAX] = {
53         { LOG_APPEND_TEXT_HOOKLIST, NULL, NULL, NULL },
54         { DEBUG_FILTERING_APPEND_TEXT_HOOKLIST, NULL, NULL, NULL }
55 };
56
57 gboolean prefs_common_enable_log_standard(void);
58 gboolean prefs_common_enable_log_warning(void);
59 gboolean prefs_common_enable_log_error(void);
60 gboolean prefs_common_enable_log_status(void);
61
62 static gboolean invoke_hook_cb (gpointer data)
63 {
64         LogText *logtext = (LogText *)data;
65         hooks_invoke(get_log_hook(logtext->instance), logtext);
66         g_free(logtext->text);
67         g_free(logtext);
68         return FALSE;
69 }
70
71 void set_log_file(LogInstance instance, const gchar *filename)
72 {
73         if (log_fp[instance])
74                 return;
75
76         /* backup old logfile if existing */
77         if (is_file_exist(filename)) {
78                 gchar *backupname;
79                 
80                 backupname = g_strconcat(filename, ".bak", NULL);
81                 if (rename(filename, backupname) < 0)
82                         FILE_OP_ERROR(filename, "rename");
83                 g_free(backupname);
84         }
85
86         log_fp[instance] = g_fopen(filename, "wb");
87         if (!log_fp[instance])
88                 FILE_OP_ERROR(filename, "fopen");
89 }
90
91 void close_log_file(LogInstance instance)
92 {
93         if (log_fp[instance]) {
94                 fclose(log_fp[instance]);
95                 log_fp[instance] = NULL;
96         }
97 }
98
99 const char *get_log_hook(LogInstance instance)
100 {
101         return log_instances[instance].hook;
102 }
103
104 void set_log_title(LogInstance instance, gchar *title)
105 {
106         log_instances[instance].title = title;
107 }
108
109 gchar *get_log_title(LogInstance instance)
110 {
111         return log_instances[instance].title;
112 }
113
114 void set_log_prefs(LogInstance instance, int* logwin_width, int* logwin_height)
115 {
116         log_instances[instance].prefs_logwin_width = logwin_width;
117         log_instances[instance].prefs_logwin_height = logwin_height;
118 }
119
120 void get_log_prefs(LogInstance instance, int** logwin_width, int** logwin_height)
121 {
122         if (logwin_width)
123                 *logwin_width = log_instances[instance].prefs_logwin_width;
124         if (logwin_height)
125                 *logwin_height = log_instances[instance].prefs_logwin_height;
126 }
127
128 void log_print(LogInstance instance, const gchar *format, ...)
129 {
130         va_list args;
131         gchar buf[BUFFSIZE + LOG_TIME_LEN];
132         time_t t;
133         LogText *logtext = g_new0(LogText, 1);
134         struct tm buft;
135
136         time(&t);
137         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
138
139         va_start(args, format);
140         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
141         va_end(args);
142
143         if (debug_get_mode()) g_print(buf);
144
145         logtext->instance = instance;
146         logtext->text = g_strdup(buf);
147         logtext->type = LOG_NORMAL;
148         
149         g_timeout_add(0, invoke_hook_cb, logtext);
150
151         if (log_fp[instance] && prefs_common_enable_log_standard()) {
152                 fputs(buf, log_fp[instance]);
153                 fflush(log_fp[instance]);
154         }
155 }
156
157 void log_message(LogInstance instance, const gchar *format, ...)
158 {
159         va_list args;
160         gchar buf[BUFFSIZE + LOG_TIME_LEN];
161         time_t t;
162         LogText *logtext = g_new0(LogText, 1);
163         struct tm buft;
164
165         time(&t);
166         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
167
168         va_start(args, format);
169         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
170         va_end(args);
171
172         if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
173
174         logtext->instance = instance;
175         logtext->text = g_strdup(buf + LOG_TIME_LEN);
176         logtext->type = LOG_MSG;
177         
178         g_timeout_add(0, invoke_hook_cb, logtext);
179
180         if (log_fp[instance] && prefs_common_enable_log_standard()) {
181                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
182                 fputs("* message: ", log_fp[instance]);
183                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
184                 fflush(log_fp[instance]);
185         }
186 }
187
188 void log_warning(LogInstance instance, const gchar *format, ...)
189 {
190         va_list args;
191         gchar buf[BUFFSIZE + LOG_TIME_LEN];
192         time_t t;
193         LogText *logtext = g_new0(LogText, 1);
194         struct tm buft;
195
196         time(&t);
197         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
198
199         va_start(args, format);
200         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
201         va_end(args);
202
203         g_warning("%s", buf);
204
205         logtext->instance = instance;
206         logtext->text = g_strdup(buf + LOG_TIME_LEN);
207         logtext->type = LOG_WARN;
208         
209         g_timeout_add(0, invoke_hook_cb, logtext);
210
211         if (log_fp[instance] && prefs_common_enable_log_warning()) {
212                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
213                 fputs("** warning: ", log_fp[instance]);
214                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
215                 fflush(log_fp[instance]);
216         }
217 }
218
219 void log_error(LogInstance instance, const gchar *format, ...)
220 {
221         va_list args;
222         gchar buf[BUFFSIZE + LOG_TIME_LEN];
223         time_t t;
224         LogText *logtext = g_new0(LogText, 1);
225         struct tm buft;
226
227         time(&t);
228         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
229
230         va_start(args, format);
231         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
232         va_end(args);
233
234         g_warning("%s", buf);
235
236         logtext->instance = instance;
237         logtext->text = g_strdup(buf + LOG_TIME_LEN);
238         logtext->type = LOG_ERROR;
239         
240         g_timeout_add(0, invoke_hook_cb, logtext);
241
242         if (log_fp[instance] && prefs_common_enable_log_error()) {
243                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
244                 fputs("*** error: ", log_fp[instance]);
245                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
246                 fflush(log_fp[instance]);
247         }
248 }
249
250 void log_status_ok(LogInstance instance, const gchar *format, ...)
251 {
252         va_list args;
253         gchar buf[BUFFSIZE + LOG_TIME_LEN];
254         time_t t;
255         LogText *logtext = g_new0(LogText, 1);
256         struct tm buft;
257
258         time(&t);
259         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
260
261         va_start(args, format);
262         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
263         va_end(args);
264
265         if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
266
267         logtext->instance = instance;
268         logtext->text = g_strdup(buf + LOG_TIME_LEN);
269         logtext->type = LOG_STATUS_OK;
270         
271         g_timeout_add(0, invoke_hook_cb, logtext);
272
273         if (log_fp[instance] && prefs_common_enable_log_status()) {
274                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
275                 fputs("* OK: ", log_fp[instance]);
276                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
277                 fflush(log_fp[instance]);
278         }
279 }
280
281 void log_status_nok(LogInstance instance, const gchar *format, ...)
282 {
283         va_list args;
284         gchar buf[BUFFSIZE + LOG_TIME_LEN];
285         time_t t;
286         LogText *logtext = g_new0(LogText, 1);
287         struct tm buft;
288
289         time(&t);
290         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
291
292         va_start(args, format);
293         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
294         va_end(args);
295
296         if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
297
298         logtext->instance = instance;
299         logtext->text = g_strdup(buf + LOG_TIME_LEN);
300         logtext->type = LOG_STATUS_NOK;
301         
302         g_timeout_add(0, invoke_hook_cb, logtext);
303
304         if (log_fp[instance] && prefs_common_enable_log_status()) {
305                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
306                 fputs("* NOT OK: ", log_fp[instance]);
307                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
308                 fflush(log_fp[instance]);
309         }
310 }
311
312 void log_status_skip(LogInstance instance, const gchar *format, ...)
313 {
314         va_list args;
315         gchar buf[BUFFSIZE + LOG_TIME_LEN];
316         time_t t;
317         LogText *logtext = g_new0(LogText, 1);
318         struct tm buft;
319
320         time(&t);
321         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
322
323         va_start(args, format);
324         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
325         va_end(args);
326
327         if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
328
329         logtext->instance = instance;
330         logtext->text = g_strdup(buf + LOG_TIME_LEN);
331         logtext->type = LOG_STATUS_SKIP;
332         
333         g_timeout_add(0, invoke_hook_cb, logtext);
334
335         if (log_fp[instance] && prefs_common_enable_log_status()) {
336                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
337                 fputs("* SKIPPED: ", log_fp[instance]);
338                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
339                 fflush(log_fp[instance]);
340         }
341 }