]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/locale/localectl.c
tree-wide: drop string.h when string-util.h or friends are included
[thirdparty/systemd.git] / src / locale / localectl.c
index b3ad2820d9b62c434d32a8fe6819e8caff74a92f..50c4c703f163da3a5c0c1716695d9badf436de6d 100644 (file)
@@ -5,28 +5,31 @@
 #include <locale.h>
 #include <stdbool.h>
 #include <stdlib.h>
-#include <string.h>
 
 #include "sd-bus.h"
 
 #include "bus-error.h"
 #include "bus-util.h"
-#include "def.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "kbd-util.h"
 #include "locale-util.h"
+#include "main-func.h"
+#include "memory-util.h"
 #include "pager.h"
+#include "pretty-print.h"
+#include "proc-cmdline.h"
 #include "set.h"
 #include "spawn-polkit-agent.h"
 #include "strv.h"
-#include "util.h"
+#include "terminal-util.h"
 #include "verbs.h"
 #include "virt.h"
 
-static bool arg_no_pager = false;
+static PagerFlags arg_pager_flags = 0;
 static bool arg_ask_password = true;
 static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
-static char *arg_host = NULL;
+static const char *arg_host = NULL;
 static bool arg_convert = true;
 
 typedef struct StatusInfo {
@@ -47,34 +50,33 @@ static void status_info_clear(StatusInfo *info) {
 }
 
 static void print_overridden_variables(void) {
-        int r;
-        char *variables[_VARIABLE_LC_MAX] = {};
-        LocaleVariable j;
+        _cleanup_(locale_variables_freep) char *variables[_VARIABLE_LC_MAX] = {};
         bool print_warning = true;
+        LocaleVariable j;
+        int r;
 
-        if (detect_container() > 0 || arg_host)
+        if (arg_transport != BUS_TRANSPORT_LOCAL)
                 return;
 
-        r = parse_env_file(NULL, "/proc/cmdline", WHITESPACE,
-                           "locale.LANG",              &variables[VARIABLE_LANG],
-                           "locale.LANGUAGE",          &variables[VARIABLE_LANGUAGE],
-                           "locale.LC_CTYPE",          &variables[VARIABLE_LC_CTYPE],
-                           "locale.LC_NUMERIC",        &variables[VARIABLE_LC_NUMERIC],
-                           "locale.LC_TIME",           &variables[VARIABLE_LC_TIME],
-                           "locale.LC_COLLATE",        &variables[VARIABLE_LC_COLLATE],
-                           "locale.LC_MONETARY",       &variables[VARIABLE_LC_MONETARY],
-                           "locale.LC_MESSAGES",       &variables[VARIABLE_LC_MESSAGES],
-                           "locale.LC_PAPER",          &variables[VARIABLE_LC_PAPER],
-                           "locale.LC_NAME",           &variables[VARIABLE_LC_NAME],
-                           "locale.LC_ADDRESS",        &variables[VARIABLE_LC_ADDRESS],
-                           "locale.LC_TELEPHONE",      &variables[VARIABLE_LC_TELEPHONE],
-                           "locale.LC_MEASUREMENT",    &variables[VARIABLE_LC_MEASUREMENT],
-                           "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
-                           NULL);
-
+        r = proc_cmdline_get_key_many(
+                        PROC_CMDLINE_STRIP_RD_PREFIX,
+                        "locale.LANG",              &variables[VARIABLE_LANG],
+                        "locale.LANGUAGE",          &variables[VARIABLE_LANGUAGE],
+                        "locale.LC_CTYPE",          &variables[VARIABLE_LC_CTYPE],
+                        "locale.LC_NUMERIC",        &variables[VARIABLE_LC_NUMERIC],
+                        "locale.LC_TIME",           &variables[VARIABLE_LC_TIME],
+                        "locale.LC_COLLATE",        &variables[VARIABLE_LC_COLLATE],
+                        "locale.LC_MONETARY",       &variables[VARIABLE_LC_MONETARY],
+                        "locale.LC_MESSAGES",       &variables[VARIABLE_LC_MESSAGES],
+                        "locale.LC_PAPER",          &variables[VARIABLE_LC_PAPER],
+                        "locale.LC_NAME",           &variables[VARIABLE_LC_NAME],
+                        "locale.LC_ADDRESS",        &variables[VARIABLE_LC_ADDRESS],
+                        "locale.LC_TELEPHONE",      &variables[VARIABLE_LC_TELEPHONE],
+                        "locale.LC_MEASUREMENT",    &variables[VARIABLE_LC_MEASUREMENT],
+                        "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION]);
         if (r < 0 && r != -ENOENT) {
                 log_warning_errno(r, "Failed to read /proc/cmdline: %m");
-                goto finish;
+                return;
         }
 
         for (j = 0; j < _VARIABLE_LC_MAX; j++)
@@ -87,9 +89,6 @@ static void print_overridden_variables(void) {
                         } else
                                 log_warning("                  %s=%s", locale_variable_to_string(j), variables[j]);
                 }
- finish:
-        for (j = 0; j < _VARIABLE_LC_MAX; j++)
-                free(variables[j]);
 }
 
 static void print_status_info(StatusInfo *i) {
@@ -184,10 +183,8 @@ static int set_locale(int argc, char **argv, void *userdata) {
                 return bus_log_create_error(r);
 
         r = sd_bus_call(bus, m, 0, &error, NULL);
-        if (r < 0) {
-                log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
-                return r;
-        }
+        if (r < 0)
+                return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, -r));
 
         return 0;
 }
@@ -200,7 +197,7 @@ static int list_locales(int argc, char **argv, void *userdata) {
         if (r < 0)
                 return log_error_errno(r, "Failed to read list of locales: %m");
 
-        (void) pager_open(arg_no_pager, false);
+        (void) pager_open(arg_pager_flags);
         strv_print(l);
 
         return 0;
@@ -229,9 +226,9 @@ static int set_vconsole_keymap(int argc, char **argv, void *userdata) {
                         NULL,
                         "ssbb", map, toggle_map, arg_convert, arg_ask_password);
         if (r < 0)
-                log_error("Failed to set keymap: %s", bus_error_message(&error, -r));
+                return log_error_errno(r, "Failed to set keymap: %s", bus_error_message(&error, -r));
 
-        return r;
+        return 0;
 }
 
 static int list_vconsole_keymaps(int argc, char **argv, void *userdata) {
@@ -242,7 +239,7 @@ static int list_vconsole_keymaps(int argc, char **argv, void *userdata) {
         if (r < 0)
                 return log_error_errno(r, "Failed to read list of keymaps: %m");
 
-        (void) pager_open(arg_no_pager, false);
+        (void) pager_open(arg_pager_flags);
 
         strv_print(l);
 
@@ -273,15 +270,14 @@ static int set_x11_keymap(int argc, char **argv, void *userdata) {
                         "ssssbb", layout, model, variant, options,
                                   arg_convert, arg_ask_password);
         if (r < 0)
-                log_error("Failed to set keymap: %s", bus_error_message(&error, -r));
+                return log_error_errno(r, "Failed to set keymap: %s", bus_error_message(&error, -r));
 
-        return r;
+        return 0;
 }
 
 static int list_x11_keymaps(int argc, char **argv, void *userdata) {
         _cleanup_fclose_ FILE *f = NULL;
         _cleanup_strv_free_ char **list = NULL;
-        char line[LINE_MAX];
         enum {
                 NONE,
                 MODELS,
@@ -306,9 +302,16 @@ static int list_x11_keymaps(int argc, char **argv, void *userdata) {
         else
                 assert_not_reached("Wrong parameter");
 
-        FOREACH_LINE(line, f, break) {
+        for (;;) {
+                _cleanup_free_ char *line = NULL;
                 char *l, *w;
 
+                r = read_line(f, LONG_LINE_MAX, &line);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to read keyboard mapping list: %m");
+                if (r == 0)
+                        break;
+
                 l = strstrip(line);
 
                 if (isempty(l))
@@ -360,23 +363,29 @@ static int list_x11_keymaps(int argc, char **argv, void *userdata) {
                         return log_oom();
         }
 
-        if (strv_isempty(list)) {
-                log_error("Couldn't find any entries.");
-                return -ENOENT;
-        }
+        if (strv_isempty(list))
+                return log_error_errno(SYNTHETIC_ERRNO(ENOENT),
+                                       "Couldn't find any entries.");
 
         strv_sort(list);
         strv_uniq(list);
 
-        (void) pager_open(arg_no_pager, false);
+        (void) pager_open(arg_pager_flags);
 
         strv_print(list);
         return 0;
 }
 
 static int help(void) {
-        printf("%s [OPTIONS...] COMMAND ...\n\n"
-               "Query or change system locale and keyboard settings.\n\n"
+        _cleanup_free_ char *link = NULL;
+        int r;
+
+        r = terminal_urlify_man("localectl", "1", &link);
+        if (r < 0)
+                return log_oom();
+
+        printf("%s%s [OPTIONS...] COMMAND ...\n\n"
+               "Query or change system locale and keyboard settings.%s\n\n"
                "  -h --help                Show this help\n"
                "     --version             Show package version\n"
                "     --no-pager            Do not pipe output into a pager\n"
@@ -397,7 +406,12 @@ static int help(void) {
                "  list-x11-keymap-variants [LAYOUT]\n"
                "                           Show known X11 keyboard mapping variants\n"
                "  list-x11-keymap-options  Show known X11 keyboard mapping options\n"
-               , program_invocation_short_name);
+               "\nSee the %s for details.\n"
+               , ansi_highlight()
+               , program_invocation_short_name
+               , ansi_normal()
+               , link
+        );
 
         return 0;
 }
@@ -446,7 +460,7 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_NO_PAGER:
-                        arg_no_pager = true;
+                        arg_pager_flags |= PAGER_DISABLE;
                         break;
 
                 case ARG_NO_ASK_PASSWORD:
@@ -493,31 +507,24 @@ static int localectl_main(sd_bus *bus, int argc, char *argv[]) {
         return dispatch_verb(argc, argv, verbs, bus);
 }
 
-int main(int argc, char*argv[]) {
-        sd_bus *bus = NULL;
+static int run(int argc, char *argv[]) {
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
         int r;
 
         setlocale(LC_ALL, "");
+        log_show_color(true);
         log_parse_environment();
         log_open();
 
         r = parse_argv(argc, argv);
         if (r <= 0)
-                goto finish;
+                return r;
 
         r = bus_connect_transport(arg_transport, arg_host, false, &bus);
-        if (r < 0) {
-                log_error_errno(r, "Failed to create bus connection: %m");
-                goto finish;
-        }
-
-        r = localectl_main(bus, argc, argv);
-
-finish:
-        /* make sure we terminate the bus connection first, and then close the
-         * pager, see issue #3543 for the details. */
-        sd_bus_flush_close_unref(bus);
-        pager_close();
+        if (r < 0)
+                return log_error_errno(r, "Failed to create bus connection: %m");
 
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        return localectl_main(bus, argc, argv);
 }
+
+DEFINE_MAIN_FUNCTION(run);