]> source.dussan.org Git - rspamd.git/commitdiff
[Fix] Deal with fmtlib exceptions properly
authorVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 23 Oct 2023 20:58:57 +0000 (21:58 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Mon, 23 Oct 2023 20:58:57 +0000 (21:58 +0100)
src/client/rspamc.cxx

index e934efeb181d5837b911d6e65333be738ff3646c..cf2f9d1dc37ac38b2dc0b9ea33abf9e7f63a4328 100644 (file)
@@ -362,6 +362,33 @@ struct fmt::formatter<rspamd_action_type> : fmt::formatter<string_view> {
        }
 };
 
+template<typename... T>
+static inline void rspamc_print(std::FILE *f, fmt::format_string<T...> fmt, T &&...args)
+{
+       static auto try_print_exception = 1;
+       try {
+               fmt::print(f, fmt, std::forward<T>(args)...);
+       } catch (const fmt::format_error &err) {
+               if (try_print_exception) {
+                       if (fprintf(f, "Format error: %s\n", err.what()) < 0) {
+                               try_print_exception = 0;
+                       }
+               }
+       } catch (std::system_error &err) {
+               if (try_print_exception) {
+                       if (fprintf(f, "System error: %s\n", err.what()) < 0) {
+                               try_print_exception = 0;
+                       }
+               }
+       } catch (...) {
+               if (try_print_exception) {
+                       if (fprintf(f, "Unknown format error\n") < 0) {
+                               try_print_exception = 0;
+                       }
+               }
+       }
+}
+
 using sort_lambda = std::function<int(const ucl_object_t *, const ucl_object_t *)>;
 static const auto sort_map = frozen::make_unordered_map<frozen::string, sort_lambda>({
        {"name", [](const ucl_object_t *o1, const ucl_object_t *o2) -> int {
@@ -507,7 +534,7 @@ rspamc_password_callback(const gchar *option_name,
                processed_passwd.resize(plen, '\0');
                plen = rspamd_read_passphrase(processed_passwd.data(), plen, 0, nullptr);
                if (plen == 0) {
-                       fmt::print(stderr, "Invalid password\n");
+                       rspamc_print(stderr, "Invalid password\n");
                        exit(EXIT_FAILURE);
                }
                processed_passwd.resize(plen);
@@ -536,7 +563,7 @@ read_cmd_line(gint *argc, gchar ***argv)
 
        /* Parse options */
        if (!g_option_context_parse(context, argc, argv, &error)) {
-               fmt::print(stderr, "option parsing failed: {}\n", error->message);
+               rspamc_print(stderr, "option parsing failed: {}\n", error->message);
                g_option_context_free(context);
                exit(EXIT_FAILURE);
        }
@@ -639,7 +666,7 @@ print_commands_list()
 {
        guint cmd_len = 0;
 
-       fmt::print(stdout, "Rspamc commands summary:\n");
+       rspamc_print(stdout, "Rspamc commands summary:\n");
 
        for (const auto &cmd: rspamc_commands) {
                auto clen = strlen(cmd.name);
@@ -650,19 +677,19 @@ print_commands_list()
        }
 
        for (const auto &cmd: rspamc_commands) {
-               fmt::print(stdout,
-                                  "  {:>{}} ({:7}{:1})\t{}\n",
-                                  cmd.name,
-                                  cmd_len,
-                                  cmd.is_controller ? "control" : "normal",
-                                  cmd.is_privileged ? "*" : "",
-                                  cmd.description);
-       }
-
-       fmt::print(stdout,
-                          "\n* is for privileged commands that may need password (see -P option)\n");
-       fmt::print(stdout,
-                          "control commands use port 11334 while normal use 11333 by default (see -h option)\n");
+               rspamc_print(stdout,
+                                        "  {:>{}} ({:7}{:1})\t{}\n",
+                                        cmd.name,
+                                        cmd_len,
+                                        cmd.is_controller ? "control" : "normal",
+                                        cmd.is_privileged ? "*" : "",
+                                        cmd.description);
+       }
+
+       rspamc_print(stdout,
+                                "\n* is for privileged commands that may need password (see -P option)\n");
+       rspamc_print(stdout,
+                                "control commands use port 11334 while normal use 11333 by default (see -h option)\n");
 }
 
 static void
@@ -707,9 +734,9 @@ add_options(GQueue *opts)
                                freeaddrinfo(res);
                        }
                        else {
-                               fmt::print(stderr, "address resolution for {} failed: {}\n",
-                                                  ip,
-                                                  gai_strerror(r));
+                               rspamc_print(stderr, "address resolution for {} failed: {}\n",
+                                                        ip,
+                                                        gai_strerror(r));
                        }
                }
                else {
@@ -847,9 +874,9 @@ rspamc_print_indented_line(FILE *out, std::string_view line) -> void
                        }
                }
                if (indent && pos) {
-                       fmt::print(out, "{:>{}}", " ", indent);
+                       rspamc_print(out, "{:>{}}", " ", indent);
                }
-               fmt::print(out, "{}\n", s);
+               rspamc_print(out, "{}\n", s);
                pos = line.find_first_not_of(whitespace, pos + s.size());//skip leading whitespace
        }
 }
@@ -904,31 +931,31 @@ rspamc_symbol_output(FILE *out, const ucl_object_t *obj)
 {
        auto first = true;
 
-       fmt::print(out, "Symbol: {} ", ucl_object_key(obj));
+       rspamc_print(out, "Symbol: {} ", ucl_object_key(obj));
        const auto *val = ucl_object_lookup(obj, "score");
 
        if (val != nullptr) {
-               fmt::print(out, "({:.2f})", ucl_object_todouble(val));
+               rspamc_print(out, "({:.2f})", ucl_object_todouble(val));
        }
        val = ucl_object_lookup(obj, "options");
        if (val != nullptr && ucl_object_type(val) == UCL_ARRAY) {
                ucl_object_iter_t it = nullptr;
                const ucl_object_t *cur;
 
-               fmt::print(out, "[");
+               rspamc_print(out, "[");
 
                while ((cur = ucl_object_iterate(val, &it, true)) != nullptr) {
                        if (first) {
-                               fmt::print(out, "{}", ucl_object_tostring(cur));
+                               rspamc_print(out, "{}", ucl_object_tostring(cur));
                                first = false;
                        }
                        else {
-                               fmt::print(out, ", {}", ucl_object_tostring(cur));
+                               rspamc_print(out, ", {}", ucl_object_tostring(cur));
                        }
                }
-               fmt::print(out, "]");
+               rspamc_print(out, "]");
        }
-       fmt::print(out, "\n");
+       rspamc_print(out, "\n");
 }
 
 static void
@@ -942,16 +969,16 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
                auto *elt = ucl_object_lookup(obj, ucl_name);
                if (elt) {
                        if (humanreport) {
-                               fmt::print(out, ",{}={}", output_message, emphasis_argument(ucl_object_tostring(elt)));
+                               rspamc_print(out, ",{}={}", output_message, emphasis_argument(ucl_object_tostring(elt)));
                        }
                        else {
-                               fmt::print(out, "{}: {}\n", output_message, emphasis_argument(ucl_object_tostring(elt)));
+                               rspamc_print(out, "{}: {}\n", output_message, emphasis_argument(ucl_object_tostring(elt)));
                        }
                }
        };
 
        if (!humanreport) {
-               fmt::print(out, "[Metric: default]\n");
+               rspamc_print(out, "[Metric: default]\n");
        }
 
        const auto *elt = ucl_object_lookup(obj, "required_score");
@@ -987,12 +1014,12 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
 
 
        if (humanreport) {
-               fmt::print(out,
-                                  "{}/{}/{}/{}",
-                                  emphasis_argument(score, 2),
-                                  emphasis_argument(greylist_score, 2),
-                                  emphasis_argument(addheader_score, 2),
-                                  emphasis_argument(required_score, 2));
+               rspamc_print(out,
+                                        "{}/{}/{}/{}",
+                                        emphasis_argument(score, 2),
+                                        emphasis_argument(greylist_score, 2),
+                                        emphasis_argument(addheader_score, 2),
+                                        emphasis_argument(required_score, 2));
        }
 
        elt = ucl_object_lookup(obj, "action");
@@ -1002,7 +1029,7 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
                if (act.has_value()) {
                        if (!tty) {
                                if (humanreport) {
-                                       fmt::print(out, ",action={}:{}", act.value(), ucl_object_tostring(elt));
+                                       rspamc_print(out, ",action={}:{}", act.value(), ucl_object_tostring(elt));
                                }
                                else {
                                        print_protocol_string("action", "Action");
@@ -1032,21 +1059,21 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
                                }
 
                                if (humanreport) {
-                                       fmt::print(out, ",action={}:{}", act.value(), colorized_action);
+                                       rspamc_print(out, ",action={}:{}", act.value(), colorized_action);
                                }
                                else {
-                                       fmt::print(out, "Action: {}\n", colorized_action);
+                                       rspamc_print(out, "Action: {}\n", colorized_action);
                                }
                        }
 
                        is_spam = act.value() < METRIC_ACTION_GREYLIST ? true : false;
                        if (!humanreport) {
-                               fmt::print(out, "Spam: {}\n", is_spam ? "true" : "false");
+                               rspamc_print(out, "Spam: {}\n", is_spam ? "true" : "false");
                        }
                }
                else {
                        if (humanreport) {
-                               fmt::print(out, ",action={}:{}", METRIC_ACTION_NOACTION, ucl_object_tostring(elt));
+                               rspamc_print(out, ",action={}:{}", METRIC_ACTION_NOACTION, ucl_object_tostring(elt));
                        }
                        else {
                                print_protocol_string("action", "Action");
@@ -1066,21 +1093,21 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
                        is_skipped = 1;
                }
 
-               fmt::print(out, ",spam={},skipped={}\n", is_spam ? 1 : 0, is_skipped);
+               rspamc_print(out, ",spam={},skipped={}\n", is_spam ? 1 : 0, is_skipped);
        }
        else if (got_scores == 2) {
-               fmt::print(out,
-                                  "Score: {} / {}\n",
-                                  emphasis_argument(score, 2),
-                                  emphasis_argument(required_score, 2));
+               rspamc_print(out,
+                                        "Score: {} / {}\n",
+                                        emphasis_argument(score, 2),
+                                        emphasis_argument(required_score, 2));
        }
 
        if (humanreport) {
-               fmt::print(out, "Content analysis details:   ({} points, {} required)\n\n",
-                                  emphasis_argument(score, 2),
-                                  emphasis_argument(addheader_score, 2));
-               fmt::print(out, " pts rule name              description\n");
-               fmt::print(out, "---- ---------------------- --------------------------------------------------\n");
+               rspamc_print(out, "Content analysis details:   ({} points, {} required)\n\n",
+                                        emphasis_argument(score, 2),
+                                        emphasis_argument(addheader_score, 2));
+               rspamc_print(out, " pts rule name              description\n");
+               rspamc_print(out, "---- ---------------------- --------------------------------------------------\n");
        }
 
        elt = ucl_object_lookup(obj, "symbols");
@@ -1101,7 +1128,7 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
                }
        }
        if (humanreport) {
-               fmt::print(out, "\n");
+               rspamc_print(out, "\n");
        }
 }
 
@@ -1122,8 +1149,8 @@ rspamc_profile_output(FILE *out, const ucl_object_t *obj)
                                         });
 
        for (const auto *cur_elt: ar) {
-               fmt::print(out, "\t{}: {:3} usec\n",
-                                  ucl_object_key(cur_elt), ucl_object_todouble(cur_elt));
+               rspamc_print(out, "\t{}: {:3} usec\n",
+                                        ucl_object_key(cur_elt), ucl_object_todouble(cur_elt));
        }
 }
 
@@ -1135,7 +1162,7 @@ rspamc_symbols_output(FILE *out, ucl_object_t *obj)
        auto print_protocol_string = [&](const char *ucl_name, const char *output_message) {
                auto *elt = ucl_object_lookup(obj, ucl_name);
                if (elt) {
-                       fmt::print(out, "{}: {}\n", output_message, ucl_object_tostring(elt));
+                       rspamc_print(out, "{}: {}\n", output_message, ucl_object_tostring(elt));
                }
        };
 
@@ -1162,7 +1189,7 @@ rspamc_symbols_output(FILE *out, ucl_object_t *obj)
                        }
                }
                else {
-                       fmt::print(out, "Urls: {}\n", emitted);
+                       rspamc_print(out, "Urls: {}\n", emitted);
                }
                free(emitted);
        }
@@ -1184,7 +1211,7 @@ rspamc_symbols_output(FILE *out, ucl_object_t *obj)
                        }
                }
                else {
-                       fmt::print(out, "Emails: {}\n", emitted);
+                       rspamc_print(out, "Emails: {}\n", emitted);
                }
                free(emitted);
        }
@@ -1201,14 +1228,14 @@ rspamc_symbols_output(FILE *out, ucl_object_t *obj)
 
                while ((cmesg = ucl_object_iterate(elt, &mit, true)) != nullptr) {
                        if (ucl_object_type(cmesg) == UCL_STRING) {
-                               fmt::print(out, "Message - {}: {}\n",
-                                                  ucl_object_key(cmesg), ucl_object_tostring(cmesg));
+                               rspamc_print(out, "Message - {}: {}\n",
+                                                        ucl_object_key(cmesg), ucl_object_tostring(cmesg));
                        }
                        else {
                                char *rendered_message;
                                rendered_message = (char *) ucl_object_emit(cmesg, UCL_EMIT_JSON_COMPACT);
-                               fmt::print(out, "Message - {}: {:.60}\n",
-                                                  ucl_object_key(cmesg), rendered_message);
+                               rspamc_print(out, "Message - {}: {:.60}\n",
+                                                        ucl_object_key(cmesg), rendered_message);
                                free(rendered_message);
                        }
                }
@@ -1216,21 +1243,21 @@ rspamc_symbols_output(FILE *out, ucl_object_t *obj)
 
        elt = ucl_object_lookup(obj, "dkim-signature");
        if (elt && elt->type == UCL_STRING) {
-               fmt::print(out, "DKIM-Signature: {}\n", ucl_object_tostring(elt));
+               rspamc_print(out, "DKIM-Signature: {}\n", ucl_object_tostring(elt));
        }
        else if (elt && elt->type == UCL_ARRAY) {
                ucl_object_iter_t it = nullptr;
                const ucl_object_t *cur;
 
                while ((cur = ucl_object_iterate(elt, &it, true)) != nullptr) {
-                       fmt::print(out, "DKIM-Signature: {}\n", ucl_object_tostring(cur));
+                       rspamc_print(out, "DKIM-Signature: {}\n", ucl_object_tostring(cur));
                }
        }
 
        elt = ucl_object_lookup(obj, "profile");
 
        if (elt) {
-               fmt::print(out, "Profile data:\n");
+               rspamc_print(out, "Profile data:\n");
                rspamc_profile_output(out, elt);
        }
 }
@@ -1242,34 +1269,34 @@ rspamc_uptime_output(FILE *out, ucl_object_t *obj)
 
        const auto *elt = ucl_object_lookup(obj, "version");
        if (elt != nullptr) {
-               fmt::print(out, "Rspamd version: {}\n", ucl_object_tostring(elt));
+               rspamc_print(out, "Rspamd version: {}\n", ucl_object_tostring(elt));
        }
 
        elt = ucl_object_lookup(obj, "uptime");
        if (elt != nullptr) {
-               fmt::print("Uptime: ");
+               rspamc_print(out, "Uptime: ");
                seconds = ucl_object_toint(elt);
                if (seconds >= 2 * 3600) {
                        days = seconds / 86400;
                        hours = seconds / 3600 - days * 24;
                        minutes = seconds / 60 - hours * 60 - days * 1440;
-                       fmt::print("{} day{} {} hour{} {} minute{}\n", days,
-                                          days > 1 ? "s" : "", hours, hours > 1 ? "s" : "",
-                                          minutes, minutes > 1 ? "s" : "");
+                       rspamc_print(out, "{} day{} {} hour{} {} minute{}\n", days,
+                                                days > 1 ? "s" : "", hours, hours > 1 ? "s" : "",
+                                                minutes, minutes > 1 ? "s" : "");
                }
                /* If uptime is less than 1 minute print only seconds */
                else if (seconds / 60 == 0) {
-                       fmt::print("{} second{}\n", seconds,
-                                          seconds > 1 ? "s" : "");
+                       rspamc_print(out, "{} second{}\n", seconds,
+                                                seconds > 1 ? "s" : "");
                }
                /* Else print the minutes and seconds. */
                else {
                        hours = seconds / 3600;
                        minutes = seconds / 60 - hours * 60;
                        seconds -= hours * 3600 + minutes * 60;
-                       fmt::print("{} hour {} minute{} {} second{}\n", hours,
-                                          minutes, minutes > 1 ? "s" : "",
-                                          seconds, seconds > 1 ? "s" : "");
+                       rspamc_print(out, "{} hour {} minute{} {} second{}\n", hours,
+                                                minutes, minutes > 1 ? "s" : "",
+                                                seconds, seconds > 1 ? "s" : "");
                }
        }
 }
@@ -1278,7 +1305,7 @@ static void
 rspamc_counters_output(FILE *out, ucl_object_t *obj)
 {
        if (obj->type != UCL_ARRAY) {
-               fmt::print(out, "Bad output\n");
+               rspamc_print(out, "Bad output\n");
                return;
        }
 
@@ -1309,24 +1336,24 @@ rspamc_counters_output(FILE *out, ucl_object_t *obj)
        memset(dash_buf, '-', dashes + max_len);
        dash_buf[dashes + max_len] = '\0';
 
-       fmt::print(out, "Symbols cache\n");
-
-       fmt::print(out, " {} \n", emphasis_argument(dash_buf));
-       fmt::print(out,
-                          "| {:<4} | {:<{}} | {:^7} | {:^13} | {:^7} |\n",
-                          "Pri",
-                          "Symbol",
-                          max_len,
-                          "Weight",
-                          "Frequency",
-                          "Hits");
-       fmt::print(out, " {} \n", emphasis_argument(dash_buf));
-       fmt::print(out, "| {:<4} | {:<{}} | {:^7} | {:^13} | {:^7} |\n", "",
-                          "", max_len,
-                          "", "hits/min", "");
+       rspamc_print(out, "Symbols cache\n");
+
+       rspamc_print(out, " {} \n", emphasis_argument(dash_buf));
+       rspamc_print(out,
+                                "| {:<4} | {:<{}} | {:^7} | {:^13} | {:^7} |\n",
+                                "Pri",
+                                "Symbol",
+                                max_len,
+                                "Weight",
+                                "Frequency",
+                                "Hits");
+       rspamc_print(out, " {} \n", emphasis_argument(dash_buf));
+       rspamc_print(out, "| {:<4} | {:<{}} | {:^7} | {:^13} | {:^7} |\n", "",
+                                "", max_len,
+                                "", "hits/min", "");
 
        for (const auto [i, cur]: rspamd::enumerate(counters_vec)) {
-               fmt::print(out, " {} \n", dash_buf);
+               rspamc_print(out, " {} \n", dash_buf);
                const auto *sym = ucl_object_lookup(cur, "symbol");
                const auto *weight = ucl_object_lookup(cur, "weight");
                const auto *freq = ucl_object_lookup(cur, "frequency");
@@ -1345,16 +1372,16 @@ rspamc_counters_output(FILE *out, ucl_object_t *obj)
                                sym_name = ucl_object_tostring(sym);
                        }
 
-                       fmt::print(out, "| {:<4} | {:<{}} | {:^7.1f} | {:^6.3f}({:^5.3f}) | {:^7} |\n", i,
-                                          sym_name,
-                                          max_len,
-                                          ucl_object_todouble(weight),
-                                          ucl_object_todouble(freq) * 60.0,
-                                          ucl_object_todouble(freq_dev) * 60.0,
-                                          (std::uintmax_t) ucl_object_toint(nhits));
+                       rspamc_print(out, "| {:<4} | {:<{}} | {:^7.1f} | {:^6.3f}({:^5.3f}) | {:^7} |\n", i,
+                                                sym_name,
+                                                max_len,
+                                                ucl_object_todouble(weight),
+                                                ucl_object_todouble(freq) * 60.0,
+                                                ucl_object_todouble(freq_dev) * 60.0,
+                                                (std::uintmax_t) ucl_object_toint(nhits));
                }
        }
-       fmt::print(out, " {} \n", dash_buf);
+       rspamc_print(out, " {} \n", dash_buf);
 }
 
 static void
@@ -1531,7 +1558,7 @@ rspamc_stat_output(FILE *out, ucl_object_t *obj)
        fmt::format_to(std::back_inserter(out_str), "Total learns: {}\n",
                                   ucl_object_toint(ucl_object_lookup(obj, "total_learns")));
 
-       fmt::print(out, "{}", out_str.c_str());
+       rspamc_print(out, "{}", out_str.c_str());
 }
 
 static void
@@ -1540,11 +1567,11 @@ rspamc_output_headers(FILE *out, struct rspamd_http_message *msg)
        struct rspamd_http_header *h;
 
        kh_foreach_value(msg->headers, h, {
-               fmt::print(out, "{}: {}\n", std::string_view{h->name.begin, h->name.len},
-                                  std::string_view{h->value.begin, h->value.len});
+               rspamc_print(out, "{}: {}\n", std::string_view{h->name.begin, h->name.len},
+                                        std::string_view{h->value.begin, h->value.len});
        });
 
-       fmt::print(out, "\n");
+       rspamc_print(out, "\n");
 }
 
 static void
@@ -1559,7 +1586,7 @@ rspamc_mime_output(FILE *out, ucl_object_t *result, GString *input,
        auto headers_pos = rspamd_string_find_eoh(input, nullptr);
 
        if (headers_pos == -1) {
-               fmt::print(stderr, "cannot find end of headers position");
+               rspamc_print(stderr, "cannot find end of headers position");
                return;
        }
 
@@ -1704,11 +1731,11 @@ rspamc_mime_output(FILE *out, ucl_object_t *result, GString *input,
 
        /* Write message */
        /* Original headers */
-       fmt::print(out, "{}", std::string_view{input->str, (std::size_t) headers_pos});
+       rspamc_print(out, "{}", std::string_view{input->str, (std::size_t) headers_pos});
        /* Added headers */
-       fmt::print(out, "{}", added_headers);
+       rspamc_print(out, "{}", added_headers);
        /* Message body */
-       fmt::print(out, "{}", input->str + headers_pos);
+       rspamc_print(out, "{}", input->str + headers_pos);
 }
 
 static void
@@ -1721,7 +1748,7 @@ rspamc_client_execute_cmd(const struct rspamc_command &cmd, ucl_object_t *result
        GPid cld;
 
        if (!g_shell_parse_argv(execute, &eargc, &eargv, &err)) {
-               fmt::print(stderr, "Cannot execute {}: {}", execute, err->message);
+               rspamc_print(stderr, "Cannot execute {}: {}", execute, err->message);
                g_error_free(err);
 
                return;
@@ -1731,7 +1758,7 @@ rspamc_client_execute_cmd(const struct rspamc_command &cmd, ucl_object_t *result
                                                                  static_cast<GSpawnFlags>(G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD), nullptr, nullptr, &cld,
                                                                  &infd, &outfd, &errfd, &exec_err)) {
 
-               fmt::print(stderr, "Cannot execute {}: {}", execute, exec_err->message);
+               rspamc_print(stderr, "Cannot execute {}: {}", execute, exec_err->message);
                g_error_free(exec_err);
 
                exit(EXIT_FAILURE);
@@ -1755,7 +1782,7 @@ rspamc_client_execute_cmd(const struct rspamc_command &cmd, ucl_object_t *result
                                        ucl_out = (char *) ucl_object_emit(result,
                                                                                                           compact ? UCL_EMIT_JSON_COMPACT : UCL_EMIT_CONFIG);
                                }
-                               fmt::print(out, "{}", ucl_out);
+                               rspamc_print(out, "{}", ucl_out);
                                free(ucl_out);
                        }
                        else {
@@ -1765,7 +1792,7 @@ rspamc_client_execute_cmd(const struct rspamc_command &cmd, ucl_object_t *result
                        ucl_object_unref(result);
                }
                else {
-                       fmt::print(out, "{}\n", err->message);
+                       rspamc_print(out, "{}\n", err->message);
                }
 
                fflush(out);
@@ -1817,14 +1844,14 @@ rspamc_client_cb(struct rspamd_client_connection *conn,
                else {
                        if (cmd.need_input && !json) {
                                if (!compact && !humanreport) {
-                                       fmt::print(out, "Results for file: {} ({:.3} seconds)\n",
-                                                          emphasis_argument(cbdata->filename), diff);
+                                       rspamc_print(out, "Results for file: {} ({:.3} seconds)\n",
+                                                                emphasis_argument(cbdata->filename), diff);
                                }
                        }
                        else {
                                if (!compact && !json && !humanreport) {
-                                       fmt::print(out, "Results for command: {} ({:.3} seconds)\n",
-                                                          emphasis_argument(cmd.name), diff);
+                                       rspamc_print(out, "Results for command: {} ({:.3} seconds)\n",
+                                                                emphasis_argument(cmd.name), diff);
                                }
                        }
 
@@ -1856,7 +1883,7 @@ rspamc_client_cb(struct rspamd_client_connection *conn,
                                                                                                                   compact ? UCL_EMIT_JSON_COMPACT : UCL_EMIT_CONFIG);
                                        }
 
-                                       fmt::print(out, "{}", ucl_out);
+                                       rspamc_print(out, "{}", ucl_out);
                                        free(ucl_out);
                                }
                                else {
@@ -1864,14 +1891,14 @@ rspamc_client_cb(struct rspamd_client_connection *conn,
                                }
 
                                if (body) {
-                                       fmt::print(out, "\nNew body:\n{}\n",
-                                                          std::string_view{body, bodylen});
+                                       rspamc_print(out, "\nNew body:\n{}\n",
+                                                                std::string_view{body, bodylen});
                                }
 
                                ucl_object_unref(result);
                        }
                        else if (err != nullptr) {
-                               fmt::print(out, "{}\n", err->message);
+                               rspamc_print(out, "{}\n", err->message);
 
                                if (json && msg != nullptr) {
                                        gsize rawlen;
@@ -1880,11 +1907,11 @@ rspamc_client_cb(struct rspamd_client_connection *conn,
 
                                        if (raw_body) {
                                                /* We can also output the resulting json */
-                                               fmt::print(out, "{}\n", std::string_view{raw_body, (std::size_t)(rawlen - bodylen)});
+                                               rspamc_print(out, "{}\n", std::string_view{raw_body, (std::size_t)(rawlen - bodylen)});
                                        }
                                }
                        }
-                       fmt::print(out, "\n");
+                       rspamc_print(out, "\n");
                }
 
                fflush(out);
@@ -1979,8 +2006,8 @@ rspamc_process_input(struct ev_loop *ev_base, const struct rspamc_command &cmd,
                }
        }
        else {
-               fmt::print(stderr, "cannot connect to {}: {}\n", connect_str,
-                                  strerror(errno));
+               rspamc_print(stderr, "cannot connect to {}: {}\n", connect_str,
+                                        strerror(errno));
                exit(EXIT_FAILURE);
        }
 }
@@ -2069,8 +2096,8 @@ rspamc_process_dir(struct ev_loop *ev_base, const struct rspamc_command &cmd,
                        if (pentry->d_type == DT_UNKNOWN) {
                                /* Fallback to lstat */
                                if (lstat(fpath.c_str(), &st) == -1) {
-                                       fmt::print(stderr, "cannot stat file {}: {}\n",
-                                                          fpath, strerror(errno));
+                                       rspamc_print(stderr, "cannot stat file {}: {}\n",
+                                                                fpath, strerror(errno));
                                        continue;
                                }
 
@@ -2087,8 +2114,8 @@ rspamc_process_dir(struct ev_loop *ev_base, const struct rspamc_command &cmd,
                        }
 #else
                        if (lstat(fpath.c_str(), &st) == -1) {
-                               fmt::print(stderr, "cannot stat file {}: {}\n",
-                                                  fpath, strerror(errno));
+                               rspamc_print(stderr, "cannot stat file {}: {}\n",
+                                                        fpath, strerror(errno));
                                continue;
                        }
 
@@ -2102,8 +2129,8 @@ rspamc_process_dir(struct ev_loop *ev_base, const struct rspamc_command &cmd,
                        else if (is_reg) {
                                auto *in = fopen(fpath.c_str(), "r");
                                if (in == nullptr) {
-                                       fmt::print(stderr, "cannot open file {}: {}\n",
-                                                          fpath, strerror(errno));
+                                       rspamc_print(stderr, "cannot open file {}: {}\n",
+                                                                fpath, strerror(errno));
                                        continue;
                                }
 
@@ -2120,7 +2147,7 @@ rspamc_process_dir(struct ev_loop *ev_base, const struct rspamc_command &cmd,
                }
        }
        else {
-               fmt::print(stderr, "cannot open directory {}: {}\n", name, strerror(errno));
+               rspamc_print(stderr, "cannot open directory {}: {}\n", name, strerror(errno));
                exit(EXIT_FAILURE);
        }
 
@@ -2167,8 +2194,8 @@ int main(int argc, char **argv, char **env)
                        exclude_compiled[i] = g_pattern_spec_new(exclude_patterns[i]);
 
                        if (exclude_compiled[i] == nullptr) {
-                               fmt::print(stderr, "Invalid glob pattern: {}\n",
-                                                  exclude_patterns[i]);
+                               rspamc_print(stderr, "Invalid glob pattern: {}\n",
+                                                        exclude_patterns[i]);
                                exit(EXIT_FAILURE);
                        }
                }
@@ -2223,7 +2250,7 @@ int main(int argc, char **argv, char **env)
                        /* In case of command read arguments starting from 2 */
                        if (cmd.cmd == RSPAMC_COMMAND_ADD_SYMBOL || cmd.cmd == RSPAMC_COMMAND_ADD_ACTION) {
                                if (argc < 4 || argc > 5) {
-                                       fmt::print(stderr, "invalid arguments\n");
+                                       rspamc_print(stderr, "invalid arguments\n");
                                        exit(EXIT_FAILURE);
                                }
                                if (argc == 5) {
@@ -2248,7 +2275,7 @@ int main(int argc, char **argv, char **env)
        }
 
        if (!maybe_cmd.has_value()) {
-               fmt::print(stderr, "invalid command\n");
+               rspamc_print(stderr, "invalid command\n");
                exit(EXIT_FAILURE);
        }
 
@@ -2275,7 +2302,7 @@ int main(int argc, char **argv, char **env)
                                struct stat st;
 
                                if (stat(argv[i], &st) == -1) {
-                                       fmt::print(stderr, "cannot stat file {}\n", argv[i]);
+                                       rspamc_print(stderr, "cannot stat file {}\n", argv[i]);
                                        exit(EXIT_FAILURE);
                                }
                                if (S_ISDIR(st.st_mode)) {
@@ -2286,7 +2313,7 @@ int main(int argc, char **argv, char **env)
                                else {
                                        in = fopen(argv[i], "r");
                                        if (in == nullptr) {
-                                               fmt::print(stderr, "cannot open file {}\n", argv[i]);
+                                               rspamc_print(stderr, "cannot open file {}\n", argv[i]);
                                                exit(EXIT_FAILURE);
                                        }
                                        rspamc_process_input(event_loop, cmd, in, argv[i], kwattrs);
@@ -2316,8 +2343,8 @@ int main(int argc, char **argv, char **env)
        for (auto cld: children) {
                auto res = 0;
                if (waitpid(cld, &res, 0) == -1) {
-                       fmt::print(stderr, "Cannot wait for {}: {}", cld,
-                                          strerror(errno));
+                       rspamc_print(stderr, "Cannot wait for {}: {}", cld,
+                                                strerror(errno));
 
                        ret = errno;
                }