diff options
author | David Sommerseth <dazo@users.sourceforge.net> | 2009-09-24 00:16:53 +0200 |
---|---|---|
committer | David Sommerseth <dazo@users.sourceforge.net> | 2009-09-24 00:16:53 +0200 |
commit | 7ae9a74c9c3bdab619ac5c0cefe1c8269bb06603 (patch) | |
tree | d4e9a61bd62b18dc37e9caabaa2d63ccc56db627 /common | |
parent | 9a2a8c5216d61dafb4232dba1ab56656390b61b0 (diff) | |
download | eurephia-7ae9a74c9c3bdab619ac5c0cefe1c8269bb06603.tar.gz eurephia-7ae9a74c9c3bdab619ac5c0cefe1c8269bb06603.tar.xz eurephia-7ae9a74c9c3bdab619ac5c0cefe1c8269bb06603.zip |
Rewritten the eurephia_log() to support syslog logging as well
Also simplified the initialisation of the logging module. By calling
the eurephia_log_init(eurephiaCTX *, char *dest, int loglevel) function,
a log context will be setup inside the eurephiaCTX.
To close the log file, eurephia_log_close(eurephiaCTX *) must be called.
The destination string to eurephia_log_init() can be:
- stdout:
Log everything to stdout
- stderr:
Log everything to stderr
- none:
Do no logging at all
- syslog:<facility>
Log via syslog. <facility> can be: user, local[0-7],
daemon or authpriv.
- Filename
All logging goes to the given filename. If the filename
string is not recognised by any of the reserved words above,
it will be handled as a filename.
Diffstat (limited to 'common')
-rw-r--r-- | common/eurephia_context.h | 7 | ||||
-rw-r--r-- | common/eurephia_log.c | 287 | ||||
-rw-r--r-- | common/eurephia_log.h | 12 |
3 files changed, 260 insertions, 46 deletions
diff --git a/common/eurephia_context.h b/common/eurephia_context.h index 877632c..e825c28 100644 --- a/common/eurephia_context.h +++ b/common/eurephia_context.h @@ -32,8 +32,8 @@ #define EUREPHIASTRUCT_H_ #include <stdio.h> -#include "eurephiadb_struct.h" - +#include <eurephiadb_struct.h> +#include <eurephia_log_struct.h> /** * eurephia context types */ @@ -58,8 +58,7 @@ typedef struct { void *fwcfg; /**< Dummy pointer, if the firewall API is not enabled */ #endif char *server_salt; /**< The in-memory password salt, used for the password cache */ - FILE *log; /**< FILE pointer to the log file */ - int loglevel; /**< Defines the log verbosity, higher number increases log verbosity */ + eurephiaLOG *log; /**< Log context, used by eurephia_log() */ int fatal_error; /**< If this flag is set, the execution should stop immediately */ int context_type; /**< Defines the context type */ } eurephiaCTX; diff --git a/common/eurephia_log.c b/common/eurephia_log.c index 0955aa0..ceff25f 100644 --- a/common/eurephia_log.c +++ b/common/eurephia_log.c @@ -31,34 +31,169 @@ #include <stdio.h> #include <stdarg.h> +#include <syslog.h> #include <string.h> #include <time.h> #include <pthread.h> +#include <assert.h> #include <eurephia_context.h> -#include "eurephia_log.h" +#include <eurephia_log.h> +#include <eurephia_nullsafe.h> /** - * Mapping table for mapping log types (defined in eurephia_log.h) - * to string values + * Maps eurephia log types (priorities) to string values + * + * @param prio eurephia logtype, such as LOG_INFO, LOG_DEBUG, LOG_FATAL, etc + * + * @return String containing the log type/prio */ -const char *erp_logtypes[] = { - "\0", - "-- INFO -- \0", /**< LOG_INFO */ - "-- DEBUG -- \0", /**< LOG_DEBUG */ - "** WARNING ** \0", /**< LOG_WARNING */ - "** ERROR ** \0", /**< LOG_ERROR */ - "** CRITICAL ** \0", /**< LOG_CRITICAL */ - "** - FATAL - ** \0", /**< LOG_FATAL */ - "** * PANIC * ** \0" /**< LOG_PANIC */ +static inline const char *logprio_str(int prio) { + switch( prio ) { + case LOG_INFO: + return "-- INFO -- \0"; + case LOG_DEBUG: + return "-- DEBUG -- \0"; + case LOG_WARNING: + return "** WARNING ** \0"; + case LOG_ERROR: + return "** ERROR ** \0"; + case LOG_CRITICAL: + return "** CRITICAL ** \0"; + case LOG_FATAL: + return "** - FATAL - ** \0"; + case LOG_PANIC: + return "** * PANIC * ** \0"; + default: + return "[[ UNKNOWN ]]\0"; + } +} + + +/** + * Mapping table for eurephia log types to syslog log types + */ +static const int syslog_priority[] = { + -1, + LOG_INFO, /**< LOG_INFO */ + LOG_DEBUG, /**< LOG_DEBUG */ + LOG_WARNING, /**< LOG_WARNING */ + LOG_ERR, /**< LOG_ERROR */ + LOG_CRIT, /**< LOG_CRITICAL */ + LOG_ALERT, /**< LOG_FATAL */ + LOG_EMERG /**< LOG_PANIC */ }; + +/** + * Converts eurephiaLOGTYPE value to a string + * + * @param lt eurephiaLOGTYPE, must be either logFILE or logSYSLOG + * + * @return Returns a static string with log type + */ +static inline const char *logtype_str(eurephiaLOGTYPE lt) { + switch( lt ) { + case logFILE: + return "file\0"; + case logSYSLOG: + return "syslog\0"; + } + return NULL; +} + + +/** + * Converts a string of log destination/facilities to syslog values + * + * @param dest String containing the log destination + * + * @return Returns a syslog compatible value, such as LOG_AUTHPRIV, LOG_LOCAL{0-7}, LOG_USER, etc. + * Unknown types will be set to syslog default, LOG_USER. + * + * @remark The following list will list up facilities which will be ignored and LOG_USER will be used + * instead: LOG_CRON, LOG_FTP, LOG_KERN, LOG_LPR, LOG_MAIL, LOG_NEWS, LOG_SYSLOG, LOG_UUCP. + * + */ +static const int syslog_logdest(const char *dest) { + if( dest == NULL ) { + return LOG_USER; + } + + if( strcasecmp(dest, "auth") == 0 ) { + return LOG_AUTHPRIV; // LOG_AUTH is deprecated, and LOG_AUTHPRIV should be used instead + } else if( strcasecmp(dest, "authpriv") == 0 ) { + return LOG_AUTHPRIV; + } else if( strcasecmp(dest, "daemon") == 0 ) { + return LOG_DAEMON; + } else if( strcasecmp(dest, "local0") == 0 ) { + return LOG_LOCAL0; + } else if( strcasecmp(dest, "local1") == 0 ) { + return LOG_LOCAL1; + } else if( strcasecmp(dest, "local2") == 0 ) { + return LOG_LOCAL2; + } else if( strcasecmp(dest, "local3") == 0 ) { + return LOG_LOCAL3; + } else if( strcasecmp(dest, "local4") == 0 ) { + return LOG_LOCAL4; + } else if( strcasecmp(dest, "local5") == 0 ) { + return LOG_LOCAL5; + } else if( strcasecmp(dest, "local6") == 0 ) { + return LOG_LOCAL6; + } else if( strcasecmp(dest, "local7") == 0 ) { + return LOG_LOCAL7; + } else { + return LOG_USER; + } +} + + /** * POSIX Mutex to avoid simultaneously logging activity from * several threads at the same time */ pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; + +/** + * Simple function for logging entries to a file with timestamp + * + * @param log FILE pointer to a log file + * @param logdst Log destiation/priority + * @param loglvl Log level of the message + * @param format stdarg, format string + * @param ap stdarg va_list, prepared by va_start() + */ +static void file_log(FILE *log, int logdst, int loglvl, const char *fmt, va_list ap) { + char tstmp_str[200]; + time_t tstmp; + struct tm *loctstmp; + + if( log == NULL ) { + return; + } + + // Get time stamp + memset(&tstmp_str, 0, 200); + tstmp = time(NULL); + loctstmp = localtime(&tstmp); + if( loctstmp != NULL ) { + if( strftime(tstmp_str, 198, "%Y-%m-%d %H:%M:%S %Z", loctstmp) == 0 ) { + snprintf(tstmp_str, 198, "(error getting time stamp string)"); + } + } else { + snprintf(tstmp_str, 198, "(error getting timestamp)"); + } + + // Do the logging + pthread_mutex_lock(&log_mutex); // Block other threads from writing when we write + fprintf(log, "[%s] %s [%i] ", tstmp_str, logprio_str(logdst), loglvl); + vfprintf(log, fmt, ap); + fprintf(log, "\n"); + fflush(log); + pthread_mutex_unlock(&log_mutex); // Unblock other threads +} + /** * Simple log function which writes log data to the log file available in the eurephiaCTX * @@ -72,32 +207,116 @@ pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; void eurephia_log(eurephiaCTX *ctx, int logdst, int loglvl, const char *fmt, ... ) { // Only log if we have an open log file and which has high enough log level - if( (ctx != NULL) && (ctx->log != NULL) && (ctx->loglevel >= loglvl) ) { + if( (ctx != NULL) && (ctx->log != NULL) && (ctx->log->opened == 1) + && (ctx->log->loglevel >= loglvl) ) { va_list ap; - char tstmp_str[200]; - time_t tstmp; - struct tm *loctstmp; - - // Get time stamp - memset(&tstmp_str, 0, 200); - tstmp = time(NULL); - loctstmp = localtime(&tstmp); - if( loctstmp != NULL ) { - if( strftime(tstmp_str, 198, "%Y-%m-%d %H:%M:%S %Z", loctstmp) == 0 ) { - snprintf(tstmp_str, 198, "(error getting time stamp string)"); - } - } else { - snprintf(tstmp_str, 198, "(error getting timestamp)"); - } va_start(ap, fmt); - pthread_mutex_lock(&log_mutex); // Block other threads from writing when we write - fprintf(ctx->log, "[%s] %s [%i] ", tstmp_str, erp_logtypes[logdst], loglvl); - vfprintf(ctx->log, fmt, ap); - fprintf(ctx->log, "\n"); - fflush(ctx->log); - pthread_mutex_unlock(&log_mutex); // Unblock other threads + switch( ctx->log->logtype ) { + case logFILE: + file_log(ctx->log->logfile, logdst, loglvl, fmt, ap); + break; + case logSYSLOG: + vsyslog(syslog_priority[logdst], fmt, ap); + break; + } va_end(ap); } } + +/** + * Closes an eurephia log context + * + * @param ctx eurephiaCTX containing the log context to be closed + * + */ +void eurephia_log_close(eurephiaCTX *ctx) { + if( (ctx == NULL) || (ctx->log == NULL) ) { + return; + } + + eurephia_log(ctx, LOG_INFO, 2, "Closing %s logging (%s).", + logtype_str(ctx->log->logtype), ctx->log->destination); + if( ctx->log->opened == 1 ) { + switch( ctx->log->logtype ) { + case logFILE: + if( ctx->log->logfile != NULL ) { + fflush(ctx->log->logfile); + fclose(ctx->log->logfile); + } + ctx->log->logfile = NULL; + break; + + case logSYSLOG: + closelog(); + break; + } + ctx->log->opened = 0; + } + free_nullsafe(ctx, ctx->log->destination); + free_nullsafe(ctx, ctx->log); +} + +/** + * Initialises and preapres the log device + * + * @param ctx eurephiaCTX where the log context will be associated + * @param dest Log destination. For can be a file name, "syslog:", "stdout:", "stderr:" or "none:". + * If it is "syslog:" it must continue with a string describing log facility such as + * "syslog:authpriv", "syslog:local0", "syslog:local1", "syslog:user", etc. If the + * facility is unknown, it will default to "user" + * + * @return Returns 1 on success, otherwise 0; + */ +int eurephia_log_init(eurephiaCTX *ctx, const char *dest, int loglevel) { + + assert( (ctx != NULL) && (dest != NULL) ); + + // Create log context + ctx->log = (eurephiaLOG *) malloc_nullsafe(ctx, sizeof(eurephiaLOG)+2); + if( ctx->log == NULL ) { + return 0; + } + + if( strncmp(dest, "syslog:", 7) == 0 ) { + ctx->log->logtype = logSYSLOG; + ctx->log->destination = strdup(dest+7); + } else { + ctx->log->logtype = logFILE; + ctx->log->destination = strdup(dest); + } + if( ctx->log->destination == NULL) { + free_nullsafe(ctx, ctx->log); + return 0; + } + ctx->log->loglevel = loglevel; + + switch( ctx->log->logtype ) { + case logFILE: // Open log file + if( strcmp(dest, "stdout:") == 0 ) { + ctx->log->logfile = stdout; + } else if( strcmp(dest, "stderr:") == 0 ) { + ctx->log->logfile = stderr; + } else if( strcmp(dest, "none:") == 0 ) { + ctx->log->logfile = NULL; + ctx->log->loglevel = 0; + ctx->log->opened = 0; + return 1; + } else if( (ctx->log->logfile = fopen(dest, "aw")) == NULL ) { + fprintf(stderr, "ERROR: Could not open log file: %s\n", ctx->log->destination); + free_nullsafe(ctx, ctx->log->destination); + free_nullsafe(ctx, ctx->log); + return 0; + } + break; + + case logSYSLOG: // Open syslog + openlog("eurephia", LOG_PID, syslog_logdest(ctx->log->destination)); + break; + } + ctx->log->opened = 1; + eurephia_log(ctx, LOG_INFO, 1, "Logging to %s (%s) started", + logtype_str(ctx->log->logtype), ctx->log->destination); + return 1; +} diff --git a/common/eurephia_log.h b/common/eurephia_log.h index 97e58d2..cb83f61 100644 --- a/common/eurephia_log.h +++ b/common/eurephia_log.h @@ -31,16 +31,9 @@ #ifndef EUREPHIA_LOG_H_ #define EUREPHIA_LOG_H_ +#include <eurephia_log_struct.h> #include <eurephia_context.h> -#define LOG_INFO 1 /**< Informational messages. Log level should be < 5 */ -#define LOG_DEBUG 2 /**< Messages intended when debugging. Only for log level > 10 */ -#define LOG_WARNING 3 /**< Input data or processing revealed unexpected data. Log level never > 2*/ -#define LOG_ERROR 4 /**< API errors but not sever, program can continue to run */ -#define LOG_CRITICAL 5 /**< Operation failed and might have been aborted. Log level always 0 */ -#define LOG_FATAL 6 /**< Operation failed and cannot continue. Log level always < 2 */ -#define LOG_PANIC 7 /**< Action failed an program could not continue to run. Log level always 0 */ - #ifdef ENABLE_DEBUG #warning ###### DEBUG LOGGING IS ENABLED - THIS COULD BE A SECURITY ISSUE ###### /** @@ -60,6 +53,9 @@ #warning ## ## #warning ########################################################################################## #endif + +int eurephia_log_init(eurephiaCTX *ctx, const char *dest, int loglvl); +void eurephia_log_close(eurephiaCTX *ctx); void eurephia_log(eurephiaCTX *ctx, int logdst, int loglvl, const char *fmt, ... ); #endif /* !EUREPHIA_LOG_H_ */ |