+ /* This is slightly dirty, since we don't undo the match registrations. */
+ return 0;
+}
+
+static int wait_for_jobs(DBusConnection *bus, Set *s) {
+ int r = 0;
+ WaitData d = { .set = s };
+
+ assert(bus);
+ assert(s);
+
+ if (!dbus_connection_add_filter(bus, wait_filter, &d, NULL))
+ return log_oom();
+
+ while (!set_isempty(s)) {
+
+ if (!dbus_connection_read_write_dispatch(bus, -1)) {
+ log_error("Disconnected from bus.");
+ return -ECONNREFUSED;
+ }
+
+ if (!d.result)
+ goto free_name;
+
+ if (!arg_quiet) {
+ if (streq(d.result, "timeout"))
+ log_error("Job for %s timed out.", strna(d.name));
+ else if (streq(d.result, "canceled"))
+ log_error("Job for %s canceled.", strna(d.name));
+ else if (streq(d.result, "dependency"))
+ log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
+ else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
+ log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
+ }
+
+ if (streq_ptr(d.result, "timeout"))
+ r = -ETIME;
+ else if (streq_ptr(d.result, "canceled"))
+ r = -ECANCELED;
+ else if (!streq_ptr(d.result, "done") && !streq_ptr(d.result, "skipped"))
+ r = -EIO;
+
+ free(d.result);
+ d.result = NULL;
+
+ free_name:
+ free(d.name);
+ d.name = NULL;
+ }
+
+ dbus_connection_remove_filter(bus, wait_filter, &d);
+ return r;
+}
+
+static int check_one_unit(DBusConnection *bus, const char *name, char **check_states, bool quiet) {
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ _cleanup_free_ char *n = NULL;
+ DBusMessageIter iter, sub;
+ const char
+ *interface = "org.freedesktop.systemd1.Unit",
+ *property = "ActiveState";
+ const char *state, *path;
+ DBusError error;
+ int r;
+
+ assert(name);
+
+ dbus_error_init(&error);
+
+ n = unit_name_mangle(name);
+ if (!n)
+ return log_oom();
+
+ r = bus_method_call_with_reply (
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "GetUnit",
+ &reply,
+ &error,
+ DBUS_TYPE_STRING, &n,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ dbus_error_free(&error);
+
+ if (!quiet)
+ puts("unknown");
+ return 0;
+ }
+
+ if (!dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID)) {
+ log_error("Failed to parse reply.");
+ return -EIO;
+ }
+
+ dbus_message_unref(reply);
+ reply = NULL;
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ &reply,
+ NULL,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &property,
+ DBUS_TYPE_INVALID);
+ if (r < 0) {
+ if (!quiet)
+ puts("unknown");
+ return 0;
+ }
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ return r;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+ log_error("Failed to parse reply.");
+ return r;
+ }
+
+ dbus_message_iter_get_basic(&sub, &state);
+
+ if (!quiet)
+ puts(state);
+
+ return strv_find(check_states, state) ? 1 : 0;
+}
+
+static void check_triggering_units(
+ DBusConnection *bus,
+ const char *unit_name) {
+
+ _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
+ DBusMessageIter iter, sub;
+ const char *interface = "org.freedesktop.systemd1.Unit",
+ *load_state_property = "LoadState",
+ *triggered_by_property = "TriggeredBy",
+ *state;
+ _cleanup_free_ char *unit_path = NULL, *n = NULL;
+ bool print_warning_label = true;
+ int r;
+
+ n = unit_name_mangle(unit_name);
+ if (!n) {
+ log_oom();
+ return;
+ }
+
+ unit_path = unit_dbus_path_from_name(n);
+ if (!unit_path) {
+ log_oom();
+ return;
+ }
+
+ r = bus_method_call_with_reply(
+ bus,
+ "org.freedesktop.systemd1",
+ unit_path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ &reply,
+ NULL,
+ DBUS_TYPE_STRING, &interface,
+ DBUS_TYPE_STRING, &load_state_property,
+ DBUS_TYPE_INVALID);
+ if (r < 0)
+ return;
+
+ if (!dbus_message_iter_init(reply, &iter) ||
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+ log_error("Failed to parse reply.");
+ return;
+ }
+
+ dbus_message_iter_recurse(&iter, &sub);
+
+ if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+ log_error("Failed to parse reply.");
+ return;
+ }
+
+ dbus_message_iter_get_basic(&sub, &state);