From d724e6e0616bad77bdcd83ed08a3f20daf5660b2 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Sun, 6 Jan 2002 18:42:26 +0000 Subject: [PATCH] updates. --- CHANGES | 38 ++ CREDITS | 9 + Makefile.am.pre | 2 +- TODO | 2 +- apps/irssi/src/silc/core/silc-core.c | 20 +- apps/silcd/server.c | 14 +- apps/silcd/serverconfig.c | 49 +-- apps/silcd/serverconfig.h | 2 +- apps/silcd/silcd.c | 11 +- doc/example_silcd.conf.in | 23 +- lib/silcsim/Makefile.am | 4 +- lib/silcutil/silclog.c | 517 ++++++++++++++-------- lib/silcutil/silclog.h | 637 +++++++++++++++++++++++---- 13 files changed, 976 insertions(+), 352 deletions(-) diff --git a/CHANGES b/CHANGES index a29581d8..dec28652 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,41 @@ +Sun Jan 6 12:49:40 EET 2002 Pekka Riikonen + + * 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 + + * 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 * Added the silc_client_del_client to remove the client from diff --git a/CREDITS b/CREDITS index 75901fc8..593cbb12 100644 --- a/CREDITS +++ b/CREDITS @@ -28,6 +28,15 @@ S: Snellmanninkatu 34 A 15 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 diff --git a/Makefile.am.pre b/Makefile.am.pre index dc200b2e..28ca886b 100644 --- a/Makefile.am.pre +++ b/Makefile.am.pre @@ -55,7 +55,7 @@ generate-server-key: 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)/ diff --git a/TODO b/TODO index 6f8aa18b..2d35cbdf 100644 --- a/TODO +++ b/TODO @@ -61,7 +61,7 @@ TODO/bugs In SILC Server ======================== 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 diff --git a/apps/irssi/src/silc/core/silc-core.c b/apps/irssi/src/silc/core/silc-core.c index 1bc44d98..4878c716 100644 --- a/apps/irssi/src/silc/core/silc-core.c +++ b/apps/irssi/src/silc/core/silc-core.c @@ -158,19 +158,10 @@ static void silc_init_userinfo(void) /* 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 */ @@ -273,8 +264,10 @@ void silc_core_init_finish(void) 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" @@ -289,7 +282,6 @@ void silc_core_init_finish(void) /* 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", ""); diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 344a89cb..55674823 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -143,7 +143,6 @@ int silc_server_init(SilcServer server) /* 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)) @@ -284,7 +283,7 @@ int silc_server_init(SilcServer server) 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 @@ -305,6 +304,9 @@ int silc_server_init(SilcServer server) 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) { @@ -499,8 +501,10 @@ void silc_server_stop(SilcServer server) { 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(); @@ -2337,7 +2341,7 @@ void silc_server_free_client_data(SilcServer server, /* 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); diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index d91db49b..4e575c2e 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -96,11 +96,12 @@ SilcServerConfig silc_server_config_alloc(char *filename) 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; } @@ -1140,7 +1141,7 @@ int silc_server_config_parse_lines(SilcServerConfig config, } 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. */ @@ -1218,48 +1219,24 @@ int silc_server_config_check_sections(uint32 checkmask) /* 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 diff --git a/apps/silcd/serverconfig.h b/apps/silcd/serverconfig.h index ef284fb0..a11fc782 100644 --- a/apps/silcd/serverconfig.h +++ b/apps/silcd/serverconfig.h @@ -267,7 +267,7 @@ int silc_server_config_parse(SilcServerConfig config, SilcBuffer buffer, 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); diff --git a/apps/silcd/silcd.c b/apps/silcd/silcd.c index ace7c3ce..e740fd1b 100644 --- a/apps/silcd/silcd.c +++ b/apps/silcd/silcd.c @@ -126,15 +126,12 @@ static void silc_checkpid(SilcServer silcd) 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:", @@ -153,11 +150,13 @@ int main(int argc, char **argv) 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"); diff --git a/doc/example_silcd.conf.in b/doc/example_silcd.conf.in index 7cce0213..479fdb5e 100644 --- a/doc/example_silcd.conf.in +++ b/doc/example_silcd.conf.in @@ -99,9 +99,18 @@ lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:706 # 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:: # warninglogile:: @@ -109,10 +118,10 @@ lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:706 # fatallogile:: # [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. diff --git a/lib/silcsim/Makefile.am b/lib/silcsim/Makefile.am index 866c941c..1608b73a 100644 --- a/lib/silcsim/Makefile.am +++ b/lib/silcsim/Makefile.am @@ -56,12 +56,12 @@ endif $(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 diff --git a/lib/silcutil/silclog.c b/lib/silcutil/silclog.c index 08805a38..e48bfeed 100644 --- a/lib/silcutil/silclog.c +++ b/lib/silcutil/silclog.c @@ -2,15 +2,15 @@ silclog.c - Author: Pekka Riikonen + Author: Johnny Mnemonic - 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 @@ -21,160 +21,334 @@ #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) { @@ -182,33 +356,26 @@ void silc_log_output_hexdump(char *file, char *function, 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; @@ -224,14 +391,14 @@ void silc_log_output_hexdump(char *file, char *function, 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, " "); @@ -239,10 +406,10 @@ void silc_log_output_hexdump(char *file, char *function, fprintf(stderr, " "); } } - + for (i = 0; i < count; i++) { char ch; - + if (data[pos] < 32 || data[pos] >= 127) ch = '.'; else @@ -258,70 +425,44 @@ void silc_log_output_hexdump(char *file, char *function, 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); } diff --git a/lib/silcutil/silclog.h b/lib/silcutil/silclog.h index 6dca78c6..222575be 100644 --- a/lib/silcutil/silclog.h +++ b/lib/silcutil/silclog.h @@ -2,15 +2,15 @@ silclog.h - Author: Pekka Riikonen + Author: Johnny Mnemonic - 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 @@ -18,114 +18,569 @@ */ +/****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 */ -- 2.24.0