#define _GNU_SOURCE #include <stdio.h> #include <stdarg.h> #include <errno.h> #include "mx_log.h" #define MX_LOG_GET (MX_LOG_NONE-1) int mx_log_errno = 0; int mx_log_level_set(int level) { static int loglevel = MX_LOG_WARNING; int oldloglevel = loglevel; switch (level) { case MX_LOG_GET: return loglevel; case MX_LOG_NONE: case MX_LOG_EMERG: case MX_LOG_ALERT: case MX_LOG_CRIT: case MX_LOG_ERR: case MX_LOG_WARNING: case MX_LOG_NOTICE: case MX_LOG_INFO: case MX_LOG_DEBUG: loglevel=level; return oldloglevel; } return -(mx_log_errno=EINVAL); } int mx_log_level_mxlog_to_syslog(int level) { level = MX_LOG_MXLOG_TO_SYSLOG(level); if (level < LOG_EMERG || level > LOG_DEBUG) return -(mx_log_errno=EINVAL); return level; } int mx_log_level_syslog_to_mxlog(int level) { if (level < LOG_EMERG || level > LOG_DEBUG) return -(mx_log_errno=EINVAL); level = MX_LOG_SYSLOG_TO_MXLOG(level); return level; } int mx_log_level_get(void) { return mx_log_level_set(MX_LOG_GET); } int mx_log_printf(const char *fmt, ...) { int len; int len2; char *msg = NULL; va_list ap; va_start(ap, fmt); len = vasprintf(&msg, fmt, ap); va_end(ap); if (len == -1) return -(mx_log_errno=ENOMEM); if (mx_log_print) return mx_log_print(msg, len); if (len == 0) { mx_free_null(msg); return 0; } len2 = fprintf(stderr, "%s\n", msg); fflush(stderr); mx_free_null(msg); if (len2 != len+1) return -(errno=EIO); return len; } static int log_log(int level, int loglevel, char *file, unsigned long line, const char *func, const char *msg) { char *prefix = ""; if (*msg == 0) return 0; switch (level) { case MX_LOG_EMERG: prefix = "EMERGENCY: "; break; case MX_LOG_ALERT: prefix = "ALERT: "; break; case MX_LOG_CRIT: prefix = "CRITCAL ERROR: "; break; case MX_LOG_ERR: prefix = "ERROR: "; break; case MX_LOG_WARNING: prefix = "WARNING: "; break; case MX_LOG_NOTICE: case MX_LOG_INFO: prefix = ""; break; case MX_LOG_DEBUG: prefix = "DEBUG: "; break; default: return -(mx_log_errno=EINVAL); } if (loglevel >= MX_LOG_DEBUG) return mx_log_printf("%s %s:%lu:%s(): %s%s", program_invocation_short_name, file, line, func, prefix, msg); return mx_log_printf("%s%s", prefix, msg); } int mx_logva_do(int level, char *file, unsigned long line, const char *func, const char *fmt, va_list ap) { int loglevel; int len; char *msg = NULL; int res; int preserved_errno = errno; loglevel = mx_log_level_get(); if (level > loglevel) { errno = preserved_errno; return 0; } len = vasprintf(&msg, fmt, ap); if (len == -1) { errno = preserved_errno; return -(mx_log_errno=ENOMEM); } if (mx_log_log) res = mx_log_log(level, loglevel, file, line, func, msg); else res = log_log(level, loglevel, file, line, func, msg); mx_free_null(msg); errno = preserved_errno; return res; } int mx_log_do(int level, char *file, unsigned long line, const char *func, const char *fmt, ...) { va_list ap; int res; va_start(ap, fmt); res = mx_logva_do(level, file, line, func, fmt, ap); va_end(ap); return res; } int mx_log_finish(void) { if (mx_log_log) mx_log_log(MX_LOG_NONE, MX_LOG_NONE, NULL, 0, NULL, NULL); if (mx_log_print) mx_log_print(NULL, 0); return 0; }