+Sun Jan 6 12:49:40 EET 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Do not print the warning about log files not being initialized
+ more than once to avoid excess logging. Affected file is
+ lib/silcutil/silclog.c.
+
+ * Fixed the SIM compilation in lib/silcsim/Makefile.am. Fixed
+ the SIM copying in make install in Makefile.am.pre.
+
+Sun Jan 6 01:10:21 CET 2001 Johnny Mnemonic <johnny@themnemonic.org>
+
+ * Rewritten silclog APIs. Globally interesting changes follows:
+ silc_log_set_files() changed to silc_log_set_file().
+ silc_log_set_callbacks() changed to silc_log_set_callback().
+ ROBOdoc documented silclog header file.
+ SilcLogCb now returns bool to wether inihibit the default
+ handler or not (to keep the old behaviour return always TRUE).
+ The new APIs should also fix the problem of the
+ silcd_error.log file that was written in the current directory.
+
+ New features:
+ Log files streams will remain opened after silc_log_set_file()
+ call, means less CPU usage notably on high traffic servers.
+ File streams are now full buffered, and flushed to the disk
+ every 5 minutes, lesses HD activity and CPU usage.
+ Messages can be redirected, allowing admins to configure
+ one single logfile for all server messages.
+ the silc_log_quick global variable to activate fast-logging.
+ Affected files lib/silcutil/silclog.[ch]
+
+ * Changed some code to conform new silclog APIs. Affected
+ files are doc/example_silcd.conf.in, silcd/server.c
+ irssi/src/silc/core/silc-core.c, silcd/serverconfig.[ch],
+ silcd/silcd.c.
+
+ * Fixed a memory leak that could occur in some situations.
+ Affected file silcd/serverconfig.c.
+
Sat Jan 5 13:37:29 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* Added the silc_client_del_client to remove the client from
S: 70100 Kuopio
S: Finland
+N: Johnny Mnemonic
+E: johnny@themnemonic.org
+W: http://www.themnemonic.org/
+P: 1024D/34E2AB40 9AC6 1460 A5D0 4DB7 70D0 5DA5 C17F 50CD 34E2 AB40
+D: RPM packages
+D: silclog, misc bugfixes
+S: 35100 Padova
+S: Italy
+
N: Juha Räsänen
E: jmrasane@lut.fi
D: Persistent nagger
fi
sim-install:
- -cp -fRL $(srcdir)/lib/silcsim/*.so $(modulesdir)/
+ $(INSTALL_DATA) $(srcdir)/lib/silcsim/*.so $(modulesdir)/
doc-install:
$(INSTALL_DATA) $(srcdir)/doc/CodingStyle $(docdir)/
========================
o strerror messages from premature EOF's to signoff messages.
- (add perhaps a socket error thingy to SilcSockeConnection).
+ (add perhaps a socket error thingy to SilcSocketConnection).
o Backup router related issues
/* Log callbacks */
-static void silc_log_info(char *message)
-{
- fprintf(stderr, "%s\n", message);
-}
-
-static void silc_log_warning(char *message)
-{
- fprintf(stderr, "%s\n", message);
-}
-
-static void silc_log_error(char *message)
+static bool silc_log_misc(SilcLogType type, char *message, void *context)
{
fprintf(stderr, "%s\n", message);
+ return TRUE;
}
/* Init SILC. Called from src/fe-text/silc.c */
silc_debug = TRUE;
silc_debug_hexdump = TRUE;
silc_log_set_debug_string(opt_debug);
- silc_log_set_callbacks(silc_log_info, silc_log_warning,
- silc_log_error, NULL);
+ silc_log_set_callback(SILC_LOG_INFO, silc_log_misc, NULL);
+ silc_log_set_callback(SILC_LOG_WARNING, silc_log_misc, NULL);
+ silc_log_set_callback(SILC_LOG_ERROR, silc_log_misc, NULL);
+ silc_log_set_callback(SILC_LOG_FATAL, silc_log_misc, NULL);
#ifndef SILC_DEBUG
fprintf(stdout,
"Run-time debugging is not enabled. To enable it recompile\n"
/* Initialize the auto_addr variables Is "server" the best choice for
* this? No existing category seems to apply.
*/
-
settings_add_bool("server", "use_auto_addr", FALSE);
settings_add_str("server", "auto_bind_ip", "");
settings_add_str("server", "auto_public_ip", "");
/* Set log files where log message should be saved. */
server->config->server = server;
- silc_server_config_setlogfiles(server->config);
/* Register all configured ciphers, PKCS and hash functions. */
if (!silc_server_config_register_ciphers(server->config))
server->schedule = silc_schedule_init(SILC_SERVER_MAX_CONNECTIONS);
if (!server->schedule)
goto err0;
-
+
/* Add the first task to the scheduler. This is task that is executed by
timeout. It expires as soon as the caller calls silc_server_run. This
task performs authentication protocol and key exchange with our
SILC_TASK_PRI_NORMAL);
server->listenning = TRUE;
+ /* Send log file configuration */
+ silc_server_config_setlogfiles(server->config, server->schedule);
+
/* If server connections has been configured then we must be router as
normal server cannot have server connections, only router connections. */
if (server->config->servers) {
{
SILC_LOG_DEBUG(("Stopping server"));
- silc_schedule_stop(server->schedule);
- silc_schedule_uninit(server->schedule);
+ if (server->schedule) {
+ silc_schedule_stop(server->schedule);
+ silc_schedule_uninit(server->schedule);
+ }
silc_server_protocols_unregister();
/* Remove client from all channels */
if (notify)
silc_server_remove_from_channels(server, NULL, client,
- TRUE, signoff, TRUE);
+ TRUE, (char *)signoff, TRUE);
else
silc_server_remove_from_channels(server, NULL, client,
FALSE, NULL, FALSE);
if ((silc_server_config_parse_lines(new, config_parse)) == FALSE)
goto fail;
- silc_free(buffer);
+ silc_buffer_free(buffer);
return new;
fail:
+ silc_buffer_free(buffer);
silc_free(new);
return NULL;
}
}
if (check == FALSE)
- return FALSE;;
+ return FALSE;
/* Check that all mandatory sections really were found. If not, the server
cannot function and we return error. */
/* Sets log files where log messages is saved by the server. */
-void silc_server_config_setlogfiles(SilcServerConfig config)
+void silc_server_config_setlogfiles(SilcServerConfig config, SilcSchedule sked)
{
SilcServerConfigSectionLogging *log;
- char *info, *warning, *error, *fatal;
- uint32 info_size, warning_size, error_size, fatal_size;
SILC_LOG_DEBUG(("Setting configured log file names"));
-
- /* Set default files before checking configuration */
- info = SILC_LOG_FILE_INFO;
- warning = SILC_LOG_FILE_WARNING;
- error = SILC_LOG_FILE_ERROR;
- fatal = SILC_LOG_FILE_FATAL;
- info_size = 0;
- warning_size = 0;
- error_size = 0;
- fatal_size = 0;
-
log = config->logging;
- while(log) {
- if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO)) {
- info = log->filename;
- info_size = log->maxsize;
- }
- if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING)) {
- warning = log->filename;
- warning_size = log->maxsize;
- }
- if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR)) {
- error = log->filename;
- error_size = log->maxsize;
- }
- if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
- fatal = log->filename;
- fatal_size = log->maxsize;
- }
+ while (log) {
+ if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_INFO))
+ silc_log_set_file(SILC_LOG_INFO, log->filename, log->maxsize, sked);
+ if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_WARNING))
+ silc_log_set_file(SILC_LOG_WARNING, log->filename, log->maxsize, sked);
+ if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_ERROR))
+ silc_log_set_file(SILC_LOG_ERROR, log->filename, log->maxsize, sked);
+ if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LF_FATAL))
+ silc_log_set_file(SILC_LOG_FATAL, log->filename, log->maxsize, sked);
log = log->next;
}
-
- silc_log_set_files(info, info_size, warning, warning_size,
- error, error_size, fatal, fatal_size);
}
/* Registers configured ciphers. These can then be allocated by the
int silc_server_config_parse_lines(SilcServerConfig config,
SilcServerConfigParse parse_config);
int silc_server_config_check_sections(uint32 checkmask);
-void silc_server_config_setlogfiles(SilcServerConfig config);
+void silc_server_config_setlogfiles(SilcServerConfig config, SilcSchedule sked);
bool silc_server_config_register_ciphers(SilcServerConfig config);
bool silc_server_config_register_pkcs(SilcServerConfig config);
bool silc_server_config_register_hashfuncs(SilcServerConfig config);
int main(int argc, char **argv)
{
- int ret;
- int opt, option_index;
- int foreground = FALSE;
+ int ret, opt, option_index;
char *config_file = NULL;
+ bool foreground = FALSE;
SilcServer silcd;
struct sigaction sa;
- silc_debug = FALSE;
-
/* Parse command line arguments */
if (argc > 1) {
while ((opt = getopt_long(argc, argv, "cf:d:hFVC:",
exit(0);
break;
case 'd':
+#ifdef SILC_DEBUG
silc_debug = TRUE;
silc_debug_hexdump = TRUE;
silc_log_set_debug_string(optarg);
foreground = TRUE;
-#ifndef SILC_DEBUG
+ silc_log_quick = TRUE;
+#else
fprintf(stdout,
"Run-time debugging is not enabled. To enable it recompile\n"
"the server with --enable-debug configuration option.\n");
# Log files.
#
# This section is used to set various logging files, their paths
-# and maximum sizes. All the other directives except those defined
-# below are ignored in this section. Log files are purged after they
-# reach the maximum set byte size.
+# and maximum sizes. There are only four defined channels allowed for
+# defining (see list below).
+# The log channels have an importance value, and most important channels
+# are printed on the less important ones, thus setting the logging file
+# for "infologfile" will ensure logging for all channels, while setting
+# logging file for "errorlogfile" will ensure logging for channels
+# "error" and "fatal" only.
+# If a message can't find a valid output file it will be discarded, thus,
+# if you unset all files you will completely disable server logging (and
+# this is NOT recommended).
+# If maximum size is given, the logfile will be rotated to a logfile with
+# the ".old" extension added. Older logfiles are flushed.
#
# Format: infologfile:<path>:<max byte size>
# warninglogile:<path>:<max byte size>
# fatallogile:<path>:<max byte size>
#
[Logging]
-infologfile:@LOGSDIR@/silcd.log:10000
-#warninglogfile:@LOGSDIR@/silcd_warning.log:10000
-#errorlogfile:@LOGSDIR@/error.log:10000
-#fatallogfile:@LOGSDIR@/silcd_error.log:
+infologfile:@LOGSDIR@/silcd.log:50000
+warninglogfile:@LOGSDIR@/silcd_warnings.log:50000
+#errorlogfile:@LOGSDIR@/silcd_errors.log:50000
+#fatallogfile:@LOGSDIR@/silcd_fatals.log:
#
# Connection classes.
$(SIM_CIPHER_OBJS): ../silccrypt/libsilccrypt.a
$(LTCOMPILE) -c $(srcdir)/../silccrypt/$*.c
$(LIBTOOL) --mode=link $(LINK) -rpath $(silc_modulesdir) -o lib$*.la $*.lo
- cd $(srcdir) && $(LN_S) -f $(srcdir)/../.libs/lib$*.so $(srcdir)/$*.sim.so
+ cd $(srcdir) && $(LN_S) -f $(srcdir)/.libs/lib$*.so $(srcdir)/$*.sim.so
$(SIM_HASH_OBJS): ../silccrypt/libsilccrypt.a
$(LTCOMPILE) -c $(srcdir)/../silccrypt/$*.c
$(LIBTOOL) --mode=link $(LINK) -rpath $(silc_modulesdir) -o lib$*.la $*.lo
- cd $(srcdir) && $(LN_S) -f $(srcdir)/../.libs/lib$*.so $(srcdir)/$*.sim.so
+ cd $(srcdir) && $(LN_S) -f $(srcdir)/.libs/lib$*.so $(srcdir)/$*.sim.so
CLEANFILES = *.sim.so *.la
silclog.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Johnny Mnemonic <johnny@themnemonic.org>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2002 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#include "silcincludes.h"
-/* Set TRUE/FALSE to enable/disable debugging */
-bool silc_debug = FALSE;
-bool silc_debug_hexdump = FALSE;
-char *silc_debug_string = NULL;
-bool log_file_open_error = FALSE;
+/* default flush time (5 minutes) */
+#define SILC_LOG_TIMEOUT 300
-/* SILC Log name strings. These strings are printed to the log file. */
-const SilcLogTypeName silc_log_types[] =
-{
- { "Info", SILC_LOG_INFO },
- { "Warning", SILC_LOG_WARNING },
- { "Error", SILC_LOG_ERROR },
- { "Fatal", SILC_LOG_FATAL },
+/* 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__++)
- { NULL, -1 },
+/* Our working struct -- at the moment we keep it private, but this could
+ * change in the future */
+struct SilcLogStruct {
+ char *filename;
+ FILE *fp;
+ uint32 maxsize;
+ char *typename;
+ SilcLogType type;
+ SilcLogCb cb;
+ void *context;
+};
+typedef struct SilcLogStruct *SilcLog;
+
+/* 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, "Fatal", SILC_LOG_FATAL, NULL, NULL},
};
-char *log_info_file;
-char *log_warning_file;
-char *log_error_file;
-char *log_fatal_file;
-uint32 log_info_size;
-uint32 log_warning_size;
-uint32 log_error_size;
-uint32 log_fatal_size;
-
-/* Log callbacks. If these are set by the application these are used
- instead of the default functions in this file. */
-static SilcLogCb info_cb = NULL;
-static SilcLogCb warning_cb = NULL;
-static SilcLogCb error_cb = NULL;
-static SilcLogCb fatal_cb = NULL;
+/* If TRUE, log files will be flushed for each log input */
+bool silc_log_quick = FALSE;
-/* Debug callbacks. If set these are used instead of default ones. */
-static SilcDebugCb debug_cb = NULL;
-static SilcDebugHexdumpCb debug_hexdump_cb = NULL;
+/* Set TRUE/FALSE to enable/disable debugging */
+bool silc_debug = FALSE;
+bool silc_debug_hexdump = FALSE;
-/* Outputs the log message to what ever log file selected. */
+/* Regular pattern matching expression for the debug output */
+static char *silc_log_debug_string = NULL;
-void silc_log_output(const char *filename, uint32 maxsize,
- SilcLogType type, char *string)
+/* Debug callbacks. If set these are used instead of default ones. */
+static SilcLogDebugCb silc_log_debug_cb = NULL;
+static void *silc_log_debug_context = NULL;
+static SilcLogHexdumpCb silc_log_hexdump_cb = NULL;
+static void *silc_log_hexdump_context = NULL;
+
+/* Did we register already our functions to the scheduler? */
+static bool silc_log_scheduled = FALSE;
+static bool silc_log_no_init = FALSE;
+
+/* 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)
{
- FILE *fp;
- const SilcLogTypeName *np;
-
- switch(type)
- {
+ /* this is not really needed, but i think it's more secure */
+ switch (type) {
case SILC_LOG_INFO:
- if (info_cb) {
- (*info_cb)(string);
- silc_free(string);
- return;
- }
- break;
+ return &silclogs[SILC_LOG_INFO];
case SILC_LOG_WARNING:
- if (warning_cb) {
- (*warning_cb)(string);
- silc_free(string);
- return;
- }
- break;
+ return &silclogs[SILC_LOG_WARNING];
case SILC_LOG_ERROR:
- if (error_cb) {
- (*error_cb)(string);
- silc_free(string);
- return;
- }
- break;
+ return &silclogs[SILC_LOG_ERROR];
case SILC_LOG_FATAL:
- if (fatal_cb) {
- (*fatal_cb)(string);
- silc_free(string);
- return;
- }
- break;
- }
+ return &silclogs[SILC_LOG_FATAL];
+ default:
+ return NULL;
+ }
+ return NULL;
+}
- if (!filename)
- fp = stderr;
- else {
- /* Purge the log file if the max size is defined. */
- if (maxsize) {
- fp = fopen(filename, "r");
- if (fp) {
- int filelen;
-
- filelen = fseek(fp, (off_t)0L, SEEK_END);
- fseek(fp, (off_t)0L, SEEK_SET);
-
- /* Purge? */
- if (filelen >= maxsize)
- unlink(filename);
-
- fclose(fp);
- }
- }
-
- /* Open the log file */
- if ((fp = fopen(filename, "a+")) == NULL) {
- if (!log_file_open_error) {
- fprintf(stderr, "warning: could not open log file "
- "%s: %s\n", filename, strerror(errno));
- fprintf(stderr, "warning: log messages will be displayed on "
- "the screen\n");
- }
- log_file_open_error = TRUE;
- fp = stderr;
+/* Given an open log file, checks the size and rotates it if there is a
+ * max size set less then the current size */
+static void silc_log_checksize(SilcLog log)
+{
+ char newname[127];
+ long size;
+
+ if (!log || !log->fp || !log->maxsize)
+ return; /* we are not interested */
+ if ((size = ftell(log->fp)) < 0) {
+ /* OMG, EBADF is here.. we'll try our best.. */
+ FILE *oldfp = log->fp;
+ fclose(oldfp); /* we can discard the error */
+ log->fp = NULL; /* make sure we don't get here recursively */
+ SILC_LOG_ERROR(("Error while checking size of the log file %s, fp=%d",
+ log->filename, oldfp));
+ return;
+ }
+ if (size < log->maxsize) return;
+
+ /* It's too big */
+ fprintf(log->fp, "[%s] [%s] Cycling log file, over max "
+ "logsize (%lu kilobytes)\n",
+ silc_get_time(), log->typename, log->maxsize / 1024);
+ fflush(log->fp);
+ fclose(log->fp);
+ snprintf(newname, sizeof(newname), "%s.old", log->filename);
+ unlink(newname);
+
+ /* I heard the following syscall may cause portability issues, but I don't
+ * have any other solution since SILC library doesn't provide any other
+ * function like this. -Johnny */
+ rename(log->filename, newname);
+ if (!(log->fp = fopen(log->filename, "w")))
+ SILC_LOG_WARNING(("Couldn't reopen logfile %s for type \"%s\": %s",
+ log->filename, log->typename, strerror(errno)));
+}
+
+/* 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->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_schedule_task_add((SilcSchedule) context, 0, silc_log_fflush_callback,
+ context, SILC_LOG_TIMEOUT, 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;
+ 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;
+ }
+
+ 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;
}
+
+ fprintf(stderr, "%s\n", string);
+ goto end;
}
- /* Get the log type name */
- for (np = silc_log_types; np->name; np++) {
- if (np->type == type)
- break;
+ /* 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 (type == 0) break;
+ log = silc_log_find_by_type(--type);
}
- fprintf(fp, "[%s] [%s] %s\n", silc_get_time(), np->name, string);
- fflush(fp);
- if (fp != stderr)
- fclose(fp);
+ /* Couldn't find any open stream.. sorry :( */
+ SILC_LOG_DEBUG(("Warning! couldn't find any available log channel!"));
+ 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);
+ }
+
+ end:
silc_free(string);
}
-/* Outputs the debug message to stderr. */
+/* returns an internally allocated pointer to a logging channel file */
+char *silc_log_get_file(SilcLogType type)
+{
+ SilcLog log;
-void silc_log_output_debug(char *file, char *function,
- int line, char *string)
+ if (!(log = silc_log_find_by_type(type)))
+ return NULL;
+ if (log->fp)
+ return log->filename;
+ return NULL;
+}
+
+/* Set and initialize the specified logging channel. See the API reference */
+bool silc_log_set_file(SilcLogType type, char *filename, uint32 maxsize,
+ SilcSchedule scheduler)
{
- if (!silc_debug) {
- silc_free(string);
- return;
+ FILE *fp = NULL;
+ SilcLog log;
+
+ log = silc_log_find_by_type(type);
+ if (!log || !scheduler)
+ return FALSE;
+
+ SILC_LOG_DEBUG(("Setting \"%s\" file to %s (max size=%d)",
+ log->typename, filename, maxsize));
+
+ /* before assuming the new file, make sure we can open it */
+ if (filename) {
+ if (!(fp = fopen(filename, "a+"))) {
+ fprintf(stderr, "warning: couldn't open log file %s: %s\n",
+ filename, strerror(errno));
+ return FALSE;
+ }
}
- if (silc_debug_string &&
- (!silc_string_regex_match(silc_debug_string, file) &&
- !silc_string_regex_match(silc_debug_string, function))) {
- silc_free(string);
- return;
+ /* remove old file */
+ if (log->filename) {
+ if (log->fp) {
+ fflush(fp);
+ fclose(fp);
+ }
+ silc_free(log->filename);
+ log->filename = NULL;
+ log->fp = NULL;
+ }
+
+ if (fp) {
+ log->filename = strdup(filename);
+ log->fp = fp;
+ log->maxsize = maxsize;
}
- if (debug_cb) {
- (*debug_cb)(file, function, line, string);
- silc_free(string);
+ if (silc_log_scheduled)
+ return TRUE;
+
+ /* make sure we write to the disk sometimes */
+ silc_schedule_task_add(scheduler, 0, silc_log_fflush_callback,
+ (void *) scheduler, SILC_LOG_TIMEOUT, 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;
+ }
fprintf(stderr, "%s:%d: %s\n", function, line, string);
fflush(stderr);
+end:
silc_free(string);
}
/* Hexdumps a message */
-void silc_log_output_hexdump(char *file, char *function,
+void silc_log_output_hexdump(char *file, char *function,
int line, void *data_in,
uint32 len, char *string)
{
int off, pos, count;
unsigned char *data = (unsigned char *)data_in;
- if (!silc_debug_hexdump) {
- silc_free(string);
- return;
- }
-
- if (silc_debug_string &&
- (!silc_string_regex_match(silc_debug_string, file) &&
- !silc_string_regex_match(silc_debug_string, function))) {
- silc_free(string);
- return;
- }
-
- if (debug_hexdump_cb) {
- (*debug_hexdump_cb)(file, function, line, data_in, len, string);
- silc_free(string);
- return;
+ 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))
+ goto end;
+ if (silc_log_hexdump_cb) {
+ if ((*silc_log_hexdump_cb)(file, function, line, data_in, len, string,
+ silc_log_hexdump_context))
+ goto end;
}
fprintf(stderr, "%s:%d: %s\n", function, line, string);
silc_free(string);
k = 0;
- off = len % 16;
pos = 0;
count = 16;
+ off = len % 16;
while (1) {
-
if (off) {
if ((len - pos) < 16 && (len - pos <= len - off))
count = off;
for (i = 0; i < count; i++) {
fprintf(stderr, "%02X ", data[pos + i]);
-
+
if ((i + 1) % 4 == 0)
fprintf(stderr, " ");
}
if (count && count < 16) {
int j;
-
+
for (j = 0; j < 16 - count; j++) {
fprintf(stderr, " ");
fprintf(stderr, " ");
}
}
-
+
for (i = 0; i < count; i++) {
char ch;
-
+
if (data[pos] < 32 || data[pos] >= 127)
ch = '.';
else
if (count < 16)
break;
}
-}
-
-/* Sets log files */
-
-void silc_log_set_files(char *info, uint32 info_size,
- char *warning, uint32 warning_size,
- char *error, uint32 error_size,
- char *fatal, uint32 fatal_size)
-{
- log_info_file = info;
- log_warning_file = warning;
- log_error_file = error;
- log_fatal_file = fatal;
-
- log_info_size = info_size;
- log_warning_size = warning_size;
- log_error_size = error_size;
- log_fatal_size = fatal_size;
-}
+ return;
-/* Sets log callbacks */
-
-void silc_log_set_callbacks(SilcLogCb info, SilcLogCb warning,
- SilcLogCb error, SilcLogCb fatal)
-{
- info_cb = info;
- warning_cb = warning;
- error_cb = error;
- fatal_cb = fatal;
-}
-
-/* Resets log callbacks */
-
-void silc_log_reset_callbacks()
-{
- info_cb = warning_cb = error_cb = fatal_cb = NULL;
+end:
+ silc_free(string);
}
/* Sets debug callbacks */
-void silc_log_set_debug_callbacks(SilcDebugCb debug,
- SilcDebugHexdumpCb debug_hexdump)
+void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
+ void *debug_context,
+ SilcLogHexdumpCb hexdump_cb,
+ void *hexdump_context)
{
- debug_cb = debug;
- debug_hexdump_cb = debug_hexdump;
+ silc_log_debug_cb = debug_cb;
+ silc_log_debug_context = debug_context;
+ silc_log_hexdump_cb = hexdump_cb;
+ silc_log_hexdump_context = hexdump_context;
}
/* Resets debug callbacks */
void silc_log_reset_debug_callbacks()
{
- debug_cb = NULL;
- debug_hexdump_cb = NULL;
+ silc_log_debug_cb = NULL;
+ silc_log_debug_context = NULL;
+ silc_log_hexdump_cb = NULL;
+ silc_log_hexdump_context = NULL;
}
/* Set current debug string */
void silc_log_set_debug_string(const char *debug_string)
{
- silc_free(silc_debug_string);
+ silc_free(silc_log_debug_string);
if ((strchr(debug_string, '(') &&
- strchr(debug_string, ')')) ||
- strchr(debug_string, '$'))
- silc_debug_string = strdup(debug_string);
+ strchr(debug_string, ')')) ||
+ strchr(debug_string, '$'))
+ silc_log_debug_string = strdup(debug_string);
else
- silc_debug_string = silc_string_regexify(debug_string);
+ silc_log_debug_string = silc_string_regexify(debug_string);
}
silclog.h
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Johnny Mnemonic <johnny@themnemonic.org>
- Copyright (C) 1997 - 2000 Pekka Riikonen
+ Copyright (C) 1997 - 2002 Pekka Riikonen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*/
+/****h* silcutil/SilcLogAPI
+ *
+ * DESCRIPTION
+ *
+ * The SILC logging APIs provide a powerful and easy-to-use interface to
+ * the logging system and debugging output.
+ *
+ ***/
+
#ifndef SILCLOG_H
#define SILCLOG_H
-/* Set TRUE/FALSE to enable/disable debugging */
-extern bool silc_debug;
-extern bool silc_debug_hexdump;
-extern char *silc_debug_string;
-
-/* SILC Log types */
+/****d* silcutil/SilcLogAPI/SilcLogType
+ *
+ * NAME
+ *
+ * typedef enum { ... } SilcLogType;
+ *
+ * DESCRIPTION
+ *
+ * This is the main logging channel id. There are currently four known
+ * logging channels (plus the debugging output channel), and they are
+ * ordered by importance.
+ * See the source code for SILC coding conventions about how choosing
+ * the right output channel.
+ *
+ * SOURCE
+ */
typedef enum {
+ /* Generic info channel file */
SILC_LOG_INFO,
+
+ /* This should be used for warnings and non critical failures */
SILC_LOG_WARNING,
+
+ /* Generic error and critical failures messages */
SILC_LOG_ERROR,
- SILC_LOG_FATAL
+
+ /* Fatal messages (usually situations that will lead to a program crash */
+ SILC_LOG_FATAL,
+
+ /* Total logging channels */
+ SILC_LOG_MAX
} SilcLogType;
+/***/
+
+/****f* silcutil/SilcLogAPI/SilcLogCb
+ *
+ * SYNOPSIS
+ *
+ * typedef bool (*SilcLogCb)(SilcLogType type, char *message,
+ * void *context);
+ *
+ * DESCRIPTION
+ *
+ * The logging custom callback function. The `type' is the channel ID
+ * that triggered the event, which allows you to use the same callback
+ * function for multiple logging channels.
+ * The `message' parameter points to a null-terminated buffer containing
+ * the received message, while `context' is the caller-specified context.
+ * The message must not be modified or freed by the callback function.
+ *
+ * SEE ALSO
+ * silc_log_set_callback
+ *
+ ***/
+typedef bool (*SilcLogCb)(SilcLogType type, char *message, void *context);
-/* Log type name structure. */
-typedef struct {
- char *name;
- SilcLogType type;
-} SilcLogTypeName;
-
-/* Log function callback. */
-typedef void (*SilcLogCb)(char *message);
-
-/* Debug function callback. */
-typedef void (*SilcDebugCb)(char *file, char *function,
- int line, char *message);
-
-/* Debug hexdump function callback. */
-typedef void (*SilcDebugHexdumpCb)(char *file, char *function,
- int line, unsigned char *data,
- uint32 data_len, char *message);
-
-/* Default log filenames */
-#define SILC_LOG_FILE_INFO "silcd.log"
-#define SILC_LOG_FILE_WARNING "silcd_error.log"
-#define SILC_LOG_FILE_ERROR SILC_LOG_FILE_WARNING
-#define SILC_LOG_FILE_FATAL SILC_LOG_FILE_WARNING
-
-/* Log files. Set by silc_log_set_logfiles. */
-extern char *log_info_file;
-extern char *log_warning_file;
-extern char *log_error_file;
-extern char *log_fatal_file;
-extern uint32 log_info_size;
-extern uint32 log_warning_size;
-extern uint32 log_error_size;
-extern uint32 log_fatal_size;
+/****f* silcutil/SilcLogAPI/SilcLogDebugCb
+ *
+ * SYNOPSIS
+ *
+ * typedef bool (*SilcLogDebugCb)(char *file, char *function, int line,
+ * char *message, void *context);
+ *
+ * DESCRIPTION
+ *
+ * The debug logging callback function. The default behaviour is to
+ * output messages to stderr. `file', `function', and `line' are the
+ * corresponding offsets in the source files. `message' points to a
+ * null-terminated buffer containing the debugging message, and `context'
+ * is the caller-specified context.
+ * The message must not be modified or freed by the callback function.
+ * If the function returns TRUE, SilcLog will assume the message as handled
+ * and won't run its default handler.
+ *
+ * SEE ALSO
+ * silc_debug, silc_log_set_debug_callbacks
+ *
+ ***/
+typedef bool (*SilcLogDebugCb)(char *file, char *function, int line,
+ char *message, void *context);
+
+/****f* silcutil/SilcLogAPI/SilcLogHexdumpCb
+ *
+ * SYNOPSIS
+ *
+ * typedef bool (*SilcDebugHexdumpCb)(char *file, char *function, int line,
+ * unsigned char *data, uint32 data_len,
+ * char *message, void *context;
+ *
+ * DESCRIPTION
+ *
+ * The hexdump logging callback function. The default behaviour is to
+ * print a formatted hexdump to stderr, and is commonly what you would it
+ * like to be. `file', `function', and `line' are the corresponding
+ * offsets in the source files. `data' is the begin of the buffer that
+ * should be hexdumped, which is `data_len' bytes long.
+ * The `message' parameter points to a null-terminated buffer containing
+ * the received message, while `context' is the caller-specified context.
+ * The message must not be modified or freed by the callback function.
+ * If the function returns TRUE, SilcLog will assume the message as handled
+ * and won't run its default handler.
+ *
+ * SEE ALSO
+ * silc_debug_hexdump, silc_log_set_debug_callbacks
+ *
+ ***/
+typedef bool (*SilcLogHexdumpCb)(char *file, char *function, int line,
+ unsigned char *data, uint32 data_len,
+ char *message, void *context);
+
+/* Global Variables */
+
+/****v* silcutil/SilcLogAPI/silc_log_quick
+ *
+ * NAME
+ *
+ * bool silc_log_quick -- enable/disable fast logging output
+ *
+ * DESCRIPTION
+ *
+ * SilcLog makes use of libc stream buffering output, which means that it
+ * saves HD activity by buffering the logging messages and writing them
+ * all together every some minutes (default is 5 minutes).
+ * Setting this variable to TRUE will force SilcLog to write messages to the
+ * filesystem as soon as they are received. This increases the CPU activity
+ * notably on bigger servers, but reduces memory usage.
+ * If you want to change the logging style on-the-fly, make sure to call
+ * silc_log_flush_all() after setting this variable to TRUE.
+ *
+ ***/
+extern bool silc_log_quick;
+
+/****v* silcutil/SilcLogAPI/silc_debug
+ *
+ * NAME
+ *
+ * bool silc_debug -- enable/disable debugging output
+ *
+ * DESCRIPTION
+ *
+ * If silc_debug is set to FALSE, debugging functions won't procude any
+ * output. This is useful when for example you compile in the debugging
+ * support but at a certain point you want to send the program in the
+ * background.
+ *
+ * SEE ALSO
+ * SILC_LOG_DEBUG
+ *
+ ***/
+extern bool silc_debug;
+
+/****v* silcutil/SilcLogAPI/silc_debug_hexdump
+ *
+ * NAME
+ *
+ * bool silc_debug_hexdump -- enable/disable debugging output
+ *
+ * DESCRIPTION
+ *
+ * If silc_debug_hexdump is set to FALSE, debugging functions won't produce
+ * any output. This is useful when for example you compile in the debugging
+ * support but at a certain point you want to send the program in the
+ * background.
+ *
+ * SEE ALSO
+ * SILC_LOG_HEXDUMP
+ *
+ ***/
+extern bool silc_debug_hexdump;
+
+/* Macros */
#ifdef WIN32
#define __FUNCTION__ ""
#endif
-/* Log macros. */
-#define SILC_LOG_INFO(fmt) (silc_log_output(log_info_file, \
- log_info_size, \
- SILC_LOG_INFO, \
- silc_format fmt))
-#define SILC_LOG_WARNING(fmt) (silc_log_output(log_warning_file, \
- log_warning_size, \
- SILC_LOG_WARNING, \
- silc_format fmt))
-#define SILC_LOG_ERROR(fmt) (silc_log_output(log_error_file, \
- log_error_size, \
- SILC_LOG_ERROR, \
- silc_format fmt))
-#define SILC_LOG_FATAL(fmt) (silc_log_output(log_fatal_file, \
- log_fatal_size, \
- SILC_LOG_FATAL, \
- silc_format fmt))
-
-/* Debug macro is a bit different from other logging macros and it
- is compiled in only if debugging is enabled. */
+/****d* silcutil/SilcLogAPI/SILC_LOG_INFO
+ *
+ * NAME
+ *
+ * #define SILC_LOG_INFO(...)
+ *
+ * DESCRIPTION
+ *
+ * This macro is a wrapper to the main logging function.
+ * It supports variable argument list formatting, and *automatically*
+ * appends newline at the end of the string.
+ *
+ * NOTES
+ *
+ * This macro requires double parenthesis to ensure that the VA list
+ * formatting would work correctly.
+ *
+ * EXAMPLE
+ *
+ * SILC_LOG_INFO(("Today i feel %s", core->mood));
+ *
+ * SOURCE
+ */
+#define SILC_LOG_INFO(fmt) silc_log_output(SILC_LOG_INFO, silc_format fmt)
+/***/
+
+/****d* silcutil/SilcLogAPI/SILC_LOG_WARNING
+ *
+ * NAME
+ *
+ * #define SILC_LOG_WARNING(...)
+ *
+ * DESCRIPTION
+ *
+ * Wrapper to the WARNING logging channel.
+ * Please see the SILC_LOG_INFO macro.
+ *
+ * SEE ALSO
+ * SILC_LOG_INFO
+ *
+ * SOURCE
+ */
+#define SILC_LOG_WARNING(fmt) silc_log_output(SILC_LOG_WARNING, silc_format fmt)
+/***/
+
+/****d* silcutil/SilcLogAPI/SILC_LOG_ERROR
+ *
+ * NAME
+ *
+ * #define SILC_LOG_ERROR(...)
+ *
+ * DESCRIPTION
+ *
+ * Wrapper to the ERROR logging channel.
+ * Please see the SILC_LOG_INFO macro.
+ *
+ * SEE ALSO
+ * SILC_LOG_INFO
+ *
+ * SOURCE
+ */
+#define SILC_LOG_ERROR(fmt) silc_log_output(SILC_LOG_ERROR, silc_format fmt)
+/***/
+
+/****d* silcutil/SilcLogAPI/SILC_LOG_FATAL
+ *
+ * NAME
+ *
+ * #define SILC_LOG_FATAL(...)
+ *
+ * DESCRIPTION
+ *
+ * Wrapper to the FATAL logging channel.
+ * Please see the SILC_LOG_INFO macro.
+ *
+ * SEE ALSO
+ * SILC_LOG_INFO
+ *
+ * SOURCE
+ */
+#define SILC_LOG_FATAL(fmt) silc_log_output(SILC_LOG_FATAL, silc_format fmt)
+/***/
+
+/****d* silcutil/SilcLogAPI/SILC_LOG_DEBUG
+ *
+ * NAME
+ *
+ * #define SILC_LOG_DEBUG(...)
+ *
+ * DESCRIPTION
+ *
+ * This is a special wrapper to the debugging output (usually stderr).
+ * The standard behaviour is the same as SILC_LOG_INFO, but this macro
+ * also depends on the global debugging macro SILC_DEBUG.
+ * Undefining the global SILC_DEBUG define causes these functions to be
+ * defined to an empty value, thus removing all logging calls from the
+ * compiled program.
+ *
+ * SEE ALSO
+ * SILC_LOG_INFO
+ *
+ * SOURCE
+ */
#ifdef SILC_DEBUG
-#define SILC_LOG_DEBUG(fmt) (silc_log_output_debug(__FILE__, \
- __FUNCTION__, \
- __LINE__, \
- silc_format fmt))
-#define SILC_LOG_HEXDUMP(fmt, data, len) \
- (silc_log_output_hexdump(__FILE__, \
- __FUNCTION__, \
- __LINE__, \
- (data), (len), \
- silc_format fmt))
+#define SILC_LOG_DEBUG(fmt) silc_log_output_debug(__FILE__, \
+ __FUNCTION__, \
+ __LINE__, \
+ silc_format fmt)
#else
#define SILC_LOG_DEBUG(fmt)
+#endif /* SILC_DEBUG */
+/***/
+
+/****d* silcutil/SilcLogAPI/SILC_LOG_HEXDUMP
+ *
+ * NAME
+ *
+ * #define SILC_LOG_HEXDUMP(...)
+ *
+ * DESCRIPTION
+ *
+ * This is a special wrapper to the hexdump output function. This macro
+ * behaves slightly differently from other logging wrappers.
+ * The first parameter, is composed by a group of parameters delimited by
+ * parenthesis.
+ * The second parameter is a (char *) pointer to the beginning of the
+ * memory section that should be hexdumped, and the third parameter is
+ * the length of this memory section.
+ * This macro is also affected by the global variable silc_debug_hexdump.
+ * Undefining the global SILC_DEBUG define causes these functions to be
+ * defined to an empty value, thus removing all logging calls from the
+ * compiled program.
+ *
+ * EXAMPLE
+ *
+ * SILC_LOG_HEXDUMP(("Outgoing packet [%d], len %d", pckt->seq, pckt->len),
+ * pckt->data, pckt->datalen);
+ *
+ * SOURCE
+ */
+#ifdef SILC_DEBUG
+#define SILC_LOG_HEXDUMP(fmt, data, len) silc_log_output_hexdump(__FILE__, \
+ __FUNCTION__, \
+ __LINE__, \
+ (data), (len), \
+ silc_format fmt)
+#else
#define SILC_LOG_HEXDUMP(fmt, data, len)
-#endif
+#endif /* SILC_DEBUG */
+/***/
/* Prototypes */
-void silc_log_output_debug(char *file, char *function,
- int line, char *string);
-void silc_log_output(const char *filename, uint32 maxsize,
- SilcLogType type, char *string);
-void silc_log_output_hexdump(char *file, char *function,
- int line, void *data_in,
- uint32 len, char *string);
-void silc_log_set_files(char *info, uint32 info_size,
- char *warning, uint32 warning_size,
- char *error, uint32 error_size,
- char *fatal, uint32 fatal_size);
-void silc_log_set_callbacks(SilcLogCb info, SilcLogCb warning,
- SilcLogCb error, SilcLogCb fatal);
+
+/****f* silcutil/SilcLogAPI/silc_log_output
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_output(SilcLogType type, char *string);
+ *
+ * DESCRIPTION
+ *
+ * This is the main function for logging output. Please note that you
+ * should rather use one of the logging wrapper macros.
+ * If you really want to use this function, its usage is quite simple.
+ * The `type' parameter identifies the channel to use, while the `string'
+ * parameter must be a dynamic allocated (null-terminated) buffer, because
+ * it will be freed at the end of this function, for internal reasons.
+ * If there are registered callbacks for the specified type, this function
+ * will first trigger those callbacks. The callback functions must NOT
+ * free or modify the original buffer.
+ *
+ * SEE ALSO
+ * SILC_LOG_INFO, SILC_LOG_WARNING, SILC_LOG_ERROR, SILC_LOG_FATAL
+ *
+ ***/
+void silc_log_output(SilcLogType type, char *string);
+
+/****f* silcutil/SilcLogAPI/silc_log_get_file
+ *
+ * SYNOPSIS
+ *
+ * char *silc_log_get_file(SilcLogType type);
+ *
+ * DESCRIPTION
+ *
+ * Returns the current logging file for the channel `type'.
+ * If there has been an error during the opening of this channel, NULL
+ * is returned, even if the file has been previously set with
+ * silc_log_set_file().
+ * The returned pointer points to internally allocated storage and must
+ * must not be freed, modified or stored.
+ *
+ ***/
+char *silc_log_get_file(SilcLogType type);
+
+/****f* silcutil/SilcLogAPI/silc_log_set_file
+ *
+ * SYNOPSIS
+ *
+ * bool silc_log_set_file(SilcLogType type, char *filename, uint32 maxsize,
+ * SilcSchedule scheduler);
+ *
+ * DESCRIPTION
+ *
+ * Sets `filename', which can be maximum `maxsize' bytes long, as the new
+ * logging file for the channel `type'. If you specify an illegal filename
+ * a warning message is printed and FALSE is returned. In this case
+ * logging settings are not changed.
+ * You can disable logging for a channel by specifying NULL filename, the
+ * maxsize in this case is not important.
+ * The `scheduler' parameter is needed by the internal logging to allow
+ * buffered output and thus to save HD activity.
+ *
+ ***/
+bool silc_log_set_file(SilcLogType type, char *filename, uint32 maxsize,
+ SilcSchedule scheduler);
+
+/****f* silcutil/SilcLogAPI/silc_log_set_callback
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_set_callback(SilcLogType type, SilcLogCb cb,
+ * void *context);
+ *
+ * DESCRIPTION
+ *
+ * Set `cb' as the default callback function for the logging channel
+ * `type'. When SilcLog receives a message for this channel, it will
+ * trigger the callback function. If the callback function returns TRUE
+ * SilcLog will assume the input as handled and won't run its default
+ * handler.
+ * You can disable/remove a callback by setting it to NULL or calling the
+ * function silc_log_reset_callbacks.
+ * If set, the callback function must be in the form described by
+ * SilcLogCb.
+ *
+ * SEE ALSO
+ * SilcLogCb, silc_log_reset_callbacks
+ *
+ ***/
+void silc_log_set_callback(SilcLogType type, SilcLogCb cb, void *context);
+
+/****f* silcutil/SilcLogAPI/silc_log_reset_callbacks
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_reset_callbacks();
+ *
+ * DESCRIPTION
+ *
+ * Removes all logging callbacks for normal channels. This function does
+ * NOT remove callbacks for debugging channels (debug and hexdump), you
+ * rather need to call silc_log_set_debug_callbacks() with NULL callbacks.
+ *
+ ***/
void silc_log_reset_callbacks();
-void silc_log_set_debug_callbacks(SilcDebugCb debug,
- SilcDebugHexdumpCb debug_hexdump);
-void silc_log_reset_debug_callbacks();
+
+/****f* silcutil/SilcLogAPI/silc_log_flush_all
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_flush_all();
+ *
+ * DESCRIPTION
+ *
+ * Forces flushing for all logging channels. This should be called for
+ * example after receiving special signals.
+ *
+ * SEE ALSO
+ * silc_log_quick
+ *
+ ***/
+void silc_log_flush_all();
+
+/****f* silcutil/SilcLogAPI/silc_log_reset_all
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_reset_all();
+ *
+ * DESCRIPTION
+ *
+ * Forces all logging channels to close and reopen their streams. Useful
+ * for example after a SIGHUP signal.
+ * Please note that this function could cause some warning messages if
+ * some logging channel points to an illegal filename.
+ *
+ ***/
+void silc_log_reset_all();
+
+/****f* silcutil/SilcLogAPI/silc_log_output_debug
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_output_debug(char *file, char *function,
+ * int line, char *string);
+ *
+ * DESCRIPTION
+ *
+ * This is the main function for debug output. Please note that you should
+ * rather use the wrapper macro SILC_LOG_DEBUG.
+ * If you want to use it anyway, the `file', `function', and `line' are the
+ * corresponding offsets in the source files, while `string' must be a
+ * dynamic allocated (null-terminated) buffer.
+ *
+ ***/
+void silc_log_output_debug(char *file, char *function,
+ int line, char *string);
+
+/****f* silcutil/SilcLogAPI/silc_log_output_hexdump
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_output_hexdump(char *file, char *function,
+ * int line, void *data_in,
+ * uint32 len, char *string);
+ *
+ * DESCRIPTION
+ *
+ * This is the main function for hexdump output. Please note that you
+ * should rather use the wrapper macro SILC_LOG_HEXDUMP.
+ * If you want to use it anyway, the `file', `function', and `line' are the
+ * corresponding offsets in the source files, `data_in' is the beginning
+ * of the buffer you wish to hexdump, which is `len' bytes long.
+ * `string' must be a dynamic allocated (null-terminated) buffer.
+ *
+ ***/
+void silc_log_output_hexdump(char *file, char *function,
+ int line, void *data_in,
+ uint32 len, char *string);
+
+/****f* silcutil/SilcLogAPI/silc_log_set_debug_callbacks
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
+ * void *debug_context,
+ * SilcLogHexdumpCb hexdump_cb,
+ * void *hexdump_context);
+ *
+ * DESCRIPTION
+ *
+ * Sets `debug_cb' as the the default callback function for the debug
+ * output, that will be called with the `debug_context' parameter.
+ * When SilcLog receives a debug message, it will trigger the callback
+ * function. If the callback function returns TRUE SilcLog will assume
+ * the input as handled and won't run its default handler.
+ * `hexdump_cb' and `hexdump_context' works the same way, except that they
+ * are referred to SILC_LOG_HEXDUMP requests.
+ * You can disable/remove a callback by setting it to NULL.
+ * If set, each callback function must be either in the form described by
+ * SilcLogDebugCb or SilcLogHexdumpCb.
+ *
+ * SEE ALSO
+ * SilcLogDebugCb, SilcLogHexdumpCb
+ *
+ ***/
+void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
+ void *debug_context,
+ SilcLogHexdumpCb hexdump_cb,
+ void *hexdump_context);
+
+/****f* silcutil/SilcLogAPI/silc_log_set_debug_string
+ *
+ * SYNOPSIS
+ *
+ * void silc_log_set_debug_string(const char *debug_string);
+ *
+ * DESCRIPTION
+ *
+ * Sets `debug_string' as the regexp string for filtering debugging
+ * output. The string is copied and it can be modified/destroyed after
+ * this function call.
+ *
+ ***/
void silc_log_set_debug_string(const char *debug_string);
-#endif
+#endif /* !SILCLOG_H */