+/* Reset a logging channel (close and reopen) */
+
+static bool silc_log_reset(SilcLog log)
+{
+ if (!log) return FALSE;
+ if (log->fp) {
+ 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)));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Internal timeout callback to flush log channels and check file sizes */
+
+SILC_TASK_CALLBACK(silc_log_fflush_callback)
+{
+ unsigned int u;
+ if (!silc_log_quick) {
+ silc_log_flush_all();
+ 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_flushdelay, 0, SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+}
+
+/* Outputs the log message to the first available channel. Channels are
+ * ordered by importance (see SilcLogType documentation).
+ * More importants channels can be printed on less important ones, but not
+ * vice-versa. */
+
+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;
+
+ /* If there is a custom callback set, use it and return. */
+ if (log->cb) {
+ if ((*log->cb)(type, string, log->context))
+ 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,
+ "Warning, trying to output without log files initialization, "
+ "log output is going to stderr\n");
+ silc_log_no_init = TRUE;
+ }
+ /* redirect output */