1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-08 11:27:32 +03:00

systemctl: port verb dispatching to generic verbs.[ch] code

Let's parse the command line the same way in our various tools.
This commit is contained in:
Lennart Poettering 2015-09-29 15:00:07 +02:00
parent 7089051f67
commit e449de8777

View File

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