1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "selinux-access.h"
25 #include "cgroup-util.h"
27 #include "path-util.h"
29 #include "bus-errors.h"
31 #include "dbus-manager.h"
32 #include "dbus-unit.h"
34 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction);
38 static int property_get_names(
41 const char *interface,
43 sd_bus_message *reply,
45 sd_bus_error *error) {
56 r = sd_bus_message_open_container(reply, 'a', "s");
60 SET_FOREACH(t, u->names, i) {
61 r = sd_bus_message_append(reply, "s", t);
66 return sd_bus_message_close_container(reply);
69 static int property_get_following(
72 const char *interface,
74 sd_bus_message *reply,
76 sd_bus_error *error) {
78 Unit *u = userdata, *f;
84 f = unit_following(u);
85 return sd_bus_message_append(reply, "s", f ? f->id : "");
88 static int property_get_dependencies(
91 const char *interface,
93 sd_bus_message *reply,
95 sd_bus_error *error) {
97 Set *s = *(Set**) userdata;
105 r = sd_bus_message_open_container(reply, 'a', "s");
109 SET_FOREACH(u, s, j) {
110 r = sd_bus_message_append(reply, "s", u->id);
115 return sd_bus_message_close_container(reply);
118 static int property_get_description(
121 const char *interface,
122 const char *property,
123 sd_bus_message *reply,
125 sd_bus_error *error) {
133 return sd_bus_message_append(reply, "s", unit_description(u));
136 static int property_get_active_state(
139 const char *interface,
140 const char *property,
141 sd_bus_message *reply,
143 sd_bus_error *error) {
151 return sd_bus_message_append(reply, "s", unit_active_state_to_string(unit_active_state(u)));
154 static int property_get_sub_state(
157 const char *interface,
158 const char *property,
159 sd_bus_message *reply,
161 sd_bus_error *error) {
169 return sd_bus_message_append(reply, "s", unit_sub_state_to_string(u));
172 static int property_get_unit_file_state(
175 const char *interface,
176 const char *property,
177 sd_bus_message *reply,
179 sd_bus_error *error) {
187 return sd_bus_message_append(reply, "s", unit_file_state_to_string(unit_get_unit_file_state(u)));
190 static int property_get_can_start(
193 const char *interface,
194 const char *property,
195 sd_bus_message *reply,
197 sd_bus_error *error) {
205 return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_start);
208 static int property_get_can_stop(
211 const char *interface,
212 const char *property,
213 sd_bus_message *reply,
215 sd_bus_error *error) {
223 /* On the lower levels we assume that every unit we can start
224 * we can also stop */
226 return sd_bus_message_append(reply, "b", unit_can_start(u) && !u->refuse_manual_stop);
229 static int property_get_can_reload(
232 const char *interface,
233 const char *property,
234 sd_bus_message *reply,
236 sd_bus_error *error) {
244 return sd_bus_message_append(reply, "b", unit_can_reload(u));
247 static int property_get_can_isolate(
250 const char *interface,
251 const char *property,
252 sd_bus_message *reply,
254 sd_bus_error *error) {
262 return sd_bus_message_append(reply, "b", unit_can_isolate(u) && !u->refuse_manual_start);
265 static int property_get_job(
268 const char *interface,
269 const char *property,
270 sd_bus_message *reply,
272 sd_bus_error *error) {
274 _cleanup_free_ char *p = NULL;
282 return sd_bus_message_append(reply, "(uo)", 0, "/");
284 p = job_dbus_path(u->job);
288 return sd_bus_message_append(reply, "(uo)", u->job->id, p);
291 static int property_get_need_daemon_reload(
294 const char *interface,
295 const char *property,
296 sd_bus_message *reply,
298 sd_bus_error *error) {
306 return sd_bus_message_append(reply, "b", unit_need_daemon_reload(u));
309 static int property_get_conditions(
312 const char *interface,
313 const char *property,
314 sd_bus_message *reply,
316 sd_bus_error *error) {
318 const char *(*to_string)(ConditionType type) = NULL;
319 Condition **list = userdata, *c;
326 to_string = streq(property, "Asserts") ? assert_type_to_string : condition_type_to_string;
328 r = sd_bus_message_open_container(reply, 'a', "(sbbsi)");
332 LIST_FOREACH(conditions, c, *list) {
336 c->result == CONDITION_UNTESTED ? 0 :
337 c->result == CONDITION_SUCCEEDED ? 1 : -1;
339 r = sd_bus_message_append(reply, "(sbbsi)",
341 c->trigger, c->negate,
342 c->parameter, tristate);
348 return sd_bus_message_close_container(reply);
351 static int property_get_load_error(
354 const char *interface,
355 const char *property,
356 sd_bus_message *reply,
358 sd_bus_error *error) {
360 _cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
367 if (u->load_error != 0)
368 sd_bus_error_set_errno(&e, u->load_error);
370 return sd_bus_message_append(reply, "(ss)", e.name, e.message);
373 int bus_unit_method_start_generic(sd_bus *bus, sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error) {
381 assert(job_type >= 0 && job_type < _JOB_TYPE_MAX);
383 r = sd_bus_message_read(message, "s", &smode);
387 mode = job_mode_from_string(smode);
389 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Job mode %s invalid", smode);
391 return bus_unit_queue_job(bus, message, u, job_type, mode, reload_if_possible, error);
394 static int method_start(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
395 return bus_unit_method_start_generic(bus, message, userdata, JOB_START, false, error);
398 static int method_stop(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
399 return bus_unit_method_start_generic(bus, message, userdata, JOB_STOP, false, error);
402 static int method_reload(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
403 return bus_unit_method_start_generic(bus, message, userdata, JOB_RELOAD, false, error);
406 static int method_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
407 return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, false, error);
410 static int method_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
411 return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, false, error);
414 static int method_reload_or_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
415 return bus_unit_method_start_generic(bus, message, userdata, JOB_RESTART, true, error);
418 static int method_reload_or_try_restart(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
419 return bus_unit_method_start_generic(bus, message, userdata, JOB_TRY_RESTART, true, error);
422 int bus_unit_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
433 r = bus_verify_manage_unit_async_for_kill(u->manager, message, error);
437 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
439 r = sd_bus_message_read(message, "si", &swho, &signo);
446 who = kill_who_from_string(swho);
448 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid who argument %s", swho);
451 if (signo <= 0 || signo >= _NSIG)
452 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
454 r = mac_selinux_unit_access_check(u, message, "stop", error);
458 r = unit_kill(u, who, signo, error);
462 return sd_bus_reply_method_return(message, NULL);
465 int bus_unit_method_reset_failed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
473 r = bus_verify_manage_unit_async(u->manager, message, error);
477 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
479 r = mac_selinux_unit_access_check(u, message, "reload", error);
483 unit_reset_failed(u);
485 return sd_bus_reply_method_return(message, NULL);
488 int bus_unit_method_set_properties(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
496 r = bus_verify_manage_unit_async(u->manager, message, error);
500 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
502 r = sd_bus_message_read(message, "b", &runtime);
506 r = mac_selinux_unit_access_check(u, message, "start", error);
510 r = bus_unit_set_properties(u, message, runtime ? UNIT_RUNTIME : UNIT_PERSISTENT, true, error);
514 return sd_bus_reply_method_return(message, NULL);
517 const sd_bus_vtable bus_unit_vtable[] = {
518 SD_BUS_VTABLE_START(0),
520 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Unit, id), SD_BUS_VTABLE_PROPERTY_CONST),
521 SD_BUS_PROPERTY("Names", "as", property_get_names, 0, SD_BUS_VTABLE_PROPERTY_CONST),
522 SD_BUS_PROPERTY("Following", "s", property_get_following, 0, 0),
523 SD_BUS_PROPERTY("Requires", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES]), SD_BUS_VTABLE_PROPERTY_CONST),
524 SD_BUS_PROPERTY("RequiresOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRES_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
525 SD_BUS_PROPERTY("Requisite", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE]), SD_BUS_VTABLE_PROPERTY_CONST),
526 SD_BUS_PROPERTY("RequisiteOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUISITE_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
527 SD_BUS_PROPERTY("Wants", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTS]), SD_BUS_VTABLE_PROPERTY_CONST),
528 SD_BUS_PROPERTY("BindsTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BINDS_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
529 SD_BUS_PROPERTY("PartOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PART_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
530 SD_BUS_PROPERTY("RequiredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
531 SD_BUS_PROPERTY("RequiredByOverridable", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_REQUIRED_BY_OVERRIDABLE]), SD_BUS_VTABLE_PROPERTY_CONST),
532 SD_BUS_PROPERTY("WantedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_WANTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
533 SD_BUS_PROPERTY("BoundBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BOUND_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
534 SD_BUS_PROPERTY("ConsistsOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONSISTS_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
535 SD_BUS_PROPERTY("Conflicts", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTS]), SD_BUS_VTABLE_PROPERTY_CONST),
536 SD_BUS_PROPERTY("ConflictedBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_CONFLICTED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
537 SD_BUS_PROPERTY("Before", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_BEFORE]), SD_BUS_VTABLE_PROPERTY_CONST),
538 SD_BUS_PROPERTY("After", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_AFTER]), SD_BUS_VTABLE_PROPERTY_CONST),
539 SD_BUS_PROPERTY("OnFailure", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_ON_FAILURE]), SD_BUS_VTABLE_PROPERTY_CONST),
540 SD_BUS_PROPERTY("Triggers", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERS]), SD_BUS_VTABLE_PROPERTY_CONST),
541 SD_BUS_PROPERTY("TriggeredBy", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_TRIGGERED_BY]), SD_BUS_VTABLE_PROPERTY_CONST),
542 SD_BUS_PROPERTY("PropagatesReloadTo", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_PROPAGATES_RELOAD_TO]), SD_BUS_VTABLE_PROPERTY_CONST),
543 SD_BUS_PROPERTY("ReloadPropagatedFrom", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_RELOAD_PROPAGATED_FROM]), SD_BUS_VTABLE_PROPERTY_CONST),
544 SD_BUS_PROPERTY("JoinsNamespaceOf", "as", property_get_dependencies, offsetof(Unit, dependencies[UNIT_JOINS_NAMESPACE_OF]), SD_BUS_VTABLE_PROPERTY_CONST),
545 SD_BUS_PROPERTY("RequiresMountsFor", "as", NULL, offsetof(Unit, requires_mounts_for), SD_BUS_VTABLE_PROPERTY_CONST),
546 SD_BUS_PROPERTY("Documentation", "as", NULL, offsetof(Unit, documentation), SD_BUS_VTABLE_PROPERTY_CONST),
547 SD_BUS_PROPERTY("Description", "s", property_get_description, 0, SD_BUS_VTABLE_PROPERTY_CONST),
548 SD_BUS_PROPERTY("LoadState", "s", property_get_load_state, offsetof(Unit, load_state), SD_BUS_VTABLE_PROPERTY_CONST),
549 SD_BUS_PROPERTY("ActiveState", "s", property_get_active_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
550 SD_BUS_PROPERTY("SubState", "s", property_get_sub_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
551 SD_BUS_PROPERTY("FragmentPath", "s", NULL, offsetof(Unit, fragment_path), SD_BUS_VTABLE_PROPERTY_CONST),
552 SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Unit, source_path), SD_BUS_VTABLE_PROPERTY_CONST),
553 SD_BUS_PROPERTY("DropInPaths", "as", NULL, offsetof(Unit, dropin_paths), SD_BUS_VTABLE_PROPERTY_CONST),
554 SD_BUS_PROPERTY("UnitFileState", "s", property_get_unit_file_state, 0, 0),
555 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveExitTimestamp", offsetof(Unit, inactive_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
556 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveEnterTimestamp", offsetof(Unit, active_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
557 BUS_PROPERTY_DUAL_TIMESTAMP("ActiveExitTimestamp", offsetof(Unit, active_exit_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
558 BUS_PROPERTY_DUAL_TIMESTAMP("InactiveEnterTimestamp", offsetof(Unit, inactive_enter_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
559 SD_BUS_PROPERTY("CanStart", "b", property_get_can_start, 0, SD_BUS_VTABLE_PROPERTY_CONST),
560 SD_BUS_PROPERTY("CanStop", "b", property_get_can_stop, 0, SD_BUS_VTABLE_PROPERTY_CONST),
561 SD_BUS_PROPERTY("CanReload", "b", property_get_can_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
562 SD_BUS_PROPERTY("CanIsolate", "b", property_get_can_isolate, 0, SD_BUS_VTABLE_PROPERTY_CONST),
563 SD_BUS_PROPERTY("Job", "(uo)", property_get_job, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
564 SD_BUS_PROPERTY("StopWhenUnneeded", "b", bus_property_get_bool, offsetof(Unit, stop_when_unneeded), SD_BUS_VTABLE_PROPERTY_CONST),
565 SD_BUS_PROPERTY("RefuseManualStart", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_start), SD_BUS_VTABLE_PROPERTY_CONST),
566 SD_BUS_PROPERTY("RefuseManualStop", "b", bus_property_get_bool, offsetof(Unit, refuse_manual_stop), SD_BUS_VTABLE_PROPERTY_CONST),
567 SD_BUS_PROPERTY("AllowIsolate", "b", bus_property_get_bool, offsetof(Unit, allow_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
568 SD_BUS_PROPERTY("DefaultDependencies", "b", bus_property_get_bool, offsetof(Unit, default_dependencies), SD_BUS_VTABLE_PROPERTY_CONST),
569 SD_BUS_PROPERTY("OnFailureJobMode", "s", property_get_job_mode, offsetof(Unit, on_failure_job_mode), SD_BUS_VTABLE_PROPERTY_CONST),
570 SD_BUS_PROPERTY("IgnoreOnIsolate", "b", bus_property_get_bool, offsetof(Unit, ignore_on_isolate), SD_BUS_VTABLE_PROPERTY_CONST),
571 SD_BUS_PROPERTY("IgnoreOnSnapshot", "b", bus_property_get_bool, offsetof(Unit, ignore_on_snapshot), SD_BUS_VTABLE_PROPERTY_CONST),
572 SD_BUS_PROPERTY("NeedDaemonReload", "b", property_get_need_daemon_reload, 0, SD_BUS_VTABLE_PROPERTY_CONST),
573 SD_BUS_PROPERTY("JobTimeoutUSec", "t", bus_property_get_usec, offsetof(Unit, job_timeout), SD_BUS_VTABLE_PROPERTY_CONST),
574 SD_BUS_PROPERTY("JobTimeoutAction", "s", property_get_failure_action, offsetof(Unit, job_timeout_action), SD_BUS_VTABLE_PROPERTY_CONST),
575 SD_BUS_PROPERTY("JobTimeoutRebootArgument", "s", NULL, offsetof(Unit, job_timeout_reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
576 SD_BUS_PROPERTY("ConditionResult", "b", bus_property_get_bool, offsetof(Unit, condition_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
577 SD_BUS_PROPERTY("AssertResult", "b", bus_property_get_bool, offsetof(Unit, assert_result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
578 BUS_PROPERTY_DUAL_TIMESTAMP("ConditionTimestamp", offsetof(Unit, condition_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
579 BUS_PROPERTY_DUAL_TIMESTAMP("AssertTimestamp", offsetof(Unit, assert_timestamp), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
580 SD_BUS_PROPERTY("Conditions", "a(sbbsi)", property_get_conditions, offsetof(Unit, conditions), 0),
581 SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
582 SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
583 SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
585 SD_BUS_METHOD("Start", "s", "o", method_start, 0),
586 SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),
587 SD_BUS_METHOD("Reload", "s", "o", method_reload, 0),
588 SD_BUS_METHOD("Restart", "s", "o", method_restart, 0),
589 SD_BUS_METHOD("TryRestart", "s", "o", method_try_restart, 0),
590 SD_BUS_METHOD("ReloadOrRestart", "s", "o", method_reload_or_restart, 0),
591 SD_BUS_METHOD("ReloadOrTryRestart", "s", "o", method_reload_or_try_restart, 0),
592 SD_BUS_METHOD("Kill", "si", NULL, bus_unit_method_kill, 0),
593 SD_BUS_METHOD("ResetFailed", NULL, NULL, bus_unit_method_reset_failed, 0),
594 SD_BUS_METHOD("SetProperties", "ba(sv)", NULL, bus_unit_method_set_properties, 0),
599 static int property_get_slice(
602 const char *interface,
603 const char *property,
604 sd_bus_message *reply,
606 sd_bus_error *error) {
614 return sd_bus_message_append(reply, "s", unit_slice_name(u));
617 const sd_bus_vtable bus_unit_cgroup_vtable[] = {
618 SD_BUS_VTABLE_START(0),
619 SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
620 SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Unit, cgroup_path), 0),
624 static int send_new_signal(sd_bus *bus, void *userdata) {
625 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
626 _cleanup_free_ char *p = NULL;
633 p = unit_dbus_path(u);
637 r = sd_bus_message_new_signal(
640 "/org/freedesktop/systemd1",
641 "org.freedesktop.systemd1.Manager",
646 r = sd_bus_message_append(m, "so", u->id, p);
650 return sd_bus_send(bus, m, NULL);
653 static int send_changed_signal(sd_bus *bus, void *userdata) {
654 _cleanup_free_ char *p = NULL;
661 p = unit_dbus_path(u);
665 /* Send a properties changed signal. First for the specific
666 * type, then for the generic unit. The clients may rely on
667 * this order to get atomic behavior if needed. */
669 r = sd_bus_emit_properties_changed_strv(
671 UNIT_VTABLE(u)->bus_interface,
676 return sd_bus_emit_properties_changed_strv(
678 "org.freedesktop.systemd1.Unit",
682 void bus_unit_send_change_signal(Unit *u) {
686 if (u->in_dbus_queue) {
687 LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u);
688 u->in_dbus_queue = false;
694 r = bus_foreach_bus(u->manager, NULL, u->sent_dbus_new_signal ? send_changed_signal : send_new_signal, u);
696 log_debug("Failed to send unit change signal for %s: %s", u->id, strerror(-r));
698 u->sent_dbus_new_signal = true;
701 static int send_removed_signal(sd_bus *bus, void *userdata) {
702 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
703 _cleanup_free_ char *p = NULL;
710 p = unit_dbus_path(u);
714 r = sd_bus_message_new_signal(
717 "/org/freedesktop/systemd1",
718 "org.freedesktop.systemd1.Manager",
723 r = sd_bus_message_append(m, "so", u->id, p);
727 return sd_bus_send(bus, m, NULL);
730 void bus_unit_send_removed_signal(Unit *u) {
734 if (!u->sent_dbus_new_signal)
735 bus_unit_send_change_signal(u);
740 r = bus_foreach_bus(u->manager, NULL, send_removed_signal, u);
742 log_debug("Failed to send unit remove signal for %s: %s", u->id, strerror(-r));
745 int bus_unit_queue_job(
747 sd_bus_message *message,
751 bool reload_if_possible,
752 sd_bus_error *error) {
754 _cleanup_free_ char *path = NULL;
761 assert(type >= 0 && type < _JOB_TYPE_MAX);
762 assert(mode >= 0 && mode < _JOB_MODE_MAX);
764 if (reload_if_possible && unit_can_reload(u)) {
765 if (type == JOB_RESTART)
766 type = JOB_RELOAD_OR_START;
767 else if (type == JOB_TRY_RESTART)
771 r = mac_selinux_unit_access_check(
773 (type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
774 type == JOB_STOP ? "stop" : "reload", error);
778 if (type == JOB_STOP &&
779 (u->load_state == UNIT_NOT_FOUND || u->load_state == UNIT_ERROR) &&
780 unit_active_state(u) == UNIT_INACTIVE)
781 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
783 if ((type == JOB_START && u->refuse_manual_start) ||
784 (type == JOB_STOP && u->refuse_manual_stop) ||
785 ((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)))
786 return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
788 r = manager_add_job(u->manager, type, u, mode, true, error, &j);
792 if (bus == u->manager->api_bus) {
794 r = sd_bus_track_new(bus, &j->clients, NULL, NULL);
799 r = sd_bus_track_add_sender(j->clients, message);
804 path = job_dbus_path(j);
808 return sd_bus_reply_method_return(message, "o", path);
811 static int bus_unit_set_transient_property(
814 sd_bus_message *message,
815 UnitSetPropertiesMode mode,
816 sd_bus_error *error) {
824 if (streq(name, "Description")) {
827 r = sd_bus_message_read(message, "s", &d);
831 if (mode != UNIT_CHECK) {
832 r = unit_set_description(u, d);
836 unit_write_drop_in_format(u, mode, name, "[Unit]\nDescription=%s\n", d);
841 } else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
844 r = sd_bus_message_read(message, "s", &s);
848 if (!unit_name_is_valid(s, TEMPLATE_INVALID) || !endswith(s, ".slice"))
849 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid slice name %s", s);
852 if (mode != UNIT_CHECK) {
853 unit_ref_unset(&u->slice);
854 unit_remove_drop_in(u, mode, name);
859 r = manager_load_unit(u->manager, s, NULL, error, &slice);
863 if (slice->type != UNIT_SLICE)
866 if (mode != UNIT_CHECK) {
867 unit_ref_set(&u->slice, slice);
868 unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s);
873 } else if (STR_IN_SET(name,
874 "Requires", "RequiresOverridable",
875 "Requisite", "RequisiteOverridable",
881 "PropagatesReloadTo", "ReloadPropagatedFrom",
887 d = unit_dependency_from_string(name);
891 r = sd_bus_message_enter_container(message, 'a', "s");
895 while ((r = sd_bus_message_read(message, "s", &other)) > 0) {
896 if (!unit_name_is_valid(other, TEMPLATE_INVALID))
897 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid unit name %s", other);
899 if (mode != UNIT_CHECK) {
900 _cleanup_free_ char *label = NULL;
902 r = unit_add_dependency_by_name(u, d, other, NULL, true);
906 label = strjoin(name, "-", other, NULL);
910 unit_write_drop_in_format(u, mode, label, "[Unit]\n%s=%s\n", name, other);
917 r = sd_bus_message_exit_container(message);
927 int bus_unit_set_properties(
929 sd_bus_message *message,
930 UnitSetPropertiesMode mode,
932 sd_bus_error *error) {
934 bool for_real = false;
941 /* We iterate through the array twice. First run we just check
942 * if all passed data is valid, second run actually applies
943 * it. This is to implement transaction-like behaviour without
944 * actually providing full transactions. */
946 r = sd_bus_message_enter_container(message, 'a', "(sv)");
953 r = sd_bus_message_enter_container(message, 'r', "sv");
957 if (for_real || mode == UNIT_CHECK)
960 /* Reached EOF. Let's try again, and this time for realz... */
961 r = sd_bus_message_rewind(message, false);
969 r = sd_bus_message_read(message, "s", &name);
973 if (!UNIT_VTABLE(u)->bus_set_property)
974 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Objects of this type do not support setting properties.");
976 r = sd_bus_message_enter_container(message, 'v', NULL);
980 r = UNIT_VTABLE(u)->bus_set_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
981 if (r == 0 && u->transient && u->load_state == UNIT_STUB)
982 r = bus_unit_set_transient_property(u, name, message, for_real ? mode : UNIT_CHECK, error);
986 return sd_bus_error_setf(error, SD_BUS_ERROR_PROPERTY_READ_ONLY, "Cannot set property %s, or unknown property.", name);
988 r = sd_bus_message_exit_container(message);
992 r = sd_bus_message_exit_container(message);
999 r = sd_bus_message_exit_container(message);
1003 if (commit && n > 0 && UNIT_VTABLE(u)->bus_commit_properties)
1004 UNIT_VTABLE(u)->bus_commit_properties(u);