summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Camera <skonfig@dtnr.ch>2022-08-14 22:39:24 +0200
committerDennis Camera <skonfig@dtnr.ch>2022-08-14 23:47:33 +0200
commit289a2e94910d3b30256799f6c261dc01b194f254 (patch)
treec634e450838a35a84a7d10cca2e0a40b7ac30638
parenta08bb6903495fb562fc3f2b881ee69eb36ac01cf (diff)
downloadskonfig-c-289a2e94910d3b30256799f6c261dc01b194f254.tar.gz
skonfig-c-289a2e94910d3b30256799f6c261dc01b194f254.zip
Implement logging module
-rw-r--r--Makefile.am2
-rw-r--r--src/config.c56
-rw-r--r--src/config.h68
-rw-r--r--src/log.c104
-rw-r--r--src/log.h148
-rw-r--r--src/skonfig.c32
-rw-r--r--src/util/font.h33
-rw-r--r--src/util/string.h4
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
/**