+Mon Jan 7 23:38:19 CET 2002 Johnny Mnemonic <johnny@themnemonic.org>
+
+ * Simple handling of TERM and HUP signals. Also added some log
+ flushing call around. Affected file is
+ silcd/silcd.c.
+
+ * Fixed small bugs in silclog.c. Now buffering output will take
+ effect after 10 seconds since startup: This will ensure that
+ no important startup messages are lost. Also output redirection
+ will preserve original format ([Date] [Type] message).
+ Affected file is lib/silcutil/silclog.c.
+
+ * Added two options to the config file, in the logging section:
+ quicklogs:<yes/no>: and flushdelay:<seconds>:. Affected files
+ lib/silcutil/silclog.[ch], silcd/serverconfig.[ch].
+
Sun Jan 6 12:49:40 EET 2002 Pekka Riikonen <priikone@silcnet.org>
* Do not print the warning about log files not being initialized
if (server->schedule) {
silc_schedule_stop(server->schedule);
silc_schedule_uninit(server->schedule);
+ server->schedule = NULL;
}
silc_server_protocols_unregister();
#include "server_internal.h"
SilcServerConfigSection silc_server_config_sections[] = {
- { "[Cipher]",
+ { "[Cipher]",
SILC_CONFIG_SERVER_SECTION_TYPE_CIPHER, 4 },
- { "[PKCS]",
+ { "[PKCS]",
SILC_CONFIG_SERVER_SECTION_TYPE_PKCS, 1 },
- { "[Hash]",
+ { "[Hash]",
SILC_CONFIG_SERVER_SECTION_TYPE_HASH_FUNCTION, 4 },
- { "[hmac]",
+ { "[hmac]",
SILC_CONFIG_SERVER_SECTION_TYPE_HMAC, 3 },
- { "[ServerKeys]",
+ { "[ServerKeys]",
SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_KEYS, 2 },
- { "[ServerInfo]",
+ { "[ServerInfo]",
SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_INFO, 4 },
- { "[AdminInfo]",
+ { "[AdminInfo]",
SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_INFO, 4 },
- { "[ListenPort]",
+ { "[ListenPort]",
SILC_CONFIG_SERVER_SECTION_TYPE_LISTEN_PORT, 3 },
- { "[Identity]",
+ { "[Identity]",
SILC_CONFIG_SERVER_SECTION_TYPE_IDENTITY, 2 },
- { "[Logging]",
+ { "[Logging]",
SILC_CONFIG_SERVER_SECTION_TYPE_LOGGING, 3 },
{ "[ConnectionClass]",
SILC_CONFIG_SERVER_SECTION_TYPE_CONNECTION_CLASS, 4 },
begin = 0;
linenum = 0;
- while((begin = silc_gets(line, sizeof(line),
+ while((begin = silc_gets(line, sizeof(line),
buffer->data, buffer->len, begin)) != EOF) {
cp = line;
linenum++;
if (ret < 0)
break;
if (ret == 0) {
- fprintf(stderr, "%s:%d: Log file section not defined\n",
+ fprintf(stderr, "%s:%d: Log file section not defined\n",
config->filename, pc->linenum);
break;
}
if (strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_INFO)
&& strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_WARNING)
&& strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_ERROR)
- && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_FATAL)) {
+ && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LF_FATAL)
+ && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LO_QUICK)
+ && strcmp(config->logging->logtype, SILC_CONFIG_SERVER_LO_FDELAY)) {
fprintf(stderr, "%s:%d: Unknown log file section '%s'\n",
config->filename, pc->linenum, config->logging->logtype);
break;
return FALSE;
}
- if (!(checkmask
+ if (!(checkmask
& (1L << SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION))) {
-
+
return FALSE;
}
void silc_server_config_setlogfiles(SilcServerConfig config, SilcSchedule sked)
{
+ long tmp;
SilcServerConfigSectionLogging *log;
SILC_LOG_DEBUG(("Setting configured log file names"));
log = config->logging;
while (log) {
+ /* Logging Files */
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_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);
+ /* Logging Options */
+ if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LO_QUICK)) {
+ if (!strcasecmp(log->filename, "yes") ||
+ !strcasecmp(log->filename, "on"))
+ silc_log_quick = TRUE;
+ }
+ if (!strcmp(log->logtype, SILC_CONFIG_SERVER_LO_FDELAY)) {
+ tmp = atol(log->filename);
+ if (tmp > 0)
+ silc_log_flushdelay = tmp;
+ else {
+ fprintf(stderr, "config: invalid flushdelay value, use quicklogs if "
+ "you want real-time logging.\n");
+ exit(1);
+ }
+ }
log = log->next;
}
#define SILC_CONFIG_SERVER_LF_WARNING "warninglogfile"
#define SILC_CONFIG_SERVER_LF_ERROR "errorlogfile"
#define SILC_CONFIG_SERVER_LF_FATAL "fatallogfile"
+#define SILC_CONFIG_SERVER_LO_QUICK "quicklogs"
+#define SILC_CONFIG_SERVER_LO_FDELAY "flushdelay"
} SilcServerConfigSectionLogging;
/* Holds all configured connection classes */
/*
silcd.c
-
+
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2001 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
GNU General Public License for more details.
*/
-/*
+/*
* Created: Wed Mar 19 00:17:12 1997
*
* This is the main program for the SILC daemon. This parses command
#include "server_internal.h"
#include "version.h"
+/* For now, we'll have this one server context global for this module. */
+static SilcServer silcd;
+
static void silc_usage();
static char *silc_server_create_identifier();
-static int
+static int
silc_server_create_key_pair(char *pkcs_name, int bits, char *path,
- char *identifier,
+ char *identifier,
SilcPublicKey *ret_pub_key,
SilcPrivateKey *ret_prv_key);
/* Long command line options */
-static struct option long_opts[] =
+static struct option long_opts[] =
{
{ "config-file", 1, NULL, 'f' },
{ "debug", 1, NULL, 'd' },
}
}
+static void got_hup(int z)
+{
+ /* First, reset all log files (they might have been deleted) */
+ silc_log_reset_all();
+ silc_log_flush_all();
+}
+
+static void stop_server(int z)
+{
+ SILC_LOG_DEBUG(("Start"));
+
+ /* Flush log files */
+ silc_log_flush_all();
+
+ /* Gracefully stop the server */
+ /* silc_server_stop(silcd); */
+ /* XXX do this for now since doing graceful exit now can remove
+ the scheduler underneath the server too early and crash it. */
+ exit(0);
+}
+
int main(int argc, char **argv)
{
int ret, opt, option_index;
char *config_file = NULL;
bool foreground = FALSE;
- SilcServer silcd;
struct sigaction sa;
/* Parse command line arguments */
if (argc > 1) {
while ((opt = getopt_long(argc, argv, "cf:d:hFVC:",
long_opts, &option_index)) != EOF) {
- switch(opt)
+ switch(opt)
{
case 'h':
silc_usage();
foreground = TRUE;
silc_log_quick = TRUE;
#else
- fprintf(stdout,
+ fprintf(stdout,
"Run-time debugging is not enabled. To enable it recompile\n"
"the server with --enable-debug configuration option.\n");
#endif
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGPIPE, &sa, NULL);
+ sa.sa_handler = got_hup;
+ sigaction(SIGHUP, &sa, NULL);
+ sa.sa_handler = stop_server;
+ sigaction(SIGTERM, &sa, NULL);
+ sa.sa_handler = stop_server;
+ sigaction(SIGINT, &sa, NULL);
/* Before running the server, fork to background. */
if (!foreground)
and we will exit. */
silc_server_run(silcd);
- /* Stop the server. This probably has been done already but it
- doesn't hurt to do it here again. */
- silc_server_stop(silcd);
+ /* The server was stopped, free it now */
silc_server_free(silcd);
-
+
+ /* Flush the logging system */
+ silc_log_flush_all();
+
exit(0);
fail:
exit(1);
# 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.
+# There are also two options, quicklogs and flushdelay. Their values
+# must be enclosed in colons (:), see the format below.
#
-# Format: infologfile:<path>:<max byte size>
+# Format: quicklogs:<yes/no>:
+# flushdelay:<seconds>:
+# infologfile:<path>:<max byte size>
# warninglogile:<path>:<max byte size>
# errorlogile:<path>:<max byte size>
# fatallogile:<path>:<max byte size>
#
[Logging]
+quicklogs:no:
+flushdelay:300:
infologfile:@LOGSDIR@/silcd.log:50000
warninglogfile:@LOGSDIR@/silcd_warnings.log:50000
#errorlogfile:@LOGSDIR@/silcd_errors.log:50000
#include "silcincludes.h"
-/* default flush time (5 minutes) */
-#define SILC_LOG_TIMEOUT 300
+/* Minimum time delay for log flushing calls (in seconds) */
+#define SILC_LOG_FLUSH_MIN_DELAY 2
/* 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__++)
bool silc_debug = FALSE;
bool silc_debug_hexdump = FALSE;
+/* Flush delay */
+long silc_log_flushdelay = 300;
+
/* Regular pattern matching expression for the debug output */
static char *silc_log_debug_string = NULL;
static bool silc_log_scheduled = FALSE;
static bool silc_log_no_init = FALSE;
+/* This is only needed during starting up -- don't lose any logging */
+static bool silc_log_starting = TRUE;
+
/* 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)
fflush(log->fp);
fclose(log->fp);
}
+ if (!log->filename) return FALSE;
if (!(log->fp = fopen(log->filename, "a+"))) {
SILC_LOG_WARNING(("Couldn't reset logfile %s for type \"%s\": %s",
log->filename, log->typename, strerror(errno)));
SILC_FOREACH_LOG(u)
silc_log_checksize(&silclogs[u]);
}
+ silc_log_starting = FALSE;
+ if (silc_log_flushdelay < SILC_LOG_FLUSH_MIN_DELAY)
+ silc_log_flushdelay = SILC_LOG_FLUSH_MIN_DELAY;
silc_schedule_task_add((SilcSchedule) context, 0, silc_log_fflush_callback,
- context, SILC_LOG_TIMEOUT, 0, SILC_TASK_TIMEOUT,
+ context, silc_log_flushdelay, 0, SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
}
void silc_log_output(SilcLogType type, char *string)
{
char *typename;
+ FILE *fp;
SilcLog log;
if ((type > SILC_LOG_MAX) || !(log = silc_log_find_by_type(type)))
goto end;
}
+ /* save the original typename, because if we redirect the channel we
+ * keep however the original destination channel name */
+ typename = log->typename;
+
if (!silc_log_scheduled) {
if (silc_log_no_init == FALSE) {
- fprintf(stderr,
+ 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;
+ /* redirect output */
+ fp = stderr;
+ log = NULL;
+ goto found;
}
- /* 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 (log && (fp = log->fp)) goto found;
if (type == 0) break;
log = silc_log_find_by_type(--type);
}
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);
+ fprintf(fp, "[%s] [%s] %s\n", silc_get_time(), typename, string);
+ if (silc_log_quick || silc_log_starting) {
+ fflush(fp);
+ if (log)
+ silc_log_checksize(log);
}
end:
if (silc_log_scheduled)
return TRUE;
- /* make sure we write to the disk sometimes */
+ /* add schedule hook with a short delay to make sure we'll use right delay */
silc_schedule_task_add(scheduler, 0, silc_log_fflush_callback,
- (void *) scheduler, SILC_LOG_TIMEOUT, 0,
+ (void *) scheduler, 10, 0,
SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
silc_log_scheduled = TRUE;
***/
extern bool silc_log_quick;
+/****v* silcutil/SilcLogAPI/silc_log_flushdelay
+ *
+ * NAME
+ *
+ * long silc_log_flushdelay -- flushing time delay
+ *
+ * DESCRIPTION
+ *
+ * Sets the logfiles flushing delay in seconds. As for now, changing this
+ * value AFTER logfiles initialization won't take effect until previous
+ * delay time will expire; for example if you change from 300 seconds to
+ * 60 seconds you will have to wait up to 300 seconds for this change to
+ * take effect.
+ *
+ ***/
+extern long silc_log_flushdelay;
+
/****v* silcutil/SilcLogAPI/silc_debug
*
* NAME