/* Copyright Yann Weber This file is part of asmsh. asmsh is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. asmsh is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with asmsh. If not, see . */ #ifndef ASMSH_LOGGER_H #define ASMSH_LOGGER_H #include "config.h" /** A logger suitable for a shell * * Collect messages and deliver them when needed * * @warning This module is totally overkill. Most of the features (log collection * etc.) seems to be useless ! Apparently, in a shell, we just want errors to be printed * on stderr ? * * TODO continue to simplify the module & implement direct logging features */ #include #include #include #include #include #include #include #define asmsh_log_trace(msg_args...) \ asmsh_log(_default_logger, ASMSH_TRACE, __FUNCTION__, msg_args) #define asmsh_log_debug(msg_args...) \ asmsh_log(_default_logger, ASMSH_DEBUG, __FUNCTION__, msg_args) #define asmsh_log_info(msg_args...) \ asmsh_log(_default_logger, ASMSH_INFO, __FUNCTION__, msg_args) #define asmsh_log_warning(msg_args...) \ asmsh_log(_default_logger, ASMSH_WARN, __FUNCTION__, msg_args) #define asmsh_log_error(msg_args...) \ asmsh_log(_default_logger, ASMSH_ERR, __FUNCTION__, msg_args) #define asmsh_log_fatal(msg_args...) \ asmsh_log(_default_logger, ASMSH_FATAL, __FUNCTION__, msg_args) #define asmsh_log_perror(msg) \ asmsh_log_error("%s : %s", msg, strerror(errno)); #define ASMSH_LOG_BUFFER_ALLOC 4096 typedef struct asmsh_logger_s asmsh_logger_t; typedef struct asmsh_log_msg_s asmsh_log_msg_t; typedef enum asmsh_loglevel_e asmsh_loglevel_t; /**@param asmsh_log_msg_t* the log message to format * @param char* the result buffer * @param int the buffer size * @return The needed size for the message in buffer (@see snprintf) * if no error, else -1 */ typedef int (asmsh_log_fmt_f)(asmsh_log_msg_t*, char*, int); enum asmsh_loglevel_e { ASMSH_TRACE = 0, ASMSH_DEBUG = 10, ASMSH_INFO = 20, ASMSH_WARN = 30, ASMSH_ERR = 40, ASMSH_FATAL = 50 }; extern asmsh_logger_t *_default_logger; struct asmsh_log_msg_s { asmsh_loglevel_t level; time_t timestamp; char *caller; char *msg; asmsh_log_msg_t *nxt; }; struct asmsh_logger_s { asmsh_loglevel_t min_level; /** Direct log fd */ //int dlog_fd; // TODO should be multiple FDs !? /** Buffered messages * * A single buffer is used to store asmsh_log_msg_t and the * associated strings (caller & msg) * msgs will be a sequence of [asmsh_log_msg_t][char*(caller)][char*(msg)]... */ void *msgs; /** Point on the address of the next message */ asmsh_log_msg_t *nxt; /** Memory used by stored messages */ size_t msgs_sz; /** Allocated buffer for messages */ size_t msgs_alloc; /** Default formatter */ asmsh_log_fmt_f *fmt; /** Default direct log formatter */ asmsh_log_fmt_f *dfmt; }; static inline int asmsh_logger_msg_islast(asmsh_logger_t *logger, asmsh_log_msg_t *msg) { return ((void*)msg) == ((void*)logger->nxt); } static inline int asmsh_logger_empty(asmsh_logger_t *logger) { return asmsh_logger_msg_islast(logger, (asmsh_log_msg_t*)logger->msgs); } /** If null use default min_level of WARN * @param asmsh_logger_t* Optionnal logger to set * @return 0 if ok else -1 */ int asmsh_logger_setup(asmsh_logger_t *logger); /** Returns a pointer on a newly allocated logger * @param asmsh_log_level_t The minimum level for a message must have to be printed * @returns A newly allocated logger that must be freed after use by @ref asmsh_logger_ferr() */ asmsh_logger_t* asmsh_logger_new(asmsh_loglevel_t min_level); /** Free a logger */ void asmsh_logger_free(asmsh_logger_t* logger); int asmsh_logger_dprint_fmt(int fd, asmsh_logger_t *logger, asmsh_log_fmt_f *custom_fmt); static int asmsh_logger_dprint(int fd, asmsh_logger_t *logger) { return asmsh_logger_dprint_fmt(fd, logger, NULL); } /// Collect & format messages before printing them on stderr static inline int asmsh_logger_stderr(asmsh_logger_t *logger) { return asmsh_logger_dprint(2, logger); } /** Log a message( see macros ) */ int asmsh_log(asmsh_logger_t *logger, asmsh_loglevel_t lvl, const char caller[], const char *msg, ...); /** Return a pointer on a static string representing a loglevel name */ const char * asmsh_loglevel_name(asmsh_loglevel_t lvl); /** Default formatter with UTC datetime, lvl, caller and message */ int asmsh_log_default_fmt(asmsh_log_msg_t *msg, char *res, int sz); /** Simple formatter with level and message */ int asmsh_log_lvl_fmt(asmsh_log_msg_t *msg, char *res, int sz); #endif