]> git.ipfire.org Git - oddments/collecty.git/commitdiff
graphs: Allow manually changing the locale
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 30 Oct 2025 19:03:25 +0000 (19:03 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 30 Oct 2025 19:03:25 +0000 (19:03 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/client/main.c
src/daemon/graph-bus.c
src/daemon/graph.c
src/daemon/graph.h

index 1ef0543142aa59b078c6d727a7412c1be77426d2..04a60bebaebb0ecc49e1c92e70e34beb85f45e00 100644 (file)
@@ -60,6 +60,9 @@ typedef struct td_client_ctx {
                const char* since;
                const char* until;
        } interval;
+
+       // Locale
+       const char* locale;
 } td_client_ctx;
 
 enum {
@@ -69,6 +72,7 @@ enum {
        OPT_SINCE      = 4,
        OPT_UNTIL      = 5,
        OPT_OMIT_TITLE = 6,
+       OPT_LOCALE     = 7,
 };
 
 static struct argp_option options[] = {
@@ -82,6 +86,9 @@ static struct argp_option options[] = {
 
        // Flags
        { "omit-title", OPT_OMIT_TITLE, NULL, 0, "Omit the title in the graph image", 0},
+
+       // Locale
+       { "locale", OPT_LOCALE, "CODE", 0, "Render the graph for a different locale", 0 },
        { NULL },
 };
 
@@ -124,6 +131,10 @@ static error_t parse(int key, char* arg, struct argp_state* state) {
                        ctx->flags |= OMIT_TITLE;
                        break;
 
+               case OPT_LOCALE:
+                       ctx->locale = arg;
+                       break;
+
                // Called for each argument
                case ARGP_KEY_ARG:
                        // Take the graph name as first argument
@@ -230,6 +241,13 @@ static int render(td_client_ctx* ctx) {
                        goto ERROR;
        }
 
+       // Send the locale
+       if (ctx->locale) {
+               r = sd_bus_message_append(m, "{sv}", "locale", "s", ctx->locale);
+               if (r < 0)
+                       goto ERROR;
+       }
+
        // Close the array
        r = sd_bus_message_close_container(m);
        if (r < 0)
index 540662e91df694620aa391f252048a4055da04d9..f37c27507f6e1b09388b4bfc4d3275d7e0307aba 100644 (file)
@@ -193,6 +193,12 @@ static int td_graph_bus_render(sd_bus_message* m, void* data, sd_bus_error* erro
 
                        if (omit_title)
                                options.flags |= TD_GRAPH_OMIT_TITLE;
+
+               // Parse "locale"
+               } else if (td_string_equals(key, "locale")) {
+                       r = sd_bus_message_read(m, "v", "s", &options.locale);
+                       if (r < 0)
+                               goto ERROR;
                }
 
                // Leave the container
index b1a8a15faa22002312cf49cd8f1a347fd23f640b..81522cafb332221c2d5a5918d7905aed5e5327c5 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <errno.h>
 #include <limits.h>
+#include <locale.h>
 #include <stdlib.h>
 
 #include <rrd.h>
@@ -267,6 +268,19 @@ static int td_graph_render_title(td_graph* self, const char* object,
        return 0;
 }
 
+static void td_graph_reset_locale(td_ctx* ctx, char* locale) {
+       const char* l = NULL;
+
+       // Nothing to do if the locale is not known
+       if (!*locale)
+               return;
+
+       // Set the locale
+       l = setlocale(LC_ALL, locale);
+       if (!l)
+               ERROR(ctx, "Failed to reset the locale to '%s': %m\n", locale);
+}
+
 int td_graph_render(td_graph* self, const char* object,
                const td_graph_render_options* options, char** buffer, size_t* length) {
        td_args* args = NULL;
@@ -279,6 +293,10 @@ int td_graph_render(td_graph* self, const char* object,
        double ymax = 0;
        int r;
 
+       // Locale
+       char locale[NAME_MAX] = "";
+       const char* l;
+
        // Measure the runtime
        clock_t t_start = 0;
        clock_t t_end = 0;
@@ -306,6 +324,15 @@ int td_graph_render(td_graph* self, const char* object,
                goto ERROR;
        }
 
+       // Fetch the current locale
+       l = setlocale(LC_ALL, NULL);
+       if (l) {
+               // Store the locale for it to be reset later
+               r = td_string_set(locale, l);
+               if (r < 0)
+                       goto ERROR;
+       }
+
        // Allocate a new argument list
        r = td_args_create(&args, self->ctx);
        if (r < 0)
@@ -406,6 +433,15 @@ int td_graph_render(td_graph* self, const char* object,
        if (r < 0)
                goto ERROR;
 
+       // Change the locale
+       if (options->locale) {
+               l = setlocale(LC_ALL, options->locale);
+               if (l)
+                       DEBUG(self->ctx, "Locale has been changed to: %s\n", l);
+               else
+                       ERROR(self->ctx, "Failed to set locale '%s': %m. Ignoring.\n", options->locale);
+       }
+
        // Call the implementation to add some arguments
        r = self->impl->render(self->ctx, self, args, object);
        if (r < 0)
@@ -421,6 +457,11 @@ int td_graph_render(td_graph* self, const char* object,
        // warning since rrdtool >= 1.9 has constified their input arguments.
        r = rrd_graph(td_args_argc(args), (void*)td_args_argv(args),
                        &data, &w, &h, f, &ymin, &ymax);
+
+       // Reset the locale again
+       td_graph_reset_locale(self->ctx, locale);
+
+       // Handle any errors
        if (r < 0) {
                ERROR(self->ctx, "Failed to generate the graph: %s\n", rrd_get_error());
                rrd_clear_error();
@@ -452,6 +493,9 @@ int td_graph_render(td_graph* self, const char* object,
        }
 
 ERROR:
+       // Reset the locale
+       td_graph_reset_locale(self->ctx, locale);
+
        if (data) {
                for (unsigned int i = 0; data[i]; i++)
                        free(data[i]);
index b2d505ac51e6c8279586354852279342ceee5bec..183b3f1c7fc5c27e98308580d4f7808aac1049ca 100644 (file)
@@ -78,6 +78,9 @@ typedef struct td_graph_render_options {
        // Output Format
        const char* format;
 
+       // Locale
+       const char* locale;
+
        // Dimensions
        struct {
                unsigned int h;