+ /* Close previous log file if it exists */
+ if (strlen(log->filename)) {
+ if (log->fp)
+ fclose(log->fp);
+ memset(log->filename, 0, sizeof(log->filename));
+ log->fp = NULL;
+ }
+
+ /* Set new log file */
+ if (fp) {
+ log->fp = fp;
+ log->maxsize = maxsize;
+
+ memset(log->filename, 0, sizeof(log->filename));
+ silc_strncat(log->filename, sizeof(log->filename), filename,
+ strlen(filename));
+ }
+
+ /* Add flush timeout */
+ if (scheduler) {
+ silc_schedule_task_del_by_callback(scheduler, silc_log_fflush_callback);
+ silc_schedule_task_add_timeout(scheduler, silc_log_fflush_callback,
+ scheduler, 10, 0);
+ silclog.scheduled = TRUE;
+ }
+
+ 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);