summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorDavid Sommerseth <dazo@users.sourceforge.net>2009-09-24 00:16:53 +0200
committerDavid Sommerseth <dazo@users.sourceforge.net>2009-09-24 00:16:53 +0200
commit7ae9a74c9c3bdab619ac5c0cefe1c8269bb06603 (patch)
treed4e9a61bd62b18dc37e9caabaa2d63ccc56db627 /common
parent9a2a8c5216d61dafb4232dba1ab56656390b61b0 (diff)
downloadeurephia-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.h7
-rw-r--r--common/eurephia_log.c287
-rw-r--r--common/eurephia_log.h12
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_ */