updates. silc.server.0.7.4
authorPekka Riikonen <priikone@silcnet.org>
Sun, 6 Jan 2002 18:42:26 +0000 (18:42 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 6 Jan 2002 18:42:26 +0000 (18:42 +0000)
13 files changed:
CHANGES
CREDITS
Makefile.am.pre
TODO
apps/irssi/src/silc/core/silc-core.c
apps/silcd/server.c
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
apps/silcd/silcd.c
doc/example_silcd.conf.in
lib/silcsim/Makefile.am
lib/silcutil/silclog.c
lib/silcutil/silclog.h

diff --git a/CHANGES b/CHANGES
index a29581d80abc34326c92db5b0afbcfade0c71596..dec28652bb2b6a1d02fd4aa49f6fca9b25049188 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,41 @@
+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
diff --git a/CREDITS b/CREDITS
index 75901fc80e3eee574d27c6e075464c9a727f6766..593cbb128cc545648c0c7194173f1a2391ee14ab 100644 (file)
--- 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
index dc200b2e650750015da41adc183dd0b898c3ff7e..28ca886b3654707b7f9b0a40f45bc84c54ba45e9 100644 (file)
@@ -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 6f8aa18b77122547cde72e38a6b8bd59ff9afce9..2d35cbdf776bbca04be194ff67bca2baa82f476f 100644 (file)
--- 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
 
index 1bc44d9855279d2b303567493e384d15b32cb09b..4878c7168ae5dea9524e2e0555c5cdf398dbdbe6 100644 (file)
@@ -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", "");
index 344a89cbd12fdbea7a6d2a915026d8781284d381..55674823206f414edd7d2407acbcd20093b6adbb 100644 (file)
@@ -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);
index d91db49b87ac9fcf97c0912db888bb7544192b28..4e575c2eb1c6d69109b8f83f4b22529b6dc75bc3 100644 (file)
@@ -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
index ef284fb01b1707d415891a73aa6bb85d1a4b78b7..a11fc782fd8af62c5bf2e4a10f4504aa7d60f579 100644 (file)
@@ -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);
index ace7c3ce463709c3689ebf491816a67eae593584..e740fd1bf27ddeb50dd9c6bcaadf5a611fd96110 100644 (file)
@@ -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");
index 7cce0213cad32d2318c78759628c8c4cdfafb708..479fdb5ee52f42aa810993f291e66728044ab9d8 100644 (file)
@@ -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:<path>:<max byte size>
 #         warninglogile:<path>:<max byte size>
@@ -109,10 +118,10 @@ lassi.kuo.fi.ssh.com:10.2.1.6:Kuopio, Finland:706
 #         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.
index 866c941c0368efad92a604213d29ba5db15b4124..1608b73a333b64448622ddcce265e17d918d4e51 100644 (file)
@@ -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
 
index 08805a3887c644aa461dff2ca6ac001360b6b6be..e48bfeed58adef486d6c40e8695a437b0e066473 100644 (file)
@@ -2,15 +2,15 @@
 
   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)
 {
@@ -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);
 }
index 6dca78c689c55c43c2d9285ab8cfa0a70f49f481..222575beaa2da02e0d04328cfbb1914bb664efcc 100644 (file)
@@ -2,15 +2,15 @@
 
   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 */