***/
#include <errno.h>
+#include <unistd.h>
#include "dbus.h"
#include "log.h"
#include "strv.h"
#include "bus-errors.h"
#include "build.h"
+#include "dbus-common.h"
+#include "install.h"
#define BUS_MANAGER_INTERFACE_BEGIN \
" <interface name=\"org.freedesktop.systemd1.Manager\">\n"
" </method>\n" \
" <method name=\"UnsetEnvironment\">\n" \
" <arg name=\"names\" type=\"as\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"UnsetAndSetEnvironment\">\n" \
+ " <arg name=\"unset\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"set\" type=\"as\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"ListUnitFiles\">\n" \
+ " <arg name=\"changes\" type=\"a(ss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"GetUnitFileState\">\n" \
+ " <arg name=\"file\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"state\" type=\"s\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"EnableUnitFiles\">\n" \
+ " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
+ " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"DisableUnitFiles\">\n" \
+ " <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=\"ReenableUnitFiles\">\n" \
+ " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
+ " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"LinkUnitFiles\">\n" \
+ " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"PresetUnitFiles\">\n" \
+ " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"carries_install_info\" type=\"b\" direction=\"out\"/>\n" \
+ " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"MaskUnitFiles\">\n" \
+ " <arg name=\"files\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"runtime\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"force\" type=\"b\" direction=\"in\"/>\n" \
+ " <arg name=\"changes\" type=\"a(sss)\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"UnmaskUnitFiles\">\n" \
+ " <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"
#define BUS_MANAGER_INTERFACE_SIGNALS \
" <arg name=\"id\" type=\"u\"/>\n" \
" <arg name=\"job\" type=\"o\"/>\n" \
" <arg name=\"result\" type=\"s\"/>\n" \
- " </signal>"
+ " </signal>" \
+ " <signal name=\"StartupFinished\">\n" \
+ " <arg name=\"kernel\" type=\"t\"/>\n" \
+ " <arg name=\"initrd\" type=\"t\"/>\n" \
+ " <arg name=\"userspace\" type=\"t\"/>\n" \
+ " <arg name=\"total\" type=\"t\"/>\n" \
+ " </signal>" \
+ " <signal name=\"UnitFilesChanged\"/>\n"
#define BUS_MANAGER_INTERFACE_PROPERTIES_GENERAL \
" <property name=\"Version\" 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=\"InitRDTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"StartupTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"StartupTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
" <property name=\"FinishTimestamp\" type=\"t\" access=\"read\"/>\n" \
+ " <property name=\"FinishTimestampMonotonic\" 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" \
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) {
+static int bus_manager_append_tainted(DBusMessageIter *i, const char *property, void *data) {
const char *t;
- char buf[64] = "", *e = buf, *p = NULL;
+ Manager *m = data;
+ char buf[LINE_MAX] = "", *e = buf, *p = NULL;
- assert(m);
assert(i);
assert(property);
+ assert(m);
if (m->taint_usr)
- e = stpcpy(e, "usr-separate-fs");
+ 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
+ if (readlink_malloc("/etc/mtab", &p) < 0)
+ e = stpcpy(e, "etc-mtab-not-symlink ");
+ else
free(p);
- t = buf;
+ if (access("/proc/cgroups", F_OK) < 0)
+ stpcpy(e, "cgroups-missing ");
+
+ t = strstrip(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) {
+static int bus_manager_append_log_target(DBusMessageIter *i, const char *property, void *data) {
const char *t;
- assert(m);
assert(i);
assert(property);
return 0;
}
-static int bus_manager_set_log_target(Manager *m, DBusMessageIter *i, const char *property) {
+static int bus_manager_set_log_target(DBusMessageIter *i, const char *property) {
const char *t;
- assert(m);
assert(i);
assert(property);
return log_set_target_from_string(t);
}
-static int bus_manager_append_log_level(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_log_level(DBusMessageIter *i, const char *property, void *data) {
const char *t;
- assert(m);
assert(i);
assert(property);
return 0;
}
-static int bus_manager_set_log_level(Manager *m, DBusMessageIter *i, const char *property) {
+static int bus_manager_set_log_level(DBusMessageIter *i, const char *property) {
const char *t;
- assert(m);
assert(i);
assert(property);
return log_set_max_level_from_string(t);
}
-static int bus_manager_append_n_names(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_n_names(DBusMessageIter *i, const char *property, void *data) {
+ Manager *m = data;
uint32_t u;
- assert(m);
assert(i);
assert(property);
+ assert(m);
u = hashmap_size(m->units);
return 0;
}
-static int bus_manager_append_n_jobs(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_n_jobs(DBusMessageIter *i, const char *property, void *data) {
+ Manager *m = data;
uint32_t u;
- assert(m);
assert(i);
assert(property);
+ assert(m);
u = hashmap_size(m->jobs);
return 0;
}
-static int bus_manager_append_progress(Manager *m, DBusMessageIter *i, const char *property, void *data) {
+static int bus_manager_append_progress(DBusMessageIter *i, const char *property, void *data) {
double d;
+ Manager *m = data;
- assert(m);
assert(i);
assert(property);
+ assert(m);
if (dual_timestamp_is_set(&m->finish_timestamp))
d = 1.0;
return ":no-sender";
}
+static DBusMessage *message_from_file_changes(
+ DBusMessage *m,
+ UnitFileChange *changes,
+ unsigned n_changes,
+ int carries_install_info) {
+
+ DBusMessageIter iter, sub, sub2;
+ DBusMessage *reply;
+ unsigned i;
+
+ reply = dbus_message_new_method_return(m);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (carries_install_info >= 0) {
+ dbus_bool_t b;
+
+ b = !!carries_install_info;
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &b))
+ goto oom;
+ }
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sss)", &sub))
+ goto oom;
+
+ for (i = 0; i < n_changes; i++) {
+ const char *type, *path, *source;
+
+ type = unit_file_change_type_to_string(changes[i].type);
+ path = strempty(changes[i].path);
+ source = strempty(changes[i].source);
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &path) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &source) ||
+ !dbus_message_iter_close_container(&sub, &sub2))
+ goto oom;
+ }
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+
+ return reply;
+
+oom:
+ dbus_message_unref(reply);
+ return NULL;
+}
+
+static int bus_manager_send_unit_files_changed(Manager *m) {
+ DBusMessage *s;
+ int r;
+
+ s = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitFilesChanged");
+ if (!s)
+ return -ENOMEM;
+
+ r = bus_broadcast(m, s);
+ dbus_message_unref(s);
+
+ return r;
+}
+
static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
Manager *m = data;
{ "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", "InitRDTimestampMonotonic", bus_property_append_uint64, "t", &m->initrd_timestamp.monotonic },
{ "org.freedesktop.systemd1.Manager", "StartupTimestamp", bus_property_append_uint64, "t", &m->startup_timestamp.realtime },
+ { "org.freedesktop.systemd1.Manager", "StartupTimestampMonotonic", bus_property_append_uint64, "t", &m->startup_timestamp.monotonic },
{ "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, 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", "FinishTimestampMonotonic", bus_property_append_uint64, "t",&m->finish_timestamp.monotonic },
+ { "org.freedesktop.systemd1.Manager", "LogLevel", bus_manager_append_log_level, "s", m, bus_manager_set_log_level },
+ { "org.freedesktop.systemd1.Manager", "LogTarget", bus_manager_append_log_target, "s", m, bus_manager_set_log_target },
+ { "org.freedesktop.systemd1.Manager", "NNames", bus_manager_append_n_names, "u", m },
+ { "org.freedesktop.systemd1.Manager", "NJobs", bus_manager_append_n_jobs, "u", m },
{ "org.freedesktop.systemd1.Manager", "NInstalledJobs",bus_property_append_uint32, "u", &m->n_installed_jobs },
{ "org.freedesktop.systemd1.Manager", "NFailedJobs", bus_property_append_uint32, "u", &m->n_failed_jobs },
- { "org.freedesktop.systemd1.Manager", "Progress", bus_manager_append_progress, "d", NULL },
+ { "org.freedesktop.systemd1.Manager", "Progress", bus_manager_append_progress, "d", m },
{ "org.freedesktop.systemd1.Manager", "Environment", bus_property_append_strv, "as", m->environment },
{ "org.freedesktop.systemd1.Manager", "ConfirmSpawn", bus_property_append_bool, "b", &m->confirm_spawn },
{ "org.freedesktop.systemd1.Manager", "ShowStatus", bus_property_append_bool, "b", &m->show_status },
char * path = NULL;
JobType job_type = _JOB_TYPE_INVALID;
bool reload_if_possible = false;
+ const char *member;
assert(connection);
assert(message);
dbus_error_init(&error);
+ member = dbus_message_get_member(message);
+
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
const char *name;
Unit *u;
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(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);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if (!(reply = dbus_message_new_method_return(message)))
&error,
DBUS_TYPE_UINT32, &pid,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if (!(reply = dbus_message_new_method_return(message)))
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
DBUS_TYPE_STRING, &smode,
DBUS_TYPE_INT32, &signo,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ if (isempty(swho))
+ who = KILL_ALL;
+ else {
+ who = kill_who_from_string(swho);
+ if (who < 0)
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+ }
+
+ if (isempty(smode))
+ mode = KILL_CONTROL_GROUP;
+ else {
+ mode = kill_mode_from_string(smode);
+ if (mode < 0)
+ return bus_send_error_reply(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 (signo <= 0 || signo >= _NSIG)
+ return bus_send_error_reply(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);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if ((r = unit_kill(u, who, mode, signo, &error)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
&error,
DBUS_TYPE_UINT32, &id,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (!(j = manager_get_job(m, id))) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if (!(reply = dbus_message_new_method_return(message)))
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(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);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
unit_reset_failed(u);
if ((r = set_put(s, client)) < 0) {
free(client);
- return bus_send_error_reply(m, connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, NULL, r);
}
if (!(reply = dbus_message_new_method_return(message)))
if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
free(client);
DBUS_TYPE_STRING, &name,
DBUS_TYPE_BOOLEAN, &cleanup,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (name && name[0] == 0)
name = NULL;
if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(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", "Reexecute")) {
- if (!(reply = dbus_message_new_method_return(message)))
- goto oom;
+ /* We don't send a reply back here, the client should
+ * just wait for us disconnecting. */
m->exit_code = MANAGER_REEXECUTE;
if (m->running_as == MANAGER_SYSTEM) {
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);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
if (m->running_as != MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
if (m->running_as != MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
if (m->running_as != MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
if (m->running_as != MANAGER_SYSTEM) {
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
- return bus_send_error_reply(m, connection, message, &error, -ENOTSUP);
+ return bus_send_error_reply(connection, message, &error, -ENOTSUP);
}
if (!(reply = dbus_message_new_method_return(message)))
if (r == -ENOMEM)
goto oom;
- return bus_send_error_reply(m, connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, NULL, r);
}
e = strv_env_merge(2, m->environment, l);
if (r == -ENOMEM)
goto oom;
- return bus_send_error_reply(m, connection, message, NULL, r);
+ return bus_send_error_reply(connection, message, NULL, r);
}
e = strv_env_delete(m->environment, 1, l);
if (!e)
goto oom;
- if (!(reply = dbus_message_new_method_return(message)))
+ if (!(reply = dbus_message_new_method_return(message))) {
+ strv_free(e);
goto oom;
+ }
strv_free(m->environment);
m->environment = e;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
+ char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
+ DBusMessageIter iter;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_parse_strv_iter(&iter, &l_unset);
+ if (r < 0) {
+ if (r == -ENOMEM)
+ goto oom;
+
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ if (!dbus_message_iter_next(&iter)) {
+ strv_free(l_unset);
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
+ }
+
+ r = bus_parse_strv_iter(&iter, &l_set);
+ if (r < 0) {
+ strv_free(l_unset);
+ if (r == -ENOMEM)
+ goto oom;
+
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ e = strv_env_delete(m->environment, 1, l_unset);
+ strv_free(l_unset);
+
+ if (!e) {
+ strv_free(l_set);
+ goto oom;
+ }
+
+ f = strv_env_merge(2, e, l_set);
+ strv_free(l_set);
+ strv_free(e);
+
+ if (!f)
+ goto oom;
+
+ if (!(reply = dbus_message_new_method_return(message))) {
+ strv_free(f);
+ goto oom;
+ }
+
+ strv_free(m->environment);
+ m->environment = f;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnitFiles")) {
+ DBusMessageIter iter, sub, sub2;
+ Hashmap *h;
+ Iterator i;
+ UnitFileList *item;
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ h = hashmap_new(string_hash_func, string_compare_func);
+ if (!h)
+ goto oom;
+
+ r = unit_file_get_list(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, h);
+ if (r < 0) {
+ unit_file_list_free(h);
+ dbus_message_unref(reply);
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub)) {
+ unit_file_list_free(h);
+ goto oom;
+ }
+
+ HASHMAP_FOREACH(item, h, i) {
+ const char *state;
+
+ state = unit_file_state_to_string(item->state);
+ assert(state);
+
+ if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &item->path) ||
+ !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) ||
+ !dbus_message_iter_close_container(&sub, &sub2)) {
+ unit_file_list_free(h);
+ goto oom;
+ }
+ }
+
+ unit_file_list_free(h);
+
+ if (!dbus_message_iter_close_container(&iter, &sub))
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitFileState")) {
+ const char *name;
+ UnitFileState state;
+ const char *s;
+
+ if (!dbus_message_get_args(
+ message,
+ &error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+ state = unit_file_get_state(m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, NULL, name);
+ if (state < 0)
+ return bus_send_error_reply(connection, message, NULL, state);
+
+ s = unit_file_state_to_string(state);
+ assert(s);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ if (!dbus_message_append_args(
+ reply,
+ DBUS_TYPE_STRING, &s,
+ DBUS_TYPE_INVALID))
+ goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "EnableUnitFiles") ||
+ 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")) {
+
+ char **l = NULL;
+ DBusMessageIter iter;
+ UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ dbus_bool_t runtime, force;
+ int carries_install_info = -1;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_parse_strv_iter(&iter, &l);
+ if (r < 0) {
+ if (r == -ENOMEM)
+ goto oom;
+
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ if (!dbus_message_iter_next(&iter) ||
+ bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, true) < 0 ||
+ bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &force, false) < 0) {
+ strv_free(l);
+ return bus_send_error_reply(connection, message, NULL, -EIO);
+ }
+
+ if (streq(member, "EnableUnitFiles")) {
+ r = unit_file_enable(scope, runtime, NULL, l, force, &changes, &n_changes);
+ carries_install_info = r;
+ } else if (streq(member, "ReenableUnitFiles")) {
+ r = unit_file_reenable(scope, runtime, NULL, l, force, &changes, &n_changes);
+ carries_install_info = r;
+ } else if (streq(member, "LinkUnitFiles"))
+ r = unit_file_link(scope, runtime, NULL, l, force, &changes, &n_changes);
+ else if (streq(member, "PresetUnitFiles")) {
+ r = unit_file_preset(scope, runtime, NULL, l, force, &changes, &n_changes);
+ carries_install_info = r;
+ } else if (streq(member, "MaskUnitFiles"))
+ r = unit_file_mask(scope, runtime, NULL, l, force, &changes, &n_changes);
+ else
+ assert_not_reached("Uh? Wrong method");
+
+ strv_free(l);
+ bus_manager_send_unit_files_changed(m);
+
+ if (r < 0) {
+ unit_file_changes_free(changes, n_changes);
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ reply = message_from_file_changes(message, changes, n_changes, carries_install_info);
+ unit_file_changes_free(changes, n_changes);
+
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "DisableUnitFiles") ||
+ dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnmaskUnitFiles")) {
+
+ char **l = NULL;
+ DBusMessageIter iter;
+ UnitFileScope scope = m->running_as == MANAGER_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER;
+ UnitFileChange *changes = NULL;
+ unsigned n_changes = 0;
+ dbus_bool_t runtime;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_parse_strv_iter(&iter, &l);
+ if (r < 0) {
+ if (r == -ENOMEM)
+ goto oom;
+
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ if (!dbus_message_iter_next(&iter) ||
+ bus_iter_get_basic_and_next(&iter, DBUS_TYPE_BOOLEAN, &runtime, false) < 0) {
+ strv_free(l);
+ return bus_send_error_reply(connection, message, NULL, -EIO);
+ }
+
+ if (streq(member, "DisableUnitFiles"))
+ r = unit_file_disable(scope, runtime, NULL, l, &changes, &n_changes);
+ else if (streq(member, "UnmaskUnitFiles"))
+ r = unit_file_unmask(scope, runtime, NULL, l, &changes, &n_changes);
+ else
+ assert_not_reached("Uh? Wrong method");
+
+ strv_free(l);
+ bus_manager_send_unit_files_changed(m);
+
+ if (r < 0) {
+ unit_file_changes_free(changes, n_changes);
+ return bus_send_error_reply(connection, message, NULL, r);
+ }
+
+ reply = message_from_file_changes(message, changes, n_changes, -1);
+ unit_file_changes_free(changes, n_changes);
+
+ if (!reply)
+ goto oom;
+
} else
- return bus_default_message_handler(m, connection, message, NULL, INTERFACES_LIST, properties);
+ return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, properties);
if (job_type != _JOB_TYPE_INVALID) {
const char *name, *smode, *old_name = NULL;
DBUS_TYPE_INVALID);
if (!b)
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
if (old_name)
if (!(u = manager_get_unit(m, old_name)) ||
!u->meta.job ||
u->meta.job->type != JOB_START) {
dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
- return bus_send_error_reply(m, connection, message, &error, -ENOENT);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
}
if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
- return bus_send_error_reply(m, connection, message, &error, -EINVAL);
+ return bus_send_error_reply(connection, message, &error, -EINVAL);
}
if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (reload_if_possible && unit_can_reload(u)) {
if (job_type == JOB_RESTART)
((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
(u->meta.refuse_manual_start || u->meta.refuse_manual_stop))) {
dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
- return bus_send_error_reply(m, connection, message, &error, -EPERM);
+ return bus_send_error_reply(connection, message, &error, -EPERM);
}
if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
- return bus_send_error_reply(m, connection, message, &error, r);
+ return bus_send_error_reply(connection, message, &error, r);
if (!(j->bus_client = strdup(message_get_sender_with_fallback(message))))
goto oom;
goto oom;
}
- free(path);
-
if (reply) {
if (!dbus_connection_send(connection, reply, NULL))
goto oom;
dbus_message_unref(reply);
}
+ free(path);
+
return DBUS_HANDLER_RESULT_HANDLED;
oom: