dbus-unit.c revision 80fbf05e75b75b7dd342ec844275efae90c479ec
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering This file is part of systemd.
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering Copyright 2010 Lennart Poettering
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering systemd is free software; you can redistribute it and/or modify it
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering under the terms of the GNU Lesser General Public License as published by
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering (at your option) any later version.
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering systemd is distributed in the hope that it will be useful, but
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering Lesser General Public License for more details.
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering You should have received a copy of the GNU Lesser General Public License
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringconst char bus_unit_interface[] _introspect_("Unit") = BUS_UNIT_INTERFACE;
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "LoadState\0" \
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "ActiveState\0" \
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "SubState\0" \
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "InactiveExitTimestamp\0" \
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "ActiveEnterTimestamp\0" \
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "ActiveExitTimestamp\0" \
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "InactiveEnterTimestamp\0" \
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering "NeedDaemonReload\0"
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_names(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &t))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_close_container(i, &sub))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_following(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering const char *d;
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_dependencies(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &u->id))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_close_container(i, &sub))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_description(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering const char *d;
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &d))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_unit_append_load_state, unit_load_state, UnitLoadState);
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_active_state(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering state = unit_active_state_to_string(unit_active_state(u));
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_sub_state(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_file_state(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering state = strempty(unit_file_state_to_string(unit_get_unit_file_state(u)));
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &state))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_can_start(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_can_stop(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering /* On the lower levels we assume that every unit we can start
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering * we can also stop */
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poetteringstatic int bus_unit_append_can_reload(DBusMessageIter *i, const char *property, void *data) {
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poetteringstatic int bus_unit_append_can_isolate(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poetteringstatic int bus_unit_append_job(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->job->id) ||
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmek !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
be3f52f4ed02a9256b1577719677b32a17b525acLennart Poettering /* No job, so let's fill in some placeholder
be3f52f4ed02a9256b1577719677b32a17b525acLennart Poettering * data. Since we need to fill in a valid path we
be3f52f4ed02a9256b1577719677b32a17b525acLennart Poettering * simple point to ourselves. */
be3f52f4ed02a9256b1577719677b32a17b525acLennart Poettering if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &id) ||
be3f52f4ed02a9256b1577719677b32a17b525acLennart Poettering !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) {
be3f52f4ed02a9256b1577719677b32a17b525acLennart Poettering if (!dbus_message_iter_close_container(i, &sub))
1ca208fb4f93e5869704af1812cbff7130a2fc03Zbigniew Jędrzejewski-Szmekstatic int bus_unit_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if ((cgb = unit_get_default_cgroup(u))) {
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering if (!(t = cgroup_bonding_to_string(cgb)))
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering t = (char*) "";
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t);
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poetteringstatic int bus_unit_append_cgroups(DBusMessageIter *i, const char *property, void *data) {
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "s", &sub))
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering LIST_FOREACH(by_unit, cgb, u->cgroup_bondings) {
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering if (!(t = cgroup_bonding_to_string(cgb)))
0f4ba83c397e807939a4eb0b2cbd04ad4ab548ccLennart Poettering success = dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &t);
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering if (!dbus_message_iter_close_container(i, &sub))
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poetteringstatic int bus_unit_append_cgroup_attrs(DBusMessageIter *i, const char *property, void *data) {
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sss)", &sub))
3731acf1acfb4a6eb68374a5b137f3b368f63381Lennart Poettering LIST_FOREACH(by_unit, a, u->cgroup_attributes) {
char *v = NULL;
bool success;
if (a->map_callback)
success =
free(v);
if (!success)
return -ENOMEM;
return -ENOMEM;
static int bus_unit_append_need_daemon_reload(DBusMessageIter *i, const char *property, void *data) {
dbus_bool_t b;
assert(i);
assert(u);
b = unit_need_daemon_reload(u);
return -ENOMEM;
assert(i);
assert(u);
if (u->load_error != 0) {
return -ENOMEM;
static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *connection, DBusMessage *message) {
bool reload_if_possible = false;
else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrRestart")) {
reload_if_possible = true;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ReloadOrTryRestart")) {
reload_if_possible = true;
if (!dbus_message_get_args(
&error,
if (who < 0)
if (mode < 0)
goto oom;
goto oom;
const char *smode;
Job *j;
dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
if (!dbus_message_get_args(
&error,
goto oom;
goto oom;
if (!dbus_message_append_args(
goto oom;
if (reply) {
goto oom;
return DBUS_HANDLER_RESULT_HANDLED;
oom:
if (reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
Unit *u;
assert(m);
FILE *f;
Iterator i;
goto oom;
goto oom;
if (k != u->id)
if (!(p = bus_path_escape(k))) {
fclose(f);
goto oom;
free(p);
if (ferror(f)) {
fclose(f);
goto oom;
fclose(f);
if (!introspection)
goto oom;
goto oom;
goto oom;
return DBUS_HANDLER_RESULT_HANDLED;
if (r == -ENOMEM)
goto oom;
oom:
if (reply)
return DBUS_HANDLER_RESULT_NEED_MEMORY;
char *p = NULL;
assert(u);
if (u->in_dbus_queue) {
u->in_dbus_queue = false;
if (!u->id)
u->sent_dbus_new_signal = true;
if (!(p = unit_dbus_path(u)))
goto oom;
if (u->sent_dbus_new_signal) {
if (!(m = bus_properties_changed_new(p,
goto oom;
goto oom;
goto oom;
if (!(m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitNew")))
goto oom;
if (!dbus_message_append_args(m,
goto oom;
goto oom;
free(p);
u->sent_dbus_new_signal = true;
oom:
free(p);
char *p = NULL;
assert(u);
if (!u->sent_dbus_new_signal)
if (!u->id)
if (!(p = unit_dbus_path(u)))
goto oom;
if (!(m = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "UnitRemoved")))
goto oom;
if (!dbus_message_append_args(m,
goto oom;
goto oom;
free(p);
oom:
free(p);
{ "Requires", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES]), true },
{ "RequiresOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), true },
{ "Requisite", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE]), true },
{ "RequisiteOverridable", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), true },
{ "RequiredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), true },
{ "RequiredByOverridable",bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), true },
{ "WantedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_WANTED_BY]), true },
{ "BoundBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_BOUND_BY]), true },
{ "Conflicts", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTS]), true },
{ "ConflictedBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), true },
{ "OnFailure", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_ON_FAILURE]), true },
{ "Triggers", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERS]), true },
{ "TriggeredBy", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), true },
{ "PropagateReloadTo", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_TO]), true },
{ "PropagateReloadFrom", bus_unit_append_dependencies, "as", offsetof(Unit, dependencies[UNIT_PROPAGATE_RELOAD_FROM]), true },
{ "InactiveExitTimestamp",bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.realtime) },
{ "InactiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, inactive_exit_timestamp.monotonic) },
{ "ActiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.realtime) },
{ "ActiveEnterTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_enter_timestamp.monotonic) },
{ "ActiveExitTimestamp", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.realtime) },
{ "ActiveExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, active_exit_timestamp.monotonic) },
{ "InactiveEnterTimestamp", bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.realtime) },
{ "InactiveEnterTimestampMonotonic",bus_property_append_usec, "t", offsetof(Unit, inactive_enter_timestamp.monotonic) },
{ "ConditionTimestamp", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.realtime) },
{ "ConditionTimestampMonotonic", bus_property_append_usec, "t", offsetof(Unit, condition_timestamp.monotonic) },
{ NULL, }