diff --git a/include/Cytoplasm/Log.h b/include/Cytoplasm/Log.h index 0074dae..ec4f277 100644 --- a/include/Cytoplasm/Log.h +++ b/include/Cytoplasm/Log.h @@ -46,6 +46,7 @@ #define LOG_FLAG_COLOR (1 << 0) #define LOG_FLAG_SYSLOG (1 << 1) +#define LOG_FLAG_STDOUT (1 << 2) /** * A log is defined as a configuration that describes the properties @@ -110,15 +111,9 @@ extern void LogConfigUnindent(LogConfig *); extern void LogConfigIndentSet(LogConfig *, size_t); /** - * Set the file stream that logging output should be written to. This - * defaults to standard output, but it can be set to standard error, - * or any other arbitrary stream. Passing a NULL value for the stream - * pointer sets the log output to the standard output. Note that the - * output stream is only used if - * .Va LOG_FLAG_SYSLOG - * is not set. + * Set the file stream that logging output should be written to. */ -extern void LogConfigOutputSet(LogConfig *, Stream *); +extern void LogConfigFileSet(LogConfig *, Stream *); /** * Set a number of boolean options on a log configuration. This @@ -135,12 +130,7 @@ extern void LogConfigOutputSet(LogConfig *, Stream *); * is checked before writing any terminal sequences. * .It LOG_FLAG_SYSLOG * When set, log output to the syslog using - * .Xr syslog 3 , - * instead of logging to the file set by - * .Fn LogConfigOutputSet . - * This flag always overrides the stream set by that function, - * regardless of when it was set, even if it was set after this flag - * was set. + * .Xr syslog 3 * .El */ extern void LogConfigFlagSet(LogConfig *, int); diff --git a/src/Log.c b/src/Log.c index ada86a4..b1ea0e6 100644 --- a/src/Log.c +++ b/src/Log.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -39,7 +40,7 @@ struct LogConfig { int level; size_t indent; - Stream *out; + Stream *file; int flags; char *tsFmt; @@ -65,8 +66,8 @@ LogConfigCreate(void) LogConfigLevelSet(config, LOG_INFO); LogConfigIndentSet(config, 0); - LogConfigOutputSet(config, NULL); /* Will set to stdout */ - LogConfigFlagSet(config, LOG_FLAG_COLOR); + LogConfigFileSet(config, NULL); + LogConfigFlagSet(config, LOG_FLAG_COLOR | LOG_FLAG_STDOUT); LogConfigTimeStampFormatSet(config, "%y-%m-%d %H:%M:%S"); return config; @@ -185,20 +186,20 @@ LogConfigLevelSet(LogConfig * config, int level) } void -LogConfigOutputSet(LogConfig * config, Stream * out) +LogConfigFileSet(LogConfig * config, Stream * file) { if (!config) { return; } - if (out) + if (file) { - config->out = out; + config->file = file; } else { - config->out = StreamStdout(); + config->file = StreamStdout(); } } @@ -222,42 +223,14 @@ LogConfigUnindent(LogConfig * config) } void -Logv(LogConfig * config, int level, const char *msg, va_list argp) +LogPrint(Stream * stream, LogConfig * config, int level, const char *msg, va_list argp) { size_t i; int doColor; char indicator; - /* - * Only proceed if we have a config and its log level is set to a - * value that permits us to log. This is as close as we can get - * to a no-op function if we aren't logging anything, without doing - * some crazy macro magic. - */ - if (!config || level > config->level) - { - return; - } - - /* Misconfiguration */ - if (!config->out) - { - return; - } - - pthread_mutex_lock(&config->lock); - - if (LogConfigFlagGet(config, LOG_FLAG_SYSLOG)) - { - /* No further print logic is needed; syslog will handle it all - * for us. */ - vsyslog(level, msg, argp); - pthread_mutex_unlock(&config->lock); - return; - } - doColor = LogConfigFlagGet(config, LOG_FLAG_COLOR) - && isatty(StreamFileno(config->out)); + && isatty(StreamFileno(stream)); if (doColor) { @@ -293,10 +266,10 @@ Logv(LogConfig * config, int level, const char *msg, va_list argp) break; } - StreamPuts(config->out, ansi); + StreamPuts(stream, ansi); } - StreamPutc(config->out, '['); + StreamPutc(stream, '['); if (config->tsFmt) { @@ -309,15 +282,15 @@ Logv(LogConfig * config, int level, const char *msg, va_list argp) if (tsLength) { - StreamPuts(config->out, tsBuffer); + StreamPuts(stream, tsBuffer); if (!isspace((unsigned char) tsBuffer[tsLength - 1])) { - StreamPutc(config->out, ' '); + StreamPutc(stream, ' '); } } } - StreamPrintf(config->out, "(%lu) ", UtilThreadNo()); + StreamPrintf(stream, "(%lu) ", UtilThreadNo()); switch (level) { @@ -350,24 +323,60 @@ Logv(LogConfig * config, int level, const char *msg, va_list argp) break; } - StreamPrintf(config->out, "%c]", indicator); + StreamPrintf(stream, "%c]", indicator); if (doColor) { /* ANSI Reset */ - StreamPuts(config->out, "\033[0m"); + StreamPuts(stream, "\033[0m"); } - StreamPutc(config->out, ' '); + StreamPutc(stream, ' '); for (i = 0; i < config->indent; i++) { - StreamPutc(config->out, ' '); + StreamPutc(config->file, ' '); } - StreamVprintf(config->out, msg, argp); - StreamPutc(config->out, '\n'); + StreamVprintf(stream, msg, argp); + StreamPutc(stream, '\n'); - StreamFlush(config->out); + StreamFlush(stream); +} + +void +Logv(LogConfig * config, int level, const char *msg, va_list argp) +{ + /* + * Only proceed if we have a config and its log level is set to a + * value that permits us to log. This is as close as we can get + * to a no-op function if we aren't logging anything, without doing + * some crazy macro magic. + */ + if (!config || level > config->level) + { + return; + } + + /* Misconfiguration */ + if (!config->file) + { + return; + } + + pthread_mutex_lock(&config->lock); + + if (LogConfigFlagGet(config, LOG_FLAG_SYSLOG)) + { + vsyslog(level, msg, argp); + } + + if (LogConfigFlagGet(config, LOG_FLAG_STDOUT)) { + LogPrint(StreamStdout(), config, level, msg, argp); + } + + if (config->file) { + LogPrint(config->file, config, level, msg, argp); + } pthread_mutex_unlock(&config->lock); }