2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2012 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/>.
22 #include "claws-features.h"
33 #include <glib/gi18n.h>
39 #define FWRITE(_b,_s,_n,_f) if (fwrite(_b,_s,_n,_f) != _n) { \
40 g_message("log fwrite failed!\n"); \
43 #define FPUTS(_b,_f) if (fputs(_b,_f) == EOF) { \
44 g_message("log fputs failed!\n"); \
47 #define FFLUSH(_f) if (fflush(_f) != 0) { \
48 g_message("log fflush failed!\n"); \
52 static FILE *log_fp
[LOG_INSTANCE_MAX
] = {
57 static size_t log_size
[LOG_INSTANCE_MAX
] = {
62 static gchar
*log_filename
[LOG_INSTANCE_MAX
] = {
67 typedef struct _LogInstanceData LogInstanceData
;
69 struct _LogInstanceData
{
72 int *prefs_logwin_width
;
73 int *prefs_logwin_height
;
76 static LogInstanceData log_instances
[LOG_INSTANCE_MAX
] = {
77 { LOG_APPEND_TEXT_HOOKLIST
, NULL
, NULL
, NULL
},
78 { DEBUG_FILTERING_APPEND_TEXT_HOOKLIST
, NULL
, NULL
, NULL
}
81 gboolean
prefs_common_enable_log_standard(void);
82 gboolean
prefs_common_enable_log_warning(void);
83 gboolean
prefs_common_enable_log_error(void);
84 gboolean
prefs_common_enable_log_status(void);
86 static gboolean
invoke_hook_cb (gpointer data
)
88 LogText
*logtext
= (LogText
*)data
;
89 hooks_invoke(get_log_hook(logtext
->instance
), logtext
);
90 g_free(logtext
->text
);
95 void set_log_file(LogInstance instance
, const gchar
*filename
)
97 gchar
*fullname
= NULL
;
101 if (!g_path_is_absolute(filename
)) {
102 fullname
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
105 fullname
= g_strdup(filename
);
107 /* backup old logfile if existing */
108 if (is_file_exist(fullname
)) {
111 backupname
= g_strconcat(fullname
, ".bak", NULL
);
112 claws_unlink(backupname
);
113 if (g_rename(fullname
, backupname
) < 0)
114 FILE_OP_ERROR(fullname
, "rename");
118 log_fp
[instance
] = g_fopen(fullname
, "wb");
119 if (!log_fp
[instance
]) {
120 FILE_OP_ERROR(fullname
, "fopen");
121 log_filename
[instance
] = NULL
;
125 log_filename
[instance
] = g_strdup(fullname
);
126 log_size
[instance
] = 0;
130 void close_log_file(LogInstance instance
)
132 if (log_fp
[instance
]) {
133 fclose(log_fp
[instance
]);
134 log_fp
[instance
] = NULL
;
135 log_size
[instance
] = 0;
136 g_free(log_filename
[instance
]);
137 log_filename
[instance
] = NULL
;
141 static void rotate_log(LogInstance instance
)
143 if (log_size
[instance
] > 10 * 1024* 1024) {
144 gchar
*filename
= g_strdup(log_filename
[instance
]);
145 debug_print("rotating %s\n", filename
);
146 close_log_file(instance
);
147 set_log_file(instance
, filename
);
152 const char *get_log_hook(LogInstance instance
)
154 return log_instances
[instance
].hook
;
157 void set_log_title(LogInstance instance
, gchar
*title
)
159 log_instances
[instance
].title
= title
;
162 gchar
*get_log_title(LogInstance instance
)
164 return log_instances
[instance
].title
;
167 void set_log_prefs(LogInstance instance
, int* logwin_width
, int* logwin_height
)
169 log_instances
[instance
].prefs_logwin_width
= logwin_width
;
170 log_instances
[instance
].prefs_logwin_height
= logwin_height
;
173 void get_log_prefs(LogInstance instance
, int** logwin_width
, int** logwin_height
)
176 *logwin_width
= log_instances
[instance
].prefs_logwin_width
;
178 *logwin_height
= log_instances
[instance
].prefs_logwin_height
;
181 void log_print(LogInstance instance
, const gchar
*format
, ...)
184 gchar buf
[BUFFSIZE
+ LOG_TIME_LEN
];
186 LogText
*logtext
= g_new0(LogText
, 1);
190 strftime(buf
, LOG_TIME_LEN
+ 1, "[%H:%M:%S] ", localtime_r(&t
, &buft
));
192 va_start(args
, format
);
193 g_vsnprintf(buf
+ LOG_TIME_LEN
, BUFFSIZE
, format
, args
);
196 if (debug_get_mode()) g_print("%s", buf
);
198 logtext
->instance
= instance
;
199 logtext
->text
= g_strdup(buf
);
200 logtext
->type
= LOG_NORMAL
;
202 g_timeout_add(0, invoke_hook_cb
, logtext
);
204 if (log_fp
[instance
] && prefs_common_enable_log_standard()) {
205 FPUTS(buf
, log_fp
[instance
])
206 log_size
[instance
] += strlen(buf
);
207 FFLUSH(log_fp
[instance
])
208 rotate_log(instance
);
212 void log_message(LogInstance instance
, const gchar
*format
, ...)
215 gchar buf
[BUFFSIZE
+ LOG_TIME_LEN
];
217 LogText
*logtext
= g_new0(LogText
, 1);
221 strftime(buf
, LOG_TIME_LEN
+ 1, "[%H:%M:%S] ", localtime_r(&t
, &buft
));
223 va_start(args
, format
);
224 g_vsnprintf(buf
+ LOG_TIME_LEN
, BUFFSIZE
, format
, args
);
227 if (debug_get_mode()) g_message("%s", buf
+ LOG_TIME_LEN
);
229 logtext
->instance
= instance
;
230 logtext
->text
= g_strdup(buf
+ LOG_TIME_LEN
);
231 logtext
->type
= LOG_MSG
;
233 g_timeout_add(0, invoke_hook_cb
, logtext
);
235 if (log_fp
[instance
] && prefs_common_enable_log_standard()) {
236 FWRITE(buf
, 1, LOG_TIME_LEN
, log_fp
[instance
])
237 FPUTS("* message: ", log_fp
[instance
])
238 log_size
[instance
] += strlen("* message: ");
239 FPUTS(buf
+ LOG_TIME_LEN
, log_fp
[instance
])
240 log_size
[instance
] += strlen(buf
);
241 FFLUSH(log_fp
[instance
])
242 rotate_log(instance
);
246 void log_warning(LogInstance instance
, const gchar
*format
, ...)
249 gchar buf
[BUFFSIZE
+ LOG_TIME_LEN
];
251 LogText
*logtext
= g_new0(LogText
, 1);
255 strftime(buf
, LOG_TIME_LEN
+ 1, "[%H:%M:%S] ", localtime_r(&t
, &buft
));
257 va_start(args
, format
);
258 g_vsnprintf(buf
+ LOG_TIME_LEN
, BUFFSIZE
, format
, args
);
261 g_warning("%s", buf
);
263 logtext
->instance
= instance
;
264 logtext
->text
= g_strdup(buf
+ LOG_TIME_LEN
);
265 logtext
->type
= LOG_WARN
;
267 g_timeout_add(0, invoke_hook_cb
, logtext
);
269 if (log_fp
[instance
] && prefs_common_enable_log_warning()) {
270 FWRITE(buf
, 1, LOG_TIME_LEN
, log_fp
[instance
])
271 FPUTS("** warning: ", log_fp
[instance
])
272 log_size
[instance
] += strlen("** warning: ");
273 FPUTS(buf
+ LOG_TIME_LEN
, log_fp
[instance
])
274 log_size
[instance
] += strlen(buf
);
275 FFLUSH(log_fp
[instance
])
276 rotate_log(instance
);
280 void log_error(LogInstance instance
, const gchar
*format
, ...)
283 gchar buf
[BUFFSIZE
+ LOG_TIME_LEN
];
285 LogText
*logtext
= g_new0(LogText
, 1);
289 strftime(buf
, LOG_TIME_LEN
+ 1, "[%H:%M:%S] ", localtime_r(&t
, &buft
));
291 va_start(args
, format
);
292 g_vsnprintf(buf
+ LOG_TIME_LEN
, BUFFSIZE
, format
, args
);
295 g_warning("%s", buf
);
297 logtext
->instance
= instance
;
298 logtext
->text
= g_strdup(buf
+ LOG_TIME_LEN
);
299 logtext
->type
= LOG_ERROR
;
301 g_timeout_add(0, invoke_hook_cb
, logtext
);
303 if (log_fp
[instance
] && prefs_common_enable_log_error()) {
304 FWRITE(buf
, 1, LOG_TIME_LEN
, log_fp
[instance
])
305 FPUTS("*** error: ", log_fp
[instance
])
306 log_size
[instance
] += strlen("*** error: ");
307 FPUTS(buf
+ LOG_TIME_LEN
, log_fp
[instance
])
308 log_size
[instance
] += strlen(buf
);
309 FFLUSH(log_fp
[instance
])
310 rotate_log(instance
);
314 void log_status_ok(LogInstance instance
, const gchar
*format
, ...)
317 gchar buf
[BUFFSIZE
+ LOG_TIME_LEN
];
319 LogText
*logtext
= g_new0(LogText
, 1);
323 strftime(buf
, LOG_TIME_LEN
+ 1, "[%H:%M:%S] ", localtime_r(&t
, &buft
));
325 va_start(args
, format
);
326 g_vsnprintf(buf
+ LOG_TIME_LEN
, BUFFSIZE
, format
, args
);
329 if (debug_get_mode()) g_message("%s", buf
+ LOG_TIME_LEN
);
331 logtext
->instance
= instance
;
332 logtext
->text
= g_strdup(buf
+ LOG_TIME_LEN
);
333 logtext
->type
= LOG_STATUS_OK
;
335 g_timeout_add(0, invoke_hook_cb
, logtext
);
337 if (log_fp
[instance
] && prefs_common_enable_log_status()) {
338 FWRITE(buf
, 1, LOG_TIME_LEN
, log_fp
[instance
])
339 FPUTS("* OK: ", log_fp
[instance
])
340 log_size
[instance
] += strlen("* OK: ");
341 FPUTS(buf
+ LOG_TIME_LEN
, log_fp
[instance
])
342 log_size
[instance
] += strlen(buf
);
343 FFLUSH(log_fp
[instance
])
344 rotate_log(instance
);
348 void log_status_nok(LogInstance instance
, const gchar
*format
, ...)
351 gchar buf
[BUFFSIZE
+ LOG_TIME_LEN
];
353 LogText
*logtext
= g_new0(LogText
, 1);
357 strftime(buf
, LOG_TIME_LEN
+ 1, "[%H:%M:%S] ", localtime_r(&t
, &buft
));
359 va_start(args
, format
);
360 g_vsnprintf(buf
+ LOG_TIME_LEN
, BUFFSIZE
, format
, args
);
363 if (debug_get_mode()) g_message("%s", buf
+ LOG_TIME_LEN
);
365 logtext
->instance
= instance
;
366 logtext
->text
= g_strdup(buf
+ LOG_TIME_LEN
);
367 logtext
->type
= LOG_STATUS_NOK
;
369 g_timeout_add(0, invoke_hook_cb
, logtext
);
371 if (log_fp
[instance
] && prefs_common_enable_log_status()) {
372 FWRITE(buf
, 1, LOG_TIME_LEN
, log_fp
[instance
])
373 FPUTS("* NOT OK: ", log_fp
[instance
])
374 log_size
[instance
] += strlen("* NOT OK: ");
375 FPUTS(buf
+ LOG_TIME_LEN
, log_fp
[instance
])
376 log_size
[instance
] += strlen(buf
);
377 FFLUSH(log_fp
[instance
])
378 rotate_log(instance
);
382 void log_status_skip(LogInstance instance
, const gchar
*format
, ...)
385 gchar buf
[BUFFSIZE
+ LOG_TIME_LEN
];
387 LogText
*logtext
= g_new0(LogText
, 1);
391 strftime(buf
, LOG_TIME_LEN
+ 1, "[%H:%M:%S] ", localtime_r(&t
, &buft
));
393 va_start(args
, format
);
394 g_vsnprintf(buf
+ LOG_TIME_LEN
, BUFFSIZE
, format
, args
);
397 if (debug_get_mode()) g_message("%s", buf
+ LOG_TIME_LEN
);
399 logtext
->instance
= instance
;
400 logtext
->text
= g_strdup(buf
+ LOG_TIME_LEN
);
401 logtext
->type
= LOG_STATUS_SKIP
;
403 g_timeout_add(0, invoke_hook_cb
, logtext
);
405 if (log_fp
[instance
] && prefs_common_enable_log_status()) {
406 FWRITE(buf
, 1, LOG_TIME_LEN
, log_fp
[instance
])
407 FPUTS("* SKIPPED: ", log_fp
[instance
])
408 log_size
[instance
] += strlen("* SKIPPED: ");
409 FPUTS(buf
+ LOG_TIME_LEN
, log_fp
[instance
])
410 log_size
[instance
] += strlen(buf
);
411 FFLUSH(log_fp
[instance
])
412 rotate_log(instance
);