X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fsystemctl%2Fsystemctl.c;h=ad0cd17e14b8e1a871d5aa13ff4063faab609236;hb=089842938dd0f4080084044bb9a1a3b00137926a;hp=2fbfd7eb9bb3d0eb28d5415ad1af4bcd8f49f17a;hpb=b43f208f78666fd27e274daa946ae57becd59dd6;p=elogind.git diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 2fbfd7eb9..ad0cd17e1 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -1500,6 +1500,213 @@ finish: return r; } +static int check_one_unit(DBusConnection *bus, char *name, bool quiet) { + DBusMessage *m = NULL, *reply = NULL; + DBusError error; + DBusMessageIter iter, sub; + const char + *interface = "org.freedesktop.systemd1.Unit", + *property = "ActiveState"; + const char *path = NULL; + const char *state; + int r = 3; /* According to LSB: "program is not running" */ + + assert(bus); + assert(name); + + dbus_error_init(&error); + + m = dbus_message_new_method_call( + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "GetUnit"); + if (!m) { + log_error("Could not allocate message."); + r = -ENOMEM; + goto finish; + } + + if (!dbus_message_append_args(m, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) { + log_error("Could not append arguments to message."); + r = -ENOMEM; + goto finish; + } + + reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error); + if (!reply) { + /* Hmm, cannot figure out anything about this unit... */ + if (!quiet) + puts("unknown"); + + goto finish; + } + + if (!dbus_message_get_args(reply, &error, + DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID)) { + log_error("Failed to parse reply: %s", bus_error_message(&error)); + r = -EIO; + goto finish; + } + + dbus_message_unref(m); + m = dbus_message_new_method_call( + "org.freedesktop.systemd1", + path, + "org.freedesktop.DBus.Properties", + "Get"); + if (!m) { + log_error("Could not allocate message."); + r = -ENOMEM; + goto finish; + } + + if (!dbus_message_append_args(m, + DBUS_TYPE_STRING, &interface, + DBUS_TYPE_STRING, &property, + DBUS_TYPE_INVALID)) { + log_error("Could not append arguments to message."); + r = -ENOMEM; + goto finish; + } + + dbus_message_unref(reply); + reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error); + if (!reply) { + log_error("Failed to issue method call: %s", bus_error_message(&error)); + r = -EIO; + goto finish; + } + + if (!dbus_message_iter_init(reply, &iter) || + dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { + log_error("Failed to parse reply."); + r = -EIO; + goto finish; + } + + dbus_message_iter_recurse(&iter, &sub); + + if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) { + log_error("Failed to parse reply."); + r = -EIO; + goto finish; + } + + dbus_message_iter_get_basic(&sub, &state); + + if (!quiet) + puts(state); + + if (streq(state, "active") || streq(state, "reloading")) + r = 0; + +finish: + if (m) + dbus_message_unref(m); + + if (reply) + dbus_message_unref(reply); + + dbus_error_free(&error); + + return r; +} + +static void check_triggering_units( + DBusConnection *bus, + const char *unit_name) { + + DBusError error; + DBusMessage *m = NULL, *reply = NULL; + DBusMessageIter iter, sub; + char *service_trigger = NULL; + const char *interface = "org.freedesktop.systemd1.Unit", + *triggered_by_property = "TriggeredBy"; + + char *unit_path = NULL; + bool print_warning_label = true; + + dbus_error_init(&error); + + unit_path = unit_dbus_path_from_name(unit_name); + if (!unit_path) { + log_error("Could not allocate dbus path."); + goto finish; + } + + m = dbus_message_new_method_call("org.freedesktop.systemd1", + unit_path, + "org.freedesktop.DBus.Properties", + "Get"); + if (!m) { + log_error("Could not allocate message."); + goto finish; + } + + if (!dbus_message_append_args(m, + DBUS_TYPE_STRING, &interface, + DBUS_TYPE_STRING, &triggered_by_property, + DBUS_TYPE_INVALID)) { + log_error("Could not append arguments to message."); + goto finish; + } + + reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error); + if (!reply) { + log_error("Failed to issue method call: %s", bus_error_message(&error)); + goto finish; + } + + if (!dbus_message_iter_init(reply, &iter) || + dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { + log_error("Failed to parse reply: %s", bus_error_message(&error)); + goto finish; + + } + + dbus_message_iter_recurse(&iter, &sub); + dbus_message_iter_recurse(&sub, &iter); + sub = iter; + + while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) { + int r; + + if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) { + log_error("Failed to parse reply: %s", bus_error_message(&error)); + goto finish; + } + + dbus_message_iter_get_basic(&sub, &service_trigger); + + r = check_one_unit(bus, service_trigger, true); + if (r < 0) + goto finish; + if (r == 0) { + if (print_warning_label) { + log_warning("Warning: Stopping %s, but it can still be activated by:", unit_name); + print_warning_label = false; + } + log_warning(" %s", service_trigger); + } + + dbus_message_iter_next(&sub); + } +finish: + if (m) + dbus_message_unref(m); + + if (reply) + dbus_message_unref(reply); + + dbus_error_free(&error); + + free(unit_path); +} + static int start_unit_one( DBusConnection *bus, const char *method, @@ -1580,6 +1787,11 @@ static int start_unit_one( } } + /* When stopping a unit warn if it can still be triggered by + * another active unit (socket, path, timer) */ + if (!arg_quiet && streq(method, "StopUnit")) + check_triggering_units(bus, name); + r = 0; finish: @@ -1865,126 +2077,20 @@ static int start_special(DBusConnection *bus, char **args) { } static int check_unit(DBusConnection *bus, char **args) { - DBusMessage *m = NULL, *reply = NULL; - const char - *interface = "org.freedesktop.systemd1.Unit", - *property = "ActiveState"; - int r = 3; /* According to LSB: "program is not running" */ - DBusError error; char **name; + int r = 3; /* According to LSB: "program is not running" */ assert(bus); assert(args); - dbus_error_init(&error); - STRV_FOREACH(name, args+1) { - const char *path = NULL; - const char *state; - DBusMessageIter iter, sub; - - if (!(m = dbus_message_new_method_call( - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "GetUnit"))) { - log_error("Could not allocate message."); - r = -ENOMEM; - goto finish; - } - - if (!dbus_message_append_args(m, - DBUS_TYPE_STRING, name, - DBUS_TYPE_INVALID)) { - log_error("Could not append arguments to message."); - r = -ENOMEM; - goto finish; - } - - if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) { - - /* Hmm, cannot figure out anything about this unit... */ - if (!arg_quiet) - puts("unknown"); - - dbus_error_free(&error); - dbus_message_unref(m); - m = NULL; - continue; - } - - if (!dbus_message_get_args(reply, &error, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID)) { - log_error("Failed to parse reply: %s", bus_error_message(&error)); - r = -EIO; - goto finish; - } - - dbus_message_unref(m); - if (!(m = dbus_message_new_method_call( - "org.freedesktop.systemd1", - path, - "org.freedesktop.DBus.Properties", - "Get"))) { - log_error("Could not allocate message."); - r = -ENOMEM; - goto finish; - } - - if (!dbus_message_append_args(m, - DBUS_TYPE_STRING, &interface, - DBUS_TYPE_STRING, &property, - DBUS_TYPE_INVALID)) { - log_error("Could not append arguments to message."); - r = -ENOMEM; - goto finish; - } - - dbus_message_unref(reply); - if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) { - log_error("Failed to issue method call: %s", bus_error_message(&error)); - r = -EIO; - goto finish; - } - - if (!dbus_message_iter_init(reply, &iter) || - dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { - log_error("Failed to parse reply."); - r = -EIO; - goto finish; - } - - dbus_message_iter_recurse(&iter, &sub); - - if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) { - log_error("Failed to parse reply."); - r = -EIO; - goto finish; - } - - dbus_message_iter_get_basic(&sub, &state); - - if (!arg_quiet) - puts(state); - - if (streq(state, "active") || streq(state, "reloading")) + int state = check_one_unit(bus, *name, arg_quiet); + if (state < 0) + return state; + if (state == 0) r = 0; - - dbus_message_unref(m); - dbus_message_unref(reply); - m = reply = NULL; } -finish: - if (m) - dbus_message_unref(m); - - if (reply) - dbus_message_unref(reply); - - dbus_error_free(&error); - return r; } @@ -2448,7 +2554,7 @@ static void print_status_info(UnitStatusInfo *i) { if (i->id && arg_transport != TRANSPORT_SSH) { printf("\n"); - show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow); + show_journal_by_unit(i->id, arg_output, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow, !arg_quiet); } if (i->need_daemon_reload) @@ -3134,12 +3240,7 @@ static int show(DBusConnection *bus, char **args) { /* Interpret as unit name */ - char *e, *p; - e = bus_path_escape(*name); - if (!e) - return -ENOMEM; - p = strappend("/org/freedesktop/systemd1/unit/", e); - free(e); + char *p = unit_dbus_path_from_name(*name); if (!p) return -ENOMEM; @@ -4108,7 +4209,7 @@ static int enable_unit(DBusConnection *bus, char **args) { } if (carries_install_info == 0) - log_warning("Warning: unit files do not carry install information. No operation executed."); + log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl."); finish: if (m)