+ silc_free(log->filename);
+ log->filename = NULL;
+ log->fp = NULL;
+ }
+
+ if (fp) {
+ log->filename = strdup(filename);
+ log->fp = fp;
+ log->maxsize = maxsize;
+ }
+
+ if (silc_log_scheduled)
+ return TRUE;
+
+ /* 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, 10, 0,
+ SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+
+ silc_log_scheduled = TRUE;
+
+ return TRUE;
+}
+
+/* Sets a log callback, set callback to NULL to return to default behaviour */
+
+void silc_log_set_callback(SilcLogType type, SilcLogCb cb, void *context)
+{
+ SilcLog log;
+
+ if (!(log = silc_log_find_by_type(type)))
+ return;
+
+ log->cb = cb;
+ log->context = context;
+}
+
+/* Resets log callbacks */
+
+void silc_log_reset_callbacks()
+{
+ unsigned int u;
+ SILC_FOREACH_LOG(u) {
+ silclogs[u].cb = NULL;
+ silclogs[u].context = NULL;
+ }
+}
+
+/* Flushes all opened logging channels */
+
+void silc_log_flush_all() {
+ unsigned int u;
+ SILC_LOG_DEBUG(("Flushing all logs"));
+ SILC_FOREACH_LOG(u) {
+ if (silclogs[u].fp)
+ fflush(silclogs[u].fp);
+ }
+}
+
+/* Resets all known logging channels */
+
+void silc_log_reset_all() {
+ unsigned int u;
+ SILC_LOG_DEBUG(("Resetting all logs"));
+ SILC_FOREACH_LOG(u)
+ silc_log_reset(&silclogs[u]);
+}
+
+/* Outputs the debug message to stderr. */
+
+void silc_log_output_debug(char *file, char *function,
+ int line, char *string)
+{
+ 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))
+ goto end;
+
+ if (silc_log_debug_cb) {
+ if ((*silc_log_debug_cb)(file, function, line, string,
+ silc_log_debug_context))
+ goto end;
+ }