From e449de87776877dc59d6662fda08621d15a19eff Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Sep 2015 15:00:07 +0200 Subject: systemctl: port verb dispatching to generic verbs.[ch] code Let's parse the command line the same way in our various tools. --- src/systemctl/systemctl.c | 460 ++++++++++++++++++++-------------------------- 1 file changed, 203 insertions(+), 257 deletions(-) (limited to 'src') diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 83a29e6abc..14ef29f76e 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -73,6 +73,7 @@ #include "unit-name.h" #include "util.h" #include "utmp-wtmp.h" +#include "verbs.h" static char **arg_types = NULL; static char **arg_states = NULL; @@ -140,7 +141,7 @@ static bool arg_plain = false; static bool arg_firmware_setup = false; static bool arg_now = false; -static int daemon_reload(char **args); +static int daemon_reload(int argc, char *argv[], void* userdata); static int halt_now(enum action a); static int check_one_unit(sd_bus *bus, const char *name, const char *good_states, bool quiet); @@ -657,7 +658,7 @@ static int get_unit_list_recursive( return c; } -static int list_units(char **args) { +static int list_units(int argc, char *argv[], void *userdata) { _cleanup_free_ UnitInfo *unit_infos = NULL; _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; @@ -670,7 +671,7 @@ static int list_units(char **args) { if (r < 0) return r; - r = get_unit_list_recursive(bus, strv_skip(args, 1), &unit_infos, &replies, &machines); + r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (r < 0) return r; @@ -864,7 +865,7 @@ static int output_sockets_list(struct socket_info *socket_infos, unsigned cs) { return 0; } -static int list_sockets(char **args) { +static int list_sockets(int argc, char *argv[], void *userdata) { _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; _cleanup_free_ UnitInfo *unit_infos = NULL; @@ -882,7 +883,7 @@ static int list_sockets(char **args) { if (r < 0) return r; - n = get_unit_list_recursive(bus, strv_skip(args, 1), &unit_infos, &replies, &machines); + n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (n < 0) return n; @@ -1170,7 +1171,7 @@ static usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next) { return next_elapse; } -static int list_timers(char **args) { +static int list_timers(int argc, char *argv[], void *userdata) { _cleanup_(message_set_freep) Set *replies = NULL; _cleanup_strv_free_ char **machines = NULL; _cleanup_free_ struct timer_info *timer_infos = NULL; @@ -1189,7 +1190,7 @@ static int list_timers(char **args) { if (r < 0) return r; - n = get_unit_list_recursive(bus, strv_skip(args, 1), &unit_infos, &replies, &machines); + n = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); if (n < 0) return n; @@ -1341,7 +1342,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) { printf("\n%u unit files listed.\n", c); } -static int list_unit_files(char **args) { +static int list_unit_files(int argc, char *argv[], void *userdata) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_free_ UnitFileList *units = NULL; UnitFileList *unit; @@ -1378,7 +1379,7 @@ static int list_unit_files(char **args) { } HASHMAP_FOREACH(u, h, i) { - if (!output_show_unit_file(u, strv_skip(args, 1))) + if (!output_show_unit_file(u, strv_skip(argv, 1))) continue; units[c++] = *u; @@ -1421,7 +1422,7 @@ static int list_unit_files(char **args) { unit_file_state_from_string(state) }; - if (output_show_unit_file(&units[c], strv_skip(args, 1))) + if (output_show_unit_file(&units[c], strv_skip(argv, 1))) c ++; } @@ -1653,15 +1654,15 @@ static int list_dependencies_one( return 0; } -static int list_dependencies(char **args) { +static int list_dependencies(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **units = NULL; _cleanup_free_ char *unit = NULL; const char *u; sd_bus *bus; int r; - if (args[1]) { - r = unit_name_mangle(args[1], UNIT_NAME_NOGLOB, &unit); + if (argv[1]) { + r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &unit); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); @@ -1890,7 +1891,7 @@ static void output_machines_list(struct machine_info *machine_infos, unsigned n) printf("\n%u machines listed.\n", n); } -static int list_machines(char **args) { +static int list_machines(int argc, char *argv[], void *userdata) { struct machine_info *machine_infos = NULL; sd_bus *bus; int r; @@ -1906,7 +1907,7 @@ static int list_machines(char **args) { if (r < 0) return r; - r = get_machine_list(bus, &machine_infos, strv_skip(args, 1)); + r = get_machine_list(bus, &machine_infos, strv_skip(argv, 1)); if (r < 0) return r; @@ -1917,7 +1918,7 @@ static int list_machines(char **args) { return 0; } -static int get_default(char **args) { +static int get_default(int argc, char *argv[], void *userdata) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_free_ char *_path = NULL; const char *path; @@ -1973,11 +1974,14 @@ static void dump_unit_file_changes(const UnitFileChange *changes, unsigned n_cha } } -static int set_default(char **args) { +static int set_default(int argc, char *argv[], void *userdata) { _cleanup_free_ char *unit = NULL; int r; - r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".target", &unit); + assert(argc >= 2); + assert(argv); + + r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &unit); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); @@ -2023,7 +2027,7 @@ static int set_default(char **args) { /* Try to reload if enabled */ if (!arg_no_reload) - r = daemon_reload(args); + r = daemon_reload(argc, argv, userdata); else r = 0; } @@ -2112,7 +2116,7 @@ static bool output_show_job(struct job_info *job, char **patterns) { return strv_fnmatch_or_empty(patterns, job->name, FNM_NOESCAPE); } -static int list_jobs(char **args) { +static int list_jobs(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; const char *name, *type, *state, *job_path, *unit_path; @@ -2149,7 +2153,7 @@ static int list_jobs(char **args) { while ((r = sd_bus_message_read(reply, "(usssoo)", &id, &name, &type, &state, &job_path, &unit_path)) > 0) { struct job_info job = { id, name, type, state }; - if (!output_show_job(&job, strv_skip(args, 1))) { + if (!output_show_job(&job, strv_skip(argv, 1))) { skipped = true; continue; } @@ -2170,13 +2174,13 @@ static int list_jobs(char **args) { return r; } -static int cancel_job(char **args) { +static int cancel_job(int argc, char *argv[], void *userdata) { sd_bus *bus; char **name; int r = 0; - if (strv_length(args) <= 1) - return daemon_reload(args); + if (argc <= 1) + return daemon_reload(argc, argv, userdata); polkit_agent_open_if_enabled(); @@ -2184,7 +2188,7 @@ static int cancel_job(char **args) { if (r < 0) return r; - STRV_FOREACH(name, args+1) { + STRV_FOREACH(name, strv_skip(argv, 1)) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; uint32_t id; int q; @@ -2715,7 +2719,7 @@ static enum action verb_to_action(const char *verb) { return _ACTION_INVALID; } -static int start_unit(char **args) { +static int start_unit(int argc, char *argv[], void *userdata) { _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL; const char *method, *mode, *one_name, *suffix = NULL; _cleanup_strv_free_ char **names = NULL; @@ -2732,10 +2736,11 @@ static int start_unit(char **args) { if (arg_action == ACTION_SYSTEMCTL) { enum action action; - method = verb_to_method(args[0]); - action = verb_to_action(args[0]); - if (streq(args[0], "isolate")) { + method = verb_to_method(argv[0]); + action = verb_to_action(argv[0]); + + if (streq(argv[0], "isolate")) { mode = "isolate"; suffix = ".target"; } else @@ -2755,7 +2760,7 @@ static int start_unit(char **args) { if (one_name) names = strv_new(one_name, NULL); else { - r = expand_names(bus, strv_skip(args, 1), suffix, &names); + r = expand_names(bus, strv_skip(argv, 1), suffix, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); } @@ -3078,13 +3083,13 @@ static int set_exit_code(uint8_t code) { return 0; } -static int start_special(char **args) { +static int start_special(int argc, char *argv[], void *userdata) { enum action a; int r; - assert(args); + assert(argv); - a = verb_to_action(args[0]); + a = verb_to_action(argv[0]); r = logind_check_inhibitors(a); if (r < 0) @@ -3099,19 +3104,19 @@ static int start_special(char **args) { if (r < 0) return r; - if (a == ACTION_REBOOT && strv_length(args) > 1) { - r = update_reboot_param_file(args[1]); + if (a == ACTION_REBOOT && argc > 1) { + r = update_reboot_param_file(argv[1]); if (r < 0) return r; - } else if (a == ACTION_EXIT && strv_length(args) > 1) { + } else if (a == ACTION_EXIT && argc > 1) { uint8_t code = 0; /* If the exit code is not given on the command line, * don't reset it to zero: just keep it as it might * have been set previously. */ - r = safe_atou8(args[1], &code); + r = safe_atou8(argv[1], &code); if (r < 0) return log_error_errno(r, "Invalid exit code."); @@ -3134,7 +3139,7 @@ static int start_special(char **args) { ACTION_REBOOT, ACTION_KEXEC, ACTION_EXIT)) - return daemon_reload(args); + return daemon_reload(argc, argv, userdata); /* First try logind, to allow authentication with polkit */ if (IN_SET(a, @@ -3153,7 +3158,7 @@ static int start_special(char **args) { /* On all other errors, try low-level operation */ } - return start_unit(args); + return start_unit(argc, argv, userdata); } static int check_unit_generic(int code, const char *good_states, char **args) { @@ -3183,16 +3188,16 @@ static int check_unit_generic(int code, const char *good_states, char **args) { return r; } -static int check_unit_active(char **args) { +static int check_unit_active(int argc, char *argv[], void *userdata) { /* According to LSB: 3, "program is not running" */ - return check_unit_generic(3, "active\0reloading\0", strv_skip(args, 1)); + return check_unit_generic(3, "active\0reloading\0", strv_skip(argv, 1)); } -static int check_unit_failed(char **args) { - return check_unit_generic(1, "failed\0", strv_skip(args, 1)); +static int check_unit_failed(int argc, char *argv[], void *userdata) { + return check_unit_generic(1, "failed\0", strv_skip(argv, 1)); } -static int kill_unit(char **args) { +static int kill_unit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; char *kill_who = NULL, **name; sd_bus *bus; @@ -3211,7 +3216,7 @@ static int kill_unit(char **args) { if (streq(arg_job_mode, "fail")) kill_who = strjoina(arg_kill_who, "-fail", NULL); - r = expand_names(bus, strv_skip(args, 1), NULL, &names); + r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); @@ -4612,16 +4617,22 @@ static int show_system_status(sd_bus *bus) { return 0; } -static int show(char **args) { - bool show_properties, show_status, new_line = false; +static int show(int argc, char *argv[], void *userdata) { + bool show_properties, show_status, show_help, new_line = false; bool ellipsized = false; int r, ret = 0; sd_bus *bus; - assert(args); + assert(argv); - show_properties = streq(args[0], "show"); - show_status = streq(args[0], "status"); + show_properties = streq(argv[0], "show"); + show_status = streq(argv[0], "status"); + show_help = streq(argv[0], "help"); + + if (show_help && argc <= 1) { + log_error("This command expects one or more unit names. Did you mean --help?"); + return -EINVAL; + } if (show_properties) pager_open_if_enabled(); @@ -4637,22 +4648,22 @@ static int show(char **args) { return r; /* If no argument is specified inspect the manager itself */ - if (show_properties && strv_length(args) <= 1) - return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized); + if (show_properties && argc <= 1) + return show_one(argv[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized); - if (show_status && strv_length(args) <= 1) { + if (show_status && argc <= 1) { pager_open_if_enabled(); show_system_status(bus); new_line = true; if (arg_all) - ret = show_all(args[0], bus, false, &new_line, &ellipsized); + ret = show_all(argv[0], bus, false, &new_line, &ellipsized); } else { _cleanup_free_ char **patterns = NULL; char **name; - STRV_FOREACH(name, strv_skip(args, 1)) { + STRV_FOREACH(name, strv_skip(argv, 1)) { _cleanup_free_ char *unit = NULL; uint32_t id; @@ -4675,8 +4686,7 @@ static int show(char **args) { } } - r = show_one(args[0], bus, unit, show_properties, - &new_line, &ellipsized); + r = show_one(argv[0], bus, unit, show_properties, &new_line, &ellipsized); if (r < 0) return r; else if (r > 0 && ret == 0) @@ -4697,8 +4707,7 @@ static int show(char **args) { if (!unit) return log_oom(); - r = show_one(args[0], bus, unit, show_properties, - &new_line, &ellipsized); + r = show_one(argv[0], bus, unit, show_properties, &new_line, &ellipsized); if (r < 0) return r; else if (r > 0 && ret == 0) @@ -4758,7 +4767,7 @@ static int cat_file(const char *filename, bool newline) { return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, false); } -static int cat(char **args) { +static int cat(int argc, char *argv[], void *userdata) { _cleanup_free_ char *user_home = NULL; _cleanup_free_ char *user_runtime = NULL; _cleanup_lookup_paths_free_ LookupPaths lp = {}; @@ -4781,7 +4790,7 @@ static int cat(char **args) { if (r < 0) return r; - r = expand_names(bus, strv_skip(args, 1), NULL, &names); + r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); @@ -4819,7 +4828,7 @@ static int cat(char **args) { return 0; } -static int set_property(char **args) { +static int set_property(int argc, char *argv[], void *userdata) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *n = NULL; @@ -4843,7 +4852,7 @@ static int set_property(char **args) { if (r < 0) return bus_log_create_error(r); - r = unit_name_mangle(args[1], UNIT_NAME_NOGLOB, &n); + r = unit_name_mangle(argv[1], UNIT_NAME_NOGLOB, &n); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); @@ -4855,7 +4864,7 @@ static int set_property(char **args) { if (r < 0) return bus_log_create_error(r); - STRV_FOREACH(i, args + 2) { + STRV_FOREACH(i, strv_skip(argv, 2)) { r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); if (r < 0) return bus_log_create_error(r); @@ -4880,7 +4889,7 @@ static int set_property(char **args) { return 0; } -static int snapshot(char **args) { +static int snapshot(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_free_ char *n = NULL, *id = NULL; @@ -4890,8 +4899,8 @@ static int snapshot(char **args) { polkit_agent_open_if_enabled(); - if (strv_length(args) > 1) { - r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".snapshot", &n); + if (argc > 1) { + r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".snapshot", &n); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); } else { @@ -4937,7 +4946,7 @@ static int snapshot(char **args) { return 0; } -static int delete_snapshot(char **args) { +static int delete_snapshot(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; sd_bus *bus; char **name; @@ -4949,7 +4958,7 @@ static int delete_snapshot(char **args) { if (r < 0) return r; - r = expand_names(bus, strv_skip(args, 1), ".snapshot", &names); + r = expand_names(bus, strv_skip(argv, 1), ".snapshot", &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); @@ -4976,7 +4985,7 @@ static int delete_snapshot(char **args) { return r; } -static int daemon_reload(char **args) { +static int daemon_reload(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; const char *method; sd_bus *bus; @@ -4996,15 +5005,15 @@ static int daemon_reload(char **args) { assert(arg_action == ACTION_SYSTEMCTL); method = - streq(args[0], "clear-jobs") || - streq(args[0], "cancel") ? "ClearJobs" : - streq(args[0], "daemon-reexec") ? "Reexecute" : - streq(args[0], "reset-failed") ? "ResetFailed" : - streq(args[0], "halt") ? "Halt" : - streq(args[0], "poweroff") ? "PowerOff" : - streq(args[0], "reboot") ? "Reboot" : - streq(args[0], "kexec") ? "KExec" : - streq(args[0], "exit") ? "Exit" : + streq(argv[0], "clear-jobs") || + streq(argv[0], "cancel") ? "ClearJobs" : + streq(argv[0], "daemon-reexec") ? "Reexecute" : + streq(argv[0], "reset-failed") ? "ResetFailed" : + streq(argv[0], "halt") ? "Halt" : + streq(argv[0], "poweroff") ? "PowerOff" : + streq(argv[0], "reboot") ? "Reboot" : + streq(argv[0], "kexec") ? "KExec" : + streq(argv[0], "exit") ? "Exit" : /* "daemon-reload" */ "Reload"; } @@ -5031,14 +5040,14 @@ static int daemon_reload(char **args) { return r < 0 ? r : 0; } -static int reset_failed(char **args) { +static int reset_failed(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; sd_bus *bus; char **name; int r, q; - if (strv_length(args) <= 1) - return daemon_reload(args); + if (argc <= 1) + return daemon_reload(argc, argv, userdata); polkit_agent_open_if_enabled(); @@ -5046,7 +5055,7 @@ static int reset_failed(char **args) { if (r < 0) return r; - r = expand_names(bus, strv_skip(args, 1), NULL, &names); + r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); @@ -5072,7 +5081,7 @@ static int reset_failed(char **args) { return r; } -static int show_environment(char **args) { +static int show_environment(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; const char *text; @@ -5113,12 +5122,11 @@ static int show_environment(char **args) { return 0; } -static int switch_root(char **args) { +static int switch_root(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *cmdline_init = NULL; const char *root, *init; sd_bus *bus; - unsigned l; int r; if (arg_transport != BUS_TRANSPORT_LOCAL) { @@ -5126,16 +5134,15 @@ static int switch_root(char **args) { return -EINVAL; } - l = strv_length(args); - if (l < 2 || l > 3) { + if (argc < 2 || argc > 3) { log_error("Wrong number of arguments."); return -EINVAL; } - root = args[1]; + root = argv[1]; - if (l >= 3) - init = args[2]; + if (argc >= 3) + init = argv[2]; else { r = parse_env_file("/proc/cmdline", WHITESPACE, "init", &cmdline_init, @@ -5182,14 +5189,15 @@ static int switch_root(char **args) { return 0; } -static int set_environment(char **args) { +static int set_environment(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; const char *method; sd_bus *bus; int r; - assert(args); + assert(argc > 1); + assert(argv); polkit_agent_open_if_enabled(); @@ -5197,7 +5205,7 @@ static int set_environment(char **args) { if (r < 0) return r; - method = streq(args[0], "set-environment") + method = streq(argv[0], "set-environment") ? "SetEnvironment" : "UnsetEnvironment"; @@ -5211,7 +5219,7 @@ static int set_environment(char **args) { if (r < 0) return bus_log_create_error(r); - r = sd_bus_message_append_strv(m, strv_skip(args, 1)); + r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); if (r < 0) return bus_log_create_error(r); @@ -5222,7 +5230,7 @@ static int set_environment(char **args) { return 0; } -static int import_environment(char **args) { +static int import_environment(int argc, char *argv[], void *userdata) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *m = NULL; sd_bus *bus; @@ -5244,7 +5252,7 @@ static int import_environment(char **args) { if (r < 0) return bus_log_create_error(r); - if (strv_isempty(strv_skip(args, 1))) + if (argc < 2) r = sd_bus_message_append_strv(m, environ); else { char **a, **b; @@ -5253,7 +5261,7 @@ static int import_environment(char **args) { if (r < 0) return bus_log_create_error(r); - STRV_FOREACH(a, strv_skip(args, 1)) { + STRV_FOREACH(a, strv_skip(argv, 1)) { if (!env_name_is_valid(*a)) { log_error("Not a valid environment variable name: %s", *a); @@ -5461,18 +5469,18 @@ static int mangle_names(char **original_names, char ***mangled_names) { return 0; } -static int enable_unit(char **args) { +static int enable_unit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; - const char *verb = args[0]; + const char *verb = argv[0]; UnitFileChange *changes = NULL; unsigned n_changes = 0; int carries_install_info = -1; int r; - if (!args[1]) + if (!argv[1]) return 0; - r = mangle_names(args+1, &names); + r = mangle_names(strv_skip(argv, 1), &names); if (r < 0) return r; @@ -5603,7 +5611,7 @@ static int enable_unit(char **args) { /* Try to reload if enabled */ if (!arg_no_reload) - r = daemon_reload(args); + r = daemon_reload(argc, argv, userdata); else r = 0; } @@ -5619,7 +5627,7 @@ static int enable_unit(char **args) { "3) A unit may be started when needed via activation (socket, path, timer,\n" " D-Bus, udev, scripted systemctl call, ...).\n"); - if (arg_now && n_changes > 0 && STR_IN_SET(args[0], "enable", "disable", "mask")) { + if (arg_now && n_changes > 0 && STR_IN_SET(argv[0], "enable", "disable", "mask")) { char *new_args[n_changes + 2]; sd_bus *bus; unsigned i; @@ -5628,12 +5636,12 @@ static int enable_unit(char **args) { if (r < 0) return r; - new_args[0] = (char*) (streq(args[0], "enable") ? "start" : "stop"); + new_args[0] = (char*) (streq(argv[0], "enable") ? "start" : "stop"); for (i = 0; i < n_changes; i++) new_args[i + 1] = basename(changes[i].path); new_args[i + 1] = NULL; - r = start_unit(new_args); + r = start_unit(strv_length(new_args), new_args, userdata); } finish: @@ -5642,21 +5650,21 @@ finish: return r; } -static int add_dependency(char **args) { +static int add_dependency(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; _cleanup_free_ char *target = NULL; - const char *verb = args[0]; + const char *verb = argv[0]; UnitDependency dep; int r = 0; - if (!args[1]) + if (!argv[1]) return 0; - r = unit_name_mangle_with_suffix(args[1], UNIT_NAME_NOGLOB, ".target", &target); + r = unit_name_mangle_with_suffix(argv[1], UNIT_NAME_NOGLOB, ".target", &target); if (r < 0) return log_error_errno(r, "Failed to mangle unit name: %m"); - r = mangle_names(args+2, &names); + r = mangle_names(strv_skip(argv, 2), &names); if (r < 0) return r; @@ -5719,7 +5727,7 @@ static int add_dependency(char **args) { return r; if (!arg_no_reload) - r = daemon_reload(args); + r = daemon_reload(argc, argv, userdata); else r = 0; } @@ -5727,7 +5735,7 @@ static int add_dependency(char **args) { return r; } -static int preset_all(char **args) { +static int preset_all(int argc, char *argv[], void *userdata) { UnitFileChange *changes = NULL; unsigned n_changes = 0; int r; @@ -5776,7 +5784,7 @@ static int preset_all(char **args) { return r; if (!arg_no_reload) - r = daemon_reload(args); + r = daemon_reload(argc, argv, userdata); else r = 0; } @@ -5787,18 +5795,18 @@ finish: return r; } -static int unit_is_enabled(char **args) { +static int unit_is_enabled(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; bool enabled; char **name; int r; - r = mangle_names(args+1, &names); + r = mangle_names(strv_skip(argv, 1), &names); if (r < 0) return r; - r = enable_sysv_units(args[0], names); + r = enable_sysv_units(argv[0], names); if (r < 0) return r; @@ -5863,7 +5871,7 @@ static int unit_is_enabled(char **args) { return !enabled; } -static int is_system_running(char **args) { +static int is_system_running(int argc, char *argv[], void *userdata) { _cleanup_free_ char *state = NULL; sd_bus *bus; int r; @@ -6189,7 +6197,7 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) { return 0; } -static int edit(char **args) { +static int edit(int argc, char *argv[], void *userdata) { _cleanup_strv_free_ char **names = NULL; _cleanup_strv_free_ char **paths = NULL; char **original, **tmp; @@ -6210,7 +6218,7 @@ static int edit(char **args) { if (r < 0) return r; - r = expand_names(bus, strv_skip(args, 1), NULL, &names); + r = expand_names(bus, strv_skip(argv, 1), NULL, &names); if (r < 0) return log_error_errno(r, "Failed to expand names: %m"); @@ -6241,7 +6249,7 @@ static int edit(char **args) { } if (!arg_no_reload && bus && !install_client_side()) - r = daemon_reload(args); + r = daemon_reload(argc, argv, userdata); end: STRV_FOREACH_PAIR(original, tmp, paths) @@ -7307,147 +7315,85 @@ static int talk_initctl(void) { #endif } -static int systemctl_main(int argc, char *argv[], int bus_error) { - - static const struct { - const char* verb; - const enum { - MORE, - LESS, - EQUAL - } argc_cmp; - const int argc; - int (* const dispatch)(char **args); - } verbs[] = { - { "list-units", MORE, 0, list_units }, - { "list-unit-files", MORE, 1, list_unit_files }, - { "list-sockets", MORE, 1, list_sockets }, - { "list-timers", MORE, 1, list_timers }, - { "list-jobs", MORE, 1, list_jobs }, - { "list-machines", MORE, 1, list_machines }, - { "clear-jobs", EQUAL, 1, daemon_reload }, - { "cancel", MORE, 2, cancel_job }, - { "start", MORE, 2, start_unit }, - { "stop", MORE, 2, start_unit }, - { "condstop", MORE, 2, start_unit }, /* For compatibility with ALTLinux */ - { "reload", MORE, 2, start_unit }, - { "restart", MORE, 2, start_unit }, - { "try-restart", MORE, 2, start_unit }, - { "reload-or-restart", MORE, 2, start_unit }, - { "reload-or-try-restart", MORE, 2, start_unit }, - { "force-reload", MORE, 2, start_unit }, /* For compatibility with SysV */ - { "condreload", MORE, 2, start_unit }, /* For compatibility with ALTLinux */ - { "condrestart", MORE, 2, start_unit }, /* For compatibility with RH */ - { "isolate", EQUAL, 2, start_unit }, - { "kill", MORE, 2, kill_unit }, - { "is-active", MORE, 2, check_unit_active }, - { "check", MORE, 2, check_unit_active }, - { "is-failed", MORE, 2, check_unit_failed }, - { "show", MORE, 1, show }, - { "cat", MORE, 2, cat, }, - { "status", MORE, 1, show }, - { "help", MORE, 2, show }, - { "snapshot", LESS, 2, snapshot }, - { "delete", MORE, 2, delete_snapshot }, - { "daemon-reload", EQUAL, 1, daemon_reload }, - { "daemon-reexec", EQUAL, 1, daemon_reload }, - { "show-environment", EQUAL, 1, show_environment }, - { "set-environment", MORE, 2, set_environment }, - { "unset-environment", MORE, 2, set_environment }, - { "import-environment", MORE, 1, import_environment}, - { "halt", EQUAL, 1, start_special, }, - { "poweroff", EQUAL, 1, start_special, }, - { "reboot", MORE, 1, start_special, }, - { "kexec", EQUAL, 1, start_special }, - { "suspend", EQUAL, 1, start_special }, - { "hibernate", EQUAL, 1, start_special }, - { "hybrid-sleep", EQUAL, 1, start_special }, - { "default", EQUAL, 1, start_special }, - { "rescue", EQUAL, 1, start_special }, - { "emergency", EQUAL, 1, start_special }, - { "exit", LESS, 2, start_special }, - { "reset-failed", MORE, 1, reset_failed }, - { "enable", MORE, 2, enable_unit, }, - { "disable", MORE, 2, enable_unit, }, - { "is-enabled", MORE, 2, unit_is_enabled, }, - { "reenable", MORE, 2, enable_unit, }, - { "preset", MORE, 2, enable_unit, }, - { "preset-all", EQUAL, 1, preset_all, }, - { "mask", MORE, 2, enable_unit, }, - { "unmask", MORE, 2, enable_unit, }, - { "link", MORE, 2, enable_unit, }, - { "switch-root", MORE, 2, switch_root }, - { "list-dependencies", LESS, 2, list_dependencies }, - { "set-default", EQUAL, 2, set_default, }, - { "get-default", EQUAL, 1, get_default, }, - { "set-property", MORE, 3, set_property }, - { "is-system-running", EQUAL, 1, is_system_running }, - { "add-wants", MORE, 3, add_dependency, }, - { "add-requires", MORE, 3, add_dependency, }, - { "edit", MORE, 2, edit, }, +static int systemctl_main(int argc, char *argv[]) { + + static const Verb verbs[] = { + { "list-units", VERB_ANY, 1, VERB_DEFAULT, list_units }, + { "list-unit-files", VERB_ANY, 1, 0, list_unit_files }, + { "list-sockets", VERB_ANY, 1, 0, list_sockets }, + { "list-timers", VERB_ANY, 1, 0, list_timers }, + { "list-jobs", VERB_ANY, 1, 0, list_jobs }, + { "list-machines", VERB_ANY, 1, 0, list_machines }, + { "clear-jobs", VERB_ANY, 1, 0, daemon_reload }, + { "cancel", 2, VERB_ANY, 0, cancel_job }, + { "start", 2, VERB_ANY, 0, start_unit }, + { "stop", 2, VERB_ANY, 0, start_unit }, + { "condstop", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */ + { "reload", 2, VERB_ANY, 0, start_unit }, + { "restart", 2, VERB_ANY, 0, start_unit }, + { "try-restart", 2, VERB_ANY, 0, start_unit }, + { "reload-or-restart", 2, VERB_ANY, 0, start_unit }, + { "reload-or-try-restart", 2, VERB_ANY, 0, start_unit }, + { "force-reload", 2, VERB_ANY, 0, start_unit }, /* For compatibility with SysV */ + { "condreload", 2, VERB_ANY, 0, start_unit }, /* For compatibility with ALTLinux */ + { "condrestart", 2, VERB_ANY, 0, start_unit }, /* For compatibility with RH */ + { "isolate", 2, 2, 0, start_unit }, + { "kill", 2, VERB_ANY, 0, kill_unit }, + { "is-active", 2, VERB_ANY, 0, check_unit_active }, + { "check", 2, VERB_ANY, 0, check_unit_active }, + { "is-failed", 2, VERB_ANY, 0, check_unit_failed }, + { "show", VERB_ANY, VERB_ANY, 0, show }, + { "cat", 2, VERB_ANY, 0, cat }, + { "status", VERB_ANY, VERB_ANY, 0, show }, + { "help", VERB_ANY, VERB_ANY, 0, show }, + { "snapshot", VERB_ANY, 2, 0, snapshot }, + { "delete", 2, VERB_ANY, 0, delete_snapshot }, + { "daemon-reload", VERB_ANY, 1, 0, daemon_reload }, + { "daemon-reexec", VERB_ANY, 1, 0, daemon_reload }, + { "show-environment", VERB_ANY, 1, 0, show_environment }, + { "set-environment", 2, VERB_ANY, 0, set_environment }, + { "unset-environment", 2, VERB_ANY, 0, set_environment }, + { "import-environment", VERB_ANY, VERB_ANY, 0, import_environment}, + { "halt", VERB_ANY, 1, 0, start_special }, + { "poweroff", VERB_ANY, 1, 0, start_special }, + { "reboot", VERB_ANY, 2, 0, start_special }, + { "kexec", VERB_ANY, 1, 0, start_special }, + { "suspend", VERB_ANY, 1, 0, start_special }, + { "hibernate", VERB_ANY, 1, 0, start_special }, + { "hybrid-sleep", VERB_ANY, 1, 0, start_special }, + { "default", VERB_ANY, 1, 0, start_special }, + { "rescue", VERB_ANY, 1, 0, start_special }, + { "emergency", VERB_ANY, 1, 0, start_special }, + { "exit", VERB_ANY, 2, 0, start_special }, + { "reset-failed", VERB_ANY, VERB_ANY, 0, reset_failed }, + { "enable", 2, VERB_ANY, 0, enable_unit }, + { "disable", 2, VERB_ANY, 0, enable_unit }, + { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled }, + { "reenable", 2, VERB_ANY, 0, enable_unit }, + { "preset", 2, VERB_ANY, 0, enable_unit }, + { "preset-all", VERB_ANY, 1, 0, preset_all }, + { "mask", 2, VERB_ANY, 0, enable_unit }, + { "unmask", 2, VERB_ANY, 0, enable_unit }, + { "link", 2, VERB_ANY, 0, enable_unit }, + { "switch-root", 2, VERB_ANY, 0, switch_root }, + { "list-dependencies", VERB_ANY, 2, 0, list_dependencies }, + { "set-default", 2, 2, 0, set_default }, + { "get-default", VERB_ANY, 1, 0, get_default, }, + { "set-property", 3, VERB_ANY, 0, set_property }, + { "is-system-running", VERB_ANY, 1, 0, is_system_running }, + { "add-wants", 3, VERB_ANY, 0, add_dependency }, + { "add-requires", 3, VERB_ANY, 0, add_dependency }, + { "edit", 2, VERB_ANY, 0, edit }, {} - }, *verb = verbs; - - int left; - - assert(argc >= 0); - assert(argv); - - left = argc - optind; - - /* Special rule: no arguments (left == 0) means "list-units" */ - if (left > 0) { - if (streq(argv[optind], "help") && !argv[optind+1]) { - log_error("This command expects one or more unit names. Did you mean --help?"); - return -EINVAL; - } - - for (; verb->verb; verb++) - if (streq(argv[optind], verb->verb)) - goto found; - - log_error("Unknown operation '%s'.", argv[optind]); - return -EINVAL; - } -found: - - switch (verb->argc_cmp) { - - case EQUAL: - if (left != verb->argc) { - log_error("Invalid number of arguments."); - return -EINVAL; - } - - break; - - case MORE: - if (left < verb->argc) { - log_error("Too few arguments."); - return -EINVAL; - } - - break; - - case LESS: - if (left > verb->argc) { - log_error("Too many arguments."); - return -EINVAL; - } - - break; - - default: - assert_not_reached("Unknown comparison operator."); - } + }; - return verb->dispatch(argv + optind); + return dispatch_verb(argc, argv, verbs, NULL); } static int reload_with_fallback(void) { /* First, try systemd via D-Bus. */ - if (daemon_reload(NULL) >= 0) + if (daemon_reload(0, NULL, NULL) >= 0) return 0; /* Nothing else worked, so let's try signals */ @@ -7462,7 +7408,7 @@ static int reload_with_fallback(void) { static int start_with_fallback(void) { /* First, try systemd via D-Bus. */ - if (start_unit(NULL) >= 0) + if (start_unit(0, NULL, NULL) >= 0) return 0; /* Nothing else worked, so let's try @@ -7705,7 +7651,7 @@ int main(int argc, char*argv[]) { switch (arg_action) { case ACTION_SYSTEMCTL: - r = systemctl_main(argc, argv, r); + r = systemctl_main(argc, argv); break; case ACTION_HALT: -- cgit v1.2.3-54-g00ecf