diff --git a/cmake/ConkyPlatformChecks.cmake b/cmake/ConkyPlatformChecks.cmake index 3305e4df1..5276107e0 100644 --- a/cmake/ConkyPlatformChecks.cmake +++ b/cmake/ConkyPlatformChecks.cmake @@ -679,13 +679,9 @@ if(BUILD_COLOUR_NAME_MAP) mark_as_advanced(APP_GPERF) endif(BUILD_COLOUR_NAME_MAP) -if(CMAKE_BUILD_TYPE MATCHES "Debug") - set(DEBUG true) -endif(CMAKE_BUILD_TYPE MATCHES "Debug") - # The version numbers are simply derived from the date and number of commits # since start of month -if(DEBUG) +if(CMAKE_BUILD_TYPE MATCHES "Debug") execute_process(COMMAND ${APP_GIT} --git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git log --since=${VERSION_MAJOR}-${VERSION_MINOR}-01 --pretty=oneline @@ -694,4 +690,4 @@ if(DEBUG) RESULT_VARIABLE RETVAL OUTPUT_VARIABLE COMMIT_COUNT OUTPUT_STRIP_TRAILING_WHITESPACE) -endif(DEBUG) +endif() diff --git a/cmake/config.h.in b/cmake/config.h.in index 5eeff2076..19044b3ee 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -6,8 +6,6 @@ #ifndef _conky_config_h_ #define _conky_config_h_ -#cmakedefine DEBUG - #define SYSTEM_NAME "@CMAKE_SYSTEM_NAME@" #define PACKAGE_NAME "@PROJECT_NAME@" #define VERSION "@VERSION@" diff --git a/lua/libcairo_imlib2_helper.h b/lua/libcairo_imlib2_helper.h index 902a45da0..d27c9ab27 100644 --- a/lua/libcairo_imlib2_helper.h +++ b/lua/libcairo_imlib2_helper.h @@ -28,27 +28,42 @@ #include #include -#include "logging.h" - -void cairo_place_image(const char *file, cairo_t *cr, int x, int y, - int width, int height, double alpha) { +#include "config.h" + +#ifdef BUILD_I18N +#include +#else +#define gettext +#endif + +// TODO: inject reference to conky logger +// Lua allows modifying .so loading, so for each loaded library check if it has +// some hardcoded set_logger function symbol, and call it to set per-library +// reference to the global logger. +#define PRINT_ERROR(Format, ...) \ + fputs(stderr, "cairoimagehelper: "); \ + fprintf(stderr, gettext(Format), ##__VA_ARGS__); \ + fputs(stderr, "\n") + +void cairo_place_image(const char *file, cairo_t *cr, int x, int y, int width, + int height, double alpha) { int w, h, stride; Imlib_Image alpha_image, image, premul; cairo_surface_t *result; if (!file) { - NORM_ERR("cairoimagehelper: File is NULL\n"); + PRINT_ERROR("File is nil"); return; } if (!cr) { - NORM_ERR("cairoimagehelper: cairo_t is NULL\n"); + PRINT_ERROR("cairo_t is nil"); return; } image = (Imlib_Image *)imlib_load_image(file); if (!image) { - NORM_ERR("cairoimagehelper: Couldn't load %s\n", file); + PRINT_ERROR("can't load %s", file); return; } @@ -57,7 +72,7 @@ void cairo_place_image(const char *file, cairo_t *cr, int x, int y, h = imlib_image_get_height(); if ((w <= 0) && (h <= 0)) { - NORM_ERR("cairoimagehelper: %s has 0 size\n", file); + PRINT_ERROR("%s has 0 size", file); return; } @@ -67,7 +82,7 @@ void cairo_place_image(const char *file, cairo_t *cr, int x, int y, /* create temporary image */ premul = imlib_create_image(width, height); if (!premul) { - NORM_ERR("cairoimagehelper: Couldn't create premul image for %s\n", file); + PRINT_ERROR("can't create premul image for %s", file); return; } @@ -83,12 +98,12 @@ void cairo_place_image(const char *file, cairo_t *cr, int x, int y, /* and use the alpha channel of the source image */ imlib_image_copy_alpha_to_image(alpha_image, 0, 0); - stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width); + stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); /* now pass the result to cairo */ result = cairo_image_surface_create_for_data( - (unsigned char *)imlib_image_get_data_for_reading_only(), CAIRO_FORMAT_ARGB32, - width, height, stride); + (unsigned char *)imlib_image_get_data_for_reading_only(), + CAIRO_FORMAT_ARGB32, width, height, stride); cairo_set_source_surface(cr, result, x, y); cairo_paint_with_alpha(cr, alpha); @@ -101,7 +116,6 @@ void cairo_place_image(const char *file, cairo_t *cr, int x, int y, imlib_free_image(); cairo_surface_destroy(result); - } void cairo_draw_image(const char *file, cairo_surface_t *cs, int x, int y, @@ -112,23 +126,23 @@ void cairo_draw_image(const char *file, cairo_surface_t *cs, int x, int y, double scaled_w, scaled_h; if (!file) { - NORM_ERR("cairoimagehelper: File is NULL\n"); + PRINT_ERROR("File is nil"); return; } if (!cs) { - NORM_ERR("cairoimagehelper: Surface is NULL\n"); + PRINT_ERROR("Surface is nil"); return; } if ((scale_x <= 0.0) && (scale_y <= 0.0)) { - NORM_ERR("cairoimagehelper: Image Scale is 0, %s\n", file); + PRINT_ERROR("Image Scale is 0, %s", file); return; } Imlib_Image *image = (Imlib_Image *)imlib_load_image(file); if (!image) { - NORM_ERR("cairoimagehelper: Couldn't load %s\n", file); + PRINT_ERROR("Couldn't load %s", file); return; } @@ -137,7 +151,7 @@ void cairo_draw_image(const char *file, cairo_surface_t *cs, int x, int y, h = imlib_image_get_height(); if ((w <= 0) && (h <= 0)) { - NORM_ERR("cairoimagehelper: %s has 0 size\n", file); + PRINT_ERROR("%s has 0 size", file); return; } @@ -145,7 +159,7 @@ void cairo_draw_image(const char *file, cairo_surface_t *cs, int x, int y, scaled_h = *return_scale_h = scale_y * (double)h; if ((scaled_w <= 0.0) && (scaled_h <= 0.0)) { - NORM_ERR("cairoimagehelper: %s scaled image has 0 size\n", file); + PRINT_ERROR("%s scaled image has 0 size", file); return; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d36f4dbc2..82e61f0e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,8 +62,21 @@ execute_process( COMMAND ${APP_GPERF} --ignore-case -LC++ -Zcolor_name_hash -t -7 -m1 -C -E ) +# Separate logger library to allow optional artifacts like lua libraries to use +# it at some point. +# With this intent, logger shouldn't depend on anything to be built before it. +add_library(conky_logger + str_buffer.cc + str_buffer.hh + logger.cc + logger.hh +) +target_include_directories(conky_logger PRIVATE ${CMAKE_BINARY_DIR}) # config.h only +set(conky_libs ${conky_libs} conky_logger) + set(conky_sources ${conky_sources} + logging.cc c++wrap.cc c++wrap.hh colour-settings.cc diff --git a/src/algebra.cc b/src/algebra.cc index 3e69294eb..05119cca7 100644 --- a/src/algebra.cc +++ b/src/algebra.cc @@ -157,7 +157,7 @@ char *arg_to_string(const char *arg) { double arg_to_double(const char *arg) { double d; if (sscanf(arg, "%lf", &d) != 1) { - NORM_ERR("converting '%s' to double failed", arg); + LOG_WARNING("invalid double string: '%s'", arg); return 0.0; } return d; @@ -165,7 +165,7 @@ double arg_to_double(const char *arg) { long arg_to_long(const char *arg) { long l; if (sscanf(arg, "%ld", &l) != 1) { - NORM_ERR("converting '%s' to long failed", arg); + LOG_WARNING("invalid long (int) string: '%s'", arg); return 0; } return l; @@ -181,7 +181,7 @@ int compare(const char *expr) { mtype = get_match_type(expr); if ((idx <= 0) || mtype == -1) { - NORM_ERR("failed to parse compare string '%s'", expr); + LOG_WARNING("failed to parse compare string: '%s'", expr); return -2; } @@ -192,15 +192,15 @@ int compare(const char *expr) { type1 = get_arg_type(expr_dup); type2 = get_arg_type(expr_dup + idx + 1); if (type1 == ARG_BAD || type2 == ARG_BAD) { - NORM_ERR("Bad arguments: '%s' and '%s'", expr_dup, (expr_dup + idx + 1)); + LOG_WARNING("bad arguments: '%s' and '%s'", expr_dup, (expr_dup + idx + 1)); free(expr_dup); return -2; } if (type1 == ARG_LONG && type2 == ARG_DOUBLE) { type1 = ARG_DOUBLE; } if (type1 == ARG_DOUBLE && type2 == ARG_LONG) { type2 = ARG_DOUBLE; } if (type1 != type2) { - NORM_ERR("trying to compare args '%s' and '%s' of different type", expr_dup, - (expr_dup + idx + 1)); + LOG_WARNING("trying to compare args '%s' and '%s' of different type", + expr_dup, (expr_dup + idx + 1)); free(expr_dup); return -2; } @@ -239,11 +239,11 @@ int check_if_match(struct text_object *obj) { generate_text_internal(expression.get(), max_user_text.get(*state), *obj->sub); - DBGP("parsed arg into '%s'", expression.get()); + LOG_TRACE("parsed arg into '%s'", expression.get()); val = compare(expression.get()); if (val == -2) { - NORM_ERR("compare failed for expression '%s'", expression.get()); + LOG_WARNING("compare failed for expression '%s'", expression.get()); } else if (val == 0) { result = 0; } diff --git a/src/apcupsd.cc b/src/apcupsd.cc index 0c739be81..4e81d23c0 100644 --- a/src/apcupsd.cc +++ b/src/apcupsd.cc @@ -202,7 +202,7 @@ int update_apcupsd() { snprintf(portbuf, 8, "%d", apcupsd.port); res = getaddrinfo(apcupsd.host, portbuf, &hints, &ai); if (res != 0) { - NORM_ERR("APCUPSD getaddrinfo: %s", gai_strerror(res)); + LOG_ERROR("unable to get APCUPSD address info: %s", gai_strerror(res)); break; } for (rp = ai; rp != nullptr; rp = rp->ai_next) { diff --git a/src/ccurl_thread.cc b/src/ccurl_thread.cc index fc4caa63a..690c58877 100644 --- a/src/ccurl_thread.cc +++ b/src/ccurl_thread.cc @@ -29,7 +29,7 @@ #include "logging.h" #include "text_object.h" -#ifdef DEBUG +#ifndef NDEBUG #include #endif /* DEBUG */ @@ -76,7 +76,8 @@ size_t curl_internal::write_cb(void *ptr, size_t size, size_t nmemb, return realsize; } -curl_internal::curl_internal(const std::string &url) : curl(curl_easy_init()) { +curl_internal::curl_internal(const std::string &url) + : curl(curl_easy_init()), url(std::string(url)) { if (!curl) throw std::runtime_error("curl_easy_init() failed"); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); @@ -132,15 +133,18 @@ void curl_internal::do_work() { case 304: break; default: - NORM_ERR("curl: no data from server, got HTTP status %ld", - http_status_code); + LOG_WARNING( + "no response data from server for '%s'; response status: %ld", + this->url.c_str(), http_status_code); break; } } else { - NORM_ERR("curl: no HTTP status from server"); + LOG_WARNING("no HTTP response from server for '%s'", + this->url.c_str()); } } else { - NORM_ERR("curl: could not retrieve data from server"); + LOG_WARNING("can't retrieve data from server for '%s'", + this->url.c_str()); } } } // namespace priv @@ -185,7 +189,7 @@ void curl_parse_arg(struct text_object *obj, const char *arg) { char *space; if (strlen(arg) < 1) { - NORM_ERR("wrong number of arguments for $curl"); + LOG_WARNING("wrong number of arguments for $curl"); return; } @@ -212,7 +216,7 @@ void curl_print(struct text_object *obj, char *p, unsigned int p_max_size) { struct curl_data *cd = static_cast(obj->data.opaque); if (!cd) { - NORM_ERR("error processing Curl data"); + LOG_ERROR("error processing curl data"); return; } ccurl_process_info(p, p_max_size, cd->uri, cd->interval); diff --git a/src/ccurl_thread.h b/src/ccurl_thread.h index da54272ec..dc8e0ed36 100644 --- a/src/ccurl_thread.h +++ b/src/ccurl_thread.h @@ -33,6 +33,7 @@ namespace priv { // factored out stuff that does not depend on the template parameters class curl_internal { + std::string url; public: std::string last_modified; std::string etag; diff --git a/src/colours.cc b/src/colours.cc index 9adc9bf91..afd11b798 100644 --- a/src/colours.cc +++ b/src/colours.cc @@ -83,17 +83,13 @@ std::optional parse_hex_color(const std::string &color) { } return -1; }; - const auto none = [&]() { - NORM_ERR("can't parse hex color '%s' (%d)", name, len); - return std::nullopt; - }; uint8_t argb[4] = {0xff, 0, 0, 0}; if (len == 3 || len == 4) { bool skip_alpha = (len == 3); for (size_t i = 0; i < len; i++) { int nib = hex_nibble_value(name[i]); - if (nib < 0) { return none(); } + if (nib < 0) { return std::nullopt; } // Duplicate the nibble, so "#abc" -> 0xaa, 0xbb, 0xcc int val = (nib << 4) + nib; @@ -104,13 +100,13 @@ std::optional parse_hex_color(const std::string &color) { for (size_t i = 0; i + 1 < len; i += 2) { int nib1 = hex_nibble_value(name[i]); int nib2 = hex_nibble_value(name[i + 1]); - if (nib1 < 0 || nib2 < 0) { return none(); } + if (nib1 < 0 || nib2 < 0) { return std::nullopt; } int val = (nib1 << 4) + nib2; argb[skip_alpha + i / 2] = val; } } else { - return none(); + return std::nullopt; } return Colour(argb[1], argb[2], argb[3], argb[0]); @@ -128,6 +124,8 @@ Colour parse_color(const std::string &color) { #undef TRY_PARSER + LOG_WARNING("can't parse color '%s'", color.c_str()); + return ERROR_COLOUR; } diff --git a/src/common.cc b/src/common.cc index bcbaeebea..5cd2ddc62 100644 --- a/src/common.cc +++ b/src/common.cc @@ -146,7 +146,7 @@ int open_fifo(const char *file, int *reported) { if (fd == -1) { if ((reported == nullptr) || *reported == 0) { - NORM_ERR("can't open %s: %s", file, strerror(errno)); + LOG_WARNING("can't open file %s: %s", file, strerror(errno)); if (reported != nullptr) { *reported = 1; } } return -1; @@ -162,7 +162,7 @@ FILE *open_file(const char *file, int *reported) { if (fp == nullptr) { if ((reported == nullptr) || *reported == 0) { - NORM_ERR("can't open %s: %s", file, strerror(errno)); + LOG_WARNING("can't open file %s: %s", file, strerror(errno)); if (reported != nullptr) { *reported = 1; } } return nullptr; @@ -318,7 +318,7 @@ void scan_loadavg_arg(struct text_object *obj, const char *arg) { (isdigit(static_cast(arg[0])) != 0)) { obj->data.i = strtol(arg, nullptr, 10); if (obj->data.i > 3 || obj->data.i < 1) { - NORM_ERR("loadavg arg needs to be in range (1,3)"); + LOG_WARNING("argument needs to be in range (1,3)"); obj->data.i = 0; } } @@ -364,8 +364,8 @@ double loadgraphval(struct text_object *obj) { uint8_t cpu_percentage(struct text_object *obj) { if (static_cast(obj->data.i) > info.cpu_count) { - NORM_ERR("obj->data.i %i info.cpu_count %i", obj->data.i, info.cpu_count); - CRIT_ERR("attempting to use more CPUs than you have!"); + LOG_DEBUG("obj->data.i=%i; info.cpu_count=%i", obj->data.i, info.cpu_count); + USER_ERR("attempting to use more CPUs than you have!"); } if (info.cpu_usage != nullptr) { return round_to_positive_int(info.cpu_usage[obj->data.i] * 100.0); @@ -375,8 +375,8 @@ uint8_t cpu_percentage(struct text_object *obj) { double cpu_barval(struct text_object *obj) { if (static_cast(obj->data.i) > info.cpu_count) { - NORM_ERR("obj->data.i %i info.cpu_count %i", obj->data.i, info.cpu_count); - CRIT_ERR("attempting to use more CPUs than you have!"); + LOG_DEBUG("obj->data.i=%i; info.cpu_count=%i", obj->data.i, info.cpu_count); + USER_ERR("attempting to use more CPUs than you have!"); } if (info.cpu_usage != nullptr) { return info.cpu_usage[obj->data.i]; } return 0.; @@ -569,7 +569,7 @@ static int check_contains(char *f, char *s) { } fclose(where); } else { - NORM_ERR("Could not open the file"); + LOG_WARNING("could not open file %s", f); } return ret; } @@ -733,7 +733,7 @@ static size_t read_github_data_cb(char *data, size_t size, size_t nmemb, 's' == *(ptr + 3) && z + 13 < sz) { /* "message": */ if ('B' == *(ptr + 10) && 'a' == *(ptr + 11) && 'd' == *(ptr + 12)) { /* "Bad credentials" */ - NORM_ERR("Bad credentials: generate a new token:\n" NEW_TOKEN); + LOG_WARNING("bad credentials: generate a new token:\n" NEW_TOKEN); snprintf(p, 80, "%s", "GitHub: Bad credentials, generate a new token."); skip = 1U; @@ -741,8 +741,8 @@ static size_t read_github_data_cb(char *data, size_t size, size_t nmemb, } if ('M' == *(ptr + 10) && 'i' == *(ptr + 11) && 's' == *(ptr + 12)) { /* Missing the 'notifications' scope. */ - NORM_ERR( - "Missing 'notifications' scope. Generate a new " + LOG_WARNING( + "missing 'notifications' scope. Generate a new " "token\n" NEW_TOKEN); snprintf( p, 80, "%s", @@ -767,7 +767,7 @@ void print_github(struct text_object *obj, char *p, unsigned int p_max_size) { CURLcode res; if (0 == strcmp(github_token.get(*state).c_str(), "")) { - NORM_ERR( + LOG_WARNING( "${github_notifications} requires token. " "Go ahead and generate one " NEW_TOKEN "Insert it in conky.config = { github_token='TOKEN_SHA' }\n"); diff --git a/src/conky-imlib2.cc b/src/conky-imlib2.cc index 64d4ce6f7..6d4990cd0 100644 --- a/src/conky-imlib2.cc +++ b/src/conky-imlib2.cc @@ -127,8 +127,8 @@ void cimlib_add_image(const char *args) { memset(cur, 0, sizeof(struct image_list_s)); if (sscanf(args, "%1023s", cur->name) == 0) { - NORM_ERR( - "Invalid args for $image. Format is: ' (-p" + LOG_WARNING( + "invalid arguments; format is: ' (-p" "x,y) (-s WxH) (-n) (-f interval)' (got '%s')", args); delete[] cur; @@ -172,7 +172,7 @@ void cimlib_add_image(const char *args) { } } if (cur->flush_interval < 0) { - NORM_ERR("Imlib2: flush interval should be >= 0"); + LOG_WARNING("imlib2 flush interval should be >= 0"); cur->flush_interval = 0; } @@ -196,17 +196,16 @@ static void cimlib_draw_image(struct image_list_s *cur, int *clip_x, image = imlib_load_image(cur->name); if (image == nullptr) { - if (rep == 0) { NORM_ERR("Unable to load image '%s'", cur->name); } + if (rep == 0) { LOG_WARNING("unable to load image %s", cur->name); } rep = 1; return; } rep = 0; /* reset so disappearing images are reported */ - DBGP( - "Drawing image '%s' at (%i,%i) scaled to %ix%i, " - "caching interval set to %i (with -n opt %i)", - cur->name, cur->x, cur->y, cur->w, cur->h, cur->flush_interval, - cur->no_cache); + LOG_TRACE("drawing image '%s' at (%i,%i) scaled to %ix%i", cur->name, cur->x, + cur->y, cur->w, cur->h); + LOG_TRACE("caching interval set to %i (with -n opt %i)", cur->flush_interval, + cur->no_cache); imlib_context_set_image(image); /* turn alpha channel on */ @@ -260,7 +259,7 @@ void cimlib_render(int x, int y, int width, int height, uint32_t flush_interval, imlib_set_cache_size(0); imlib_set_cache_size(size); cimlib_cache_flush_last = now; - DBGP("Flushing Imlib2 cache (%li)\n", now); + LOG_TRACE("flushing imlib2 cache (%li)\n", now); } /* take all the little rectangles to redraw and merge them into diff --git a/src/conky.cc b/src/conky.cc index 71a19816b..34152561b 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -172,9 +172,6 @@ const char builtin_config_magic[] = "==builtin=="; // #define SIGNAL_BLOCKING #undef SIGNAL_BLOCKING -/* debugging level, used by logging.h */ -int global_debug_level = 0; - /* disable inotify auto reload feature if desired */ static conky::simple_config_setting disable_auto_reload( "disable_auto_reload", false, false); @@ -719,9 +716,7 @@ static void generate_text() { p[k] = '\n'; j = 0; } else { - NORM_ERR( - "The end of the text_buffer is reached, increase " - "\"text_buffer_size\""); + LOG_WARNING("text_buffer exhausted, increase \"text_buffer_size\""); } } else { j++; @@ -862,7 +857,8 @@ void update_text_area() { last_font_height = font_height(); for_each_line(text_buffer, text_size_updater); - text_size = text_size.max(conky::vec2i(text_size.x() + 1, dpi_scale(minimum_height.get(*state)))); + text_size = text_size.max( + conky::vec2i(text_size.x() + 1, dpi_scale(minimum_height.get(*state)))); int mw = dpi_scale(maximum_width.get(*state)); if (mw > 0) text_size = text_size.min(conky::vec2i(mw, text_size.y())); } @@ -1374,7 +1370,8 @@ int draw_each_line_inner(char *s, int special_index, int last_special_applied) { } #ifdef BUILD_MATH if (show_graph_scale.get(*state) && (current->show_scale == 1)) { - // Set the foreground colour to the first colour, ensures the scale text is always drawn in the same colour + // Set the foreground colour to the first colour, ensures the + // scale text is always drawn in the same colour set_foreground_color(current->first_colour); int tmp_x = cur_x; int tmp_y = cur_y; @@ -1685,7 +1682,7 @@ void log_system_details() { char *session = getenv("GDMSESSION"); char *desktop = getenv("XDG_CURRENT_DESKTOP"); if (desktop != nullptr || session != nullptr) { - NORM_ERR("'%s' %s session running '%s' desktop", session, session_ty, + LOG_INFO("'%s' %s session running '%s' desktop", session, session_ty, desktop); } } @@ -1760,7 +1757,7 @@ void main_loop() { if (g_sighup_pending != 0) { g_sighup_pending = 0; - NORM_ERR("received SIGUSR1. reloading the config file."); + LOG_NOTICE("received SIGUSR1. reloading the config file."); reload_config(); } @@ -1768,7 +1765,7 @@ void main_loop() { if (g_sigusr2_pending != 0) { g_sigusr2_pending = 0; // refresh view; - NORM_ERR("received SIGUSR2. refreshing."); + LOG_NOTICE("received SIGUSR2. refreshing."); update_text(); draw_stuff(); for (auto output : display_outputs()) output->flush(); @@ -1776,7 +1773,7 @@ void main_loop() { if (g_sigterm_pending != 0) { g_sigterm_pending = 0; - NORM_ERR("received SIGHUP, SIGINT, or SIGTERM to terminate. bye!"); + LOG_NOTICE("received SIGHUP, SIGINT, or SIGTERM to terminate. bye!"); terminate = 1; for (auto output : display_outputs()) output->sigterm_cleanup(); } @@ -1807,7 +1804,7 @@ void main_loop() { if (ev->wd == inotify_config_wd && (ev->mask & IN_MODIFY || ev->mask & IN_IGNORED)) { /* current_config should be reloaded */ - NORM_ERR("'%s' modified, reloading...", current_config.c_str()); + LOG_NOTICE("'%s' modified, reloading...", current_config.c_str()); reload_config(); if (ev->mask & IN_IGNORED) { /* for some reason we get IN_IGNORED here @@ -1847,10 +1844,11 @@ static void reload_config() { struct stat sb {}; if ((stat(current_config.c_str(), &sb) != 0) || (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode))) { - NORM_ERR(_("Config file '%s' is gone, continuing with config from " - "memory.\nIf you recreate this file sent me a SIGUSR1 to tell " - "me about it. ( kill -s USR1 %d )"), - current_config.c_str(), getpid()); + LOG_WARNING( + _("Config file '%s' is gone, continuing with config from " + "memory.\nIf you recreate this file sent me a SIGUSR1 to tell " + "me about it. ( kill -s USR1 %d )"), + current_config.c_str(), getpid()); return; } clean_up(); @@ -1914,6 +1912,11 @@ void clean_up(void) { state.reset(); } +void handle_terminate() { + clean_up(); + std::abort(); +} + static void set_default_configurations() { update_uname(); info.memmax = 0; @@ -2006,19 +2009,14 @@ void load_config_file() { } catch (lua::syntax_error &e) { #define SYNTAX_ERR_READ_CONF "Syntax error (%s) while reading config file. " #ifdef BUILD_OLD_CONFIG - NORM_ERR(_(SYNTAX_ERR_READ_CONF), e.what()); - NORM_ERR(_("Assuming it's in old syntax and attempting conversion.")); + LOG_WARNING(SYNTAX_ERR_READ_CONF, e.what()); + LOG_NOTICE("assuming old syntax in use; attempting conversion..."); // the strchr thingy skips the first line (#! /usr/bin/lua) l.loadstring(strchr(convertconf, '\n')); l.pushstring(current_config.c_str()); l.call(1, 1); #else - char *syntaxerr; - if (asprintf(&syntaxerr, _(SYNTAX_ERR_READ_CONF), e.what())) { - std::string syntaxerrobj(syntaxerr); - free(syntaxerr); - throw conky::error(syntaxerrobj); - } + throw conky::error(SYNTAX_ERR_READ_CONF, e.what()); #endif } l.call(0, 0); @@ -2027,7 +2025,7 @@ void load_config_file() { l.getfield(-1, "text"); l.replace(-2); if (l.type(-1) != lua::TSTRING) { - throw conky::error(_("missing text block in configuration")); + throw conky::error("missing text block in configuration"); } /* Remove \\-\n. */ @@ -2072,7 +2070,7 @@ void set_current_config() { #define NOCFGFILEFOUND "no personal or system-wide config file found" #ifdef BUILD_BUILTIN_CONFIG current_config = builtin_config_magic; - NORM_ERR(NOCFGFILEFOUND ", using builtin default"); + LOG_WARNING(NOCFGFILEFOUND ", using builtin default"); #else throw conky::error(NOCFGFILEFOUND); #endif @@ -2084,7 +2082,7 @@ void set_current_config() { /* : means that character before that takes an argument */ const char *getopt_string = - "vVqdDSs:t:u:i:hc:p:" + "vVqdDLSs:t:u:i:hc:p:" #ifdef BUILD_X11 "x:y:w:a:X:m:f:" #ifdef OWN_WINDOW @@ -2100,7 +2098,8 @@ const char *getopt_string = const struct option longopts[] = { {"help", 0, nullptr, 'h'}, {"version", 0, nullptr, 'v'}, {"short-version", 0, nullptr, 'V'}, {"quiet", 0, nullptr, 'q'}, - {"debug", 0, nullptr, 'D'}, {"config", 1, nullptr, 'c'}, + {"debug", 0, nullptr, 'D'}, {"log-less", 0, nullptr, 'L'}, + {"config", 1, nullptr, 'c'}, #ifdef BUILD_BUILTIN_CONFIG {"print-config", 0, nullptr, 'C'}, #endif @@ -2208,7 +2207,7 @@ void initialisation(int argc, char **argv) { case 'u': state->pushnumber(strtod(optarg, &conv_end)); if (*conv_end != 0) { - CRIT_ERR("'%s' is an invalid update interval", optarg); + USER_ERR("'%s' is an invalid update interval", optarg); } update_interval.lua_set(*state); break; @@ -2216,7 +2215,7 @@ void initialisation(int argc, char **argv) { case 'i': state->pushinteger(strtol(optarg, &conv_end, 10)); if (*conv_end != 0) { - CRIT_ERR("'%s' is an invalid number of update times", optarg); + USER_ERR("'%s' is an invalid number of update times", optarg); } total_run_times.lua_set(*state); break; @@ -2224,7 +2223,7 @@ void initialisation(int argc, char **argv) { case 'x': state->pushinteger(strtol(optarg, &conv_end, 10)); if (*conv_end != 0) { - CRIT_ERR("'%s' is an invalid value for the X-position", optarg); + USER_ERR("'%s' is an invalid value for the X-position", optarg); } gap_x.lua_set(*state); break; @@ -2232,7 +2231,7 @@ void initialisation(int argc, char **argv) { case 'y': state->pushinteger(strtol(optarg, &conv_end, 10)); if (*conv_end != 0) { - CRIT_ERR("'%s' is a wrong value for the Y-position", optarg); + USER_ERR("'%s' is a wrong value for the Y-position", optarg); } gap_y.lua_set(*state); break; @@ -2266,8 +2265,7 @@ void initialisation(int argc, char **argv) { switch (pid) { case -1: - NORM_ERR(PACKAGE_NAME ": couldn't fork() to background: %s", - strerror(errno)); + LOG_WARNING("couldn't fork() to background: %s", strerror(errno)); break; case 0: @@ -2279,8 +2277,7 @@ void initialisation(int argc, char **argv) { default: /* parent process */ - fprintf(stderr, PACKAGE_NAME ": forked to background, pid is %d\n", - pid); + LOG_NOTICE("forked to background, pid is %d\n", pid); fflush(stderr); throw fork_throw(); } @@ -2317,7 +2314,7 @@ void initialisation(int argc, char **argv) { sigaction(SIGUSR2, &act, &oact) < 0 || sigaction(SIGHUP, &act, &oact) < 0 || sigaction(SIGTERM, &act, &oact) < 0) { - NORM_ERR("error setting signal handler: %s", strerror(errno)); + LOG_ERROR("can't set signal handler: %s", strerror(errno)); } llua_startup_hook(); diff --git a/src/conky.h b/src/conky.h index efb8633f9..d3c49fd8b 100644 --- a/src/conky.h +++ b/src/conky.h @@ -106,6 +106,9 @@ struct text_object; /* sony support */ #include "sony.h" +void clean_up(void); +void handle_terminate(); + /* A size for temporary, static buffers to use when * one doesn't know what to choose. Defaults to 256. */ extern conky::range_config_setting text_buffer_size; diff --git a/src/core.cc b/src/core.cc index 0ce2cbdcb..cf17192f5 100644 --- a/src/core.cc +++ b/src/core.cc @@ -174,7 +174,7 @@ void stock_parse_arg(struct text_object *obj, const char *arg) { obj->data.s = nullptr; if (sscanf(arg, "%7s %15s", stock, data) != 2) { - NORM_ERR("wrong number of arguments for $stock"); + LOG_WARNING("wrong number of arguments for $stock"); return; } if (!strcasecmp("ask", data)) { @@ -342,7 +342,7 @@ void stock_parse_arg(struct text_object *obj, const char *arg) { } else if (!strcasecmp("dy", data)) { strncpy(data, "y", 3); } else { - NORM_ERR( + LOG_WARNING( "\"%s\" is not supported by $stock. Supported: 1ytp, 200ma, 50ma, " "52weeklow, 52weekhigh, 52weekrange, adv, ag, ahcrt, ask, askrt, " "asksize, bid, bidrt, bidsize, bookvalue, c200ma, c50ma, c52whigh, " @@ -380,25 +380,34 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->line = line; + LOG_CONTEXT(variable, s); + +// FIXME: don't exit for invalid arguments unless command affects other +// commands (e.g. $if_exists) +#define FREE_AND_CRASH(a, ...) \ + free(obj); \ + free(free_at_crash); \ + COMMAND_ARG_ERR(#a, __VA_ARGS__) + /* helper defines for internal use only */ #define __OBJ_HEAD(a, n) \ if (!strcmp(s, #a)) { \ obj->cb_handle = create_cb_handle(n); #define __OBJ_IF obj_be_ifblock_if(ifblock_opaque, obj) -#define __OBJ_ARG(...) \ - if (!arg) { \ - free(s); \ - CRIT_ERR_FREE(obj, free_at_crash, __VA_ARGS__); \ +#define __OBJ_ARG(a, ...) \ + if (!arg) { \ + free(s); \ + FREE_AND_CRASH(a, __VA_ARGS__); \ } /* defines to be used below */ #define OBJ(a, n) __OBJ_HEAD(a, n) { -#define OBJ_ARG(a, n, ...) __OBJ_HEAD(a, n) __OBJ_ARG(__VA_ARGS__) { +#define OBJ_ARG(a, n, ...) __OBJ_HEAD(a, n) __OBJ_ARG(a, __VA_ARGS__) { #define OBJ_IF(a, n) \ __OBJ_HEAD(a, n) __OBJ_IF; \ { -#define OBJ_IF_ARG(a, n, ...) \ - __OBJ_HEAD(a, n) __OBJ_ARG(__VA_ARGS__) __OBJ_IF; \ +#define OBJ_IF_ARG(a, n, ...) \ + __OBJ_HEAD(a, n) __OBJ_ARG(a, __VA_ARGS__) __OBJ_IF; \ { #define END \ } \ @@ -423,11 +432,11 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, * a bit of paranoia. screen out funky paths * i hope no device will have a '.' in its name */ - NORM_ERR("acpiacadapter: arg must not contain '/' or '.'"); + LOG_WARNING("argument must not contain '/' or '.'"); } else obj->data.opaque = strdup(arg); #else - NORM_ERR("acpiacadapter: arg is only used on linux"); + LOG_INFO("argument is only used on linux"); #endif } obj->callbacks.print = &print_acpiacadapter; @@ -439,7 +448,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, static_cast(strtol(&arg[0], nullptr, 10)) > info.cpu_count) { obj->data.i = 1; - /* NORM_ERR("freq: Invalid CPU number or you don't have that many CPUs! " + /* LOG_WARNING("freq: Invalid CPU number or you don't have that many CPUs! " "Displaying the clock for CPU 1."); */ } else { obj->data.i = strtol(&arg[0], nullptr, 10); @@ -451,7 +460,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, static_cast(strtol(&arg[0], nullptr, 10)) > info.cpu_count) { obj->data.i = 1; - /* NORM_ERR("freq_g: Invalid CPU number or you don't have that many " + /* LOG_WARNING("freq_g: Invalid CPU number or you don't have that many " "CPUs! Displaying the clock for CPU 1."); */ } else { obj->data.i = strtol(&arg[0], nullptr, 10); @@ -464,25 +473,22 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, static_cast(strtol(&arg[0], nullptr, 10)) > info.cpu_count) { obj->data.i = 1; - /* NORM_ERR("cpugovernor: Invalid CPU number or you don't have that " + /* LOG_WARNING("cpugovernor: Invalid CPU number or you don't have that " "many CPUs! Displaying the scaling governor for CPU 1."); */ } else { obj->data.i = strtol(&arg[0], nullptr, 10); } obj->callbacks.print = &print_cpugovernor; #endif /* __linux__ */ - END OBJ_ARG(read_tcp, nullptr, - "read_tcp: Needs \"(host) port\" as argument(s)") + END OBJ_ARG(read_tcp, nullptr, "needs \"(host) port\" as argument(s)") parse_read_tcpip_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_read_tcp; obj->callbacks.free = &free_read_tcpip; - END OBJ_ARG(read_udp, nullptr, - "read_udp: Needs \"(host) port\" as argument(s)") + END OBJ_ARG(read_udp, nullptr, "needs \"(host) port\" as argument(s)") parse_read_tcpip_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_read_udp; obj->callbacks.free = &free_read_tcpip; - END OBJ_ARG(tcp_ping, nullptr, - "tcp_ping: Needs \"host (port)\" as argument(s)") + END OBJ_ARG(tcp_ping, nullptr, "needs \"host (port)\" as argument(s)") parse_tcp_ping_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_tcp_ping; obj->callbacks.free = &free_tcp_ping; @@ -491,7 +497,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, if (!arg || strlen(arg) >= 3 || strtol(&arg[0], nullptr, 10) == 0 || (unsigned int)strtol(&arg[0], nullptr, 10) > info.cpu_count) { obj->data.i = 1; - /* NORM_ERR("voltage_mv: Invalid CPU number or you don't have that many " + /* LOG_WARNING("voltage_mv: Invalid CPU number or you don't have that many " "CPUs! Displaying voltage for CPU 1."); */ } else { obj->data.i = strtol(&arg[0], nullptr, 10); @@ -501,7 +507,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, if (!arg || strlen(arg) >= 3 || strtol(&arg[0], nullptr, 10) == 0 || (unsigned int)strtol(&arg[0], nullptr, 10) > info.cpu_count) { obj->data.i = 1; - /* NORM_ERR("voltage_v: Invalid CPU number or you don't have that many " + /* LOG_WARNING("voltage_v: Invalid CPU number or you don't have that many " "CPUs! Displaying voltage for CPU 1."); */ } else { obj->data.i = strtol(&arg[0], nullptr, 10); @@ -616,7 +622,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, #endif /* !__OpenBSD__ */ #if defined(__linux__) - END OBJ_ARG(disk_protect, 0, "disk_protect needs an argument") obj->data.s = + END OBJ_ARG(disk_protect, 0, "missing an argument") obj->data.s = strndup(dev_name(arg), text_buffer_size.get(*state)); obj->callbacks.print = &print_disk_protect_queue; obj->callbacks.free = &gen_free_opaque; @@ -638,7 +644,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, &print_i8k_buttons_status; #if defined(BUILD_IBM) END OBJ(ibm_fan, 0) obj->callbacks.print = &get_ibm_acpi_fan; - END OBJ_ARG(ibm_temps, &get_ibm_acpi_temps, "ibm_temps: needs an argument") + END OBJ_ARG(ibm_temps, &get_ibm_acpi_temps, "missing an argument") parse_ibm_temps_arg(obj, arg); obj->callbacks.print = &print_ibm_temps; END OBJ(ibm_volume, 0) obj->callbacks.print = &get_ibm_acpi_volume; @@ -648,46 +654,42 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, /* information from sony_laptop kernel module * /sys/devices/platform/sony-laptop */ END OBJ(sony_fanspeed, 0) obj->callbacks.print = &get_sony_fanspeed; - END OBJ_ARG(ioscheduler, 0, "get_ioscheduler needs an argument (e.g. hda)") - obj->data.s = strndup(dev_name(arg), text_buffer_size.get(*state)); + END OBJ_ARG(ioscheduler, 0, "missing an argument (e.g. hda)") obj->data.s = + strndup(dev_name(arg), text_buffer_size.get(*state)); obj->callbacks.print = &print_ioscheduler; obj->callbacks.free = &gen_free_opaque; END OBJ(laptop_mode, 0) obj->callbacks.print = &print_laptop_mode; - END OBJ_ARG( - pb_battery, 0, - "pb_battery: needs one argument: status, percent or time") if (strcmp(arg, - "st" - "at" - "u" - "s") == - EQUAL) { + // clang-format off + END OBJ_ARG(pb_battery, 0, "requires one argument: status, percent or time") + if (strcmp(arg, "status") == EQUAL) { obj->data.i = PB_BATT_STATUS; } else if (strcmp(arg, "percent") == EQUAL) { obj->data.i = PB_BATT_PERCENT; } else if (strcmp(arg, "time") == EQUAL) { obj->data.i = PB_BATT_TIME; } else { - NORM_ERR("pb_battery: illegal argument '%s', defaulting to status", arg); + LOG_WARNING("illegal argument '%s', defaulting to status", arg); obj->data.i = PB_BATT_STATUS; } + // clang-format on obj->callbacks.print = get_powerbook_batt_info; #endif /* __linux__ */ #if (defined(__FreeBSD__) || defined(__linux__) || defined(__DragonFly__) || \ (defined(__APPLE__) && defined(__MACH__))) - END OBJ_IF_ARG(if_up, nullptr, "if_up needs an argument") + END OBJ_IF_ARG(if_up, nullptr, "missing an argument") parse_if_up_arg(obj, arg); obj->callbacks.iftest = &interface_up; obj->callbacks.free = &free_if_up; #endif #if defined(__OpenBSD__) - END OBJ_ARG(obsd_sensors_temp, 0, "obsd_sensors_temp: needs an argument") + END OBJ_ARG(obsd_sensors_temp, 0, "missing an argument") parse_obsd_sensor(obj, arg); obj->callbacks.print = &print_obsd_sensors_temp; END OBJ_ARG(obsd_sensors_fan, 0, - "obsd_sensors_fan: needs 2 arguments (device and sensor number)") + "requires 2 arguments (device and sensor number)") parse_obsd_sensor(obj, arg); obj->callbacks.print = &print_obsd_sensors_fan; END OBJ_ARG(obsd_sensors_volt, 0, - "obsd_sensors_volt: needs 2 arguments (device and sensor number)") + "requires 2 arguments (device and sensor number)") parse_obsd_sensor(obj, arg); obj->callbacks.print = &print_obsd_sensors_volt; END OBJ(obsd_vendor, 0) obj->callbacks.print = &get_obsd_vendor; @@ -864,10 +866,10 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.free = &gen_free_opaque; #endif /* BUILD_IMLIB2 */ #ifdef BUILD_MYSQL - END OBJ_ARG(mysql, 0, "mysql needs a query") obj->data.s = strdup(arg); + END OBJ_ARG(mysql, 0, "missing a query") obj->data.s = strdup(arg); obj->callbacks.print = &print_mysql; #endif /* BUILD_MYSQL */ - END OBJ_ARG(no_update, nullptr, "no_update needs arguments") + END OBJ_ARG(no_update, nullptr, "missing argument text") scan_no_update(obj, arg); obj->callbacks.print = &print_no_update; obj->callbacks.free = &free_no_update; @@ -916,28 +918,28 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, END OBJ(catp, 0) obj->data.s = STRNDUP_ARG; obj->callbacks.print = &print_catp; obj->callbacks.free = &gen_free_opaque; - END OBJ_ARG(exec, nullptr, "exec needs arguments: ") + END OBJ_ARG(exec, nullptr, "requires arguments: ") scan_exec_arg(obj, arg, EF_EXEC); obj->parse = false; obj->thread = false; register_exec(obj); obj->callbacks.print = &print_exec; obj->callbacks.free = &free_exec; - END OBJ_ARG(execi, nullptr, "execi needs arguments: ") + END OBJ_ARG(execi, nullptr, "requires arguments: ") scan_exec_arg(obj, arg, EF_EXECI); obj->parse = false; obj->thread = false; register_execi(obj); obj->callbacks.print = &print_exec; obj->callbacks.free = &free_execi; - END OBJ_ARG(execp, nullptr, "execp needs arguments: ") + END OBJ_ARG(execp, nullptr, "requires arguments: ") scan_exec_arg(obj, arg, EF_EXEC); obj->parse = true; obj->thread = false; register_exec(obj); obj->callbacks.print = &print_exec; obj->callbacks.free = &free_exec; - END OBJ_ARG(execpi, nullptr, "execpi needs arguments: ") + END OBJ_ARG(execpi, nullptr, "requires arguments: ") scan_exec_arg(obj, arg, EF_EXECI); obj->parse = true; obj->thread = false; @@ -945,54 +947,53 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.print = &print_exec; obj->callbacks.free = &free_execi; END OBJ_ARG(execbar, nullptr, - "execbar needs arguments: [height],[width] ") + "requires arguments: [height],[width] ") scan_exec_arg(obj, arg, EF_EXEC | EF_BAR); register_exec(obj); obj->callbacks.barval = &execbarval; obj->callbacks.free = &free_exec; END OBJ_ARG(execibar, nullptr, - "execibar needs arguments: [height],[width] ") + "requires arguments: [height],[width] ") scan_exec_arg(obj, arg, EF_EXECI | EF_BAR); register_execi(obj); obj->callbacks.barval = &execbarval; obj->callbacks.free = &free_execi; #ifdef BUILD_GUI END OBJ_ARG(execgauge, nullptr, - "execgauge needs arguments: [height],[width] ") + "requires arguments: [height],[width] ") scan_exec_arg(obj, arg, EF_EXEC | EF_GAUGE); register_exec(obj); obj->callbacks.gaugeval = &execbarval; obj->callbacks.free = &free_exec; - END OBJ_ARG( - execigauge, nullptr, - "execigauge needs arguments: [height],[width] ") + END OBJ_ARG(execigauge, nullptr, + "requires arguments: [height],[width] ") scan_exec_arg(obj, arg, EF_EXECI | EF_GAUGE); register_execi(obj); obj->callbacks.gaugeval = &execbarval; obj->callbacks.free = &free_execi; END OBJ_ARG(execgraph, nullptr, - "execgraph needs arguments: [height],[width] [color1] " + "requires arguments: [height],[width] [color1] " "[color2] [scale] [-t|-l]") scan_exec_arg(obj, arg, EF_EXEC | EF_GRAPH); register_exec(obj); obj->callbacks.graphval = &execbarval; obj->callbacks.free = &free_exec; END OBJ_ARG(execigraph, nullptr, - "execigraph needs arguments: " + "requires arguments: " "[height],[width] [color1] [color2] [scale] [-t|-l]") scan_exec_arg(obj, arg, EF_EXECI | EF_GRAPH); register_execi(obj); obj->callbacks.graphval = &execbarval; obj->callbacks.free = &free_execi; #endif /* BUILD_GUI */ - END OBJ_ARG(texeci, nullptr, "texeci needs arguments: ") + END OBJ_ARG(texeci, nullptr, "requires arguments: ") scan_exec_arg(obj, arg, EF_EXECI); obj->parse = false; obj->thread = true; register_execi(obj); obj->callbacks.print = &print_exec; obj->callbacks.free = &free_execi; - END OBJ_ARG(texecpi, nullptr, "texecpi needs arguments: ") + END OBJ_ARG(texecpi, nullptr, "requires arguments: ") scan_exec_arg(obj, arg, EF_EXECI); obj->parse = true; obj->thread = true; @@ -1032,7 +1033,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, END OBJ(save_coordinates, nullptr) obj->data.l = arg != nullptr ? strtol(arg, nullptr, 10) : 0; obj->callbacks.print = &new_save_coordinates; - END OBJ_ARG(goto, nullptr, "goto needs arguments") obj->data.l = + END OBJ_ARG(goto, nullptr, "requires arguments") obj->data.l = strtol(arg, nullptr, 10); obj->callbacks.print = &new_goto; #ifdef BUILD_GUI @@ -1040,14 +1041,14 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.print = &new_tab; #endif /* BUILD_GUI */ #ifdef __linux__ - END OBJ_ARG(i2c, 0, "i2c needs arguments") parse_i2c_sensor(obj, arg); + END OBJ_ARG(i2c, 0, "requires arguments") parse_i2c_sensor(obj, arg); obj->callbacks.print = &print_sysfs_sensor; obj->callbacks.free = &free_sysfs_sensor; - END OBJ_ARG(platform, 0, "platform needs arguments") + END OBJ_ARG(platform, 0, "requires arguments") parse_platform_sensor(obj, arg); obj->callbacks.print = &print_sysfs_sensor; obj->callbacks.free = &free_sysfs_sensor; - END OBJ_ARG(hwmon, 0, "hwmon needs argumanets") parse_hwmon_sensor(obj, arg); + END OBJ_ARG(hwmon, 0, "requires argumanets") parse_hwmon_sensor(obj, arg); obj->callbacks.print = &print_sysfs_sensor; obj->callbacks.free = &free_sysfs_sensor; #endif /* __linux__ */ @@ -1078,49 +1079,47 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, #endif /* BUILD_IPV6 */ END #endif /* __linux__ */ - OBJ_ARG(tail, nullptr, "tail needs arguments") + OBJ_ARG(tail, nullptr, "requires arguments") init_tailhead("tail", arg, obj, free_at_crash); obj->callbacks.print = &print_tail; obj->callbacks.free = &free_tailhead; - END OBJ_ARG(head, nullptr, "head needs arguments") + END OBJ_ARG(head, nullptr, "requires arguments") init_tailhead("head", arg, obj, free_at_crash); obj->callbacks.print = &print_head; obj->callbacks.free = &free_tailhead; - END OBJ_ARG(lines, nullptr, "lines needs an argument") obj->data.s = - STRNDUP_ARG; + END OBJ_ARG(lines, nullptr, "requires an argument") obj->data.s = STRNDUP_ARG; obj->callbacks.print = &print_lines; obj->callbacks.free = &gen_free_opaque; - END OBJ_ARG(words, nullptr, "words needs a argument") obj->data.s = - STRNDUP_ARG; + END OBJ_ARG(words, nullptr, "requires an argument") obj->data.s = STRNDUP_ARG; obj->callbacks.print = &print_words; obj->callbacks.free = &gen_free_opaque; END OBJ(loadavg, &update_load_average) scan_loadavg_arg(obj, arg); obj->callbacks.print = &print_loadavg; - END OBJ_IF_ARG(if_empty, nullptr, "if_empty needs an argument") obj->sub = + END OBJ_IF_ARG(if_empty, nullptr, "requires an argument") obj->sub = static_cast(malloc(sizeof(struct text_object))); extract_variable_text_internal(obj->sub, arg); obj->callbacks.iftest = &if_empty_iftest; - END OBJ_IF_ARG(if_match, nullptr, "if_match needs arguments") obj->sub = + END OBJ_IF_ARG(if_match, nullptr, "requires arguments") obj->sub = static_cast(malloc(sizeof(struct text_object))); extract_variable_text_internal(obj->sub, arg); obj->callbacks.iftest = &check_if_match; - END OBJ_IF_ARG(if_existing, nullptr, "if_existing needs an argument or two") + END OBJ_IF_ARG(if_existing, nullptr, "requires an argument or two") obj->data.s = STRNDUP_ARG; obj->callbacks.iftest = &if_existing_iftest; obj->callbacks.free = &gen_free_opaque; #if defined(__linux__) || defined(__FreeBSD__) - END OBJ_IF_ARG(if_mounted, 0, "if_mounted needs an argument") obj->data.s = + END OBJ_IF_ARG(if_mounted, 0, "requires an argument") obj->data.s = STRNDUP_ARG; obj->callbacks.iftest = &check_mount; obj->callbacks.free = &gen_free_opaque; - END OBJ_IF_ARG(if_running, &update_top, "if_running needs an argument") - top_running = 1; + END OBJ_IF_ARG(if_running, &update_top, "requires an argument") top_running = + 1; obj->data.s = STRNDUP_ARG; obj->callbacks.iftest = &if_running_iftest; obj->callbacks.free = &gen_free_opaque; #elif defined(__APPLE__) && defined(__MACH__) - END OBJ_IF_ARG(if_mounted, nullptr, "if_mounted needs an argument") - obj->data.s = STRNDUP_ARG; + END OBJ_IF_ARG(if_mounted, nullptr, "requires an argument") obj->data.s = + STRNDUP_ARG; obj->callbacks.iftest = &check_mount; obj->callbacks.free = &gen_free_opaque; @@ -1129,7 +1128,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.print = &print_sip_status; obj->callbacks.free = &gen_free_opaque; #else - END OBJ_IF_ARG(if_running, 0, "if_running needs an argument") + END OBJ_IF_ARG(if_running, 0, "requires an argument") char buf[DEFAULT_TEXT_BUFFER_SIZE]; @@ -1269,146 +1268,140 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, END OBJ(desktop_number, nullptr) obj->callbacks.print = &print_desktop_number; END OBJ(desktop_name, nullptr) obj->callbacks.print = &print_desktop_name; #endif /* BUILD_GUI */ - END OBJ_ARG(format_time, nullptr, "format_time needs a pid as argument") - obj->sub = static_cast(malloc(sizeof(struct text_object))); + END OBJ_ARG(format_time, nullptr, "requires a pid as argument") obj->sub = + static_cast(malloc(sizeof(struct text_object))); extract_variable_text_internal(obj->sub, arg); obj->callbacks.print = &print_format_time; END OBJ(nodename, nullptr) obj->callbacks.print = &print_nodename; END OBJ(nodename_short, nullptr) obj->callbacks.print = &print_nodename_short; - END OBJ_ARG(cmdline_to_pid, nullptr, - "cmdline_to_pid needs a command line as argument") + END OBJ_ARG(cmdline_to_pid, nullptr, "requires a command line as argument") scan_cmdline_to_pid_arg(obj, arg, free_at_crash); obj->callbacks.print = &print_cmdline_to_pid; obj->callbacks.free = &gen_free_opaque; - END OBJ_ARG(pid_chroot, nullptr, "pid_chroot needs a pid as argument") + END OBJ_ARG(pid_chroot, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_chroot; - END OBJ_ARG(pid_cmdline, nullptr, "pid_cmdline needs a pid as argument") + END OBJ_ARG(pid_cmdline, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_cmdline; - END OBJ_ARG(pid_cwd, nullptr, "pid_cwd needs a pid as argument") + END OBJ_ARG(pid_cwd, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_cwd; - END OBJ_ARG(pid_environ, nullptr, "pid_environ needs arguments") + END OBJ_ARG(pid_environ, nullptr, "requires arguments") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_environ; - END OBJ_ARG(pid_environ_list, nullptr, - "pid_environ_list needs a pid as argument") + END OBJ_ARG(pid_environ_list, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_environ_list; - END OBJ_ARG(pid_exe, nullptr, "pid_exe needs a pid as argument") + END OBJ_ARG(pid_exe, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_exe; - END OBJ_ARG(pid_nice, nullptr, "pid_nice needs a pid as argument") + END OBJ_ARG(pid_nice, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_nice; - END OBJ_ARG(pid_openfiles, nullptr, "pid_openfiles needs a pid as argument") + END OBJ_ARG(pid_openfiles, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_openfiles; - END OBJ_ARG(pid_parent, nullptr, "pid_parent needs a pid as argument") + END OBJ_ARG(pid_parent, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_parent; - END OBJ_ARG(pid_priority, nullptr, "pid_priority needs a pid as argument") + END OBJ_ARG(pid_priority, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_priority; - END OBJ_ARG(pid_state, nullptr, "pid_state needs a pid as argument") + END OBJ_ARG(pid_state, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_state; - END OBJ_ARG(pid_state_short, nullptr, - "pid_state_short needs a pid as argument") + END OBJ_ARG(pid_state_short, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_state_short; - END OBJ_ARG(pid_stderr, nullptr, "pid_stderr needs a pid as argument") + END OBJ_ARG(pid_stderr, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_stderr; - END OBJ_ARG(pid_stdin, nullptr, "pid_stdin needs a pid as argument") + END OBJ_ARG(pid_stdin, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_stdin; - END OBJ_ARG(pid_stdout, nullptr, "pid_stdout needs a pid as argument") + END OBJ_ARG(pid_stdout, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_stdout; - END OBJ_ARG(pid_threads, nullptr, "pid_threads needs a pid as argument") + END OBJ_ARG(pid_threads, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_threads; - END OBJ_ARG(pid_thread_list, nullptr, - "pid_thread_list needs a pid as argument") + END OBJ_ARG(pid_thread_list, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_thread_list; - END OBJ_ARG(pid_time_kernelmode, nullptr, - "pid_time_kernelmode needs a pid as argument") + END OBJ_ARG(pid_time_kernelmode, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_time_kernelmode; - END OBJ_ARG(pid_time_usermode, nullptr, - "pid_time_usermode needs a pid as argument") + END OBJ_ARG(pid_time_usermode, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_time_usermode; - END OBJ_ARG(pid_time, nullptr, "pid_time needs a pid as argument") + END OBJ_ARG(pid_time, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_time; - END OBJ_ARG(pid_uid, nullptr, "pid_uid needs a pid as argument") + END OBJ_ARG(pid_uid, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_uid; - END OBJ_ARG(pid_euid, nullptr, "pid_euid needs a pid as argument") + END OBJ_ARG(pid_euid, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_euid; - END OBJ_ARG(pid_suid, nullptr, "pid_suid needs a pid as argument") + END OBJ_ARG(pid_suid, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_suid; - END OBJ_ARG(pid_fsuid, nullptr, "pid_fsuid needs a pid as argument") + END OBJ_ARG(pid_fsuid, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_fsuid; - END OBJ_ARG(pid_gid, nullptr, "pid_gid needs a pid as argument") + END OBJ_ARG(pid_gid, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_gid; - END OBJ_ARG(pid_egid, nullptr, "pid_egid needs a pid as argument") + END OBJ_ARG(pid_egid, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_egid; - END OBJ_ARG(pid_sgid, nullptr, "pid_sgid needs a pid as argument") + END OBJ_ARG(pid_sgid, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_sgid; - END OBJ_ARG(pid_fsgid, nullptr, "pid_fsgid needs a pid as argument") + END OBJ_ARG(pid_fsgid, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_fsgid; - END OBJ_ARG(gid_name, nullptr, "gid_name needs a gid as argument") + END OBJ_ARG(gid_name, nullptr, "requires a gid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_gid_name; - END OBJ_ARG(uid_name, nullptr, "uid_name needs a uid as argument") + END OBJ_ARG(uid_name, nullptr, "requires a uid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_uid_name; - END OBJ_ARG(pid_read, nullptr, "pid_read needs a pid as argument") + END OBJ_ARG(pid_read, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_read; - END OBJ_ARG(pid_vmpeak, nullptr, "pid_vmpeak needs a pid as argument") + END OBJ_ARG(pid_vmpeak, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmpeak; - END OBJ_ARG(pid_vmsize, nullptr, "pid_vmsize needs a pid as argument") + END OBJ_ARG(pid_vmsize, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmsize; - END OBJ_ARG(pid_vmlck, nullptr, "pid_vmlck needs a pid as argument") + END OBJ_ARG(pid_vmlck, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmlck; - END OBJ_ARG(pid_vmhwm, nullptr, "pid_vmhwm needs a pid as argument") + END OBJ_ARG(pid_vmhwm, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmhwm; - END OBJ_ARG(pid_vmrss, nullptr, "pid_vmrss needs a pid as argument") + END OBJ_ARG(pid_vmrss, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmrss; - END OBJ_ARG(pid_vmdata, nullptr, "pid_vmdata needs a pid as argument") + END OBJ_ARG(pid_vmdata, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmdata; - END OBJ_ARG(pid_vmstk, nullptr, "pid_vmstk needs a pid as argument") + END OBJ_ARG(pid_vmstk, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmstk; - END OBJ_ARG(pid_vmexe, nullptr, "pid_vmexe needs a pid as argument") + END OBJ_ARG(pid_vmexe, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmexe; - END OBJ_ARG(pid_vmlib, nullptr, "pid_vmlib needs a pid as argument") + END OBJ_ARG(pid_vmlib, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmlib; - END OBJ_ARG(pid_vmpte, nullptr, "pid_vmpte needs a pid as argument") + END OBJ_ARG(pid_vmpte, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_vmpte; - END OBJ_ARG(pid_write, nullptr, "pid_write needs a pid as argument") + END OBJ_ARG(pid_write, nullptr, "requires a pid as argument") extract_object_args_to_sub(obj, arg); obj->callbacks.print = &print_pid_write; #ifdef __DragonFly__ @@ -1483,18 +1476,18 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.print = &print_tztime; obj->callbacks.free = &free_tztime; #ifdef BUILD_ICAL - END OBJ_ARG(ical, 0, "ical requires arguments") + END OBJ_ARG(ical, 0, "requires arguments") parse_ical_args(obj, arg, free_at_crash, s); obj->callbacks.print = &print_ical; obj->callbacks.free = &free_ical; #endif #ifdef BUILD_IRC - END OBJ_ARG(irc, 0, "irc requires arguments") parse_irc_args(obj, arg); + END OBJ_ARG(irc, 0, "requires arguments") parse_irc_args(obj, arg); obj->callbacks.print = &print_irc; obj->callbacks.free = &free_irc; #endif #ifdef BUILD_ICONV - END OBJ_ARG(iconv_start, 0, "Iconv requires arguments") + END OBJ_ARG(iconv_start, 0, "requires arguments") init_iconv_start(obj, free_at_crash, arg); obj->callbacks.print = &print_iconv_start; obj->callbacks.free = &free_iconv; @@ -1511,8 +1504,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, END OBJ_IF(if_updatenr, nullptr) obj->data.i = arg != nullptr ? strtol(arg, nullptr, 10) : 0; if (obj->data.i == 0) { - CRIT_ERR_FREE(obj, free_at_crash, - "if_updatenr needs a number above 0 as argument"); + FREE_AND_CRASH("if_updatenr", "requires a number above 0 as argument"); } set_updatereset(obj->data.i > get_updatereset() ? obj->data.i : get_updatereset()); @@ -1542,8 +1534,8 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.free = &free_user_names; END OBJ(user_times, &update_users) obj->callbacks.print = &print_user_times; obj->callbacks.free = &free_user_times; - END OBJ_ARG(user_time, 0, "user time needs a console name as argument") - obj->data.s = STRNDUP_ARG; + END OBJ_ARG(user_time, 0, "a console name argument is required") obj->data.s = + STRNDUP_ARG; obj->callbacks.print = &print_user_time; obj->callbacks.free = &free_user_time; END OBJ(user_terms, &update_users) obj->callbacks.print = &print_user_terms; @@ -1581,43 +1573,42 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.print = &print_pop3_used; obj->callbacks.free = &free_mail_obj; #ifdef BUILD_IBM - END OBJ_ARG(smapi, 0, "smapi needs an argument") obj->data.s = STRNDUP_ARG; + END OBJ_ARG(smapi, 0, "requires an argument") obj->data.s = STRNDUP_ARG; obj->callbacks.print = &print_smapi; obj->callbacks.free = &gen_free_opaque; - END OBJ_IF_ARG(if_smapi_bat_installed, 0, - "if_smapi_bat_installed needs an argument") obj->data.s = - STRNDUP_ARG; + END OBJ_IF_ARG(if_smapi_bat_installed, 0, "requires an argument") + obj->data.s = STRNDUP_ARG; obj->callbacks.iftest = &smapi_bat_installed; obj->callbacks.free = &gen_free_opaque; - END OBJ_ARG(smapi_bat_perc, 0, "smapi_bat_perc needs an argument") - obj->data.s = STRNDUP_ARG; + END OBJ_ARG(smapi_bat_perc, 0, "requires an argument") obj->data.s = + STRNDUP_ARG; obj->callbacks.percentage = &smapi_bat_percentage; obj->callbacks.free = &gen_free_opaque; - END OBJ_ARG(smapi_bat_temp, 0, "smapi_bat_temp needs an argument") - obj->data.s = STRNDUP_ARG; + END OBJ_ARG(smapi_bat_temp, 0, "requires an argument") obj->data.s = + STRNDUP_ARG; obj->callbacks.print = &print_smapi_bat_temp; obj->callbacks.free = &gen_free_opaque; - END OBJ_ARG(smapi_bat_power, 0, "smapi_bat_power needs an argument") - obj->data.s = STRNDUP_ARG; + END OBJ_ARG(smapi_bat_power, 0, "requires an argument") obj->data.s = + STRNDUP_ARG; obj->callbacks.print = &print_smapi_bat_power; obj->callbacks.free = &gen_free_opaque; - END OBJ_ARG(smapi_bat_bar, 0, "smapi_bat_bar needs an argument") int cnt; + END OBJ_ARG(smapi_bat_bar, 0, "requires an argument") int cnt; if (sscanf(arg, "%i %n", &obj->data.i, &cnt) <= 0) { - NORM_ERR("first argument to smapi_bat_bar must be an integer value"); + LOG_WARNING("first argument must be an integer value"); obj->data.i = -1; } else arg = scan_bar(obj, arg + cnt, 100); obj->callbacks.barval = &smapi_bat_barval; #endif /* BUILD_IBM */ #ifdef BUILD_MPD -#define mpd_set_maxlen(name) \ - if (arg) { \ - int i; \ - sscanf(arg, "%d", &i); \ - if (i > 0) \ - obj->data.i = i + 1; \ - else \ - NORM_ERR(#name ": invalid length argument"); \ +#define mpd_set_maxlen(name) \ + if (arg) { \ + int i; \ + sscanf(arg, "%d", &i); \ + if (i > 0) \ + obj->data.i = i + 1; \ + else \ + LOG_WARNING("invalid length argument"); \ } END OBJ(mpd_artist, nullptr) mpd_set_maxlen(mpd_artist); obj->callbacks.print = &print_mpd_artist; @@ -1750,13 +1741,12 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, #endif /* BUILD_XMMS2 */ #ifdef BUILD_AUDACIOUS END OBJ(audacious_status, 0) obj->callbacks.print = &print_audacious_status; - END OBJ_ARG(audacious_title, 0, "audacious_title needs an argument") + END OBJ_ARG(audacious_title, 0, "requires a length argument") sscanf(arg, "%d", &obj->data.i); if (obj->data.i > 0) { ++obj->data.i; } else { - CRIT_ERR_FREE(obj, free_at_crash, - "audacious_title: invalid length argument"); + FREE_AND_CRASH("audacious_title", "invalid length argument"); } obj->callbacks.print = &print_audacious_title; END OBJ(audacious_length, 0) obj->callbacks.print = &print_audacious_length; @@ -1783,7 +1773,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.barval = &audacious_barval; #endif /* BUILD_AUDACIOUS */ #ifdef BUILD_CURL - END OBJ_ARG(curl, 0, "curl needs arguments: ") + END OBJ_ARG(curl, 0, "requires arguments: ") curl_parse_arg(obj, arg); obj->callbacks.print = &curl_print; obj->callbacks.free = &curl_obj_free; @@ -1791,59 +1781,58 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, #endif /* BUILD_CURL */ #ifdef BUILD_RSS END OBJ_ARG(rss, 0, - "rss needs arguments: " + "requires arguments: " "[act_par] [spaces in front]") rss_scan_arg(obj, arg); obj->callbacks.print = &rss_print_info; obj->callbacks.free = &rss_free_obj_info; #endif /* BUILD_RSS */ END OBJ_ARG(lua, nullptr, - "lua needs arguments: [function parameters]") + "requires arguments: [function parameters]") obj->data.s = STRNDUP_ARG; obj->callbacks.print = &print_lua; obj->callbacks.free = &gen_free_opaque; - END OBJ_ARG( - lua_parse, nullptr, - "lua_parse needs arguments: [function parameters]") + END OBJ_ARG(lua_parse, nullptr, + "requires arguments: [function parameters]") obj->data.s = STRNDUP_ARG; obj->callbacks.print = &print_lua_parse; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(lua_bar, nullptr, - "lua_bar needs arguments: , " + "requires arguments: , " "[function parameters]") arg = scan_bar(obj, arg, 100); if (arg != nullptr) { obj->data.s = STRNDUP_ARG; } else { - CRIT_ERR_FREE(obj, free_at_crash, - "lua_bar needs arguments: , " - "[function parameters]"); + FREE_AND_CRASH("lua_bar", + "requires arguments: , " + "[function parameters]"); } obj->callbacks.barval = &lua_barval; obj->callbacks.free = &gen_free_opaque; #ifdef BUILD_GUI - END OBJ_ARG( - lua_graph, nullptr, - "lua_graph needs arguments: [height],[width] [gradient " - "colour 1] [gradient colour 2] [scale] [-t] [-l]") auto [buf, skip] = + END OBJ_ARG(lua_graph, nullptr, + "requires arguments: [height],[width] [gradient " + "colour 1] [gradient colour 2] [scale] [-t] [-l]") auto [buf, + skip] = scan_command(arg); scan_graph(obj, arg + skip, 100); if (buf != nullptr) { obj->data.s = buf; } else { - CRIT_ERR_FREE(obj, free_at_crash, - "lua_graph needs arguments: [height],[width] " - "[gradient colour 1] [gradient colour 2] [scale] [-t] [-l]"); + FREE_AND_CRASH("lua_graph", + "requires arguments: [height],[width] " + "[gradient colour 1] [gradient colour 2] [scale] [-t] [-l]"); } obj->callbacks.graphval = &lua_barval; obj->callbacks.free = &gen_free_opaque; END OBJ_ARG(lua_gauge, nullptr, - "lua_gauge needs arguments: , " + "requires arguments: , " "[function parameters]") arg = scan_gauge(obj, arg, 100); if (arg != nullptr) { obj->data.s = STRNDUP_ARG; } else { - CRIT_ERR_FREE(obj, free_at_crash, - "lua_gauge needs arguments: , " - "[function parameters]"); + FREE_AND_CRASH("lua_gauge", + "requires arguments: , " + "[function parameters]"); } obj->callbacks.gaugeval = &lua_barval; obj->callbacks.free = &gen_free_opaque; @@ -1854,7 +1843,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.free = &free_hddtemp; #endif /* BUILD_HDDTEMP */ #ifdef BUILD_PORT_MONITORS - END OBJ_ARG(tcp_portmon, &tcp_portmon_update, "tcp_portmon: needs arguments") + END OBJ_ARG(tcp_portmon, &tcp_portmon_update, "requires arguments") tcp_portmon_init(obj, arg); obj->callbacks.print = &tcp_portmon_action; obj->callbacks.free = &tcp_portmon_free; @@ -1867,16 +1856,16 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, &print_entropy_poolsize; END OBJ(entropy_bar, &update_entropy) scan_bar(obj, arg, 1); obj->callbacks.barval = &entropy_barval; - END OBJ_ARG(blink, nullptr, "blink needs a argument") obj->sub = + END OBJ_ARG(blink, nullptr, "requires an argument") obj->sub = static_cast(malloc(sizeof(struct text_object))); extract_variable_text_internal(obj->sub, arg); obj->callbacks.print = &print_blink; - END OBJ_ARG(to_bytes, nullptr, "to_bytes needs a argument") obj->sub = + END OBJ_ARG(to_bytes, nullptr, "requires an argument") obj->sub = static_cast(malloc(sizeof(struct text_object))); extract_variable_text_internal(obj->sub, arg); obj->callbacks.print = &print_to_bytes; #ifdef BUILD_CURL - END OBJ_ARG(stock, 0, "stock needs arguments") stock_parse_arg(obj, arg); + END OBJ_ARG(stock, 0, "requires arguments") stock_parse_arg(obj, arg); obj->callbacks.print = &print_stock; obj->callbacks.free = &free_stock; #endif /* BUILD_CURL */ @@ -1896,49 +1885,34 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, obj->callbacks.print = &print_combine; obj->callbacks.free = &free_combine; #ifdef BUILD_NVIDIA - END OBJ_ARG(nvidia, 0, "nvidia needs an argument") if (set_nvidia_query( - obj, arg, - text_node_t:: - NONSPECIAL)) { - CRIT_ERR_FREE(obj, free_at_crash, - "nvidia: invalid argument" - " specified: '%s'", - arg); + END OBJ_ARG( + nvidia, 0, + "requires an argument") if (set_nvidia_query(obj, arg, + text_node_t::NONSPECIAL)) { + FREE_AND_CRASH("nvidia", "invalid subcommand '%s'", arg); } obj->callbacks.print = &print_nvidia_value; obj->callbacks.free = &free_nvidia; - END OBJ_ARG( - nvidiabar, 0, - "nvidiabar needs an argument") if (set_nvidia_query(obj, arg, - text_node_t::BAR)) { - CRIT_ERR_FREE(obj, free_at_crash, - "nvidiabar: invalid argument" - " specified: '%s'", - arg); + END OBJ_ARG(nvidiabar, 0, + "requires an argument") if (set_nvidia_query(obj, arg, + text_node_t::BAR)) { + FREE_AND_CRASH("nvidiabar", "invalid subcommand '%s'", arg); } obj->callbacks.barval = &get_nvidia_barval; obj->callbacks.free = &free_nvidia; END OBJ_ARG( nvidiagraph, 0, - "nvidiagraph needs an argument") if (set_nvidia_query(obj, arg, - text_node_t:: - GRAPH)) { - CRIT_ERR_FREE(obj, free_at_crash, - "nvidiagraph: invalid argument" - " specified: '%s'", - arg); + "requires an argument") if (set_nvidia_query(obj, arg, + text_node_t::GRAPH)) { + FREE_AND_CRASH("nvidiagraph", "invalid subcommand: '%s'", arg); } obj->callbacks.graphval = &get_nvidia_barval; obj->callbacks.free = &free_nvidia; END OBJ_ARG( nvidiagauge, 0, - "nvidiagauge needs an argument") if (set_nvidia_query(obj, arg, - text_node_t:: - GAUGE)) { - CRIT_ERR_FREE(obj, free_at_crash, - "nvidiagauge: invalid argument" - " specified: '%s'", - arg); + "requires an argument") if (set_nvidia_query(obj, arg, + text_node_t::GAUGE)) { + FREE_AND_CRASH("nvidiagauge", "invalid subcommand: '%s'", arg); } obj->callbacks.gaugeval = &get_nvidia_barval; obj->callbacks.free = &free_nvidia; @@ -1946,9 +1920,8 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, #ifdef BUILD_APCUPSD END OBJ_ARG( apcupsd, &update_apcupsd, - "apcupsd needs arguments: ") if (apcupsd_scan_arg(arg) != - 0) { - CRIT_ERR_FREE(obj, free_at_crash, "apcupsd needs arguments: "); + "requires arguments: ") if (apcupsd_scan_arg(arg) != 0) { + FREE_AND_CRASH("apcupsd", "invalid arguments; required: "); } obj->callbacks.print = &gen_print_nothing; END OBJ(apcupsd_name, &update_apcupsd) obj->callbacks.print = @@ -1983,7 +1956,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, &print_apcupsd_lastxfer; #endif /* BUILD_APCUPSD */ #ifdef BUILD_JOURNAL - END OBJ_ARG(journal, 0, "journal needs arguments") + END OBJ_ARG(journal, 0, "requires arguments") init_journal("journal", arg, obj, free_at_crash); obj->callbacks.print = &print_journal; obj->callbacks.free = &free_journal; @@ -2034,11 +2007,13 @@ struct text_object *construct_text_object(char *s, const char *arg, long line, END { auto *buf = static_cast(malloc(text_buffer_size.get(*state))); - NORM_ERR("unknown variable '$%s'", s); + LOG_WARNING("unknown variable"); snprintf(buf, text_buffer_size.get(*state), "${%s}", s); obj_be_plain_text(obj, buf); free(buf); } + +#undef FREE_AND_CRASH #undef OBJ #undef OBJ_IF #undef OBJ_ARG @@ -2216,8 +2191,8 @@ int extract_variable_text_internal(struct text_object *retval, obj = create_plain_text(s); if (obj != nullptr) { append_object(retval, obj); } - if (ifblock_stack_empty(&ifblock_opaque) == 0) { - NORM_ERR("one or more $endif's are missing"); + if (!ifblock_stack_empty(&ifblock_opaque)) { + LOG_WARNING("one or more $endif's are missing"); } free(orig_p); diff --git a/src/darwin.mm b/src/darwin.mm index ebdc182fb..83ab05855 100644 --- a/src/darwin.mm +++ b/src/darwin.mm @@ -87,11 +87,8 @@ #include #endif -/* debugging defines */ -#define DEBUG_MODE - /* (E)nhanced printf */ -#ifdef DEBUG_MODE +#if true // ifdef NDEBUG #include void eprintf(const char *fmt, ...) { va_list args; @@ -417,7 +414,7 @@ int check_mount(struct text_object *obj) { num_mounts = getmntinfo(&mounts, MNT_WAIT); if (num_mounts < 0) { - NORM_ERR("could not get mounts using getmntinfo"); + LOG_ERROR("could not get mounts using getmntinfo"); return 0; } @@ -928,9 +925,8 @@ void get_cpu_count() { /* * Allocate ncpus+1 slots because cpu_usage[0] is overall usage. */ - info.cpu_usage = - static_cast(malloc((info.cpu_count + 1) * sizeof(float))); - if (info.cpu_usage == nullptr) { CRIT_ERR("malloc"); } + info.cpu_usage = new float[info.cpu_count + 1]; + if (info.cpu_usage == nullptr) { CRIT_ERR("unable to allocate cpu_usage for %d cores", info.cpu_count + 1); } } } @@ -1357,7 +1353,7 @@ int get_sip_status() { if (csr_get_active_config == nullptr) /* check if weakly linked symbol exists */ { - NORM_ERR("$sip_status will not work on this version of macOS\n"); + LOG_WARNING("$sip_status will not work on this version of macOS\n"); return 0; } @@ -1400,7 +1396,7 @@ void print_sip_status(struct text_object *obj, char *p, unsigned int p_max_size) nullptr) /* check if weakly linked symbol exists */ { snprintf(p, p_max_size, "%s", "unsupported"); - NORM_ERR("$sip_status will not work on this version of macOS\n"); + LOG_WARNING("$sip_status will not work on this version of macOS\n"); return; } @@ -1471,13 +1467,12 @@ void print_sip_status(struct text_object *obj, char *p, unsigned int p_max_size) break; default: snprintf(p, p_max_size, "%s", "unsupported"); - NORM_ERR( - "print_sip_status: unsupported argument passed to $sip_status"); + LOG_WARNING("unsupported argument"); break; } } else { /* bad argument */ snprintf(p, p_max_size, "%s", "unsupported"); - NORM_ERR("print_sip_status: unsupported argument passed to $sip_status"); + LOG_WARNING("unsupported argument"); } } @@ -1517,13 +1512,13 @@ void print_sip_status(struct text_object *obj, char *p, int p_max_size) { break; default: snprintf(p, p_max_size, "%s", "unsupported"); - NORM_ERR( - "print_sip_status: unsupported argument passed to $sip_status"); + LOG_WARNING( + "unsupported argument provided: %s", ); break; } } else { /* bad argument */ snprintf(p, p_max_size, "%s", "unsupported"); - NORM_ERR("print_sip_status: unsupported argument passed to $sip_status"); + LOG_WARNING("unsupported argument provided: %s", ); } } diff --git a/src/data-source.cc b/src/data-source.cc index e6b5e7325..39828d265 100644 --- a/src/data-source.cc +++ b/src/data-source.cc @@ -23,6 +23,7 @@ #include #include "data-source.hh" +#include "logging.h" #include #include @@ -108,10 +109,11 @@ disabled_data_source::disabled_data_source(lua::state *l, const std::string &name, const std::string &setting) : simple_numeric_source(l, name, &NaN) { - // XXX some generic way of reporting errors? NORM_ERR? - std::cerr << "Support for variable '" << name - << "' has been disabled during compilation. Please recompile with '" - << setting << "'" << std::endl; + LOG_CONTEXT(variable, name); + LOG_WARNING( + "support for variable hasn't been enabled at " + "compilation; please recompile conky with '%s'", + setting.c_str()); } } // namespace priv diff --git a/src/diskio.cc b/src/diskio.cc index 04f267716..685cf53de 100644 --- a/src/diskio.cc +++ b/src/diskio.cc @@ -101,11 +101,11 @@ struct diskio_stat *prepare_diskio_stat(const char *s) { snprintf(&(stat_name[0]), text_buffer_size.get(*state), "/dev/%s", &(device_name[0])); if ((stat(&(stat_name[0]), &sb) != 0) || !S_ISBLK(sb.st_mode)) { - NORM_ERR("diskio device '%s' does not exist", &device_s[0]); + LOG_WARNING("diskio device '%s' does not exist", &device_s[0]); } } else if ((0 == (strncmp(s, "partuuid:", 9))) && ((stat(rpbuf2, &sb) != 0) || !S_ISBLK(sb.st_mode))) { - NORM_ERR("diskio device '%s' does not exist", &device_s[0]); + LOG_WARNING("diskio device '%s' does not exist", &device_s[0]); } #endif diff --git a/src/display-file.cc b/src/display-file.cc index f1ff4c0f1..692cb4db7 100644 --- a/src/display-file.cc +++ b/src/display-file.cc @@ -82,13 +82,13 @@ void display_output_file::begin_draw_stuff() { if (static_cast(!overwrite_file.get(*state).empty()) != 0u) { overwrite_fpointer = fopen(overwrite_file.get(*state).c_str(), "we"); if (overwrite_fpointer == nullptr) { - NORM_ERR("Cannot overwrite '%s'", overwrite_file.get(*state).c_str()); + LOG_WARNING("cannot overwrite '%s'", overwrite_file.get(*state).c_str()); } } if (static_cast(!append_file.get(*state).empty()) != 0u) { append_fpointer = fopen(append_file.get(*state).c_str(), "ae"); if (append_fpointer == nullptr) { - NORM_ERR("Cannot append to '%s'", append_file.get(*state).c_str()); + LOG_WARNING("cannot append to '%s'", append_file.get(*state).c_str()); } } } diff --git a/src/display-http.cc b/src/display-http.cc index 78bfeee89..739419e25 100644 --- a/src/display-http.cc +++ b/src/display-http.cc @@ -83,9 +83,9 @@ class out_to_http_setting : public conky::simple_config_setting { if (init && do_convert(l, -1).first) { /* warn about old default port */ if (http_port.get(*state) == 10080) { - NORM_ERR( - "warning: port 10080 is blocked by browsers " - "like Firefox and Chromium, you may want to change http_port."); + LOG_WARNING( + "port 10080 is blocked by browsers like Firefox and Chromium, you " + "may want to change http_port setting."); } httpd = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, http_port.get(*state), diff --git a/src/display-output.cc b/src/display-output.cc index fafcf8c45..eb59a7098 100644 --- a/src/display-output.cc +++ b/src/display-output.cc @@ -36,7 +36,7 @@ namespace conky { inline void log_missing(const char *name, const char *flag) { - DBGP( + LOG_INFO( "%s display output disabled. Enable by recompiling with '%s' " "flag enabled.", name, flag); @@ -87,7 +87,9 @@ bool initialize_display_outputs() { register_output(outputs); register_output(outputs); - for (auto out : outputs) { NORM_ERR("FOUND: %s", out->name.c_str()); } + for (auto out : outputs) { + LOG_TRACE("%s output display found.", out->name.c_str()); + } // Sort display outputs by descending priority, to try graphical ones first. sort(outputs.begin(), outputs.end(), &display_output_base::priority_compare); diff --git a/src/display-wayland.cc b/src/display-wayland.cc index 937c58c41..d6b5d3cb9 100644 --- a/src/display-wayland.cc +++ b/src/display-wayland.cc @@ -543,7 +543,7 @@ static void seat_name_listener(void *data, struct wl_seat *wl_seat, bool display_output_wayland::initialize() { epoll_fd = epoll_create1(0); if (epoll_fd < 0) { - perror("conky: epoll_create"); + SYSTEM_ERR("unable to create epoll"); return false; } global_display = wl_display_connect(NULL); @@ -615,7 +615,7 @@ bool display_output_wayland::main_loop_wait(double t) { ep[0].data.ptr = nullptr; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, wl_display_get_fd(global_display), &ep[0]) == -1) { - perror("conky: epoll_ctl: add"); + SYSTEM_ERR("can't watch for wayland display fd: %s", strerror(errno)); return false; } added = true; @@ -625,8 +625,7 @@ bool display_output_wayland::main_loop_wait(double t) { int ep_count = epoll_wait(epoll_fd, ep, ARRAY_LENGTH(ep), ms); if (ep_count > 0) { if (ep[0].events & (EPOLLERR | EPOLLHUP)) { - NORM_ERR("output closed"); - exit(1); + SYSTEM_ERR("wayland display fd watcher closed unexpectedly"); return false; } } diff --git a/src/display-x11.cc b/src/display-x11.cc index 59e707131..210ed8ad8 100644 --- a/src/display-x11.cc +++ b/src/display-x11.cc @@ -200,7 +200,7 @@ static void X11_create_window() { #ifdef BUILD_XDAMAGE if (XDamageQueryExtension(display, &x11_stuff.event_base, &x11_stuff.error_base) == 0) { - NORM_ERR("Xdamage extension unavailable"); + LOG_WARNING("Xdamage extension unavailable"); x11_stuff.damage = 0; } else { x11_stuff.damage = @@ -269,7 +269,11 @@ bool display_output_x11::main_loop_wait(double t) { s = select(ConnectionNumber(display) + 1, &fdsr, nullptr, nullptr, &tv); if (s == -1) { - if (errno != EINTR) { NORM_ERR("can't select(): %s", strerror(errno)); } + if (errno != EINTR) { + LOG_ERROR("can't check X11 display readyness with select(): %s", + strerror(errno)); + LOG_INFO("text won't be updated"); + } } else { /* timeout */ if (s == 0) { update_text(); } @@ -313,7 +317,7 @@ bool display_output_x11::main_loop_wait(double t) { window.drawable = window.back_buffer; } else { // this is probably reallllly bad - NORM_ERR("Failed to allocate back buffer"); + LOG_ERROR("failed to allocate back buffer"); } XSetForeground(display, window.gc, 0); XFillRectangle(display, window.drawable, window.gc, 0, 0, @@ -335,7 +339,7 @@ bool display_output_x11::main_loop_wait(double t) { /* update struts */ if ((changed != 0) && own_window_type.get(*state) == window_type::PANEL) { - NORM_ERR("defining struts"); + LOG_DEBUG("modifying X11 WM struts (if supported)"); set_struts(text_alignment.get(*state)); } } @@ -1101,6 +1105,9 @@ void display_output_x11::free_fonts(bool utf8) { } #endif /* BUILD_XFT */ } + +const char *X_FALLBACK_FONT = "fixed"; +const char *XFT_FALLBACK_FONT = "courier-12"; void display_output_x11::load_fonts(bool utf8) { x_fonts.resize(fonts.size()); for (unsigned int i = 0; i < fonts.size(); i++) { @@ -1115,15 +1122,14 @@ void display_output_x11::load_fonts(bool utf8) { if (xfont.xftfont != nullptr) { continue; } - NORM_ERR("can't load Xft font '%s'", font.name.c_str()); - if ((xfont.xftfont = XftFontOpenName(display, screen, "courier-12")) != - nullptr) { + LOG_WARNING("can't load Xft font '%s'", font.name.c_str()); + LOG_INFO("using font '%s' as fallback", XFT_FALLBACK_FONT); + if ((xfont.xftfont = XftFontOpenName(display, screen, + XFT_FALLBACK_FONT)) != nullptr) { continue; } - CRIT_ERR("can't load Xft font '%s'", "courier-12"); - - continue; + SYSTEM_ERR("fallback Xft font (%s) can't be loaded", XFT_FALLBACK_FONT); } #endif if (utf8 && xfont.fontset == nullptr) { @@ -1134,20 +1140,22 @@ void display_output_x11::load_fonts(bool utf8) { &missingnum, &missingdrawn); XFreeStringList(missing); if (xfont.fontset == nullptr) { - NORM_ERR("can't load font '%s'", font.name.c_str()); + LOG_WARNING("can't load font '%s'", font.name.c_str()); + LOG_INFO("using '%s' font as fallback", X_FALLBACK_FONT); xfont.fontset = XCreateFontSet(display, "fixed", &missing, &missingnum, &missingdrawn); if (xfont.fontset == nullptr) { - CRIT_ERR("can't load font '%s'", "fixed"); + SYSTEM_ERR("fallback font (%s) can't be loaded", X_FALLBACK_FONT); } } } /* load normal font */ if ((xfont.font == nullptr) && (xfont.font = XLoadQueryFont(display, font.name.c_str())) == nullptr) { - NORM_ERR("can't load font '%s'", font.name.c_str()); + LOG_WARNING("can't load font '%s'", font.name.c_str()); + LOG_INFO("using '%s' font as fallback", X_FALLBACK_FONT); if ((xfont.font = XLoadQueryFont(display, "fixed")) == nullptr) { - CRIT_ERR("can't load font '%s'", "fixed"); + SYSTEM_ERR("fallback font (%s) can't be loaded", X_FALLBACK_FONT); } } } diff --git a/src/exec.cc b/src/exec.cc index edd605714..a3148715c 100644 --- a/src/exec.cc +++ b/src/exec.cc @@ -198,15 +198,12 @@ static inline double get_barnum(const char *buf) { double barnum; if (sscanf(buf, "%lf", &barnum) != 1) { - NORM_ERR( - "reading exec value failed (perhaps it's not the " - "correct format?)"); + LOG_WARNING("can't read value ('%s') failed; is it in the correct format?", + buf); return 0.0; } if (barnum > 100.0 || barnum < 0.0) { - NORM_ERR( - "your exec value is not between 0 and 100, " - "therefore it will be ignored"); + LOG_WARNING("value is not between 0 and 100; will be ignored"); return 0.0; } @@ -256,7 +253,7 @@ void scan_exec_arg(struct text_object *obj, const char *arg, /* store the interval in ed->interval */ if (sscanf(arg, "%f %n", &ed->interval, &n) <= 0) { - NORM_ERR("missing execi interval: ${execi* command}"); + LOG_WARNING("missing interval (${execi* })a"); delete ed; ed = nullptr; return; @@ -277,9 +274,7 @@ void scan_exec_arg(struct text_object *obj, const char *arg, auto [buf, skip] = scan_command(cmd); scan_graph(obj, cmd + skip, 100); cmd = buf; - if (cmd == nullptr) { - NORM_ERR("error parsing arguments to execgraph object"); - } + if (cmd == nullptr) { LOG_WARNING("error parsing object arguments"); } #endif /* BUILD_GUI */ } diff --git a/src/freebsd.cc b/src/freebsd.cc index 0243c4624..5662ebd92 100644 --- a/src/freebsd.cc +++ b/src/freebsd.cc @@ -67,10 +67,6 @@ #define KELVTOC(x) ((x - 2732) / 10.0) #define MAXSHOWDEVS 16 -#if 0 -#define FREEBSD_DEBUG -#endif - kvm_t *kd; std::mutex kvm_proc_mutex; diff --git a/src/fs.cc b/src/fs.cc index 061ef5ac9..89898f51c 100644 --- a/src/fs.cc +++ b/src/fs.cc @@ -108,7 +108,7 @@ struct fs_stat *prepare_fs_stat(const char *s) { } /* new path */ if (next == nullptr) { - NORM_ERR("too many fs stats"); + LOG_WARNING("too many fs stats"); return nullptr; } strncpy(next->path, s, DEFAULT_TEXT_BUFFER_SIZE); @@ -145,7 +145,7 @@ static void update_fs_stat(struct fs_stat *fs) { get_fs_type(fs->path, fs->type); #endif } else { - NORM_ERR("statfs '%s': %s", fs->path, strerror(errno)); + LOG_ERROR("statfs failed for '%s': %s", fs->path, strerror(errno)); fs->size = 0; fs->avail = 0; fs->free = 0; @@ -162,7 +162,7 @@ void get_fs_type(const char *path, char *result) { if (statfs_func(path, &s) == 0) { strncpy(result, s.f_fstypename, DEFAULT_TEXT_BUFFER_SIZE); } else { - NORM_ERR("statfs '%s': %s", path, strerror(errno)); + LOG_ERROR("statfs failed for '%s': %s", path, strerror(errno)); } return; #elif defined(__sun) @@ -176,7 +176,8 @@ void get_fs_type(const char *path, char *result) { char *slash; if (mtab == nullptr) { - NORM_ERR("setmntent /proc/mounts: %s", strerror(errno)); + LOG_ERROR("unable to access mount table entries for /proc/mounts: %s", + strerror(errno)); strncpy(result, "unknown", DEFAULT_TEXT_BUFFER_SIZE); return; } @@ -192,14 +193,14 @@ void get_fs_type(const char *path, char *result) { fseek(mtab, 0, SEEK_SET); slash = strrchr(search_path, '/'); if (slash == nullptr) { - CRIT_ERR("invalid path '%s'", path); + USER_ERR("invalid path '%s'", path); } else { if (strlen(slash) == 1) /* trailing slash */ *(slash) = '\0'; else if (strlen(slash) > 1) *(slash + 1) = '\0'; else - CRIT_ERR("found a crack in the matrix!"); + SYSTEM_ERR("found a crack in the matrix!"); } } while (strlen(search_path) > 0); free(search_path); diff --git a/src/hddtemp.cc b/src/hddtemp.cc index e2bab99f1..da27c324d 100644 --- a/src/hddtemp.cc +++ b/src/hddtemp.cc @@ -95,15 +95,17 @@ static char *fetch_hddtemp_output(void) { char *buf = nullptr; int buflen, offset = 0, rlen; struct addrinfo hints, *result, *rp; - int i; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; /* XXX: hddtemp has no ipv6 support (yet?) */ hints.ai_socktype = SOCK_STREAM; - if ((i = getaddrinfo(hddtemp_host.get(*state).c_str(), - hddtemp_port.get(*state).c_str(), &hints, &result))) { - NORM_ERR("getaddrinfo(): %s", gai_strerror(i)); + const std::string host = hddtemp_host.get(*state); + const std::string port = hddtemp_port.get(*state); + int err = getaddrinfo(host.c_str(), port.c_str(), &hints, &result); + if (err) { + LOG_ERROR("can't resolve specified host and port: %s (host: %s, port: %s)", + gai_strerror(err), host.c_str(), port.c_str()); return nullptr; } @@ -114,7 +116,7 @@ static char *fetch_hddtemp_output(void) { close(sockfd); } if (!rp) { - NORM_ERR("could not connect to hddtemp host"); + LOG_ERROR("can't open a socket connection to host"); goto GET_OUT; } diff --git a/src/ical.cc b/src/ical.cc index fb39ac1ed..a55ff5537 100644 --- a/src/ical.cc +++ b/src/ical.cc @@ -111,14 +111,17 @@ void parse_ical_args(struct text_object *obj, const char *arg, if (sscanf(arg, "%d %s", &num, filename) != 2) { free(filename); free(obj); - CRIT_ERR_FREE(free_at_crash, free_at_crash2, - "wrong number of arguments for $ical"); + free(free_at_crash); + free(free_at_crash2); + COMMAND_ARG_ERR("ical", "wrong number of arguments"); } file = fopen(filename, "r"); if (!file) { free(obj); + free(filename); free(free_at_crash); - CRIT_ERR_FREE(filename, free_at_crash2, "Can't read file %s", filename); + free(free_at_crash2); + LOG_ERROR("can't read file %s", filename); return; } free(filename); @@ -130,7 +133,7 @@ void parse_ical_args(struct text_object *obj, const char *arg, if (!curc) { icalparser_free(parser); icalcomponent_free(allc); - NORM_ERR("No ical events available"); + LOG_INFO("no events available"); return; } ll_start = add_event(nullptr, curc); diff --git a/src/logger.cc b/src/logger.cc new file mode 100644 index 000000000..95b073b48 --- /dev/null +++ b/src/logger.cc @@ -0,0 +1,69 @@ +#include "logger.hh" + +#include + +using namespace conky::log; + +// enum class detail { +// TIME, +// LEVEL, +// SOURCE, +// CONTEXT, +// }; + +namespace conky::log::_priv { + +void format_time(str_buffer &buffer, const ::conky::log::logger &logger_state, + const ::conky::log::msg_details &entry_state) { + std::time_t current_time = + std::chrono::system_clock::to_time_t(entry_state.time.value()); + auto millis = std::chrono::duration_cast( + entry_state.time.value().time_since_epoch()); + struct tm local_time; + localtime_r(¤t_time, &local_time); + size_t time_len = 0; + time_len += std::strftime(out, max_length, "%F %T", &local_time); + time_len += snprintf(&out[time_len], max_length - time_len, ".%03d", + static_cast(millis.count() % 1000)); + + return time_len; +} + +#define VAL_AND_LEN(STR) (std::make_pair(STR, sizeof(STR))) +const std::array, 7> _LVL_STRINGS{ + VAL_AND_LEN("CRITICAL"), VAL_AND_LEN("ERROR"), VAL_AND_LEN("WARNING"), + VAL_AND_LEN("NOTICE"), VAL_AND_LEN("INFO"), VAL_AND_LEN("DEBUG"), + VAL_AND_LEN("TRACE"), +}; +#undef VAL_AND_LEN +void format_level(str_buffer &buffer, const ::conky::log::logger &logger_state, + const ::conky::log::msg_details &entry_state) { + buffer.append( + _LVL_STRINGS[static_cast(entry_state.level) - 1].first); +} + +void format_source(str_buffer &buffer, const ::conky::log::logger &logger_state, + const ::conky::log::msg_details &entry_state) { + entry_state->level +} + +void format_detail(str_buffer &buffer, const ::conky::log::logger &logger_state, + const ::conky::log::msg_details &entry_state, + detail detail) { + switch (detail) { + case detail::TIME: + format_time(buffer, logger_state, entry_state); + break; + case detail::LEVEL: + format_level(buffer, logger_state, entry_state); + break; + case detail::SOURCE: + format_source(buffer, logger_state, entry_state); + break; + case detail::CONTEXT: + format_context(buffer, logger_state, entry_state); + break; + } +} + +} // namespace conky::log::_priv diff --git a/src/logger.hh b/src/logger.hh new file mode 100644 index 000000000..9cab0e939 --- /dev/null +++ b/src/logger.hh @@ -0,0 +1,530 @@ +/* + * + * Conky, a system monitor, based on torsmo + * + * Any original torsmo code is licensed under the BSD license + * + * All code written since the fork of torsmo is licensed under the GPL + * + * Please see COPYING for details + * + * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen + * Copyright (c) 2005-2024 Brenden Matthews, Philip Kovacs, et. al. + * (see AUTHORS) + * All rights reserved. + * + * This program 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 + * (at your option) any later version. + * + * This program 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 this program. If not, see . + * + */ + +#ifndef _CONKY_LOGGER_H +#define _CONKY_LOGGER_H + +#include "config.h" + +#include "str_buffer.hh" + +#ifdef BUILD_I18N +#include +#else +#define gettext(string) (string) +#endif +#define _(string) gettext(string) + +#include +#include +#include +#include // correct formatting for int types +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __has_include() +#define HAS_SYSLOG +#endif + +#ifdef HAS_SYSLOG +extern "C" { +#include +// hide syslog level definitions +#undef LOG_EMERG +#undef LOG_ALERT +#undef LOG_CRIT +#undef LOG_ERR +#undef LOG_WARNING +#undef LOG_NOTICE +#undef LOG_INFO +#undef LOG_DEBUG +} +#endif /* HAS_SYSLOG */ + +#define ENABLE_LOG_COLORS // FIXME: Make compile option after debugging + +#ifdef ENABLE_LOG_COLORS + +extern "C" { +#include +} + +namespace fs = std::filesystem; + +namespace conky::log { +/// Control Sequence Introducer +#define CSI "\033[" +#define NORMAL "0;" +#define BOLD "1;" + +struct colors { + struct color { + const char *value; + size_t length; + }; + +#define DECL_COLOR(Name, Value) \ + static inline color Name = color { #Value, sizeof(#Value) } + + // Should work on most posix compliant systems (or be hidden): Linux, FreeBSD, + // MacOS, and (even) Windows 10. Feel free to add custom definitions if ANSI + // colors don't work for you + DECL_COLOR(BLACK, CSI NORMAL "30m"); + DECL_COLOR(RED, CSI NORMAL "31m"); + DECL_COLOR(GREEN, CSI NORMAL "32m"); + DECL_COLOR(YELLOW, CSI NORMAL "33m"); + DECL_COLOR(BLUE, CSI NORMAL "34m"); + DECL_COLOR(MAGENTA, CSI NORMAL "35m"); + DECL_COLOR(CYAN, CSI NORMAL "36m"); + DECL_COLOR(WHITE, CSI NORMAL "37m"); + DECL_COLOR(BLACK_BOLD, CSI BOLD "30m"); + DECL_COLOR(RED_BOLD, CSI BOLD "31m"); + DECL_COLOR(GREEN_BOLD, CSI BOLD "32m"); + DECL_COLOR(YELLOW_BOLD, CSI BOLD "33m"); + DECL_COLOR(BLUE_BOLD, CSI BOLD "34m"); + DECL_COLOR(MAGENTA_BOLD, CSI BOLD "35m"); + DECL_COLOR(CYAN_BOLD, CSI BOLD "36m"); + DECL_COLOR(WHITE_BOLD, CSI BOLD "37m"); + DECL_COLOR(RESET, CSI "0m"); + +#undef DECL_COLOR +}; + +#undef BOLD +#undef NORMAL +#undef CSI +} // namespace conky::log + +#endif /* ENABLE_LOG_COLORS */ + +namespace conky::log { +/// @brief Logging levels. +/// +/// Values match syslog ones, with addition of `TRACE` which is local. +/// `Emergency` (0) and `Alert` (1) are not used as they're not warranted from a +/// userspace application. +enum class log_level : uint8_t { + OFF = 1, + CRITICAL = 2, + ERROR = 3, + WARNING = 4, + NOTICE = 5, + INFO = 6, + /// @brief Debug information. + /// + /// Previously DBGP. + DEBUG = 7, + /// @brief Very detailed information useful for debugging purposes. + /// + /// Previously DBGP2. + TRACE = 8, +}; + +const auto level_names = std::array{ + "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG", "TRACE", +}; +const size_t MAX_LEVEL_NAME_LEN = 8; + +constexpr inline const char *log_level_to_cstr(log_level level) { + return level_names[static_cast(level) - 2]; +} + +using clock = std::chrono::system_clock; +using instant = clock::time_point; + +struct source_details { + const char *file = nullptr; + size_t line; +}; + +struct msg_details { + log_level level; + std::optional source; + std::optional time; +}; + +enum class detail { + LEVEL, + SOURCE, + TIME, + CONTEXT, +}; + +static const size_t TIME_LEN = 24; + +namespace _priv { +constexpr inline const char *_log_level_fmt(log_level level) { + return _FMT_DATA[static_cast(level) - 2].first; +} +constexpr inline size_t _log_level_fmt_len(log_level level) { + return _FMT_DATA[static_cast(level) - 2].second; +} + +/// @brief Given some `base` path string view, returns last part of the string +/// that contains (starts with) `/src/`. If no such path is found, `begin` of +/// `base` is returned instead. First `/` character is excluded from result. +/// +/// @note Provided `base` should (but doesn't have to) be a null terminated +/// string. +/// +/// @param base string to trim +/// @return start of `base` or ending that starts with `/src/` +constexpr const char *relative_source_path(const std::string_view &base) { + // leave space to lookup previous "/src/" characters + auto last = base.begin() + 5; + for (auto it = base.end(); it != last; it--) { + if (*it == '/' && *(it - 1) == 'c' && *(it - 2) == 'r' && + *(it - 3) == 's' && *(it - 4) == '/') { + return it - 3; + } + } + return base.begin(); +} + +template +inline void _impl_fprintf(FILE *out, const char *format, Args &&...args) { + fprintf(out, format, args...); +} +inline void _impl_fprintf(FILE *out, const char *format) { + fprintf(out, "%s", format); +} + +inline bool check_color_support(FILE *stream) { +#ifdef ENABLE_LOG_COLORS + if (stream == stdout) { + return isatty(1); + } else if (stream == stderr) { + return isatty(2); + } + return false; +#else + return false; +#endif /* ENABLE_LOG_COLORS */ +} + +class ::conky::log::logger; +void format_detail(str_buffer &buffer, const ::conky::log::logger &logger_state, + const ::conky::log::msg_details &entry_state, detail detail); +} // namespace _priv + +const log_level DEFAULT_LOG_LEVEL = log_level::NOTICE; +class logger { + const char *name; + std::map context; + size_t context_length; + + public: + struct sink { + log_level level = DEFAULT_LOG_LEVEL; + bool colorize = false; + std::unordered_set details; + + sink(log_level level, bool colorize) + : log_level(level), colorize(colorize) {} + + bool is_enabled(log_level level) const { + return static_cast(this->level) >= static_cast(level); + } + void set_log_level(log_level level) { this->level = level; } + void log_more() { + this->level = + static_cast(std::min(static_cast(this->level) + 1, + static_cast(log_level::TRACE))); + } + void log_less() { + this->level = + static_cast(std::max(static_cast(this->log_level) - 1, + static_cast(log_level::OFF))); + } + + virtual FILE *get_stream() { return nullptr; } + + virtual void format_detail(const char *out, size_t max_length, + const msg_details &info, detail detail) { + std::string formatted = _priv::format_detail(str_buffer(out, max_length), + *this, info, detail); + } + + virtual void format_preamble() {} + + virtual void format_output() {} + + virtual void write(const msg_details &info, const char *message) = 0; + }; + +#ifdef HAS_SYSLOG + class syslog_sink : public sink { + public: + syslog_sink() : sink(log_level, false) { + openlog(PACKAGE_NAME, LOG_PID, LOG_USER); + } + ~syslog_sink() { closelog(); } + + void write(const msg_details &info, const char *message) override { + if (static_cast(info.level) >= + static_cast(log_level::CRITICAL) && + static_cast(info.level) < static_cast(log_level::TRACE)) { + syslog(static_cast(info.level), "%s", message); + } + } + }; +#endif /* HAS_SYSLOG */ + + class console_sink : public sink { + FILE *stream; + + public: + console_sink(FILE *stream, log_level level, bool colorize) + : sink(level, colorize), stream(stream) {} + + FILE *get_stream() override { return stream; } + + void write(const msg_details &info, const char *message) override { + fputs(message, stream); + } + }; + + struct file_sink : public sink { + fs::path file; + FILE *stream; + + public: + file_sink(fs::path file, log_level log_level) : sink(level, false) { + this->stream = fopen(file.c_str(), "a+"); + } + ~file_sink() { fclose(stream); } + + const fs::path &get_path() const { return this->file; } + FILE *get_stream() override { return stream; } + + void write(const msg_details &info, const char *message) override { + fputs(message, stream); + } + }; + + private: + std::vector> sinks; + + public: + struct context_guard { + logger *parent; + const char *key; + + context_guard(logger *parent, const char *key) : parent(parent), key(key) { + if (parent->context_length > 0) + parent->context_length++; // delimiter (';') + parent->context_length += + strlen(key) + 1 + parent->context.at(key).length(); // key=value + } + ~context_guard() { + parent->context_length -= + strlen(key) + 1 + parent->context.at(key).length(); // key=value + if (parent->context_length > 0) + parent->context_length--; // delimiter (';') + parent->context.erase(key); + } + + std::string &value() const { return parent->context.at(key); } + }; + + public: + logger(const char *name) : name(name) { + this->sinks.emplace_back(console_sink{ + stderr, + log_level::NOTICE, + _priv::check_color_support(stderr), + }); + +#ifdef HAS_SYSLOG + this->sinks.emplace_back(syslog_sink()); +#else + this->sinks.emplace_back(file_sink{ + "/tmp/conky.log", + level::DEBUG, + }); +#endif + } + + std::shared_ptr add_log_file(const fs::path &path, + log_level level = DEFAULT_LOG_LEVEL) { + auto s = std::shared_ptr(new file_sink{path, level}); + this->sinks.emplace_back(s); + return s; + } + + std::shared_ptr get_stream_sink(FILE *stream) { + for (const auto &s : this->sinks) { + if (s->get_stream() == stream) { return s; } + } + return nullptr; + } + + template + [[nodiscard]] volatile context_guard add_context(const char *key, T value) { + static_assert(std::is_convertible_v, + "can't convert context value to std::string"); + context.emplace(std::make_pair(key, std::string(value))); + return context_guard(this, key); + } + + template + inline void log_print_fmt(msg_details &&details, const char *format, + Args &&...args) { + // skip formatting if no targets will log + if (!is_any_enabled(log_level)) return; + + static const size_t MAX_FILE_LEN = 32; + static const size_t MAX_LOCATION_LEN = MAX_FILE_LEN + 1 + 5; // name:line + +#ifdef ENABLE_LOG_COLORS + static const size_t MAX_COLOR_LEN = 16; +#else + static const size_t MAX_COLOR_LEN = 0; +#endif + + static const size_t BASE_PREAMBLE_LENGTH = + 2 + TIME_LEN + 2 + MAX_LEVEL_NAME_LEN + 2 + MAX_LOCATION_LEN + + 3 * MAX_COLOR_LEN; + + size_t preamble_length = BASE_PREAMBLE_LENGTH; + if (context_length > 0) { + preamble_length += 2 + context_length; // [context] +#ifdef ENABLE_LOG_COLORS + preamble_length += COLOR_LEN; +#endif + } + + // using a string here would require several intermediate buffers so it's + // not really worth the convenience + char preamble[preamble_length + 1]; + size_t offset = 0; + + template + const auto print_tag = inline[&]( + F formatter, std::optional color = std::nullopt) { + preamble[offset] = '['; + offset++; + +#ifdef ENABLE_LOG_COLORS + if (color.has_value()) { + std::strncat(&preamble[offset], color.value, color.length); + offset += color.length; + } +#endif + + offset += formatter(offset); + +#ifdef ENABLE_LOG_COLORS + if (color.has_value()) { + std::strncat(&preamble[offset], colors::RESET.value, + colors::RESET.length); + offset += colors::RESET.length; + } +#endif + + preamble[offset] = ']'; + offset++; + preamble[offset] = '\0'; + }; + + preamble[0] = '['; + + // append time + offset += _priv::format_log_time(&preamble[offset], TIME_LEN, + details.time.value_or(clock::now())); + + // append log level + std::strncat(&preamble[offset], _priv::_log_level_fmt(log_level), + _priv::_log_level_fmt_len(log_level)); + offset += _priv::_log_level_fmt_len(log_level) - 1; + + // append source information + if (details.source.has_value()) { + auto source = details.source.value(); + offset += snprintf(&preamble[offset], preamble_length - offset, + "[%s:%ld]", source.file, source.line); + } + + if (context_length > 0) { + std::string buffer; + buffer.reserve(context_length); + for (const auto &[key, value] : context) { + if (!buffer.empty()) buffer += ";"; + buffer += key; + buffer += '='; + buffer += value; + } + offset += snprintf(&preamble[offset], preamble_length - offset, "[%s]", + buffer.c_str()); + } + + // localized output to console + for (const auto &target : this->entries) { + if (!target.is_enabled(log_level)) continue; + fprintf(target.stream, "%s: ", preamble); + _priv::_impl_fprintf(target.stream, _(format), args...); + fputs("\n", target.stream); + } + } + + template + void log_location(const char *file, size_t line, const char *format, + Args &&...args) { + this->log_print_fmt( + msg_details{ + .level = level, + .source = std::optional(source_details{file, line}), + }, + format, args...); + } + + template + void log(const char *format, Args &&...args) { + this->log_print_fmt( + msg_details{ + .level = level, + }, + format, args...); + } +}; + +} // namespace conky::log + +#endif /* _CONKY_LOGGER_H */ diff --git a/src/logging.cc b/src/logging.cc new file mode 100644 index 000000000..56a6aeb34 --- /dev/null +++ b/src/logging.cc @@ -0,0 +1,3 @@ +#include "logging.h" + +conky::log::logger DEFAULT_LOGGER("conky"); diff --git a/src/logging.h b/src/logging.h index ef6cc4264..d6eb66165 100644 --- a/src/logging.h +++ b/src/logging.h @@ -30,11 +30,9 @@ #ifndef _LOGGING_H #define _LOGGING_H -#include // correct formatting for int types -#include -#include -#include "config.h" -#include "i18n.h" +#include "logger.hh" + +#include class fork_throw : public std::runtime_error { public: @@ -62,63 +60,133 @@ class obj_create_error : public std::runtime_error { obj_create_error(const std::string &msg) : std::runtime_error(msg) {} }; -void clean_up(void); - -template -inline void gettextize_format(const char *format, Args &&...args) { - fprintf(stderr, _(format), args...); -} - -// explicit specialization for no arguments to avoid the -// "format not a string literal and no format arguments" warning -inline void gettextize_format(const char *format) { fputs(_(format), stderr); } +extern conky::log::logger DEFAULT_LOGGER; + +#define LOG(Level, ...) \ + DEFAULT_LOGGER.log_location<::conky::log::log_level::Level>( \ + ::conky::log::_priv::relative_source_path(__FILE__), __LINE__, \ + __VA_ARGS__) + +#define LOG_CRITICAL(...) LOG(CRITICAL, __VA_ARGS__) +#define LOG_ERROR(...) LOG(ERROR, __VA_ARGS__) +#define LOG_WARNING(...) LOG(WARNING, __VA_ARGS__) +#define LOG_NOTICE(...) LOG(NOTICE, __VA_ARGS__) +#define LOG_INFO(...) LOG(INFO, __VA_ARGS__) +#define LOG_DEBUG(...) LOG(DEBUG, __VA_ARGS__) +#define LOG_TRACE(...) LOG(TRACE, __VA_ARGS__) + +#define LOG_CONTEXT(Key, Value) \ + volatile ::conky::log::logger::context_guard _log_guard_##Key = \ + DEFAULT_LOGGER.add_context(#Key, Value) + +// backwards compatibility aliases +#define NORM_ERR(...) LOG_INFO(__VA_ARGS__) +#define DBGP(...) LOG_DEBUG(__VA_ARGS__) +#define DBGP2(...) LOG_TRACE(__VA_ARGS__) + +/// @brief Error that warrants termination of the program, and is caused by +/// developer so it should produce a core dump for reporting. +/// +/// @param Format printf style format string. +/// @param Args printf style arguments. +#define CRIT_ERR(...) \ + LOG_CRITICAL(__VA_ARGS__); \ + std::terminate() +namespace conky { +namespace _priv_error_print { template -void NORM_ERR(const char *format, Args &&...args) { - fprintf(stderr, PACKAGE_NAME ": "); - gettextize_format(format, args...); - fputs("\n", stderr); -} - -/* critical error with additional cleanup */ -template -__attribute__((noreturn)) inline void CRIT_ERR_FREE(void *memtofree1, - void *memtofree2, - const char *format, - Args &&...args) { - NORM_ERR(format, args...); - free(memtofree1); - free(memtofree2); - clean_up(); - exit(EXIT_FAILURE); +inline std::string alloc_printf(const char *format, Args &&...args) { + auto size = std::snprintf(nullptr, 0, format, args...); + char output[size + 1]; + std::snprintf(output, sizeof(output), format, args...); + return std::string(&output[0]); } - -/* critical error */ -template -__attribute__((noreturn)) inline void CRIT_ERR(const char *format, - Args &&...args) { - CRIT_ERR_FREE(nullptr, nullptr, format, args...); +inline std::string alloc_printf(const char *format) { + return std::string(format); } +} // namespace _priv_error_print -namespace conky { -class error : public std::runtime_error { - public: +struct error : public std::runtime_error { + /// @brief Construct a new error. + /// + /// @param msg already localized error message. error(const std::string &msg) : std::runtime_error(msg) {} + /// @brief Construct a new error. + /// + /// @param msg unlocalized error message. + error(const char *msg) : std::runtime_error(_(msg)) {} + /// @brief Construct a new error. + /// + /// @param format unlocalized format of error message. + /// @param args format arguments. + template + error(const char *format, Args &&...args) + : error(_priv_error_print::alloc_printf(_(format), args...)) {} +}; + +struct bad_command_arguments_error : public std::runtime_error { + std::string command; + + /// @brief Construct a new error. + /// + /// @param command command with invalid arguments. + /// @param msg already localized error message. + bad_command_arguments_error(const char *command, const std::string &msg) + : std::runtime_error(msg), command(command) {} + /// @brief Construct a new error. + /// + /// @param command command with invalid arguments. + /// @param msg unlocalized error message. + bad_command_arguments_error(const char *command, const char *msg) + : std::runtime_error(_(msg)), command(std::string(command)) {} + /// @brief Construct a new error. + /// + /// @param command command with invalid arguments. + /// @param format unlocalized format of error message. + /// @param args format arguments. + template + bad_command_arguments_error(const char *command, const char *format, + Args &&...args) + : bad_command_arguments_error( + _priv_error_print::alloc_printf(_(format), args...)), + command(std::string(command)) {} }; } // namespace conky -/* debugging output */ -extern int global_debug_level; - -#define __DBGP(level, ...) \ - do { \ - if (global_debug_level > level) { \ - fprintf(stderr, "DEBUG(%d) [" __FILE__ ":%d]: ", level, __LINE__); \ - gettextize_format(__VA_ARGS__); \ - fputs("\n", stderr); \ - } \ - } while (0) -#define DBGP(...) __DBGP(0, __VA_ARGS__) -#define DBGP2(...) __DBGP(1, __VA_ARGS__) +/// @brief Error that warrants termination of the program, but is caused by user +/// error (e.g. bad input) and as such a core dump isn't useful. +/// +/// @param Format printf style format string. +/// @param Args printf style arguments. +#define USER_ERR(...) \ + LOG_ERROR(__VA_ARGS__); \ + throw conky::error(__VA_ARGS__) + +/// @brief Error caused by system not supporting some required conky feature. +/// +/// We assume the fault is with user for not properly configuring conky so we +/// don't produce a core dump. +/// +/// @param Format printf style format string. +/// @param Args printf style arguments. +#define SYSTEM_ERR(...) \ + LOG_ERROR(__VA_ARGS__); \ + throw conky::error(__VA_ARGS__) + +/// @brief Invalid command arguments error. +/// +/// @param Command command with invalid arguments. +/// @param Format printf style format string. +/// @param Args printf style arguments. +#define COMMAND_ARG_ERR(Command, ...) \ + LOG_ERROR(__VA_ARGS__); \ + throw conky::bad_command_arguments_error(Command, __VA_ARGS__) + +/* critical error with additional cleanup */ +#define CRIT_ERR_FREE(memtofree1, memtofree2, ...) \ + free(memtofree1); \ + free(memtofree2); \ + SYSTEM_ERR(__VA_ARGS__); #endif /* _LOGGING_H */ diff --git a/src/main.cc b/src/main.cc index 8e937c61e..8a20c74b1 100644 --- a/src/main.cc +++ b/src/main.cc @@ -141,7 +141,7 @@ static void print_version() { #ifdef BUILD_PULSEAUDIO << _(" * PulseAudio\n") #endif /* BUIL_PULSEAUDIO */ -#ifdef DEBUG +#ifndef NDEBUG << _(" * Debugging extensions\n") #endif #if defined BUILD_LUA_CAIRO || defined BUILD_LUA_IMLIB2 || BUILD_LUA_RSVG @@ -237,8 +237,10 @@ static void print_help(const char *prog_name) { " -v, --version version with build details\n" " -V, --short-version short version\n" " -q, --quiet quiet mode\n" - " -D, --debug increase debugging output, ie. -DD for " - "more debugging\n" + " -D, --debug increase logging output, e.g. -DD for " + "tracing messages\n" + " -L, --log-less decrease logging output, e.g. -LL for " + "only errors\n" " -c, --config=FILE config file to load\n" #ifdef BUILD_BUILTIN_CONFIG " -C, --print-config print the builtin default config to " @@ -282,6 +284,8 @@ inline void reset_optind() { } int main(int argc, char **argv) { + std::set_terminate(&handle_terminate); + #ifdef BUILD_I18N setlocale(LC_ALL, ""); bindtextdomain(PACKAGE_NAME, LOCALE_DIR); @@ -320,7 +324,10 @@ int main(int argc, char **argv) { switch (c) { case 'D': - global_debug_level++; + DEFAULT_LOGGER.get_stream_sink(stderr)->log_more(); + break; + case 'L': + DEFAULT_LOGGER.get_stream_sink(stderr)->log_less(); break; case 'v': print_version(); @@ -332,9 +339,8 @@ int main(int argc, char **argv) { current_config = optarg; break; case 'q': - if (freopen("/dev/null", "w", stderr) == nullptr) { - CRIT_ERR("could not open /dev/null as stderr!"); - } + DEFAULT_LOGGER.get_stream_sink(stderr)->set_log_level( + conky::log::log_level::OFF); break; case 'h': print_help(argv[0]); diff --git a/src/nvidia.cc b/src/nvidia.cc index 6f680339d..6ef13aa85 100644 --- a/src/nvidia.cc +++ b/src/nvidia.cc @@ -405,8 +405,8 @@ unique_display_t nvidia_display_setting::get_nvdisplay() { if (!nvdisplay.empty()) { unique_display_t nvd(XOpenDisplay(nvdisplay.c_str()), &close_nvdisplay); if (!nvd) { - NORM_ERR(nullptr, NULL, "can't open nvidia display: %s", - XDisplayName(nvdisplay.c_str())); + SYSTEM_ERR("can't open nvidia display: %s", + XDisplayName(nvdisplay.c_str())); } return nvd; } @@ -704,14 +704,14 @@ static inline int get_nvidia_target_count(Display *dpy, TARGET_ID tid) { if (num_tgts < 1 && tid == TARGET_GPU) { // Print error and exit if there's no NVIDIA's GPU - NORM_ERR(nullptr, NULL, - "%s:" - "\n Trying to query Nvidia target failed (using the " - "proprietary drivers)." - "\n Are you sure they are installed correctly and a " - "Nvidia GPU is in use?" - "\n (display: %d,Nvidia target_count: %d)", - __func__, dpy, num_tgts); + SYSTEM_ERR( + "%s:" + "\n Trying to query Nvidia target failed (using the " + "proprietary drivers)." + "\n Are you sure they are installed correctly and a " + "Nvidia GPU is in use?" + "\n (display: %d, Nvidia target_count: %d)", + __func__, dpy, num_tgts); } return num_tgts; diff --git a/src/rss.cc b/src/rss.cc index d85831977..914de7e52 100644 --- a/src/rss.cc +++ b/src/rss.cc @@ -52,7 +52,7 @@ class rss_cb : public curl_callback> { std::unique_lock lock(Base::result_mutex); Base::result = tmp; - } catch (std::runtime_error &e) { NORM_ERR("%s", e.what()); } + } catch (std::runtime_error &e) { LOG_ERROR("%s", e.what()); } } public: @@ -140,7 +140,7 @@ static void rss_process_info(char *p, int p_max_size, const std::string &uri, free(tmpspaces); } } else { - NORM_ERR("rss: Invalid action '%s'", action); + LOG_WARNING("rss: Invalid action '%s'", action); } } } @@ -155,7 +155,7 @@ void rss_scan_arg(struct text_object *obj, const char *arg) { argc = sscanf(arg, "%127s %f %63s %d %u", rd->uri, &rd->interval, rd->action, &rd->act_par, &rd->nrspaces); if (argc < 3) { - NORM_ERR("wrong number of arguments for $rss"); + LOG_WARNING("wrong number of arguments for $rss"); free(rd); return; } @@ -166,7 +166,7 @@ void rss_print_info(struct text_object *obj, char *p, unsigned int p_max_size) { struct rss_data *rd = (struct rss_data *)obj->data.opaque; if (!rd) { - NORM_ERR("error processing RSS data"); + LOG_ERROR("invalid RSS data"); return; } rss_process_info(p, p_max_size, rd->uri, rd->action, rd->act_par, diff --git a/src/semaphore.hh b/src/semaphore.hh index 31effd09b..554294e18 100644 --- a/src/semaphore.hh +++ b/src/semaphore.hh @@ -66,7 +66,7 @@ class semaphore { if (ret == DISPATCH_EAGAIN) { return false; } else if (errno != EINTR) { - abort(); + std::terminate(); } } return true; @@ -96,7 +96,7 @@ class semaphore { void wait() { while (sem_wait(&sem)) { - if (errno != EINTR) abort(); + if (errno != EINTR) std::terminate(); } } @@ -105,7 +105,7 @@ class semaphore { if (errno == EAGAIN) return false; else if (errno != EINTR) - abort(); + std::terminate(); } return true; } diff --git a/src/setting.cc b/src/setting.cc index 7b69683d1..78c5db472 100644 --- a/src/setting.cc +++ b/src/setting.cc @@ -52,14 +52,14 @@ settings_map *settings; priv::config_setting_base *get_setting(lua::state &l, int index) { lua::Type type = l.type(index); if (type != lua::TSTRING) { - NORM_ERR("invalid setting of type '%s'", l.type_name(type)); + LOG_WARNING("invalid setting of type '%s'", l.type_name(type)); return nullptr; } const std::string &name = l.tostring(index); auto iter = settings->find(name); if (iter == settings->end()) { - NORM_ERR("Unknown setting '%s'", name.c_str()); + LOG_WARNING("Unknown setting '%s'", name.c_str()); return nullptr; } diff --git a/src/setting.hh b/src/setting.hh index 195dccbbd..86604387f 100644 --- a/src/setting.hh +++ b/src/setting.hh @@ -132,7 +132,7 @@ struct lua_traits { msg += "'" + i->first + "'"; } msg += "."; - NORM_ERR("%s", msg.c_str()); + LOG_WARNING("%s", msg.c_str()); return {T(), false}; } @@ -280,7 +280,7 @@ simple_config_setting::do_convert(lua::state &l, int index) { if (l.isnil(index)) return {default_value, true}; if (l.type(index) != Traits::type) { - NORM_ERR( + LOG_WARNING( "Invalid value of type '%s' for setting '%s'. " "Expected value of type '%s'.", l.type_name(l.type(index)), Base::name.c_str(), @@ -297,7 +297,7 @@ void simple_config_setting::lua_setter(lua::state &l, bool init) { bool ok = true; if (!init && !modifiable) { - NORM_ERR("Setting '%s' is not modifiable", Base::name.c_str()); + LOG_WARNING("Setting '%s' is not modifiable", Base::name.c_str()); ok = false; } @@ -350,7 +350,7 @@ class range_config_setting : public simple_config_setting { int index) { auto ret = Base::do_convert(l, index); if (ret.second && !between(ret.first, min, max)) { - NORM_ERR("Value is out of range for setting '%s'", Base::name.c_str()); + LOG_WARNING("Value is out of range for setting '%s'", Base::name.c_str()); // we ignore out-of-range values. an alternative would be to clamp them. // do we want to do that? ret.second = false; diff --git a/src/smapi.cc b/src/smapi.cc index bc86c076b..fb0b75f65 100644 --- a/src/smapi.cc +++ b/src/smapi.cc @@ -91,7 +91,7 @@ static char *smapi_get_bat_val(const char *args) { if (sscanf(args, "%i %n", &idx, &cnt) <= 0 || snprintf(fname, 127, "%s", (args + cnt)) < 0) { - NORM_ERR("smapi: wrong arguments, should be 'bat,,'"); + LOG_WARNING("smapi: wrong arguments, should be 'bat,,'"); return nullptr; } @@ -127,7 +127,7 @@ uint8_t smapi_bat_percentage(struct text_object *obj) { ? smapi_get_bat_int(idx, "remaining_percent") : 0; } else - NORM_ERR("argument to smapi_bat_perc must be an integer"); + LOG_WARNING("argument to smapi_bat_perc must be an integer"); return val; } @@ -142,7 +142,7 @@ void print_smapi_bat_temp(struct text_object *obj, char *p, /* temperature is in milli degree celsius */ temp_print(p, p_max_size, val / 1000, TEMP_CELSIUS, 1); } else - NORM_ERR("argument to smapi_bat_temp must be an integer"); + LOG_WARNING("argument to smapi_bat_temp must be an integer"); } void print_smapi_bat_power(struct text_object *obj, char *p, @@ -155,7 +155,7 @@ void print_smapi_bat_power(struct text_object *obj, char *p, /* power_now is in mW, set to W with one digit precision */ snprintf(p, p_max_size, "%.1f", ((double)val / 1000)); } else - NORM_ERR("argument to smapi_bat_power must be an integer"); + LOG_WARNING("argument to smapi_bat_power must be an integer"); } double smapi_bat_barval(struct text_object *obj) { @@ -169,6 +169,6 @@ int smapi_bat_installed(struct text_object *obj) { if (obj->data.s && sscanf(obj->data.s, "%i", &idx) == 1) { if (!smapi_bat_installed_internal(idx)) { return 0; } } else - NORM_ERR("argument to if_smapi_bat_installed must be an integer"); + LOG_WARNING("argument to if_smapi_bat_installed must be an integer"); return 1; } diff --git a/src/solaris.cc b/src/solaris.cc index 35a0e322d..2145b87a2 100644 --- a/src/solaris.cc +++ b/src/solaris.cc @@ -75,7 +75,7 @@ static void update_kstat() { if (kstat == nullptr) { if ((kstat = kstat_open()) == nullptr) { pthread_mutex_unlock(&kstat_mtx); - NORM_ERR("can't open kstat: %s", strerror(errno)); + LOG_ERROR("can't open kstat: %s", strerror(errno)); return; } kstat_updated = 0; @@ -104,7 +104,7 @@ static kstat_named_t *get_kstat(const char *module, int inst, const char *name, pthread_mutex_lock(&kstat_mtx); ksp = kstat_lookup(kstat, (char *)module, inst, (char *)name); if (ksp == nullptr) { - NORM_ERR("cannot lookup kstat %s:%d:%s:%s %s", module, inst, name, stat, + LOG_WARNING("cannot lookup kstat %s:%d:%s:%s %s", module, inst, name, stat, strerror(errno)); pthread_mutex_unlock(&kstat_mtx); return nullptr; @@ -117,13 +117,13 @@ static kstat_named_t *get_kstat(const char *module, int inst, const char *name, pthread_mutex_unlock(&kstat_mtx); return knp; } else { - NORM_ERR("kstat %s:%d:%s:%s has unexpected type %d", module, inst, name, + LOG_ERROR("kstat %s:%d:%s:%s has unexpected type %d", module, inst, name, stat, ksp->ks_type); pthread_mutex_unlock(&kstat_mtx); return nullptr; } } - NORM_ERR("cannot read kstat %s:%d:%s:%s", module, inst, name, stat); + LOG_ERROR("cannot read kstat %s:%d:%s:%s", module, inst, name, stat); pthread_mutex_unlock(&kstat_mtx); return nullptr; } @@ -220,13 +220,13 @@ int update_net_stats(void) { /* Find all active net interfaces */ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - NORM_ERR("cannot create socket: %s", strerror(errno)); + LOG_ERROR("cannot create socket: %s", strerror(errno)); return 0; } ifc.ifc_buf = buf; ifc.ifc_len = sizeof(buf); if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { - NORM_ERR("ioctl(SIOCGIFCONF) failed: %s", strerror(errno)); + LOG_ERROR("ioctl(SIOCGIFCONF) failed: %s", strerror(errno)); (void)close(sockfd); return 0; } @@ -253,7 +253,7 @@ int update_net_stats(void) { /* Get received bytes */ knp = get_kstat("link", -1, ifr->ifr_name, "rbytes"); if (knp == nullptr) { - NORM_ERR("cannot read rbytes for %s\n", ifr->ifr_name); + LOG_WARNING("cannot read rbytes for %s\n", ifr->ifr_name); continue; } r = (long long)knp->value.ui32; @@ -267,7 +267,7 @@ int update_net_stats(void) { /* Get transceived bytes */ knp = get_kstat("link", -1, ifr->ifr_name, "obytes"); if (knp == nullptr) { - NORM_ERR("cannot read obytes for %s\n", ifr->ifr_name); + LOG_WARNING("cannot read obytes for %s\n", ifr->ifr_name); continue; } t = (long long)knp->value.ui32; diff --git a/src/specials.cc b/src/specials.cc index 44cecbf37..934cd7d53 100644 --- a/src/specials.cc +++ b/src/specials.cc @@ -221,7 +221,7 @@ std::pair scan_command(const char *s) { _ptr != s) { _size = _ptr - s - 1; } else { - NORM_ERR("mismatched double-quote in execgraph object"); + LOG_WARNING("mismatched double-quote in execgraph object"); return {nullptr, 0}; } diff --git a/src/str_buffer.cc b/src/str_buffer.cc new file mode 100644 index 000000000..7fac38bc2 --- /dev/null +++ b/src/str_buffer.cc @@ -0,0 +1,139 @@ +#include "str_buffer.hh" + +#include +#include + +char *str_buffer::take_data() { + char *ret = this->m_data; + this->m_data = nullptr; + this->m_capacity = 0; + m_length = 0; + return ret; +} + +void str_buffer::resize(size_t size) { + char *new_data = new char[size + 1]; + memcpy(new_data, m_data, std::min(m_length, size)); + free(m_data); + m_data = new_data; + std::fill(m_data + m_length, m_data + size + 1, '\0'); + m_capacity = size; + m_length = std::min(m_length, size); +} +void str_buffer::set_length(size_t len) { + m_length = len; + m_data[m_length] = '\0'; +} + +static inline double GROW_FACTOR = 1.5; +inline void autogrow(str_buffer *buffer) { + size_t new_capacity = + std::max(static_cast(GROW_FACTOR * + static_cast(buffer->capacity())), + static_cast(1)); + buffer->resize(new_capacity); +} + +void str_buffer::append(const char *str, size_t len) { + while (m_length + len >= sizeof(m_data)) { autogrow(this); } + std::memcpy(m_data + m_length, str, len); + m_length += len; +} +void str_buffer::push(char c) { + if (m_length + 1 >= sizeof(m_data)) { autogrow(this); } + m_data[m_length++] = c; +} +void str_buffer::append(const str_buffer &other) { + while (m_length + other.m_length >= sizeof(m_data)) { autogrow(this); } + std::memcpy(m_data + m_length, other.m_data, other.m_length); + m_length += other.m_length; +} +void str_buffer::append(const str_buffer &other, size_t offset, size_t len) { + while (m_length + len >= sizeof(m_data)) { autogrow(this); } + std::memcpy(m_data + m_length, other.m_data + offset, len); + m_length += len; +} +void str_buffer::clear() { + m_length = 0; + m_data[0] = '\0'; +} + +// assignment +str_buffer &str_buffer::operator=(const str_buffer &other) { + if (this == &other) { return *this; } + if (m_capacity < other.m_length) { resize(other.m_length); } + std::memcpy(m_data, other.m_data, other.m_length); + m_length = other.m_length; + return *this; +} +str_buffer &str_buffer::operator=(const char *str) { + if (m_capacity < strlen(str)) { resize(strlen(str)); } + std::memcpy(m_data, str, strlen(str)); + m_length = strlen(str); + return *this; +} +str_buffer &str_buffer::operator=(const std::string &str) { + if (m_capacity < str.length()) { resize(str.length()); } + std::memcpy(m_data, str.data(), str.length()); + m_length = str.length(); + return *this; +} +// move assignment +str_buffer &str_buffer::operator=(str_buffer &&other) { + if (this == &other) { return *this; } + free(m_data); + m_data = other.m_data; + m_capacity = other.m_capacity; + m_length = other.m_length; + other.m_data = nullptr; + other.m_capacity = 0; + other.m_length = 0; + return *this; +} +str_buffer &str_buffer::operator=(std::string &&str) { + if (m_capacity < str.length()) { resize(str.length()); } + std::memcpy(m_data, str.data(), str.length()); + m_length = str.length(); + return *this; +} + +void str_buffer::replace_first(const char *old_str, const char *new_str) { + size_t old_len = std::strlen(old_str); + size_t new_len = std::strlen(new_str); + char *pos = std::strstr(m_data, old_str); + if (pos == NULL) { return; } + std::memmove(pos + new_len, pos + old_len, + m_length - (pos + old_len - m_data)); + std::memcpy(pos, new_str, new_len); + m_length += new_len - old_len; +} +void str_buffer::replace_all(const char *old_str, const char *new_str) { + size_t old_len = strlen(old_str); + size_t new_len = strlen(new_str); + while (true) { + char *pos = strstr(m_data, old_str); + if (pos == NULL) { break; } + std::memmove(pos + new_len, pos + old_len, + m_length - (pos + old_len - m_data)); + std::memcpy(pos, new_str, new_len); + m_length += new_len - old_len; + } +} +void str_buffer::replace_last(const char *old_str, const char *new_str) { + size_t old_len = std::strlen(old_str); + size_t new_len = std::strlen(new_str); + char *pos = std::strrchr(m_data, old_str[0]); + if (pos == NULL) { return; } + if (pos == m_data) { + if (old_len == 1) { + std::memcpy(pos, new_str, new_len); + m_length += new_len - 1; + return; + } + pos += old_len - 1; + } + std::memmove(pos + new_len, pos + old_len, + m_length - (pos + old_len - m_data)); + std::memcpy(pos, new_str, new_len); + m_length += new_len - old_len; +} \ No newline at end of file diff --git a/src/str_buffer.hh b/src/str_buffer.hh new file mode 100644 index 000000000..42dddb363 --- /dev/null +++ b/src/str_buffer.hh @@ -0,0 +1,108 @@ +#ifndef _CONKY_STR_BUFFER_H +#define _CONKY_STR_BUFFER_H + +#include +#include +#include + +/// @brief Container for string manipulation that grows automatically like +/// `std::vector`, but supports its internal storage to be moved out for raw +/// access. +/// Interface is similar to `std::string`, but mutating raw state m_data is not +/// considered UB. +/// +/// @note Not thread-safe. +class str_buffer { + char *m_data; + size_t m_capacity = 0; + size_t m_length = 0; + + public: + str_buffer(size_t size) { m_data = new char[size]; } + str_buffer() : str_buffer(128) {} + ~str_buffer() { free(m_data); } + + inline char *data() { return m_data; } + char *take_data(); + inline std::string to_string() { return std::string(m_data, m_length); } + + void resize(size_t size); + void set_length(size_t len); + + public: + void append(const char *str, size_t len); + inline void append(const char *str) { append(str, strlen(str)); } + void push(char c); + void append(const str_buffer &other); + void append(const str_buffer &other, size_t offset, size_t length); + void clear(); + + inline size_t size() const { return m_length; } + inline size_t capacity() const { return m_capacity; } + + inline char &operator[](size_t i) { return m_data[i]; } + inline const char operator[](size_t i) const { return m_data[i]; } + inline const char at(size_t i) const { return m_data[i]; } + + inline str_buffer &operator+=(const char *str) { + append(str, strlen(str)); + return *this; + } + inline str_buffer &operator+=(char c) { + push(c); + return *this; + } + inline str_buffer &operator+=(const str_buffer &other) { + append(other); + return *this; + } + + // assignment + str_buffer &operator=(const str_buffer &other); + str_buffer &operator=(const char *str); + str_buffer &operator=(const std::string &str); + + // move assignment + str_buffer &operator=(str_buffer &&other); + str_buffer &operator=(std::string &&str); + + // comparison + inline bool operator==(const str_buffer &other) const { + return m_length == other.m_length && + std::memcmp(m_data, other.m_data, m_length) == 0; + } + inline bool operator==(const char *other) const { + return std::memcmp(m_data, other, m_length) == 0; + } + inline bool operator==(const std::string &other) const { + return m_length == other.length() && + std::memcmp(m_data, other.data(), m_length) == 0; + } + + inline bool operator!=(const str_buffer &other) const { + return !operator==(other); + } + inline bool operator!=(const char *other) const { return !operator==(other); } + + // iterators + inline const char *begin() const { return m_data; } + inline const char *end() const { return m_data + m_length; } + + // string operations + inline void to_lower() { + for (size_t i = 0; i < m_length; ++i) { + m_data[i] = std::tolower(m_data[i]); + } + } + inline void to_upper() { + for (size_t i = 0; i < m_length; ++i) { + m_data[i] = std::toupper(m_data[i]); + } + } + + void replace_first(const char *old_str, const char *new_str); + void replace_all(const char *old_str, const char *new_str); + void replace_last(const char *old_str, const char *new_str); +}; + +#endif /* _CONKY_STR_BUFFER_H */ diff --git a/src/template.cc b/src/template.cc index 6045fe8dc..55ab56b92 100644 --- a/src/template.cc +++ b/src/template.cc @@ -230,7 +230,7 @@ char *find_and_replace_templates(const char *inbuf) { free(tmpl_out); o = outbuf + strlen(outbuf); } else { - NORM_ERR("failed to handle template '%s' with args '%s'", templ, args); + LOG_WARNING("failed to handle template '%s' with args '%s'", templ, args); } } *o = '\0'; diff --git a/src/timeinfo.cc b/src/timeinfo.cc index bd6665b61..da658d462 100644 --- a/src/timeinfo.cc +++ b/src/timeinfo.cc @@ -161,7 +161,7 @@ static void do_format_time(struct text_object *obj, char *p, hidestring; if (!times_in_seconds.get(*state)) { - NORM_ERR("Enable \"times_in_seconds\" to use $format_time"); + LOG_WARNING("Enable \"times_in_seconds\" to use $format_time"); return; } @@ -242,7 +242,7 @@ static void do_format_time(struct text_object *obj, char *p, } } else { currentchar--; - NORM_ERR( + LOG_WARNING( "$format_time needs a digit behind 'S' to specify " "precision"); } @@ -254,8 +254,8 @@ static void do_format_time(struct text_object *obj, char *p, output_length++; break; default: - NORM_ERR("$format_time doesn't have a special char '%c'", - *currentchar); + LOG_WARNING("$format_time doesn't have a special char '%c'", + *currentchar); } } else if (*currentchar == '(') { for (temp = currentchar + 1; *temp != 0 && *temp != ')'; temp++) { @@ -293,7 +293,7 @@ static void do_format_time(struct text_object *obj, char *p, p_max_size - output_length + strlen(temp)); output_length += strlen(temp); } else { - NORM_ERR("The format string for $format_time is too long"); + LOG_WARNING("The format string for $format_time is too long"); } free(temp); } @@ -304,12 +304,13 @@ static void do_format_time(struct text_object *obj, char *p, } p[output_length] = 0; } else { - NORM_ERR( + LOG_WARNING( "$format_time needs a output-format starting with a \"-char as 2nd " "argument"); } } else { - NORM_ERR("$format_time didn't receive a time in seconds as first argument"); + LOG_WARNING( + "$format_time didn't receive a time in seconds as first argument"); } } diff --git a/src/top.cc b/src/top.cc index 493e8b152..9ec957845 100644 --- a/src/top.cc +++ b/src/top.cc @@ -563,7 +563,7 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) { int n; if (arg == nullptr) { - NORM_ERR("top needs arguments"); + LOG_WARNING("top needs arguments"); return 0; } @@ -587,9 +587,9 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) { #endif /* BUILD_IOSTATS */ } else { #ifdef BUILD_IOSTATS - NORM_ERR("Must be top, top_mem, top_time or top_io"); + LOG_WARNING("Must be top, top_mem, top_time or top_io"); #else /* BUILD_IOSTATS */ - NORM_ERR("Must be top, top_mem or top_time"); + LOG_WARNING("Must be top, top_mem or top_time"); #endif /* BUILD_IOSTATS */ free_and_zero(obj->data.opaque); return 0; @@ -625,20 +625,21 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) { obj->callbacks.print = &print_top_io_perc; #endif /* BUILD_IOSTATS */ } else { - NORM_ERR("invalid type arg for top"); + LOG_WARNING("invalid type arg for top"); #ifdef BUILD_IOSTATS - NORM_ERR( + LOG_WARNING( "must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize, " "io_read, io_write, io_perc"); #else /* BUILD_IOSTATS */ - NORM_ERR("must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize"); + LOG_WARNING( + "must be one of: name, cpu, pid, mem, time, mem_res, mem_vsize"); #endif /* BUILD_IOSTATS */ free_and_zero(td->s); free_and_zero(obj->data.opaque); return 0; } if (n < 1 || n > MAX_SP) { - NORM_ERR("invalid num arg for top. Must be between 1 and %d.", MAX_SP); + LOG_WARNING("invalid num arg for top. Must be between 1 and %d.", MAX_SP); free_and_zero(td->s); free_and_zero(obj->data.opaque); return 0; @@ -646,7 +647,7 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) { td->num = n - 1; } else { - NORM_ERR("invalid argument count for top"); + LOG_WARNING("invalid argument count for top"); free_and_zero(td->s); free_and_zero(obj->data.opaque); return 0; diff --git a/src/update-cb.cc b/src/update-cb.cc index 2096ea23c..a7b5ac905 100644 --- a/src/update-cb.cc +++ b/src/update-cb.cc @@ -43,8 +43,8 @@ void callback_base::stop() { sem_start.post(); if (pipefd.second >= 0) { if (write(pipefd.second, "X", 1) != 1) { - NORM_ERR("can't write 'X' to pipefd %d: %s", pipefd.second, - strerror(errno)); + LOG_WARNING("can't write 'X' to pipefd %d: %s", pipefd.second, + strerror(errno)); } } thread->join(); diff --git a/src/user.cc b/src/user.cc index c5912262f..ebd628ce8 100644 --- a/src/user.cc +++ b/src/user.cc @@ -51,10 +51,10 @@ void print_uid_name(struct text_object *obj, char *p, unsigned int p_max_size) { if (pw != nullptr) { snprintf(p, p_max_size, "%s", pw->pw_name); } else { - NORM_ERR("The uid %d doesn't exist", uid); + LOG_WARNING("The uid %d doesn't exist", uid); } } else { - NORM_ERR("$uid_name didn't receive a uid as argument"); + LOG_WARNING("$uid_name didn't receive a uid as argument"); } } @@ -73,9 +73,9 @@ void print_gid_name(struct text_object *obj, char *p, unsigned int p_max_size) { if (grp != nullptr) { snprintf(p, p_max_size, "%s", grp->gr_name); } else { - NORM_ERR("The gid %d doesn't exist", gid); + LOG_WARNING("The gid %d doesn't exist", gid); } } else { - NORM_ERR("$gid_name didn't receive a gid as argument"); + LOG_WARNING("$gid_name didn't receive a gid as argument"); } } diff --git a/src/x11-color.cc b/src/x11-color.cc index fa081abf7..27781cbcf 100644 --- a/src/x11-color.cc +++ b/src/x11-color.cc @@ -23,7 +23,7 @@ unsigned long Colour::to_x11_color(Display *display, int screen, xcolor.green = this->green * 257; xcolor.blue = this->blue * 257; if (XAllocColor(display, DefaultColormap(display, screen), &xcolor) == 0) { - // NORM_ERR("can't allocate X color"); + // LOG_WARNING("can't allocate X color"); return 0; } diff --git a/src/x11-settings.cc b/src/x11-settings.cc index 63e971b42..3f8f85ea2 100644 --- a/src/x11-settings.cc +++ b/src/x11-settings.cc @@ -36,7 +36,7 @@ bool use_xdbe_setting::set_up(lua::state &l) { int major, minor; if (XdbeQueryExtension(display, &major, &minor) == 0) { - NORM_ERR("No compatible double buffer extension found"); + LOG_WARNING("No compatible double buffer extension found"); return false; } @@ -45,7 +45,7 @@ bool use_xdbe_setting::set_up(lua::state &l) { if (window.back_buffer != None) { window.drawable = window.back_buffer; } else { - NORM_ERR("Failed to allocate back buffer"); + LOG_WARNING("Failed to allocate back buffer"); return false; } @@ -64,7 +64,7 @@ void use_xdbe_setting::lua_setter(lua::state &l, bool init) { l.pushboolean(false); } - NORM_ERR("drawing to %s buffer", + LOG_INFO("drawing to %s buffer", do_convert(l, -1).first ? "double" : "single"); } @@ -82,7 +82,7 @@ bool use_xpmdb_setting::set_up(lua::state &l) { if (window.back_buffer != None) { window.drawable = window.back_buffer; } else { - NORM_ERR("Failed to allocate back buffer"); + LOG_WARNING("Failed to allocate back buffer"); return false; } @@ -101,7 +101,7 @@ void use_xpmdb_setting::lua_setter(lua::state &l, bool init) { l.pushboolean(false); } - NORM_ERR("drawing to %s buffer", + LOG_INFO("drawing to %s buffer", do_convert(l, -1).first ? "double" : "single"); } diff --git a/src/x11.cc b/src/x11.cc index deec6cbdf..5e9b411a7 100644 --- a/src/x11.cc +++ b/src/x11.cc @@ -252,7 +252,7 @@ void init_x11() { std::string err = std::string("can't open display: ") + XDisplayName(disp); #ifdef BUILD_WAYLAND - NORM_ERR(err.c_str()); + LOG_ERROR(err.c_str()); return; #else /* BUILD_WAYLAND */ throw std::runtime_error(err); @@ -343,15 +343,13 @@ void update_x11_workarea() { int heads = 0; XineramaScreenInfo *si = XineramaQueryScreens(display, &heads); if (si == nullptr) { - NORM_ERR( - "warning: XineramaQueryScreen returned nullptr, ignoring head " - "settings"); + LOG_WARNING("XineramaQueryScreen returned nullptr, ignoring head settings"); return; /* queryscreens failed? */ } int i = head_index.get(*state); if (i < 0 || i >= heads) { - NORM_ERR("warning: invalid head index, ignoring head settings"); + LOG_WARNING("invalid head index, ignoring head settings"); return; } @@ -455,7 +453,7 @@ static int get_argb_visual(Visual **visual, int *depth) { visual_list[i].blue_mask == 0x0000ff)) { *visual = visual_list[i].visual; *depth = visual_list[i].depth; - DBGP("Found ARGB Visual"); + LOG_TRACE("Found ARGB Visual"); XFree(visual_list); return 1; } @@ -621,7 +619,7 @@ void x11_init_window(lua::state &l, bool own) { int major_version; int minor_version; if (XShapeQueryVersion(display, &major_version, &minor_version) == 0) { - NORM_ERR("Input shapes are not supported"); + LOG_WARNING("Input shapes are not supported"); } else { if (own_window.get(*state) && (own_window_type.get(*state) != window_type::NORMAL || @@ -823,14 +821,14 @@ void x11_init_window(lua::state &l, bool own) { if (!XQueryExtension(display, "XInputExtension", &window.xi_opcode, &_ignored, &_ignored)) { // events will still ~work but let the user know why they're buggy - NORM_ERR("XInput extension is not supported by X11!"); + LOG_WARNING("XInput extension is not supported by X11!"); break; } int major = 2, minor = 0; int retval = XIQueryVersion(display, &major, &minor); if (retval != 0) { - NORM_ERR("Error: XInput 2.0 is not supported!"); + LOG_ERROR("XInput 2.0 is not supported!"); break; } @@ -1148,26 +1146,38 @@ void set_struts(alignment align) { case alignment::TOP_LEFT: case alignment::TOP_RIGHT: case alignment::TOP_MIDDLE: - sizes[*x11_strut::TOP] = std::clamp(window.geometry.end_y(), 0, display_height); - sizes[*x11_strut::TOP_START_X] = std::clamp(window.geometry.x(), 0, display_width); - sizes[*x11_strut::TOP_END_X] = std::clamp(window.geometry.end_x(), 0, display_width); + sizes[*x11_strut::TOP] = + std::clamp(window.geometry.end_y(), 0, display_height); + sizes[*x11_strut::TOP_START_X] = + std::clamp(window.geometry.x(), 0, display_width); + sizes[*x11_strut::TOP_END_X] = + std::clamp(window.geometry.end_x(), 0, display_width); break; case alignment::BOTTOM_LEFT: case alignment::BOTTOM_RIGHT: case alignment::BOTTOM_MIDDLE: - sizes[*x11_strut::BOTTOM] = display_height - std::clamp(window.geometry.y(), 0, display_height); - sizes[*x11_strut::BOTTOM_START_X] = std::clamp(window.geometry.x(), 0, display_width); - sizes[*x11_strut::BOTTOM_END_X] = std::clamp(window.geometry.end_x(), 0, display_width); + sizes[*x11_strut::BOTTOM] = + display_height - std::clamp(window.geometry.y(), 0, display_height); + sizes[*x11_strut::BOTTOM_START_X] = + std::clamp(window.geometry.x(), 0, display_width); + sizes[*x11_strut::BOTTOM_END_X] = + std::clamp(window.geometry.end_x(), 0, display_width); break; case alignment::MIDDLE_LEFT: - sizes[*x11_strut::LEFT] = std::clamp(window.geometry.end_x(), 0, display_width); - sizes[*x11_strut::LEFT_START_Y] = std::clamp(window.geometry.y(), 0, display_height); - sizes[*x11_strut::LEFT_END_Y] = std::clamp(window.geometry.end_y(), 0, display_height); + sizes[*x11_strut::LEFT] = + std::clamp(window.geometry.end_x(), 0, display_width); + sizes[*x11_strut::LEFT_START_Y] = + std::clamp(window.geometry.y(), 0, display_height); + sizes[*x11_strut::LEFT_END_Y] = + std::clamp(window.geometry.end_y(), 0, display_height); break; case alignment::MIDDLE_RIGHT: - sizes[*x11_strut::RIGHT] = display_width - std::clamp(window.geometry.x(), 0, display_width); - sizes[*x11_strut::RIGHT_START_Y] = std::clamp(window.geometry.y(), 0, display_height); - sizes[*x11_strut::RIGHT_END_Y] = std::clamp(window.geometry.end_y(), 0, display_height); + sizes[*x11_strut::RIGHT] = + display_width - std::clamp(window.geometry.x(), 0, display_width); + sizes[*x11_strut::RIGHT_START_Y] = + std::clamp(window.geometry.y(), 0, display_height); + sizes[*x11_strut::RIGHT_END_Y] = + std::clamp(window.geometry.end_y(), 0, display_height); break; default: // can't reserve space in middle of the screen @@ -1204,8 +1214,8 @@ void xpmdb_swap_buffers(void) { XCopyArea(display, window.back_buffer, window.window, window.gc, 0, 0, window.geometry.width(), window.geometry.height(), 0, 0); XSetForeground(display, window.gc, 0); - XFillRectangle(display, window.drawable, window.gc, 0, 0, window.geometry.width(), - window.geometry.height()); + XFillRectangle(display, window.drawable, window.gc, 0, 0, + window.geometry.width(), window.geometry.height()); XFlush(display); } }