2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2009 Hiroyuki Yamamoto and the Claws Mail team
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.
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.
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/>.
32 #include <glib/gi18n.h>
38 static FILE *log_fp[LOG_INSTANCE_MAX] = {
43 static size_t log_size[LOG_INSTANCE_MAX] = {
48 static gchar *log_filename[LOG_INSTANCE_MAX] = {
53 typedef struct _LogInstanceData LogInstanceData;
55 struct _LogInstanceData {
58 int *prefs_logwin_width;
59 int *prefs_logwin_height;
62 static LogInstanceData log_instances[LOG_INSTANCE_MAX] = {
63 { LOG_APPEND_TEXT_HOOKLIST, NULL, NULL, NULL },
64 { DEBUG_FILTERING_APPEND_TEXT_HOOKLIST, NULL, NULL, NULL }
67 gboolean prefs_common_enable_log_standard(void);
68 gboolean prefs_common_enable_log_warning(void);
69 gboolean prefs_common_enable_log_error(void);
70 gboolean prefs_common_enable_log_status(void);
72 static gboolean invoke_hook_cb (gpointer data)
74 LogText *logtext = (LogText *)data;
75 hooks_invoke(get_log_hook(logtext->instance), logtext);
76 g_free(logtext->text);
81 void set_log_file(LogInstance instance, const gchar *filename)
83 gchar *fullname = NULL;
87 if (!g_path_is_absolute(filename)) {
88 fullname = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
91 fullname = g_strdup(filename);
93 /* backup old logfile if existing */
94 if (is_file_exist(fullname)) {
97 backupname = g_strconcat(fullname, ".bak", NULL);
98 claws_unlink(backupname);
99 if (g_rename(fullname, backupname) < 0)
100 FILE_OP_ERROR(fullname, "rename");
104 log_fp[instance] = g_fopen(fullname, "wb");
105 if (!log_fp[instance]) {
106 FILE_OP_ERROR(fullname, "fopen");
107 log_filename[instance] = NULL;
111 log_filename[instance] = g_strdup(fullname);
112 log_size[instance] = 0;
116 void close_log_file(LogInstance instance)
118 if (log_fp[instance]) {
119 fclose(log_fp[instance]);
120 log_fp[instance] = NULL;
121 log_size[instance] = 0;
122 g_free(log_filename[instance]);
123 log_filename[instance] = NULL;
127 static void rotate_log(LogInstance instance)
129 if (log_size[instance] > 10 * 1024* 1024) {
130 gchar *filename = g_strdup(log_filename[instance]);
131 debug_print("rotating %s\n", filename);
132 close_log_file(instance);
133 set_log_file(instance, filename);
138 const char *get_log_hook(LogInstance instance)
140 return log_instances[instance].hook;
143 void set_log_title(LogInstance instance, gchar *title)
145 log_instances[instance].title = title;
148 gchar *get_log_title(LogInstance instance)
150 return log_instances[instance].title;
153 void set_log_prefs(LogInstance instance, int* logwin_width, int* logwin_height)
155 log_instances[instance].prefs_logwin_width = logwin_width;
156 log_instances[instance].prefs_logwin_height = logwin_height;
159 void get_log_prefs(LogInstance instance, int** logwin_width, int** logwin_height)
162 *logwin_width = log_instances[instance].prefs_logwin_width;
164 *logwin_height = log_instances[instance].prefs_logwin_height;
167 void log_print(LogInstance instance, const gchar *format, ...)
170 gchar buf[BUFFSIZE + LOG_TIME_LEN];
172 LogText *logtext = g_new0(LogText, 1);
176 strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
178 va_start(args, format);
179 g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
182 if (debug_get_mode()) g_print("%s", buf);
184 logtext->instance = instance;
185 logtext->text = g_strdup(buf);
186 logtext->type = LOG_NORMAL;
188 g_timeout_add(0, invoke_hook_cb, logtext);
190 if (log_fp[instance] && prefs_common_enable_log_standard()) {
192 r = fputs(buf, log_fp[instance]);
193 log_size[instance] += strlen(buf);
194 r = fflush(log_fp[instance]);
195 rotate_log(instance);
199 void log_message(LogInstance instance, const gchar *format, ...)
202 gchar buf[BUFFSIZE + LOG_TIME_LEN];
204 LogText *logtext = g_new0(LogText, 1);
208 strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
210 va_start(args, format);
211 g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
214 if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
216 logtext->instance = instance;
217 logtext->text = g_strdup(buf + LOG_TIME_LEN);
218 logtext->type = LOG_MSG;
220 g_timeout_add(0, invoke_hook_cb, logtext);
222 if (log_fp[instance] && prefs_common_enable_log_standard()) {
224 r = fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
225 r = fputs("* message: ", log_fp[instance]);
226 log_size[instance] += strlen("* message: ");
227 r = fputs(buf + LOG_TIME_LEN, log_fp[instance]);
228 log_size[instance] += strlen(buf);
229 r = fflush(log_fp[instance]);
230 rotate_log(instance);
234 void log_warning(LogInstance instance, const gchar *format, ...)
237 gchar buf[BUFFSIZE + LOG_TIME_LEN];
239 LogText *logtext = g_new0(LogText, 1);
243 strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
245 va_start(args, format);
246 g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
249 g_warning("%s", buf);
251 logtext->instance = instance;
252 logtext->text = g_strdup(buf + LOG_TIME_LEN);
253 logtext->type = LOG_WARN;
255 g_timeout_add(0, invoke_hook_cb, logtext);
257 if (log_fp[instance] && prefs_common_enable_log_warning()) {
259 r = fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
260 r = fputs("** warning: ", log_fp[instance]);
261 log_size[instance] += strlen("** warning: ");
262 r = fputs(buf + LOG_TIME_LEN, log_fp[instance]);
263 log_size[instance] += strlen(buf);
264 r = fflush(log_fp[instance]);
265 rotate_log(instance);
269 void log_error(LogInstance instance, const gchar *format, ...)
272 gchar buf[BUFFSIZE + LOG_TIME_LEN];
274 LogText *logtext = g_new0(LogText, 1);
278 strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
280 va_start(args, format);
281 g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
284 g_warning("%s", buf);
286 logtext->instance = instance;
287 logtext->text = g_strdup(buf + LOG_TIME_LEN);
288 logtext->type = LOG_ERROR;
290 g_timeout_add(0, invoke_hook_cb, logtext);
292 if (log_fp[instance] && prefs_common_enable_log_error()) {
294 r = fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
295 r = fputs("*** error: ", log_fp[instance]);
296 log_size[instance] += strlen("*** error: ");
297 r = fputs(buf + LOG_TIME_LEN, log_fp[instance]);
298 log_size[instance] += strlen(buf);
299 r = fflush(log_fp[instance]);
300 rotate_log(instance);
304 void log_status_ok(LogInstance instance, const gchar *format, ...)
307 gchar buf[BUFFSIZE + LOG_TIME_LEN];
309 LogText *logtext = g_new0(LogText, 1);
313 strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
315 va_start(args, format);
316 g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
319 if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
321 logtext->instance = instance;
322 logtext->text = g_strdup(buf + LOG_TIME_LEN);
323 logtext->type = LOG_STATUS_OK;
325 g_timeout_add(0, invoke_hook_cb, logtext);
327 if (log_fp[instance] && prefs_common_enable_log_status()) {
329 r = fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
330 r = fputs("* OK: ", log_fp[instance]);
331 log_size[instance] += strlen("* OK: ");
332 r = fputs(buf + LOG_TIME_LEN, log_fp[instance]);
333 log_size[instance] += strlen(buf);
334 r = fflush(log_fp[instance]);
335 rotate_log(instance);
339 void log_status_nok(LogInstance instance, const gchar *format, ...)
342 gchar buf[BUFFSIZE + LOG_TIME_LEN];
344 LogText *logtext = g_new0(LogText, 1);
348 strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
350 va_start(args, format);
351 g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
354 if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
356 logtext->instance = instance;
357 logtext->text = g_strdup(buf + LOG_TIME_LEN);
358 logtext->type = LOG_STATUS_NOK;
360 g_timeout_add(0, invoke_hook_cb, logtext);
362 if (log_fp[instance] && prefs_common_enable_log_status()) {
364 r = fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
365 r = fputs("* NOT OK: ", log_fp[instance]);
366 log_size[instance] += strlen("* NOT OK: ");
367 r = fputs(buf + LOG_TIME_LEN, log_fp[instance]);
368 log_size[instance] += strlen(buf);
369 r = fflush(log_fp[instance]);
370 rotate_log(instance);
374 void log_status_skip(LogInstance instance, const gchar *format, ...)
377 gchar buf[BUFFSIZE + LOG_TIME_LEN];
379 LogText *logtext = g_new0(LogText, 1);
383 strftime(buf, LOG_TIME_LEN + 1, "[%H:%M:%S] ", localtime_r(&t, &buft));
385 va_start(args, format);
386 g_vsnprintf(buf + LOG_TIME_LEN, BUFFSIZE, format, args);
389 if (debug_get_mode()) g_message("%s", buf + LOG_TIME_LEN);
391 logtext->instance = instance;
392 logtext->text = g_strdup(buf + LOG_TIME_LEN);
393 logtext->type = LOG_STATUS_SKIP;
395 g_timeout_add(0, invoke_hook_cb, logtext);
397 if (log_fp[instance] && prefs_common_enable_log_status()) {
399 r = fwrite(buf, 1, LOG_TIME_LEN, log_fp[instance]);
400 r = fputs("* SKIPPED: ", log_fp[instance]);
401 log_size[instance] += strlen("* SKIPPED: ");
402 r = fputs(buf + LOG_TIME_LEN, log_fp[instance]);
403 log_size[instance] += strlen(buf);
404 r = fflush(log_fp[instance]);
405 rotate_log(instance);