X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilclog.c;h=976005266bb108c190096d9bd6134b79c103d838;hb=c257b555225193e54d85daf541d29578b3c93882;hp=b415c664d1eecc3ed45b0b6829da2895f859c206;hpb=a818c5b5411bbc4436d1c5f011236985c96bb787;p=silc.git diff --git a/lib/silcutil/silclog.c b/lib/silcutil/silclog.c index b415c664..97600526 100644 --- a/lib/silcutil/silclog.c +++ b/lib/silcutil/silclog.c @@ -2,9 +2,9 @@ silclog.c - Author: Johnny Mnemonic + Author: Giovanni Giacobbi - Copyright (C) 1997 - 2002 Pekka Riikonen + Copyright (C) 1997 - 2005 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 @@ -30,24 +30,28 @@ /* Our working struct -- at the moment we keep it private, but this could * change in the future */ struct SilcLogStruct { - char *filename; + char filename[256]; FILE *fp; SilcUInt32 maxsize; - char *typename; + const char *typename; SilcLogType type; SilcLogCb cb; void *context; }; typedef struct SilcLogStruct *SilcLog; -/* These are the known logging channels */ +/* These are the known logging channels. We initialize this struct with most + * of the fields set to NULL, because we'll fill in those values at runtime. */ static struct SilcLogStruct silclogs[SILC_LOG_MAX] = { - {NULL, NULL, 0, "Info", SILC_LOG_INFO, NULL, NULL}, - {NULL, NULL, 0, "Warning", SILC_LOG_WARNING, NULL, NULL}, - {NULL, NULL, 0, "Error", SILC_LOG_ERROR, NULL, NULL}, - {NULL, NULL, 0, "Fatal", SILC_LOG_FATAL, NULL, NULL}, + {"", NULL, 0, "Info", SILC_LOG_INFO, NULL, NULL}, + {"", NULL, 0, "Warning", SILC_LOG_WARNING, NULL, NULL}, + {"", NULL, 0, "Error", SILC_LOG_ERROR, NULL, NULL}, + {"", NULL, 0, "Fatal", SILC_LOG_FATAL, NULL, NULL}, }; +/* Causes logging output to contain timestamps */ +bool silc_log_timestamp = TRUE; + /* If TRUE, log files will be flushed for each log input */ bool silc_log_quick = FALSE; @@ -55,13 +59,13 @@ bool silc_log_quick = FALSE; bool silc_debug = FALSE; bool silc_debug_hexdump = FALSE; -/* Flush delay */ +/* Flush delay (in seconds) */ long silc_log_flushdelay = 300; /* Regular pattern matching expression for the debug output */ -char *silc_log_debug_string = NULL; +char silc_log_debug_string[128]; -/* Debug callbacks. If set these are used instead of default ones. */ +/* Debug callbacks. If set, these are triggered for each specific output. */ static SilcLogDebugCb silc_log_debug_cb = NULL; static void *silc_log_debug_context = NULL; static SilcLogHexdumpCb silc_log_hexdump_cb = NULL; @@ -71,7 +75,7 @@ static void *silc_log_hexdump_context = 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 */ +/* This is only needed during starting up -- don't lose any logging message */ static bool silc_log_starting = TRUE; /* The type wrapper utility. Translates a SilcLogType id to the corresponding @@ -95,7 +99,7 @@ static SilcLog silc_log_find_by_type(SilcLogType type) } /* Given an open log file, checks the size and rotates it if there is a - * max size set less then the current size */ + * max size set lower then the current size */ static void silc_log_checksize(SilcLog log) { char newname[127]; @@ -103,24 +107,27 @@ static void silc_log_checksize(SilcLog log) 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", + SILC_LOG_ERROR(("Error while checking size of the log file %s, fp=%p", log->filename, oldfp)); return; } - if (size < log->maxsize) 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); + silc_get_time(0), log->typename, (unsigned long)log->maxsize / 1024); fflush(log->fp); fclose(log->fp); - snprintf(newname, sizeof(newname), "%s.old", log->filename); + memset(newname, 0, sizeof(newname)); + snprintf(newname, sizeof(newname) - 1, "%s.old", log->filename); unlink(newname); /* I heard the following syscall may cause portability issues, but I don't @@ -130,6 +137,9 @@ static void silc_log_checksize(SilcLog log) 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))); +#ifdef HAVE_CHMOD + chmod(log->filename, 0600); +#endif /* HAVE_CHMOD */ } /* Reset a logging channel (close and reopen) */ @@ -141,12 +151,13 @@ static bool silc_log_reset(SilcLog log) fflush(log->fp); fclose(log->fp); } - if (!log->filename) return FALSE; + if (!log->filename[0]) 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))); + log->filename, log->typename, strerror(errno))); return FALSE; } + return TRUE; } @@ -170,28 +181,28 @@ SILC_TASK_CALLBACK(silc_log_fflush_callback) /* 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 + * More important channels can be printed on less important ones, but not * vice-versa. */ void silc_log_output(SilcLogType type, char *string) { - char *typename; + const char *typename = NULL; FILE *fp; SilcLog log; if ((type > SILC_LOG_MAX) || !(log = silc_log_find_by_type(type))) goto end; + /* Save the original typename, because even if we redirect the message + * to another channel we'll keep however the original channel name */ + typename = log->typename; + /* If there is a custom callback set, use it and return. */ if (log->cb) { if ((*log->cb)(type, string, log->context)) goto end; } - /* save the original typename, because if we redirect the channel we - * keep however the original destination channel name */ - typename = log->typename; - if (!silc_log_scheduled) { if (silc_log_no_init == FALSE) { fprintf(stderr, @@ -217,14 +228,24 @@ void silc_log_output(SilcLogType type, char *string) goto end; found: - fprintf(fp, "[%s] [%s] %s\n", silc_get_time(), typename, string); + /* writes the logging string to the selected channel */ + if (silc_log_timestamp) + fprintf(fp, "[%s] [%s] %s\n", silc_get_time(0), typename, string); + else + fprintf(fp, "[%s] %s\n", typename, string); + if (silc_log_quick || silc_log_starting) { fflush(fp); - if (log) + if (log) /* we may have been redirected to stderr */ silc_log_checksize(log); } end: + /* If debugging, also output the logging message to the console */ + if (typename && silc_debug) { + fprintf(stderr, "[Logging] [%s] %s\n", typename, string); + fflush(stderr); + } silc_free(string); } @@ -248,7 +269,7 @@ bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize, SilcLog log; log = silc_log_find_by_type(type); - if (!log || !scheduler) + if (!log) return FALSE; SILC_LOG_DEBUG(("Setting \"%s\" file to %s (max size=%d)", @@ -261,34 +282,39 @@ bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize, filename, strerror(errno)); return FALSE; } +#ifdef HAVE_CHMOD + chmod(filename, 0600); +#endif /* HAVE_CHMOD */ } - /* remove old file */ - if (log->filename) { - if (log->fp) { - fflush(fp); - fclose(fp); - } - silc_free(log->filename); - log->filename = NULL; + /* clean the logging channel */ + if (strlen(log->filename)) { + if (log->fp) + fclose(log->fp); + memset(log->filename, 0, sizeof(log->filename)); log->fp = NULL; } if (fp) { - log->filename = strdup(filename); + memset(log->filename, 0, sizeof(log->filename)); + strncpy(log->filename, filename, + strlen(filename) < sizeof(log->filename) ? strlen(filename) : + sizeof(log->filename) - 1); log->fp = fp; log->maxsize = maxsize; } - if (silc_log_scheduled) - return TRUE; - - /* 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, 10, 0, - SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); + if (scheduler) { + if (silc_log_scheduled) + return TRUE; - silc_log_scheduled = TRUE; + /* 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, 10, 0, + SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); + silc_log_scheduled = TRUE; + } return TRUE; } @@ -335,11 +361,13 @@ void silc_log_reset_all() { SILC_LOG_DEBUG(("Resetting all logs")); SILC_FOREACH_LOG(u) silc_log_reset(&silclogs[u]); + /* Immediately flush any possible warning message */ + silc_log_flush_all(); } /* Outputs the debug message to stderr. */ -void silc_log_output_debug(char *file, char *function, +void silc_log_output_debug(char *file, const char *function, int line, char *string) { if (!silc_debug) @@ -351,7 +379,7 @@ void silc_log_output_debug(char *file, char *function, goto end; if (silc_log_debug_cb) { - if ((*silc_log_debug_cb)(file, function, line, string, + if ((*silc_log_debug_cb)(file, (char *)function, line, string, silc_log_debug_context)) goto end; } @@ -365,7 +393,7 @@ void silc_log_output_debug(char *file, char *function, /* Hexdumps a message */ -void silc_log_output_hexdump(char *file, char *function, +void silc_log_output_hexdump(char *file, const char *function, int line, void *data_in, SilcUInt32 len, char *string) { @@ -382,7 +410,8 @@ void silc_log_output_hexdump(char *file, char *function, goto end; if (silc_log_hexdump_cb) { - if ((*silc_log_hexdump_cb)(file, function, line, data_in, len, string, + if ((*silc_log_hexdump_cb)(file, (char *)function, line, + data_in, len, string, silc_log_hexdump_context)) goto end; } @@ -475,11 +504,17 @@ void silc_log_reset_debug_callbacks() void silc_log_set_debug_string(const char *debug_string) { - silc_free(silc_log_debug_string); - if ((strchr(debug_string, '(') && - strchr(debug_string, ')')) || - strchr(debug_string, '$')) - silc_log_debug_string = strdup(debug_string); + char *string; + int len; + if ((strchr(debug_string, '(') && strchr(debug_string, ')')) || + strchr(debug_string, '$')) + string = strdup(debug_string); else - silc_log_debug_string = silc_string_regexify(debug_string); + string = silc_string_regexify(debug_string); + len = strlen(string); + if (len >= sizeof(silc_log_debug_string)) + len = sizeof(silc_log_debug_string) - 1; + memset(silc_log_debug_string, 0, sizeof(silc_log_debug_string)); + strncpy(silc_log_debug_string, string, len); + silc_free(string); }