mirror of
https://github.com/systemd/systemd.git
synced 2024-12-26 03:22:00 +03:00
localectl: use dispatch_verb()
This commit is contained in:
parent
f46bc484f7
commit
1d4ecb98be
@ -39,6 +39,7 @@
|
||||
#include "spawn-polkit-agent.h"
|
||||
#include "strv.h"
|
||||
#include "util.h"
|
||||
#include "verbs.h"
|
||||
#include "virt.h"
|
||||
|
||||
static bool arg_no_pager = false;
|
||||
@ -142,7 +143,7 @@ static void print_status_info(StatusInfo *i) {
|
||||
printf(" X11 Options: %s\n", i->x11_options);
|
||||
}
|
||||
|
||||
static int show_status(sd_bus *bus, char **args, unsigned n) {
|
||||
static int show_status(int argc, char **argv, void *userdata) {
|
||||
_cleanup_(status_info_clear) StatusInfo info = {};
|
||||
static const struct bus_properties_map map[] = {
|
||||
{ "VConsoleKeymap", "s", NULL, offsetof(StatusInfo, vconsole_keymap) },
|
||||
@ -157,6 +158,7 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
|
||||
};
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
sd_bus *bus = userdata;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
@ -176,13 +178,13 @@ static int show_status(sd_bus *bus, char **args, unsigned n) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int set_locale(sd_bus *bus, char **args, unsigned n) {
|
||||
static int set_locale(int argc, char **argv, void *userdata) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
sd_bus *bus = userdata;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(args);
|
||||
|
||||
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
||||
|
||||
@ -196,7 +198,7 @@ static int set_locale(sd_bus *bus, char **args, unsigned n) {
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append_strv(m, args + 1);
|
||||
r = sd_bus_message_append_strv(m, argv + 1);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
@ -213,12 +215,10 @@ static int set_locale(sd_bus *bus, char **args, unsigned n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int list_locales(sd_bus *bus, char **args, unsigned n) {
|
||||
static int list_locales(int argc, char **argv, void *userdata) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
int r;
|
||||
|
||||
assert(args);
|
||||
|
||||
r = get_locales(&l);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read list of locales: %m");
|
||||
@ -229,23 +229,18 @@ static int list_locales(sd_bus *bus, char **args, unsigned n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
|
||||
static int set_vconsole_keymap(int argc, char **argv, void *userdata) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
const char *map, *toggle_map;
|
||||
sd_bus *bus = userdata;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(args);
|
||||
|
||||
if (n > 3) {
|
||||
log_error("Too many arguments.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
||||
|
||||
map = args[1];
|
||||
toggle_map = n > 2 ? args[2] : "";
|
||||
map = argv[1];
|
||||
toggle_map = argc > 2 ? argv[2] : "";
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
@ -262,12 +257,10 @@ static int set_vconsole_keymap(sd_bus *bus, char **args, unsigned n) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
|
||||
static int list_vconsole_keymaps(int argc, char **argv, void *userdata) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
int r;
|
||||
|
||||
assert(args);
|
||||
|
||||
r = get_keymaps(&l);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read list of keymaps: %m");
|
||||
@ -279,25 +272,18 @@ static int list_vconsole_keymaps(sd_bus *bus, char **args, unsigned n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
|
||||
static int set_x11_keymap(int argc, char **argv, void *userdata) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
const char *layout, *model, *variant, *options;
|
||||
sd_bus *bus = userdata;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(args);
|
||||
|
||||
if (n > 5) {
|
||||
log_error("Too many arguments.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
|
||||
|
||||
layout = args[1];
|
||||
model = n > 2 ? args[2] : "";
|
||||
variant = n > 3 ? args[3] : "";
|
||||
options = n > 4 ? args[4] : "";
|
||||
layout = argv[1];
|
||||
model = argc > 2 ? argv[2] : "";
|
||||
variant = argc > 3 ? argv[3] : "";
|
||||
options = argc > 4 ? argv[4] : "";
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
@ -315,7 +301,7 @@ static int set_x11_keymap(sd_bus *bus, char **args, unsigned n) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
|
||||
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];
|
||||
@ -328,22 +314,17 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
|
||||
} state = NONE, look_for;
|
||||
int r;
|
||||
|
||||
if (n > 2) {
|
||||
log_error("Too many arguments.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
f = fopen("/usr/share/X11/xkb/rules/base.lst", "re");
|
||||
if (!f)
|
||||
return log_error_errno(errno, "Failed to open keyboard mapping list. %m");
|
||||
|
||||
if (streq(args[0], "list-x11-keymap-models"))
|
||||
if (streq(argv[0], "list-x11-keymap-models"))
|
||||
look_for = MODELS;
|
||||
else if (streq(args[0], "list-x11-keymap-layouts"))
|
||||
else if (streq(argv[0], "list-x11-keymap-layouts"))
|
||||
look_for = LAYOUTS;
|
||||
else if (streq(args[0], "list-x11-keymap-variants"))
|
||||
else if (streq(argv[0], "list-x11-keymap-variants"))
|
||||
look_for = VARIANTS;
|
||||
else if (streq(args[0], "list-x11-keymap-options"))
|
||||
else if (streq(argv[0], "list-x11-keymap-options"))
|
||||
look_for = OPTIONS;
|
||||
else
|
||||
assert_not_reached("Wrong parameter");
|
||||
@ -376,7 +357,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
|
||||
|
||||
w = l + strcspn(l, WHITESPACE);
|
||||
|
||||
if (n > 1) {
|
||||
if (argc > 1) {
|
||||
char *e;
|
||||
|
||||
if (*w == 0)
|
||||
@ -392,7 +373,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
|
||||
|
||||
*e = 0;
|
||||
|
||||
if (!streq(w, args[1]))
|
||||
if (!streq(w, argv[1]))
|
||||
continue;
|
||||
} else
|
||||
*w = 0;
|
||||
@ -416,7 +397,7 @@ static int list_x11_keymaps(sd_bus *bus, char **args, unsigned n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void help(void) {
|
||||
static int help(void) {
|
||||
printf("%s [OPTIONS...] COMMAND ...\n\n"
|
||||
"Query or change system locale and keyboard settings.\n\n"
|
||||
" -h --help Show this help\n"
|
||||
@ -440,6 +421,12 @@ static void help(void) {
|
||||
" Show known X11 keyboard mapping variants\n"
|
||||
" list-x11-keymap-options Show known X11 keyboard mapping options\n"
|
||||
, program_invocation_short_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verb_help(int argc, char **argv, void *userdata) {
|
||||
return help();
|
||||
}
|
||||
|
||||
static int parse_argv(int argc, char *argv[]) {
|
||||
@ -472,8 +459,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
switch (c) {
|
||||
|
||||
case 'h':
|
||||
help();
|
||||
return 0;
|
||||
return help();
|
||||
|
||||
case ARG_VERSION:
|
||||
return version();
|
||||
@ -512,86 +498,22 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
static int localectl_main(sd_bus *bus, int argc, char *argv[]) {
|
||||
|
||||
static const struct {
|
||||
const char* verb;
|
||||
const enum {
|
||||
MORE,
|
||||
LESS,
|
||||
EQUAL
|
||||
} argc_cmp;
|
||||
const int argc;
|
||||
int (* const dispatch)(sd_bus *bus, char **args, unsigned n);
|
||||
} verbs[] = {
|
||||
{ "status", LESS, 1, show_status },
|
||||
{ "set-locale", MORE, 2, set_locale },
|
||||
{ "list-locales", EQUAL, 1, list_locales },
|
||||
{ "set-keymap", MORE, 2, set_vconsole_keymap },
|
||||
{ "list-keymaps", EQUAL, 1, list_vconsole_keymaps },
|
||||
{ "set-x11-keymap", MORE, 2, set_x11_keymap },
|
||||
{ "list-x11-keymap-models", EQUAL, 1, list_x11_keymaps },
|
||||
{ "list-x11-keymap-layouts", EQUAL, 1, list_x11_keymaps },
|
||||
{ "list-x11-keymap-variants", LESS, 2, list_x11_keymaps },
|
||||
{ "list-x11-keymap-options", EQUAL, 1, list_x11_keymaps },
|
||||
static const Verb verbs[] = {
|
||||
{ "status", VERB_ANY, 1, VERB_DEFAULT, show_status },
|
||||
{ "set-locale", 2, VERB_ANY, 0, set_locale },
|
||||
{ "list-locales", VERB_ANY, 1, 0, list_locales },
|
||||
{ "set-keymap", 2, 3, 0, set_vconsole_keymap },
|
||||
{ "list-keymaps", VERB_ANY, 1, 0, list_vconsole_keymaps },
|
||||
{ "set-x11-keymap", 2, 5, 0, set_x11_keymap },
|
||||
{ "list-x11-keymap-models", VERB_ANY, 1, 0, list_x11_keymaps },
|
||||
{ "list-x11-keymap-layouts", VERB_ANY, 1, 0, list_x11_keymaps },
|
||||
{ "list-x11-keymap-variants", VERB_ANY, 2, 0, list_x11_keymaps },
|
||||
{ "list-x11-keymap-options", VERB_ANY, 1, 0, list_x11_keymaps },
|
||||
{ "help", VERB_ANY, VERB_ANY, 0, verb_help }, /* Not documented, but supported since it is created. */
|
||||
{}
|
||||
};
|
||||
|
||||
int left;
|
||||
unsigned i;
|
||||
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
left = argc - optind;
|
||||
|
||||
if (left <= 0)
|
||||
/* Special rule: no arguments means "status" */
|
||||
i = 0;
|
||||
else {
|
||||
if (streq(argv[optind], "help")) {
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(verbs); i++)
|
||||
if (streq(argv[optind], verbs[i].verb))
|
||||
break;
|
||||
|
||||
if (i >= ELEMENTSOF(verbs)) {
|
||||
log_error("Unknown operation %s", argv[optind]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
switch (verbs[i].argc_cmp) {
|
||||
|
||||
case EQUAL:
|
||||
if (left != verbs[i].argc) {
|
||||
log_error("Invalid number of arguments.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MORE:
|
||||
if (left < verbs[i].argc) {
|
||||
log_error("Too few arguments.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LESS:
|
||||
if (left > verbs[i].argc) {
|
||||
log_error("Too many arguments.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Unknown comparison operator.");
|
||||
}
|
||||
|
||||
return verbs[i].dispatch(bus, argv + optind, left);
|
||||
return dispatch_verb(argc, argv, verbs, bus);
|
||||
}
|
||||
|
||||
int main(int argc, char*argv[]) {
|
||||
|
Loading…
Reference in New Issue
Block a user