summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/dbus-manager.c28
-rw-r--r--src/core/org.freedesktop.systemd1.conf4
-rw-r--r--src/shared/install.c86
-rw-r--r--src/shared/install.h2
-rw-r--r--src/systemctl/systemctl.c65
5 files changed, 183 insertions, 2 deletions
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 56b02a1cf5..f3ddfc9761 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -227,6 +227,13 @@
" <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
" <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
" <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetDefaultTarget\">\n" \
+ " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetDefaultTarget\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"out\"/>\n" \
" </method>\n"
#define BUS_MANAGER_INTERFACE_SIGNALS \
@@ -1728,7 +1735,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReenableUnitFiles") ||
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LinkUnitFiles") ||
dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PresetUnitFiles") ||
- dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles")) {
+ dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "MaskUnitFiles") ||
+ dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetDefaultTarget")) {
char **l = NULL;
DBusMessageIter iter;
@@ -1771,6 +1779,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
carries_install_info = r;
} else if (streq(member, "MaskUnitFiles"))
r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
+ else if (streq(member, "SetDefaultTarget"))
+ r = unit_file_set_default(scope, NULL, l[0], &changes, &n_changes);
else
assert_not_reached("Uh? Wrong method");
@@ -1838,6 +1848,22 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
if (!reply)
goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetDefaultTarget")) {
+ UnitFileScope scope = m->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+ _cleanup_free_ char *default_target = NULL;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ r = unit_file_get_default(scope, NULL, &default_target);
+
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &default_target, DBUS_TYPE_INVALID)) {
+ goto oom;
+ }
} else {
const BusBoundProperties bps[] = {
{ "org.freedesktop.systemd1.Manager", bus_systemd_properties, systemd_property_string },
diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf
index a07a8e1ce3..a375dce0b0 100644
--- a/src/core/org.freedesktop.systemd1.conf
+++ b/src/core/org.freedesktop.systemd1.conf
@@ -86,6 +86,10 @@
send_interface="org.freedesktop.systemd1.Manager"
send_member="Dump"/>
+ <allow send_destination="org.freedesktop.systemd1"
+ send_interface="org.freedesktop.systemd1.Manager"
+ send_member="GetDefaultTarget"/>
+
<allow receive_sender="org.freedesktop.systemd1"/>
</policy>
diff --git a/src/shared/install.c b/src/shared/install.c
index 8f27c6d479..954dcb1e71 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -1570,6 +1570,92 @@ int unit_file_reenable(
return r;
}
+int unit_file_set_default(
+ UnitFileScope scope,
+ const char *root_dir,
+ char *file,
+ UnitFileChange **changes,
+ unsigned *n_changes) {
+
+ _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ _cleanup_install_context_done_ InstallContext c = {};
+ _cleanup_free_ char *config_path = NULL;
+ char *path;
+ int r;
+ InstallInfo *i = NULL;
+
+ assert(scope >= 0);
+ assert(scope < _UNIT_FILE_SCOPE_MAX);
+
+ if (unit_name_to_type(file) != UNIT_TARGET)
+ return -EINVAL;
+
+ r = lookup_paths_init_from_scope(&paths, scope);
+ if (r < 0)
+ return r;
+
+ r = get_config_path(scope, false, root_dir, &config_path);
+ if (r < 0)
+ return r;
+
+ r = install_info_add_auto(&c, file);
+ if (r < 0)
+ return r;
+
+ i = (InstallInfo*)hashmap_first(c.will_install);
+
+ r = unit_file_search(&c, i, &paths, root_dir, false);
+ if (r < 0)
+ return r;
+
+ path = strappenda(config_path, "/default.target");
+ r = create_symlink(i->path, path, true, changes, n_changes);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int unit_file_get_default(
+ UnitFileScope scope,
+ const char *root_dir,
+ char **name) {
+
+ _cleanup_lookup_paths_free_ LookupPaths paths = {};
+ char **p;
+ int r;
+
+ r = lookup_paths_init_from_scope(&paths, scope);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(p, paths.unit_path) {
+ _cleanup_free_ char *path = NULL, *tmp = NULL;
+
+ if (isempty(root_dir))
+ path = strappend(*p, "/default.target");
+ else
+ path = strjoin(root_dir, "/", *p, "/default.target", NULL);
+
+ if (!path)
+ return -ENOMEM;
+
+ r = readlink_malloc(path, &tmp);
+ if (r == -ENOENT)
+ continue;
+ else if (r < 0)
+ return r;
+
+ *name = strdup(path_get_file_name(tmp));
+ if (!*name)
+ return -ENOMEM;
+
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
UnitFileState unit_file_get_state(
UnitFileScope scope,
const char *root_dir,
diff --git a/src/shared/install.h b/src/shared/install.h
index 94516c9d05..5609d1e8df 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -80,6 +80,8 @@ int unit_file_link(UnitFileScope scope, bool runtime, const char *root_dir, char
int unit_file_preset(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
int unit_file_mask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], bool force, UnitFileChange **changes, unsigned *n_changes);
int unit_file_unmask(UnitFileScope scope, bool runtime, const char *root_dir, char *files[], UnitFileChange **changes, unsigned *n_changes);
+int unit_file_set_default(UnitFileScope scope, const char *root_dir, char *file, UnitFileChange **changes, unsigned *n_changes);
+int unit_file_get_default(UnitFileScope scope, const char *root_dir, char **name);
UnitFileState unit_file_get_state(UnitFileScope scope, const char *root_dir, const char *filename);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index f8573d315c..56021a6889 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -1177,6 +1177,59 @@ static int list_dependencies(DBusConnection *bus, char **args) {
return list_dependencies_one(bus, u, 0, &units, 0);
}
+static int get_default(DBusConnection *bus, char **args) {
+ char *path = NULL;
+ _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
+ int r;
+ _cleanup_dbus_error_free_ DBusError error;
+
+ dbus_error_init(&error);
+
+ if (!bus || avoid_bus()) {
+ r = unit_file_get_default(arg_scope, arg_root, &path);
+
+ if (r < 0) {
+ log_error("Operation failed: %s", strerror(-r));
+ goto finish;
+ }
+
+ r = 0;
+ } else {
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetDefaultTarget",
+ &reply,
+ NULL,
+ DBUS_TYPE_INVALID);
+
+ if (r < 0) {
+ log_error("Operation failed: %s", strerror(-r));
+ goto finish;
+ }
+
+ if (!dbus_message_get_args(reply, &error,
+ DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse reply: %s", bus_error_message(&error));
+ dbus_error_free(&error);
+ return -EIO;
+ }
+ }
+
+ if (path)
+ printf("%s\n", path);
+
+finish:
+ if ((!bus || avoid_bus()) && path)
+ free(path);
+
+ return r;
+
+}
+
struct job_info {
uint32_t id;
char *name, *type, *state;
@@ -4243,6 +4296,8 @@ static int enable_unit(DBusConnection *bus, char **args) {
r = unit_file_mask(arg_scope, arg_runtime, arg_root, mangled_names, arg_force, &changes, &n_changes);
else if (streq(verb, "unmask"))
r = unit_file_unmask(arg_scope, arg_runtime, arg_root, mangled_names, &changes, &n_changes);
+ else if (streq(verb, "set-default"))
+ r = unit_file_set_default(arg_scope, arg_root, args[1], &changes, &n_changes);
else
assert_not_reached("Unknown verb");
@@ -4286,6 +4341,8 @@ static int enable_unit(DBusConnection *bus, char **args) {
else if (streq(verb, "unmask")) {
method = "UnmaskUnitFiles";
send_force = false;
+ } else if (streq(verb, "set-default")) {
+ method = "SetDefaultTarget";
} else
assert_not_reached("Unknown verb");
@@ -4585,6 +4642,8 @@ static int systemctl_help(void) {
" unmask [NAME...] Unmask one or more units\n"
" link [PATH...] Link one or more units files into\n"
" the search path\n"
+ " get-default Get the name of the default target\n"
+ " set-default NAME Set the default target\n"
" is-enabled [NAME...] Check whether unit files are enabled\n\n"
"Job Commands:\n"
" list-jobs List jobs\n"
@@ -5646,6 +5705,8 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
{ "link", MORE, 2, enable_unit },
{ "switch-root", MORE, 2, switch_root },
{ "list-dependencies", LESS, 2, list_dependencies },
+ { "set-default", EQUAL, 2, enable_unit },
+ { "get-default", LESS, 1, get_default },
};
int left;
@@ -5717,7 +5778,9 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
!streq(verbs[i].verb, "preset") &&
!streq(verbs[i].verb, "mask") &&
!streq(verbs[i].verb, "unmask") &&
- !streq(verbs[i].verb, "link")) {
+ !streq(verbs[i].verb, "link") &&
+ !streq(verbs[i].verb, "set-default") &&
+ !streq(verbs[i].verb, "get-default")) {
if (running_in_chroot() > 0) {
log_info("Running in chroot, ignoring request.");