#include "silcincludes.h"
-/* default flush time (5 minutes) */
-#define SILC_LOG_TIMEOUT 300
+/* Minimum time delay for log flushing calls (in seconds) */
+#define SILC_LOG_FLUSH_MIN_DELAY 2
/* nice macro for looping through all logs -- makes the code more readable */
#define SILC_FOREACH_LOG(__x__) for (__x__ = 0; __x__ < SILC_LOG_MAX; __x__++)
struct SilcLogStruct {
char *filename;
FILE *fp;
- uint32 maxsize;
+ SilcUInt32 maxsize;
char *typename;
SilcLogType type;
SilcLogCb cb;
/* These are the known logging channels */
static struct SilcLogStruct silclogs[SILC_LOG_MAX] = {
{NULL, NULL, 0, "Info", SILC_LOG_INFO, NULL, NULL},
- {NULL, NULL, 0, "Error", SILC_LOG_ERROR, NULL, NULL},
{NULL, NULL, 0, "Warning", SILC_LOG_WARNING, NULL, NULL},
+ {NULL, NULL, 0, "Error", SILC_LOG_ERROR, NULL, NULL},
{NULL, NULL, 0, "Fatal", SILC_LOG_FATAL, NULL, NULL},
};
bool silc_debug = FALSE;
bool silc_debug_hexdump = FALSE;
+/* Flush delay */
+long silc_log_flushdelay = 300;
+
/* Regular pattern matching expression for the debug output */
-static char *silc_log_debug_string = NULL;
+char *silc_log_debug_string = NULL;
/* Debug callbacks. If set these are used instead of default ones. */
static SilcLogDebugCb silc_log_debug_cb = NULL;
static bool silc_log_scheduled = FALSE;
static bool silc_log_no_init = FALSE;
+/* This is only needed during starting up -- don't lose any logging */
+static bool silc_log_starting = TRUE;
+
/* The type wrapper utility. Translates a SilcLogType id to the corresponding
* logfile, or NULL if not found. */
static SilcLog silc_log_find_by_type(SilcLogType type)
fflush(log->fp);
fclose(log->fp);
}
+ if (!log->filename) return FALSE;
if (!(log->fp = fopen(log->filename, "a+"))) {
SILC_LOG_WARNING(("Couldn't reset logfile %s for type \"%s\": %s",
log->filename, log->typename, strerror(errno)));
SILC_FOREACH_LOG(u)
silc_log_checksize(&silclogs[u]);
}
+ silc_log_starting = FALSE;
+ if (silc_log_flushdelay < SILC_LOG_FLUSH_MIN_DELAY)
+ silc_log_flushdelay = SILC_LOG_FLUSH_MIN_DELAY;
silc_schedule_task_add((SilcSchedule) context, 0, silc_log_fflush_callback,
- context, SILC_LOG_TIMEOUT, 0, SILC_TASK_TIMEOUT,
+ context, silc_log_flushdelay, 0, SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
}
void silc_log_output(SilcLogType type, char *string)
{
char *typename;
+ FILE *fp;
SilcLog log;
if ((type > SILC_LOG_MAX) || !(log = silc_log_find_by_type(type)))
goto end;
}
+ /* save the original typename, because if we redirect the channel we
+ * keep however the original destination channel name */
+ typename = log->typename;
+
if (!silc_log_scheduled) {
if (silc_log_no_init == FALSE) {
- fprintf(stderr,
+ fprintf(stderr,
"Warning, trying to output without log files initialization, "
"log output is going to stderr\n");
silc_log_no_init = TRUE;
}
-
- fprintf(stderr, "%s\n", string);
- goto end;
+ /* redirect output */
+ fp = stderr;
+ log = NULL;
+ goto found;
}
- /* save the original typename, because if we redirect the channel we
- * keep however the original destination channel name */
- typename = log->typename;
-
/* ok, now we have to find an open stream */
while (TRUE) {
- if (log && log->fp) goto found;
+ if (log && (fp = log->fp)) goto found;
if (type == 0) break;
log = silc_log_find_by_type(--type);
}
goto end;
found:
- fprintf(log->fp, "[%s] [%s] %s\n", silc_get_time(), typename, string);
- if (silc_log_quick) {
- fflush(log->fp);
- silc_log_checksize(log);
+ fprintf(fp, "[%s] [%s] %s\n", silc_get_time(), typename, string);
+ if (silc_log_quick || silc_log_starting) {
+ fflush(fp);
+ if (log)
+ silc_log_checksize(log);
}
end:
}
/* Set and initialize the specified logging channel. See the API reference */
-bool silc_log_set_file(SilcLogType type, char *filename, uint32 maxsize,
+bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
SilcSchedule scheduler)
{
FILE *fp = NULL;
if (silc_log_scheduled)
return TRUE;
- /* make sure we write to the disk sometimes */
+ /* add schedule hook with a short delay to make sure we'll use right delay */
silc_schedule_task_add(scheduler, 0, silc_log_fflush_callback,
- (void *) scheduler, SILC_LOG_TIMEOUT, 0,
+ (void *) scheduler, 10, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
silc_log_scheduled = TRUE;
{
if (!silc_debug)
goto end;
+
if (silc_log_debug_string &&
- !silc_string_regex_match(silc_log_debug_string, file) &&
- !silc_string_regex_match(silc_log_debug_string, function))
+ !silc_string_regex_match(silc_log_debug_string, file) &&
+ !silc_string_regex_match(silc_log_debug_string, function))
goto end;
+
if (silc_log_debug_cb) {
if ((*silc_log_debug_cb)(file, function, line, string,
silc_log_debug_context))
goto end;
}
+
fprintf(stderr, "%s:%d: %s\n", function, line, string);
fflush(stderr);
-end:
+
+ end:
silc_free(string);
}
void silc_log_output_hexdump(char *file, char *function,
int line, void *data_in,
- uint32 len, char *string)
+ SilcUInt32 len, char *string)
{
int i, k;
int off, pos, count;
if (!silc_debug_hexdump)
goto end;
+
if (silc_log_debug_string &&
- !silc_string_regex_match(silc_log_debug_string, file) &&
- !silc_string_regex_match(silc_log_debug_string, function))
+ !silc_string_regex_match(silc_log_debug_string, file) &&
+ !silc_string_regex_match(silc_log_debug_string, function))
goto end;
+
if (silc_log_hexdump_cb) {
if ((*silc_log_hexdump_cb)(file, function, line, data_in, len, string,
silc_log_hexdump_context))
}
fprintf(stderr, "%s:%d: %s\n", function, line, string);
- silc_free(string);
k = 0;
pos = 0;
if (count < 16)
break;
}
- return;
-end:
+ end:
silc_free(string);
}