#include "dbus.h"
#include "log.h"
#include "dbus-unit.h"
+#include "bus-errors.h"
+
+const char bus_unit_interface[] = BUS_UNIT_INTERFACE;
int bus_unit_append_names(Manager *m, DBusMessageIter *i, const char *property, void *data) {
char *t;
return 0;
}
-DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_unit_append_kill_mode, kill_mode, KillMode);
-
-static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusMessage *message) {
+static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *connection, DBusMessage *message) {
DBusMessage *reply = NULL;
Manager *m = u->meta.manager;
DBusError error;
JobType job_type = _JOB_TYPE_INVALID;
+ char *path = NULL;
+ bool reload_if_possible = false;
dbus_error_init(&error);
job_type = JOB_RELOAD;
else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Restart"))
job_type = JOB_RESTART;
- else if (UNIT_VTABLE(u)->bus_message_handler)
- return UNIT_VTABLE(u)->bus_message_handler(u, message);
+ else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "TryRestart"))
+ job_type = JOB_TRY_RESTART;
+ else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrRestart")) {
+ reload_if_possible = true;
+ job_type = JOB_RESTART;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrTryRestart")) {
+ reload_if_possible = true;
+ job_type = JOB_TRY_RESTART;
+ } else if (UNIT_VTABLE(u)->bus_message_handler)
+ return UNIT_VTABLE(u)->bus_message_handler(u, connection, message);
else
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
JobMode mode;
Job *j;
int r;
- char *path;
+
+ if (job_type == JOB_START && u->meta.only_by_dependency) {
+ dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Unit may be activated by dependency only.");
+ return bus_send_error_reply(m, connection, message, &error, -EPERM);
+ }
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &smode,
DBUS_TYPE_INVALID))
- return bus_send_error_reply(m, message, &error, -EINVAL);
+ return bus_send_error_reply(m, connection, message, &error, -EINVAL);
- if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID)
- return bus_send_error_reply(m, message, NULL, -EINVAL);
+ if (reload_if_possible && unit_can_reload(u)) {
+ if (job_type == JOB_RESTART)
+ job_type = JOB_RELOAD_OR_START;
+ else if (job_type == JOB_TRY_RESTART)
+ job_type = JOB_RELOAD;
+ }
- if ((r = manager_add_job(m, job_type, u, mode, true, &j)) < 0)
- return bus_send_error_reply(m, message, NULL, r);
+ 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);
+ }
+
+ if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
+ return bus_send_error_reply(m, connection, message, &error, r);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
goto oom;
}
+ free(path);
+
if (reply) {
- if (!dbus_connection_send(m->api_bus, reply, NULL))
+ if (!dbus_connection_send(connection, reply, NULL))
goto oom;
dbus_message_unref(reply);
return DBUS_HANDLER_RESULT_HANDLED;
oom:
+ free(path);
+
if (reply)
dbus_message_unref(reply);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
-static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
+static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
Manager *m = data;
Unit *u;
int r;
assert(message);
assert(m);
- log_debug("Got D-Bus request: %s.%s() on %s",
- dbus_message_get_interface(message),
- dbus_message_get_member(message),
- dbus_message_get_path(message));
-
if ((r = manager_get_unit_from_dbus_path(m, dbus_message_get_path(message), &u)) < 0) {
if (r == -ENOMEM)
if (r == -ENOENT)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- return bus_send_error_reply(m, message, NULL, r);
+ return bus_send_error_reply(m, connection, message, NULL, r);
}
- return bus_unit_message_dispatch(u, message);
+ return bus_unit_message_dispatch(u, connection, message);
}
const DBusObjectPathVTable bus_unit_vtable = {
DBusMessage *m = NULL;
assert(u);
- assert(u->meta.in_dbus_queue);
- LIST_REMOVE(Meta, dbus_queue, u->meta.manager->dbus_unit_queue, &u->meta);
- u->meta.in_dbus_queue = false;
+ if (u->meta.in_dbus_queue) {
+ LIST_REMOVE(Meta, dbus_queue, u->meta.manager->dbus_unit_queue, &u->meta);
+ u->meta.in_dbus_queue = false;
+ }
- if (set_isempty(u->meta.manager->subscribed)) {
+ if (!bus_has_subscriber(u->meta.manager)) {
u->meta.sent_dbus_new_signal = true;
return;
}
goto oom;
}
- if (!dbus_connection_send(u->meta.manager->api_bus, m, NULL))
+ if (bus_broadcast(u->meta.manager, m) < 0)
goto oom;
free(p);
assert(u);
- if (set_isempty(u->meta.manager->subscribed) || !u->meta.sent_dbus_new_signal)
+ if (!bus_has_subscriber(u->meta.manager))
return;
+ if (!u->meta.sent_dbus_new_signal)
+ bus_unit_send_change_signal(u);
+
if (!(p = unit_dbus_path(u)))
goto oom;
DBUS_TYPE_INVALID))
goto oom;
- if (!dbus_connection_send(u->meta.manager->api_bus, m, NULL))
+ if (bus_broadcast(u->meta.manager, m) < 0)
goto oom;
free(p);