+ return TRUE;
+}
+
+/* Return log filename */
+
+char *silc_log_get_file(SilcLogType type)
+{
+ SilcLog log = silc_log_get_context(type);
+ return log && log->fp ? log->filename : NULL;
+}
+
+/* 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 = silc_log_get_context(type);
+ if (log) {
+ log->cb = cb;
+ log->context = context;
+ }
+}
+
+/* Reset log callbacks */
+
+void silc_log_reset_callbacks(void)
+{
+ SilcLog log;
+ log = silc_log_get_context(SILC_LOG_INFO);
+ log->cb = log->context = NULL;
+ log = silc_log_get_context(SILC_LOG_WARNING);
+ log->cb = log->context = NULL;
+ log = silc_log_get_context(SILC_LOG_ERROR);
+ log->cb = log->context = NULL;
+ log = silc_log_get_context(SILC_LOG_FATAL);
+ log->cb = log->context = NULL;
+}
+
+/* Flush all log files */
+
+void silc_log_flush_all(void)
+{
+ SilcLog log;
+ log = silc_log_get_context(SILC_LOG_INFO);
+ if (log->fp)
+ fflush(log->fp);
+ log = silc_log_get_context(SILC_LOG_WARNING);
+ if (log->fp)
+ fflush(log->fp);
+ log = silc_log_get_context(SILC_LOG_ERROR);
+ if (log->fp)
+ fflush(log->fp);
+ log = silc_log_get_context(SILC_LOG_FATAL);
+ if (log->fp)
+ fflush(log->fp);
+}
+
+/* Reset a log file */
+
+static void silc_log_reset(SilcLog log)
+{
+ if (log->fp) {
+ fflush(log->fp);
+ fclose(log->fp);
+ }
+
+ if (!strlen(log->filename))
+ return;
+
+ log->fp = fopen(log->filename, "a+");
+ if (!log->fp)
+ SILC_LOG_WARNING(("Couldn't reset log file '%s' for type '%s': %s",
+ log->filename, log->typename, strerror(errno)));
+}
+
+/* Reset all log files */
+
+void silc_log_reset_all(void)
+{
+ SilcLog log;
+ log = silc_log_get_context(SILC_LOG_INFO);
+ if (log->fp)
+ silc_log_reset(log);
+ log = silc_log_get_context(SILC_LOG_WARNING);
+ if (log->fp)
+ silc_log_reset(log);
+ log = silc_log_get_context(SILC_LOG_ERROR);
+ if (log->fp)
+ silc_log_reset(log);
+ log = silc_log_get_context(SILC_LOG_FATAL);
+ if (log->fp)
+ silc_log_reset(log);
+ silc_log_flush_all();
+}
+
+/* Sets debug callbacks */
+
+void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
+ void *debug_context,
+ SilcLogHexdumpCb hexdump_cb,
+ void *hexdump_context)
+{
+ silclog.debug_cb = debug_cb;
+ silclog.debug_context = debug_context;
+ silclog.hexdump_cb = hexdump_cb;
+ silclog.hexdump_context = hexdump_context;
+}
+
+/* Resets debug callbacks */
+
+void silc_log_reset_debug_callbacks()
+{
+ silclog.debug_cb = NULL;
+ silclog.debug_context = NULL;
+ silclog.hexdump_cb = NULL;
+ silclog.hexdump_context = NULL;
+}
+
+/* Set current debug string */
+
+void silc_log_set_debug_string(const char *debug_string)
+{
+ char *string;
+ int len;
+ if ((strchr(debug_string, '(') && strchr(debug_string, ')')) ||
+ strchr(debug_string, '$'))
+ string = strdup(debug_string);
+ else
+ string = silc_string_regexify(debug_string);
+ len = strlen(string);
+ if (len >= sizeof(silclog.debug_string))
+ len = sizeof(silclog.debug_string) - 1;
+ memset(silclog.debug_string, 0, sizeof(silclog.debug_string));
+ strncpy(silclog.debug_string, string, len);