4391764dc96cfcc234ebd07c05b743c8eb9c2723
[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 2 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, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
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 static gboolean invoke_hook_cb (gpointer data)
58 {
59         LogText *logtext = (LogText *)data;
60         hooks_invoke(get_log_hook(logtext->instance), logtext);
61         g_free(logtext->text);
62         g_free(logtext);
63         return FALSE;
64 }
65
66 void set_log_file(LogInstance instance, const gchar *filename)
67 {
68         if (log_fp[instance])
69                 return;
70
71         /* backup old logfile if existing */
72         if (is_file_exist(filename)) {
73                 gchar *backupname;
74                 
75                 backupname = g_strconcat(filename, ".bak", NULL);
76                 if (rename(filename, backupname) < 0)
77                         FILE_OP_ERROR(filename, "rename");
78                 g_free(backupname);
79         }
80
81         log_fp[instance] = g_fopen(filename, "wb");
82         if (!log_fp[instance])
83                 FILE_OP_ERROR(filename, "fopen");
84 }
85
86 void close_log_file(LogInstance instance)
87 {
88         if (log_fp[instance]) {
89                 fclose(log_fp[instance]);
90                 log_fp[instance] = NULL;
91         }
92 }
93
94 const char *get_log_hook(LogInstance instance)
95 {
96         return log_instances[instance].hook;
97 }
98
99 void set_log_title(LogInstance instance, gchar *title)
100 {
101         log_instances[instance].title = title;
102 }
103
104 gchar *get_log_title(LogInstance instance)
105 {
106         return log_instances[instance].title;
107 }
108
109 void set_log_prefs(LogInstance instance, int* logwin_width, int* logwin_height)
110 {
111         log_instances[instance].prefs_logwin_width = logwin_width;
112         log_instances[instance].prefs_logwin_height = logwin_height;
113 }
114
115 void get_log_prefs(LogInstance instance, int** logwin_width, int** logwin_height)
116 {
117         if (logwin_width)
118                 *logwin_width = log_instances[instance].prefs_logwin_width;
119         if (logwin_height)
120                 *logwin_height = log_instances[instance].prefs_logwin_height;
121 }
122
123 void log_print(LogInstance instance, const gchar *format, ...)
124 {
125         va_list args;
126         gchar buf[BUFFSIZE + LOG_TIME_LEN];
127         time_t t;
128         LogText *logtext = g_new0(LogText, 1);
129         struct tm buft;
130
131         time(&t);
132         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
133
134         va_start(args, format);
135         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
136         va_end(args);
137
138         if (debug_get_mode()) fputs(buf, stdout);
139
140         logtext->instance = instance;
141         logtext->text = g_strdup(buf);
142         logtext->type = LOG_NORMAL;
143         
144         g_timeout_add(0, invoke_hook_cb, logtext);
145         
146         if (log_fp[instance]) {
147                 fputs(buf, log_fp[instance]);
148                 fflush(log_fp[instance]);
149         }
150 }
151
152 void log_message(LogInstance instance, const gchar *format, ...)
153 {
154         va_list args;
155         gchar buf[BUFFSIZE + LOG_TIME_LEN];
156         time_t t;
157         LogText *logtext = g_new0(LogText, 1);
158         struct tm buft;
159
160         time(&t);
161         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
162
163         va_start(args, format);
164         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
165         va_end(args);
166
167         if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
168
169         logtext->instance = instance;
170         logtext->text = g_strdup(buf + LOG_TIME_LEN);
171         logtext->type = LOG_MSG;
172         
173         g_timeout_add(0, invoke_hook_cb, logtext);
174
175         if (log_fp[instance]) {
176                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
177                 fputs("* message: ", log_fp[instance]);
178                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
179                 fflush(log_fp[instance]);
180         }
181 }
182
183 void log_warning(LogInstance instance, const gchar *format, ...)
184 {
185         va_list args;
186         gchar buf[BUFFSIZE + LOG_TIME_LEN];
187         time_t t;
188         LogText *logtext = g_new0(LogText, 1);
189         struct tm buft;
190
191         time(&t);
192         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
193
194         va_start(args, format);
195         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
196         va_end(args);
197
198         g_warning("%s", buf);
199
200         logtext->instance = instance;
201         logtext->text = g_strdup(buf + LOG_TIME_LEN);
202         logtext->type = LOG_WARN;
203         
204         g_timeout_add(0, invoke_hook_cb, logtext);
205
206         if (log_fp[instance]) {
207                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
208                 fputs("** warning: ", log_fp[instance]);
209                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
210                 fflush(log_fp[instance]);
211         }
212 }
213
214 void log_error(LogInstance instance, const gchar *format, ...)
215 {
216         va_list args;
217         gchar buf[BUFFSIZE + LOG_TIME_LEN];
218         time_t t;
219         LogText *logtext = g_new0(LogText, 1);
220         struct tm buft;
221
222         time(&t);
223         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
224
225         va_start(args, format);
226         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
227         va_end(args);
228
229         g_warning("%s", buf);
230
231         logtext->instance = instance;
232         logtext->text = g_strdup(buf + LOG_TIME_LEN);
233         logtext->type = LOG_ERROR;
234         
235         g_timeout_add(0, invoke_hook_cb, logtext);
236
237         if (log_fp[instance]) {
238                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
239                 fputs("*** error: ", log_fp[instance]);
240                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
241                 fflush(log_fp[instance]);
242         }
243 }
244
245 void log_status_ok(LogInstance instance, const gchar *format, ...)
246 {
247         va_list args;
248         gchar buf[BUFFSIZE + LOG_TIME_LEN];
249         time_t t;
250         LogText *logtext = g_new0(LogText, 1);
251         struct tm buft;
252
253         time(&t);
254         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
255
256         va_start(args, format);
257         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
258         va_end(args);
259
260         if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
261
262         logtext->instance = instance;
263         logtext->text = g_strdup(buf + LOG_TIME_LEN);
264         logtext->type = LOG_STATUS_OK;
265         
266         g_timeout_add(0, invoke_hook_cb, logtext);
267
268         if (log_fp[instance]) {
269                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
270                 fputs("* OK: ", log_fp[instance]);
271                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
272                 fflush(log_fp[instance]);
273         }
274 }
275
276 void log_status_nok(LogInstance instance, const gchar *format, ...)
277 {
278         va_list args;
279         gchar buf[BUFFSIZE + LOG_TIME_LEN];
280         time_t t;
281         LogText *logtext = g_new0(LogText, 1);
282         struct tm buft;
283
284         time(&t);
285         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
286
287         va_start(args, format);
288         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
289         va_end(args);
290
291         if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
292
293         logtext->instance = instance;
294         logtext->text = g_strdup(buf + LOG_TIME_LEN);
295         logtext->type = LOG_STATUS_NOK;
296         
297         g_timeout_add(0, invoke_hook_cb, logtext);
298
299         if (log_fp[instance]) {
300                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
301                 fputs("* NOT OK: ", log_fp[instance]);
302                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
303                 fflush(log_fp[instance]);
304         }
305 }
306
307 void log_status_skip(LogInstance instance, const gchar *format, ...)
308 {
309         va_list args;
310         gchar buf[BUFFSIZE + LOG_TIME_LEN];
311         time_t t;
312         LogText *logtext = g_new0(LogText, 1);
313         struct tm buft;
314
315         time(&t);
316         strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
317
318         va_start(args, format);
319         g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
320         va_end(args);
321
322         if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
323
324         logtext->instance = instance;
325         logtext->text = g_strdup(buf + LOG_TIME_LEN);
326         logtext->type = LOG_STATUS_SKIP;
327         
328         g_timeout_add(0, invoke_hook_cb, logtext);
329
330         if (log_fp[instance]) {
331                 fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
332                 fputs("* SKIPPED: ", log_fp[instance]);
333                 fputs(buf + LOG_TIME_LEN, log_fp[instance]);
334                 fflush(log_fp[instance]);
335         }
336 }