#include "dbus-manager.h"
#include "strv.h"
#include "bus-errors.h"
+#include "build.h"
#define BUS_MANAGER_INTERFACE_BEGIN \
" <interface name=\"org.freedesktop.systemd1.Manager\">\n"
" <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" </method>\n" \
+ " <method name=\"KillUnit\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"signal\" type=\"i\" direction=\"in\"/>\n" \
+ " </method>\n" \
" <method name=\"ResetFailedUnit\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" </method>\n" \
" <signal name=\"JobRemoved\">\n" \
" <arg name=\"id\" type=\"u\"/>\n" \
" <arg name=\"job\" type=\"o\"/>\n" \
- " <arg name=\"success\" type=\"b\"/>\n" \
+ " <arg name=\"result\" type=\"s\"/>\n" \
" </signal>"
-
#define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
" <property name=\"Version\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Distribution\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Features\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Tainted\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"RunningAs\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"InitRDTimestamp\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
- " <property name=\"LogLevel\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"LogTarget\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"LogLevel\" type=\"s\" access=\"readwrite\"/>\n" \
+ " <property name=\"LogTarget\" type=\"s\" access=\"readwrite\"/>\n" \
" <property name=\"NNames\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"NJobs\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"NInstalledJobs\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"NotifySocket\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"MountAuto\" type=\"b\" access=\"read\"/>\n" \
- " <property name=\"SwapAuto\" type=\"b\" access=\"read\"/>\n"
+ " <property name=\"SwapAuto\" type=\"b\" access=\"read\"/>\n" \
+ " <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
+ " <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n"
#ifdef HAVE_SYSV_COMPAT
#define BUS_MANAGER_INTERFACE_PROPERTIES_SYSV \
#define INTROSPECTION_END \
"</node>\n"
-const char bus_manager_interface[] = BUS_MANAGER_INTERFACE;
+#define INTERFACES_LIST \
+ BUS_GENERIC_INTERFACES_LIST \
+ "org.freedesktop.systemd1.Manager\0"
+
+const char bus_manager_interface[] _introspect_("Manager") = BUS_MANAGER_INTERFACE;
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs);
+static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_exec_output, exec_output, ExecOutput);
+
+static int bus_manager_append_tainted(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+ const char *t;
+ char buf[64] = "", *e = buf, *p = NULL;
+
+ assert(m);
+ assert(i);
+ assert(property);
+
+ if (path_is_mount_point("/usr") > 0 || dir_is_empty("/usr") > 0)
+ e = stpcpy(e, "usr-separate-fs");
+
+ if (readlink_malloc("/etc/mtab", &p) < 0) {
+ if (e != buf)
+ e = stpcpy(e, " ");
+ e = stpcpy(e, "etc-mtab-not-symlink");
+ } else
+ free(p);
+
+ t = buf;
+
+ if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
+ return -ENOMEM;
+
+ return 0;
+}
static int bus_manager_append_log_target(Manager *m, DBusMessageIter *i, const char *property, void *data) {
const char *t;
return 0;
}
+static int bus_manager_set_log_target(Manager *m, DBusMessageIter *i, const char *property) {
+ const char *t;
+
+ assert(m);
+ assert(i);
+ assert(property);
+
+ dbus_message_iter_get_basic(i, &t);
+
+ return log_set_target_from_string(t);
+}
+
static int bus_manager_append_log_level(Manager *m, DBusMessageIter *i, const char *property, void *data) {
const char *t;
return 0;
}
+static int bus_manager_set_log_level(Manager *m, DBusMessageIter *i, const char *property) {
+ const char *t;
+
+ assert(m);
+ assert(i);
+ assert(property);
+
+ dbus_message_iter_get_basic(i, &t);
+
+ return log_set_max_level_from_string(t);
+}
+
static int bus_manager_append_n_names(Manager *m, DBusMessageIter *i, const char *property, void *data) {
uint32_t u;
const BusProperty properties[] = {
{ "org.freedesktop.systemd1.Manager", "Version", bus_property_append_string, "s", PACKAGE_STRING },
+ { "org.freedesktop.systemd1.Manager", "Distribution", bus_property_append_string, "s", DISTRIBUTION },
+ { "org.freedesktop.systemd1.Manager", "Features", bus_property_append_string, "s", SYSTEMD_FEATURES },
{ "org.freedesktop.systemd1.Manager", "RunningAs", bus_manager_append_running_as, "s", &m->running_as },
+ { "org.freedesktop.systemd1.Manager", "Tainted", bus_manager_append_tainted, "s", m },
+ { "org.freedesktop.systemd1.Manager", "InitRDTimestamp", bus_property_append_uint64, "t", &m->initrd_timestamp.realtime },
{ "org.freedesktop.systemd1.Manager", "StartupTimestamp", bus_property_append_uint64, "t", &m->startup_timestamp.realtime },
{ "org.freedesktop.systemd1.Manager", "FinishTimestamp", bus_property_append_uint64, "t", &m->finish_timestamp.realtime },
- { "org.freedesktop.systemd1.Manager", "LogLevel", bus_manager_append_log_level, "s", NULL },
- { "org.freedesktop.systemd1.Manager", "LogTarget", bus_manager_append_log_target, "s", NULL },
+ { "org.freedesktop.systemd1.Manager", "LogLevel", bus_manager_append_log_level, "s", NULL, bus_manager_set_log_level},
+ { "org.freedesktop.systemd1.Manager", "LogTarget", bus_manager_append_log_target, "s", NULL, bus_manager_set_log_target},
{ "org.freedesktop.systemd1.Manager", "NNames", bus_manager_append_n_names, "u", NULL },
{ "org.freedesktop.systemd1.Manager", "NJobs", bus_manager_append_n_jobs, "u", NULL },
{ "org.freedesktop.systemd1.Manager", "NInstalledJobs",bus_property_append_uint32, "u", &m->n_installed_jobs },
{ "org.freedesktop.systemd1.Manager", "NotifySocket", bus_property_append_string, "s", m->notify_socket },
{ "org.freedesktop.systemd1.Manager", "ControlGroupHierarchy", bus_property_append_string, "s", m->cgroup_hierarchy },
{ "org.freedesktop.systemd1.Manager", "MountAuto", bus_property_append_bool, "b", &m->mount_auto },
- { "org.freedesktop.systemd1.Manager", "SwapAuto", bus_property_append_bool, "b", &m->swap_auto },
+ { "org.freedesktop.systemd1.Manager", "SwapAuto", bus_property_append_bool, "b", &m->swap_auto },
+ { "org.freedesktop.systemd1.Manager", "DefaultControllers", bus_property_append_strv, "as", m->default_controllers },
+ { "org.freedesktop.systemd1.Manager", "DefaultStandardOutput", bus_manager_append_exec_output, "s", &m->default_std_output },
+ { "org.freedesktop.systemd1.Manager", "DefaultStandardError", bus_manager_append_exec_output, "s", &m->default_std_error },
#ifdef HAVE_SYSV_COMPAT
{ "org.freedesktop.systemd1.Manager", "SysVConsole", bus_property_append_bool, "b", &m->sysv_console },
{ "org.freedesktop.systemd1.Manager", "SysVInitPath", bus_property_append_strv, "as", m->lookup_paths.sysvinit_path },
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ReloadOrTryRestartUnit")) {
reload_if_possible = true;
job_type = JOB_TRY_RESTART;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KillUnit")) {
+ const char *name, *swho, *smode;
+ int32_t signo;
+ Unit *u;
+ KillMode mode;
+ KillWho who;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &swho,
+ DBUS_TYPE_STRING, &smode,
+ DBUS_TYPE_INT32, &signo,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+
+ if ((mode = kill_mode_from_string(smode)) < 0 ||
+ (who = kill_who_from_string(swho)) < 0 ||
+ signo <= 0 ||
+ signo >= _NSIG)
+ return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+
+ if (!(u = manager_get_unit(m, name))) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ }
+
+ if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
+ return bus_send_error_reply(m, connection, message, &error, r);
+
+ if (!(reply = dbus_message_new_method_return(message)))
+ goto oom;
+
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) {
uint32_t id;
Job *j;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
if (m->running_as == MANAGER_SYSTEM) {
- dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for session managers.");
+ dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
}
m->environment = e;
} else
- return bus_default_message_handler(m, connection, message, NULL, properties);
+ return bus_default_message_handler(m, connection, message, NULL, INTERFACES_LIST, properties);
if (job_type != _JOB_TYPE_INVALID) {
const char *name, *smode, *old_name = NULL;