daf71ef61c
This is just some refactoring: shifting around of code, not change in codeflow. This splits up the way too huge systemctl.c in multiple more easily digestable files. It roughly follows the rule that each family of verbs gets its own .c/.h file pair, and so do all the compat executable names we support. Plus three extra files for sysv compat (which existed before already, but I renamed slightly, to get the systemctl- prefix lik everything else), a -util file with generic stuff everything uses, and a -logind file with everything that talks directly to logind instead of PID1. systemctl is still a bit too complex for my taste, but I think this way itc omes in a more digestable bits at least. No change of behaviour, just reshuffling of some code.
159 lines
5.2 KiB
C
159 lines
5.2 KiB
C
/* SPDX-License-Identifier: LGPL-2.1+ */
|
|
|
|
#include "bus-error.h"
|
|
#include "bus-locator.h"
|
|
#include "proc-cmdline.h"
|
|
#include "systemctl-daemon-reload.h"
|
|
#include "systemctl-set-default.h"
|
|
#include "systemctl-util.h"
|
|
#include "systemctl.h"
|
|
|
|
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
|
char **ret = data;
|
|
|
|
if (streq(key, "systemd.unit")) {
|
|
if (proc_cmdline_value_missing(key, value))
|
|
return 0;
|
|
if (!unit_name_is_valid(value, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
|
|
log_warning("Unit name specified on %s= is not valid, ignoring: %s", key, value);
|
|
return 0;
|
|
}
|
|
|
|
return free_and_strdup_warn(ret, key);
|
|
|
|
} else if (!value) {
|
|
if (runlevel_to_target(key))
|
|
return free_and_strdup_warn(ret, key);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void emit_cmdline_warning(void) {
|
|
if (arg_quiet || arg_root)
|
|
/* don't bother checking the commandline if we're operating on a container */
|
|
return;
|
|
|
|
_cleanup_free_ char *override = NULL;
|
|
int r;
|
|
|
|
r = proc_cmdline_parse(parse_proc_cmdline_item, &override, 0);
|
|
if (r < 0)
|
|
log_debug_errno(r, "Failed to parse kernel command line, ignoring: %m");
|
|
if (override)
|
|
log_notice("Note: found \"%s\" on the kernel commandline, which overrides the default unit.",
|
|
override);
|
|
}
|
|
|
|
static int determine_default(char **ret_name) {
|
|
int r;
|
|
|
|
if (install_client_side()) {
|
|
r = unit_file_get_default(arg_scope, arg_root, ret_name);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to get default target: %m");
|
|
return 0;
|
|
|
|
} else {
|
|
sd_bus *bus;
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
const char *name;
|
|
|
|
r = acquire_bus(BUS_MANAGER, &bus);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
r = bus_call_method(bus, bus_systemd_mgr, "GetDefaultTarget", &error, &reply, NULL);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to get default target: %s", bus_error_message(&error, r));
|
|
|
|
r = sd_bus_message_read(reply, "s", &name);
|
|
if (r < 0)
|
|
return bus_log_parse_error(r);
|
|
|
|
return free_and_strdup_warn(ret_name, name);
|
|
}
|
|
}
|
|
|
|
int get_default(int argc, char *argv[], void *userdata) {
|
|
_cleanup_free_ char *name = NULL;
|
|
int r;
|
|
|
|
r = determine_default(&name);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
printf("%s\n", name);
|
|
|
|
emit_cmdline_warning();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int set_default(int argc, char *argv[], void *userdata) {
|
|
_cleanup_free_ char *unit = NULL;
|
|
UnitFileChange *changes = NULL;
|
|
size_t n_changes = 0;
|
|
int r;
|
|
|
|
assert(argc >= 2);
|
|
assert(argv);
|
|
|
|
r = unit_name_mangle_with_suffix(argv[1], "set-default",
|
|
arg_quiet ? 0 : UNIT_NAME_MANGLE_WARN,
|
|
".target", &unit);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to mangle unit name: %m");
|
|
|
|
if (install_client_side()) {
|
|
r = unit_file_set_default(arg_scope, UNIT_FILE_FORCE, arg_root, unit, &changes, &n_changes);
|
|
unit_file_dump_changes(r, "set default", changes, n_changes, arg_quiet);
|
|
|
|
if (r > 0)
|
|
r = 0;
|
|
} else {
|
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
|
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
sd_bus *bus;
|
|
|
|
polkit_agent_open_maybe();
|
|
|
|
r = acquire_bus(BUS_MANAGER, &bus);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
r = bus_call_method(bus, bus_systemd_mgr, "SetDefaultTarget", &error, &reply, "sb", unit, 1);
|
|
if (r < 0)
|
|
return log_error_errno(r, "Failed to set default target: %s", bus_error_message(&error, r));
|
|
|
|
r = bus_deserialize_and_dump_unit_file_changes(reply, arg_quiet, &changes, &n_changes);
|
|
if (r < 0)
|
|
goto finish;
|
|
|
|
/* Try to reload if enabled */
|
|
if (!arg_no_reload)
|
|
r = daemon_reload(argc, argv, userdata);
|
|
else
|
|
r = 0;
|
|
}
|
|
|
|
emit_cmdline_warning();
|
|
|
|
if (!arg_quiet) {
|
|
_cleanup_free_ char *final = NULL;
|
|
|
|
r = determine_default(&final);
|
|
if (r < 0)
|
|
return r;
|
|
|
|
if (!streq(final, unit))
|
|
log_notice("Note: \"%s\" is the default unit (possibly a runtime override).", final);
|
|
}
|
|
|
|
finish:
|
|
unit_file_changes_free(changes, n_changes);
|
|
|
|
return r;
|
|
}
|