diff options
| author | Dennis Camera <skonfig@dtnr.ch> | 2022-08-14 22:39:24 +0200 |
|---|---|---|
| committer | Dennis Camera <skonfig@dtnr.ch> | 2022-08-14 23:47:33 +0200 |
| commit | 289a2e94910d3b30256799f6c261dc01b194f254 (patch) | |
| tree | c634e450838a35a84a7d10cca2e0a40b7ac30638 | |
| parent | a08bb6903495fb562fc3f2b881ee69eb36ac01cf (diff) | |
| download | skonfig-c-289a2e94910d3b30256799f6c261dc01b194f254.tar.gz skonfig-c-289a2e94910d3b30256799f6c261dc01b194f254.zip | |
Implement logging module
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | src/config.c | 56 | ||||
| -rw-r--r-- | src/config.h | 68 | ||||
| -rw-r--r-- | src/log.c | 104 | ||||
| -rw-r--r-- | src/log.h | 148 | ||||
| -rw-r--r-- | src/skonfig.c | 32 | ||||
| -rw-r--r-- | src/util/font.h | 33 | ||||
| -rw-r--r-- | src/util/string.h | 4 |
8 files changed, 391 insertions, 56 deletions
diff --git a/Makefile.am b/Makefile.am index fa24baf..6dfcb92 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,5 +10,5 @@ endif bin_PROGRAMS = skonfig skonfig_SOURCES = src/skonfig.c \ - src/config.c \ + src/config.c src/log.c \ src/util/array.c src/util/fs.c src/util/string.c diff --git a/src/config.c b/src/config.c index 1d369c4..a042102 100644 --- a/src/config.c +++ b/src/config.c @@ -5,13 +5,14 @@ #include <stdlib.h> #include <string.h> +#include <strings.h> #include <unistd.h> /******************************************************************************/ /* Type conversions */ -inline const char *archiving_to_string(enum sk_archiving_mode a) { +const char *sk_archiving_mode_to_string(enum sk_archiving_mode a) { switch (a) { case SK_ARCHIVING_NONE: return "none"; @@ -28,19 +29,15 @@ inline const char *archiving_to_string(enum sk_archiving_mode a) { } } -inline enum sk_colour_output string_to_colour_output(const char *in) { - if (!strcmp(in, "always")) { - return SK_COLOUR_ALWAYS; - } else if (!strcmp(in, "never")) { - return SK_COLOUR_NEVER; - } else if (!strcmp(in, "auto")) { - return SK_COLOUR_AUTO; - } else { - return SK_COLOUR_NEVER; +enum sk_archiving_mode sk_archiving_mode_of_string(const char *s) { + for (enum sk_archiving_mode a = SK_ARCHIVING_MIN; a <= SK_ARCHIVING_MAX; ++a) { + if (!strcasecmp(s, sk_archiving_mode_to_string(a))) + return a; } + return SK_ARCHIVING_NONE; } -inline const char *colour_output_to_string(enum sk_colour_output c) { +const char *sk_colour_output_to_string(enum sk_colour_output c) { switch (c) { case SK_COLOUR_NEVER: return "never"; @@ -53,24 +50,15 @@ inline const char *colour_output_to_string(enum sk_colour_output c) { } } -inline const char *verbosity_to_string(enum sk_log_verb v) { - switch (v) { - case LOG_OFF: - return "off"; - case LOG_ERROR: - return "error"; - case LOG_WARNING: - return "warning"; - case LOG_INFO: - return "info"; - case LOG_VERBOSE: - return "verbose"; - case LOG_DEBUG: - return "debug"; - case LOG_TRACE: - return "trace"; - default: - return NULL; +enum sk_colour_output sk_colour_output_of_string(const char *s) { + if (!strcasecmp(s, "always")) { + return SK_COLOUR_ALWAYS; + } else if (!strcasecmp(s, "never")) { + return SK_COLOUR_NEVER; + } else if (!strcasecmp(s, "auto")) { + return SK_COLOUR_AUTO; + } else { + return SK_COLOUR_NEVER; } } @@ -90,7 +78,7 @@ static struct sk_config sk_config_defaults = { .remote_exec = "ssh -o User=root", .inventory_dir = "manifest/inventory", .jobs = 1, - .verbosity_level = LOG_INFO, + .verbosity_level = SK_LOG_INFO, .archiving = SK_ARCHIVING_NONE, .save_output_streams = true, .log_timestamp = false @@ -159,15 +147,15 @@ void sk_config_print(struct sk_config *config, FILE *outstream) { config->global.remote_shell, config->global.cache_path_pattern, conf_dir_str, - colour_output_to_string(config->global.coloured_output), + sk_colour_output_to_string(config->global.coloured_output), config->global.init_manifest, config->global.out_path, config->global.remote_out_path, config->global.remote_exec, config->global.inventory_dir, config->global.jobs, - verbosity_to_string(config->global.verbosity_level), - archiving_to_string(config->global.archiving), + sk_log_level_to_string(config->global.verbosity_level), + sk_archiving_mode_to_string(config->global.archiving), boolstr(config->global.save_output_streams), boolstr(config->global.log_timestamp) ); @@ -263,7 +251,7 @@ inline searchpath_t _searchpath_conf(const char *in) { return (searchpath_t)buf; } -#define _colour_conf(c) string_to_colour_output(c) +#define _colour_conf(c) sk_colour_output_of_string(c) /* if the envonment variable is set, always disable coloured output, not matter * its value */ diff --git a/src/config.h b/src/config.h index bfd7029..6594618 100644 --- a/src/config.h +++ b/src/config.h @@ -3,6 +3,8 @@ #include "../config.h" +#include "log.h" + #include <stdio.h> #if HAVE_STDBOOL_H @@ -14,19 +16,6 @@ typedef char * path_t; typedef char * dir_t; typedef char ** searchpath_t; -enum sk_log_verb { - LOG_OFF = 0, - LOG_ERROR, - LOG_WARNING, - LOG_INFO, - LOG_VERBOSE, - LOG_DEBUG, - LOG_TRACE, - - SK_LOG_MIN = LOG_OFF, - SK_LOG_MAX = LOG_TRACE -}; - enum sk_colour_output { SK_COLOUR_NEVER = 0, SK_COLOUR_ALWAYS, @@ -38,7 +27,10 @@ enum sk_archiving_mode { SK_ARCHIVING_TAR, SK_ARCHIVING_TGZ, SK_ARCHIVING_TBZ2, - SK_ARCHIVING_TXZ + SK_ARCHIVING_TXZ, + + SK_ARCHIVING_MIN = SK_ARCHIVING_NONE, + SK_ARCHIVING_MAX = SK_ARCHIVING_TXZ }; struct sk_config_global { @@ -53,7 +45,7 @@ struct sk_config_global { command_t remote_exec; dir_t inventory_dir; unsigned int jobs; - enum sk_log_verb verbosity_level; + sk_log_level verbosity_level; enum sk_archiving_mode archiving; bool save_output_streams; bool log_timestamp; @@ -63,6 +55,52 @@ struct sk_config { struct sk_config_global global; }; +/* type conversion functions */ + +/** + * sk_archiving_mode_to_string: + * return the string representation of an sk_archiving_mode. + * + * @param a: an sk_archiving_mode. + * @return the string representation of a. + */ +const char *sk_archiving_mode_to_string(enum sk_archiving_mode a); + +/** + * sk_archiving_mode_of_string: + * returns an sk_archiving_mode of a string representation. + * + * In case an invalid string representation is given, + * SK_ARCHIVING_NONE is returned. + * + * @param s: the string representation of an sk_archiving_mode. + * @return an sk_archiving_mode. + */ +enum sk_archiving_mode sk_archiving_mode_of_string(const char *s); + +/** + * sk_colour_output_to_string: + * returns the string representation of an sk_colour_output. + * + * @param c: the sk_colour_output. + * @return the string representation of c. + */ +const char *sk_colour_output_to_string(enum sk_colour_output c); + +/** + * sk_colour_output_of_string: + * convert a string to sk_colour_output. + * + * s is interpreted case-insensitively. + * In case an invalid string representation is given, + * SK_COLOUR_NEVER is returned. + * + * @param s: the string representation of an sk_colour_output. + * @return sk_colour_output + */ +enum sk_colour_output sk_colour_output_of_string(const char *s); + + /* functions */ /** diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..7a3bf3f --- /dev/null +++ b/src/log.c @@ -0,0 +1,104 @@ +#include "log.h" + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include <ctype.h> + +static sk_log_level _sk_log_level = +#if DEBUG + SK_LOG_DEBUG; +#else + SK_LOG_INFO; +#endif +static sk_font_map _sk_log_font; /* defaults to NULL */ + +sk_font_map _SK_LOG_COLOURED = { + [SK_LOG_ERROR] = SK_FONT_FG_RED, + [SK_LOG_WARN] = SK_FONT_FG_YELLOW, + [SK_LOG_INFO] = SK_FONT_FG_BLUE, + [SK_LOG_DEBUG] = SK_FONT_FG_WHITE, + [SK_LOG_TRACE] = SK_FONT_FG_WHITE +}; +sk_font_map _SK_LOG_MONOCHROME = { + [SK_LOG_ERROR] = SK_FONT_FG_DEFAULT, + [SK_LOG_WARN] = SK_FONT_FG_DEFAULT, + [SK_LOG_INFO] = SK_FONT_FG_DEFAULT, + [SK_LOG_DEBUG] = SK_FONT_FG_DEFAULT, + [SK_LOG_TRACE] = SK_FONT_FG_DEFAULT +}; + +const char *sk_log_level_to_string(sk_log_level level) { + switch (level) { + /* case SK_LOG_OFF: + * return "off"; */ + case SK_LOG_ERROR: + return "error"; + case SK_LOG_WARN: + return "warning"; + case SK_LOG_INFO: + return "info"; + case SK_LOG_DEBUG: + return "debug"; + case SK_LOG_TRACE: + return "trace"; + default: + return NULL; + } +} + +sk_log_level sk_log_level_of_string(const char *s) { + for (sk_log_level l = SK_LOG_MIN; l <= SK_LOG_MAX; ++l) { + if (!strcasecmp(s, sk_log_level_to_string(l))) + return l; + } + return 0; +} + + +sk_log_level sk_log_level_get() { + return _sk_log_level; +} + +void sk_log_level_set(sk_log_level new) { + _sk_log_level = new; +} + +sk_font_map *sk_log_font_get() { + return &_sk_log_font; +} + +void sk_log_font_set(sk_font_map *restrict font) { + (void)memcpy(&_sk_log_font, font, sizeof(sk_font_map)); +} + +# define LOG_PREFIX_LEN 8 +int sk_log(sk_log_level level, const char *restrict format, ...) { + if (level <= _sk_log_level) { + FILE *stream = (level <= SK_LOG_WARN ? stderr : stdout); + + char prefix[LOG_PREFIX_LEN+1]; + (void)strncpy(prefix, sk_log_level_to_string(level), LOG_PREFIX_LEN); + for (int i = 0; i < LOG_PREFIX_LEN && prefix[i] != '\0'; ++i) + prefix[i] = toupper(prefix[i]); + prefix[LOG_PREFIX_LEN] = '\0'; + + fprintf(stream, "%s%s: ", + (NULL != _sk_log_font[level] ? _sk_log_font[level] : ""), + prefix); + + va_list ap; + va_start(ap, format); + int rv = vfprintf(stream, format, ap); + va_end(ap); + + fprintf(stream, SK_FONT_RESET "\n"); + + return rv; + } + + return 0; +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..0ad1b97 --- /dev/null +++ b/src/log.h @@ -0,0 +1,148 @@ +#ifndef _SK_LOG_H +#define _SK_LOG_H + +#include "util/font.h" + + +/* types */ + +enum sk_log_level { + SK_LOG_ERROR = 1, + SK_LOG_WARN, + SK_LOG_INFO, + SK_LOG_DEBUG, + SK_LOG_TRACE, + + SK_LOG_MIN = SK_LOG_ERROR, + SK_LOG_MAX = SK_LOG_TRACE +}; + +typedef enum sk_log_level sk_log_level; +typedef const char * sk_font_map[SK_LOG_MAX+1]; + +/* font maps */ + +extern sk_font_map _SK_LOG_COLOURED; +extern sk_font_map _SK_LOG_MONOCHROME; +#define SK_LOG_COLOURED &_SK_LOG_COLOURED +#define SK_LOG_MONOCHROME &_SK_LOG_MONOCHROME + + +/* type conversion functions */ + +/** + * sk_log_level_to_string: + * converts an sk_log_level to its string representation. + * + * @param level: the log level + * @return the string representation of level. + */ +const char *sk_log_level_to_string(sk_log_level level); + +/** + * sk_log_level_of_string: + * converts a string representation to its sk_log_level. + * + * s is compared case-insensitively. + * In case an invalid string representation is given, + * 0 is returned. + * + * @param s: the string representation of the log level + * @return sk_log_level + */ +sk_log_level sk_log_level_of_string(const char *s); + + +/* getters/setters for global state variables */ + +/** + * sk_log_level_get: + * returns the current minimum log level to be logged. + * + * @return the log level + */ +sk_log_level sk_log_level_get(); + +/** + * sk_log_level_set: + * sets a new minimum log level to be logged. + * + * @param new: the new minimum log level. + */ +void sk_log_level_set(sk_log_level new); + +/** + * sk_log_font_get: + * get the current logging font map. + * + * @return the current logging font map + */ +sk_font_map *sk_log_font_get(); + +/** + * sk_log_font_set: + * sets a new logging font map. + * + * @param font: the new logging font map. + */ +void sk_log_font_set(sk_font_map *restrict font); + + +/* logging functions */ + +/** + * sk_log: + * a generic logging function accepting the log level as a function argument. + * + * The message given using a format and format arguments will be formatted using + * a standard format and a new line will be appended. + * + * @param level: the log level of this message. + * @param format: the message as a format string, cf. printf(3). + * @param varg: format arguments if needed. + * @return the number of bytes logged (0 if no message was logged due to + * "insufficient" log level, and a negative number if an error occurred) + */ +int sk_log(sk_log_level level, const char *restrict format, ...); + +/** + * sk_error: + * log an error message. + * + * cf. sk_log(). + */ +#define sk_error(format, ...) sk_log(SK_LOG_ERROR, format, ## __VA_ARGS__) + +/** + * sk_warn: + * log a warning message. + * + * cf. sk_log(). + */ +#define sk_warn(format, ...) sk_log(SK_LOG_WARN, format, ## __VA_ARGS__) + +/** + * sk_info: + * log an informational message. + * + * cf. sk_log(). + */ +#define sk_info(format, ...) sk_log(SK_LOG_INFO, format, ## __VA_ARGS__) + +/** + * sk_debug: + * log a debug message. + * + * cf. sk_log(). + */ +#define sk_debug(format, ...) sk_log(SK_LOG_DEBUG, format, ## __VA_ARGS__) + +/** + * sk_trace: + * log a trace message. + * + * cf. sk_log(). + */ +#define sk_trace(format, ...) sk_log(SK_LOG_TRACE, format, ## __VA_ARGS__) + +#endif diff --git a/src/skonfig.c b/src/skonfig.c index 1b97adf..eea5fb1 100644 --- a/src/skonfig.c +++ b/src/skonfig.c @@ -1,6 +1,7 @@ #include "../config.h" #include "config.h" +#include "log.h" #include "util/array.h" #include "util/fs.h" #include "util/string.h" @@ -167,19 +168,23 @@ void sk_init_config(struct sk_config *config, const char *config_file) { if (config_file) { /* Parse config file (as given by option) */ +#if DEBUG printf("processing config file (opt): %s\n", config_file); +#endif fh = fopen(config_file, "r"); if (fh) { sk_config_parse_file(config, fh); fclose(fh); } else { - fprintf(stderr, "invalid config file: %s\n", config_file); - exit(1); + sk_error("invalid config file: %s", config_file); + exit(EXIT_FAILURE); } } else if ((config_file = sk_config_find())) { /* found a config file in default location */ +#if DEBUG printf("processing config file (found): %s\n", config_file); +#endif fh = fopen(config_file, "r"); sk_config_parse_file(config, fh); @@ -220,7 +225,7 @@ int main(int argc, char *argv[]) { /* check if conf_root exists */ if (!is_dir(options.conf_root)) { - fprintf(stderr, "Cannot find configuration directory.\n"); + sk_error("cannot find configuration directory."); perror(options.conf_root); /* is_dir sets errno */ /* TODO: Add link to Getting Started guide */ return EXIT_FAILURE; @@ -238,12 +243,29 @@ int main(int argc, char *argv[]) { if (config->global.verbosity_level > SK_LOG_MAX) config->global.verbosity_level = SK_LOG_MAX; + sk_log_level_set(config->global.verbosity_level); + switch (config->global.coloured_output) { + case SK_COLOUR_NEVER: + sk_log_font_set(SK_LOG_MONOCHROME); + break; + case SK_COLOUR_ALWAYS: + sk_log_font_set(SK_LOG_COLOURED); + break; + case SK_COLOUR_AUTO: + if (isatty(fileno(stdout))) { + sk_log_font_set(SK_LOG_COLOURED); + } else { + sk_log_font_set(SK_LOG_MONOCHROME); + } + break; + } + #if DEBUG sk_config_print(config, stdout); /* DEBUG */ #endif - printf("conf dir: %s\n", options.conf_root); - printf("target host: %s\n", options.target_host); + sk_debug("conf dir: %s", options.conf_root); + sk_debug("target host: %s", options.target_host); sk_config_free(config); diff --git a/src/util/font.h b/src/util/font.h new file mode 100644 index 0000000..60c1b31 --- /dev/null +++ b/src/util/font.h @@ -0,0 +1,33 @@ +#ifndef _SK_UTIL_FONT_H +#define _SK_UTIL_FONT_H + +#include "string.h" + +#define _sk_font_set(code) "\033[" quote(code) "m" + +#define SK_FONT_RESET _sk_font_set(0) +#define SK_FONT_BOLD _sk_font_set(1) +#define SK_FONT_UNDERLINE _sk_font_set(4) +#define SK_FONT_SLOW_BLINK _sk_font_set(5) +#define SK_FONT_NORMAL _sk_font_set(22) +#define SK_FONT_NO_UNDERLINE _sk_font_set(24) +#define SK_FONT_FG_BLACK _sk_font_set(30) +#define SK_FONT_FG_RED _sk_font_set(31) +#define SK_FONT_FG_GREEN _sk_font_set(32) +#define SK_FONT_FG_YELLOW _sk_font_set(33) +#define SK_FONT_FG_BLUE _sk_font_set(34) +#define SK_FONT_FG_MAGENTA _sk_font_set(35) +#define SK_FONT_FG_CYAN _sk_font_set(36) +#define SK_FONT_FG_WHITE _sk_font_set(37) +#define SK_FONT_FG_DEFAULT _sk_font_set(39) +#define SK_FONT_BG_BLACK _sk_font_set(40) +#define SK_FONT_BG_RED _sk_font_set(41) +#define SK_FONT_BG_GREEN _sk_font_set(42) +#define SK_FONT_BG_YELLOW _sk_font_set(43) +#define SK_FONT_BG_BLUE _sk_font_set(44) +#define SK_FONT_BG_MAGENTA _sk_font_set(45) +#define SK_FONT_BG_CYAN _sk_font_set(46) +#define SK_FONT_BG_WHITE _sk_font_set(47) +#define SK_FONT_BG_DEFAULT _sk_font_set(49) + +#endif diff --git a/src/util/string.h b/src/util/string.h index 6f71a11..39c9268 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -1,6 +1,8 @@ #ifndef _SK_UTIL_STRING_H #define _SK_UTIL_STRING_H +#include "../../config.h" + #include "array.h" #include <stddef.h> @@ -23,7 +25,7 @@ #ifdef HAVE_STRINGIZE #define quote(x) #x #else -#define quote(x) "x" +#error "No CPP stringize operator available?" #endif /** |
